aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Smokowski <ss835w@att.com>2017-02-09 15:27:43 -0500
committerSteve Smokowski <ss835w@att.com>2017-02-09 15:28:15 -0500
commit4c790f64daf7822de00405140d17e08f296a642f (patch)
tree1a608a463115640bc59260eef90a08a70c93880c
parent2f3dcb75d2f658fd7af04ea908c70c5104c2b9ef (diff)
Initial OpenECOMP A&AI commit
Change-Id: I8b06519995d9dc0f220b80a6d9a71865b23e4edb Signed-off-by: Steve Smokowski <ss835w@att.com>
-rw-r--r--.gitignore10
-rw-r--r--LICENSE.TXT23
-rw-r--r--aai-schema/.gitignore2
-rw-r--r--aai-schema/pom.xml92
-rw-r--r--aai-schema/src/main/resources/aai_schema/aai_schema_v8.xsd3699
-rw-r--r--aai-schema/src/main/resources/oxm/aai_oxm_v8.xml3076
-rw-r--r--ajsc-aai/.gitignore7
-rw-r--r--ajsc-aai/ajsc-shared-config/README.txt6
-rw-r--r--ajsc-aai/ajsc-shared-config/etc/aft.properties7
-rw-r--r--ajsc-aai/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml87
-rw-r--r--ajsc-aai/ajsc-shared-config/etc/localhost-access-logback.xml38
-rw-r--r--ajsc-aai/ajsc-shared-config/etc/logback.xml296
-rw-r--r--ajsc-aai/ajsc/pom.xml25
-rw-r--r--ajsc-aai/antBuild/build.xml231
-rw-r--r--ajsc-aai/bundleconfig-local/README.txt10
-rw-r--r--ajsc-aai/bundleconfig-local/RELEASE_NOTES.txt1
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/AAFUserRoles.properties5
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/Introscope.properties8
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties3
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties4
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties29
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadConsumer.properties30
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadPublisher.properties29
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadStatusPublisher.properties29
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/aaiconfig.properties95
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/app-intercepts.properties8
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/createDBSchema-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/dataGrooming-logback.xml108
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/dataSnapshot-logback.xml108
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/default-logback.xml20
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/deltool-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/error.properties128
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/getres-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/logging.properties128
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/methodMapper.properties2
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/posttool-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/preferredRoute.txt1
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/puttool-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/rshiptool-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/schemaMod-logback.xml62
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/uniquePropertyCheck-logback.xml62
-rw-r--r--ajsc-aai/bundleconfig-local/etc/appprops/updtool-logback.xml93
-rw-r--r--ajsc-aai/bundleconfig-local/etc/auth/aai_keystorebin0 -> 4002 bytes
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/addmanualdata/README30
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/closed-loop-named-query-1.0.json78
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json98
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceModel-1.0.json72
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json126
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getVserver-1.0.json105
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/resource-model-json/000-README10
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/schemamods/README18
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/service-model-json/000-README10
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json7
-rw-r--r--ajsc-aai/bundleconfig-local/etc/sysprops/sys-props.properties112
-rw-r--r--ajsc-aai/bundleconfig-local/etc/sysprops/template.sys-props.properties92
-rw-r--r--ajsc-aai/bundleconfig-local/swm-var-ajsc.txt3
-rw-r--r--ajsc-aai/bundleconfig-local/symlinks.txt6
-rw-r--r--ajsc-aai/pom.xml625
-rw-r--r--ajsc-aai/services/README.txt8
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml20
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy36
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml95
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt1
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt1
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props1
-rw-r--r--ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route4
-rw-r--r--ajsc-aai/src/main/assemble/ajsc_module_assembly.xml66
-rw-r--r--ajsc-aai/src/main/assemble/ajsc_props_assembly.xml23
-rw-r--r--ajsc-aai/src/main/assemble/ajsc_runtime_assembly.xml44
-rw-r--r--ajsc-aai/src/main/config/ajsc-jetty.xml168
-rw-r--r--ajsc-aai/src/main/config/ajsc-jolokia-override-web.xml46
-rw-r--r--ajsc-aai/src/main/config/ajsc-override-web.xml41
-rw-r--r--ajsc-aai/src/main/config/ajsc-request.xml49
-rw-r--r--ajsc-aai/src/main/config/caet.properties0
-rw-r--r--ajsc-aai/src/main/config/hazelcast-client.properties25
-rw-r--r--ajsc-aai/src/main/config/jul-redirect.properties13
-rw-r--r--ajsc-aai/src/main/config/realm.properties11
-rw-r--r--ajsc-aai/src/main/config/runner-web.xml111
-rw-r--r--ajsc-aai/src/main/config/template.ajsc-jetty.xml169
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java54
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java127
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java37
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/audit/ListEndpoints.java249
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/auth/AAIAuth.java61
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/AAIProperties.java35
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditDoc.java89
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditOXM.java241
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditTitan.java127
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Auditor.java58
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditorFactory.java48
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/CompareByName.java36
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBIndex.java105
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBProperty.java86
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/EdgeProperty.java70
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ManageTitanSchema.java329
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Named.java31
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java95
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java126
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java307
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java2184
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java257
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbEdgeGroup.java525
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java3964
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbSearchWithTags.java771
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java209
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/GenTester.java175
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java3490
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java321
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ResultSet.java124
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaGenerator.java433
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java456
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java255
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmap/AAIGraph.java142
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmap/ActionsGraph.java418
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmap/GraphHelpersMoxy.java2136
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmap/RelationshipGraph.java299
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmap/SearchGraph.java1475
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/DbEdgeRules.java300
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/RestRules.java274
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java127
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java43
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapPublisher.java54
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIClient.java164
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadConsumer.java207
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventProcessor.java340
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventStatus.java25
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResource.java675
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKey.java103
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKeys.java40
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResources.java86
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItem.java107
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItems.java40
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/NotificationEvent.java564
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/ObjectFactory.java77
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessage.java125
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageData.java78
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageDatum.java81
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessages.java118
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/package-info.java32
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/Fault.java382
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/ObjectFactory.java95
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/PolicyException.java134
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RESTResponse.java86
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RequestError.java87
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/Info.java385
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/ObjectFactory.java95
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/Fault.java382
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ObjectFactory.java95
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RESTResponse.java86
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RequestError.java86
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ServiceException.java134
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/IncludeNodeFilter.java127
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItem.java197
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItemData.java155
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/ObjectFactory.java106
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/SecondaryFilter.java183
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/StartNodeFilter.java155
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/TaggedInventoryItemList.java96
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/search/package-info.java29
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntries.java131
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntry.java438
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIException.java164
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIExceptionWithInfo.java134
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java880
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/extensions/ExtensionController.java168
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/ConvertXmlToJsonMoxyOxm.java111
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/CreateWidgetModels.java164
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/DbMaps.java64
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelListener.java85
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelMoxyOxm.java988
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java302
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java647
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/Introspector.java459
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorFactory.java67
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorWalker.java147
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/JSONStrategy.java363
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/Loader.java116
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/LoaderFactory.java46
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/MarshallerProperties.java139
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelInjestor.java171
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelType.java25
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyLoader.java134
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyStrategy.java355
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoInjestor.java63
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoLoader.java128
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoStrategy.java383
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/Version.java25
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/Wanderer.java75
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java167
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/CreateUUID.java48
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/DefaultFields.java48
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Error.java25
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/InjectKeysFromURI.java70
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IntrospectorValidator.java278
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Issue.java144
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IssueResolver.java33
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Severity.java27
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/logging/AAILogger.java492
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorLogHelper.java587
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorObject.java328
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLine.java488
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLineBuilder.java64
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/LegacyQueryParser.java163
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParser.java148
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParserStrategy.java86
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/RelationshipQueryParser.java72
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/TraversalStrategy.java76
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryParser.java58
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueStrategy.java75
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueURIQueryParser.java169
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/relationship/RelationshipToURI.java217
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/Parsable.java71
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIParser.java272
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToDBKey.java127
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToExtensionInformation.java170
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToObject.java224
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToRelationshipObject.java166
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GraphTraversalBuilder.java275
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineBuilder.java215
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineTraversal.java77
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinQueryBuilder.java273
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinTraversal.java102
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinUnique.java102
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/QueryBuilder.java221
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/query/builder/TraversalQuery.java102
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java412
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/CustomJacksonJaxBJsonProvider.java71
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java111
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java132
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/HttpMethod.java33
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java593
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/MediaType.java66
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/RESTAPI.java391
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/RestProviders.java666
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java126
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java144
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/actions/ActionsProvider.java275
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/db/DBRequest.java218
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java584
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java219
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java241
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/translog/TransLogRestProvider.java284
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java97
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java173
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java149
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java160
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java1418
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DeleteSemantic.java40
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRule.java202
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java310
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeType.java26
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/GraphSingleton.java81
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/MultiplicityRule.java28
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/TitanGraphSingleton.java74
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/QueryStyle.java25
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TitanDBEngine.java107
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java166
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java165
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinPipelineQueryEngine.java186
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java176
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/QueryEngine.java98
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/tasks/ScheduledTasks.java159
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerateFitNesseTests.java134
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerationTest.java77
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/InjectResourceVersion.java132
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/LocateEndPoints.java579
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/OXMTest.java63
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/PopulateObject.java232
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/TestDataGenerator.java66
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testing/UpdateObject.java205
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AbstractWriter.java491
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AddNamedPropWildcard.java96
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FMObject.java148
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FitNesseJUnitWriter.java141
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/RelationshipWriter.java405
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuite.java441
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuiteWriter.java375
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/child_test_content_txt.ftl33
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/empty_context_txt.ftl21
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/end_point_suite_content_txt.ftl32
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/junit_class_java.ftl33
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/properties_xml.ftl48
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/recursive_teardown_content_txt.ftl29
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_content_txt.ftl37
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_content_txt.ftl36
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_reversed_content_txt.ftl36
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/remove_children_content_txt.ftl25
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/static_page_content_txt.ftl21
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/version_suite_content_txt.ftl31
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiServerURLBase.java79
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiVersion.java73
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java119
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfig.java320
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfigCommandLinePropGetter.java66
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConstants.java113
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIPrimaryHost.java444
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIRSyncUtility.java224
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAITxnLog.java563
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/AAIUtils.java54
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/CNName.java94
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayout.java28
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayoutEncoder.java40
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/DME2RestFlag.java55
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/DataConversionHelper.java63
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/DeleteResource.java302
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/Entity.java196
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/EntityList.java114
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/FileWatcher.java59
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java141
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateXsd.java1491
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/GetResource.java161
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/HbaseSaltPrefixer.java60
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java175
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthExternalClient.java151
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java98
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/KeyValueList.java138
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/MapperUtil.java116
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/MergeResource.java205
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/PojoUtils.java990
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/PostResource.java186
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/PutActionsNotify.java253
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/PutResource.java470
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java234
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/Request.java160
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/RestController.java750
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/RestObject.java46
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/RestURL.java799
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java211
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java264
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/util/UpdateResource.java146
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/workarounds/LegacyURLTransformer.java96
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/workarounds/ModifyOXMProperties.java220
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/workarounds/NamingExceptions.java79
-rw-r--r--ajsc-aai/src/main/java/org/openecomp/aai/workarounds/RemoveDME2QueryParams.java65
-rw-r--r--ajsc-aai/src/main/resources/docker/Dockerfile86
-rw-r--r--ajsc-aai/src/main/resources/docker/Dockerfile.ext76
-rw-r--r--ajsc-aai/src/main/resources/docker/aai.sh42
-rw-r--r--ajsc-aai/src/main/resources/docker/commonLibs/README1
-rw-r--r--ajsc-aai/src/main/resources/docker/init-chef.sh32
-rw-r--r--ajsc-aai/src/main/resources/docker/startup.sh96
-rw-r--r--ajsc-aai/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context1
-rw-r--r--ajsc-aai/src/main/runtime/context/default#0.context1
-rw-r--r--ajsc-aai/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroRole/ajscadmin.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroRole/contextadmin#default.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroUser/ajsc.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json1
-rw-r--r--ajsc-aai/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json1
-rw-r--r--ajsc-aai/src/main/scripts/PropertyChangeName.sh87
-rw-r--r--ajsc-aai/src/main/scripts/aaiadmin.crontab25
-rw-r--r--ajsc-aai/src/main/scripts/addResourceVersionProperty.sh55
-rw-r--r--ajsc-aai/src/main/scripts/audit_schema.sh46
-rw-r--r--ajsc-aai/src/main/scripts/changePropertyCardinality.sh85
-rw-r--r--ajsc-aai/src/main/scripts/createDBSchema.sh58
-rw-r--r--ajsc-aai/src/main/scripts/dataGrooming.sh131
-rw-r--r--ajsc-aai/src/main/scripts/dataRestoreFromSnapshot.sh85
-rw-r--r--ajsc-aai/src/main/scripts/dataSnapshot.sh59
-rw-r--r--ajsc-aai/src/main/scripts/deleteTool.sh61
-rw-r--r--ajsc-aai/src/main/scripts/deobfuscatePW.sh63
-rw-r--r--ajsc-aai/src/main/scripts/dotOutEnd_cleanup.sh81
-rw-r--r--ajsc-aai/src/main/scripts/dotOutMiddle_cleanup.sh81
-rw-r--r--ajsc-aai/src/main/scripts/edgeTagger.sh96
-rw-r--r--ajsc-aai/src/main/scripts/fix_yang_classes.pl64
-rw-r--r--ajsc-aai/src/main/scripts/forceDeleteTool.sh73
-rw-r--r--ajsc-aai/src/main/scripts/generate.sh91
-rw-r--r--ajsc-aai/src/main/scripts/getTool.sh61
-rw-r--r--ajsc-aai/src/main/scripts/install/addManualData.sh111
-rw-r--r--ajsc-aai/src/main/scripts/install/doSchemaMods.sh102
-rw-r--r--ajsc-aai/src/main/scripts/install/instutils.sh722
-rw-r--r--ajsc-aai/src/main/scripts/install/updateQueryData.sh103
-rw-r--r--ajsc-aai/src/main/scripts/logcleanup.sh80
-rw-r--r--ajsc-aai/src/main/scripts/notifyTool.sh61
-rw-r--r--ajsc-aai/src/main/scripts/postTool.sh61
-rw-r--r--ajsc-aai/src/main/scripts/putTool.sh61
-rw-r--r--ajsc-aai/src/main/scripts/rshipTool.sh75
-rw-r--r--ajsc-aai/src/main/scripts/run_ChangeAuthMethod.sh107
-rw-r--r--ajsc-aai/src/main/scripts/run_DbTestProcessBuilder.sh49
-rw-r--r--ajsc-aai/src/main/scripts/run_FixXSD.sh67
-rw-r--r--ajsc-aai/src/main/scripts/schemaMod.sh94
-rw-r--r--ajsc-aai/src/main/scripts/uniquePropertyCheck.sh64
-rw-r--r--ajsc-aai/src/main/scripts/updateTool.sh61
-rw-r--r--ajsc-aai/src/main/scripts/yangToJava.sh117
-rw-r--r--ajsc-aai/src/main/xjb/bindings.xjb11
-rw-r--r--ajsc-aai/src/test/java/bundleconfig-local/etc/appprops/aaiconfig.properties21
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/dbmap/ActionsGraphTest.java2485
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/dbmap/SearchGraphTest.java739
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionTest.java148
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionWithInfoTest.java150
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GraphTraversalTest.java360
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GremlinPipelineTraversalTest.java408
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyGremlinQueryTest.java252
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyQueryTest.java168
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipGremlinQueryTest.java649
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipQueryTest.java287
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryTest.java322
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueURIQueryTest.java210
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIParserTest.java116
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToDBKeyTest.java186
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToExtensionInformationTest.java85
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToObjectTest.java251
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToRelationshipObjectTest.java165
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/rest/search/SearchProviderTest.java372
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/rest/util/ValidateEncodingTest.java105
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/schema/db/AuditOXMTest.java94
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/schema/db/ManageSchemaTest.java120
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/serialization/db/DBSerializerMaxRetryTest.java85
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiServerURLBaseTest.java88
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiVersionTest.java93
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIAppServletContextListenerTest.java179
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIConfigPasswordDecodingTest.java56
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIPrimaryHostTest.java203
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIRSyncUtilityTest.java216
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAITxnLogTest.java362
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/AAIUtilsTest.java113
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/CNNameTest.java141
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/CustomLogPatternLayoutTest.java50
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/DataConversionHelperTest.java89
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestConfig.java303
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestFileWatcher.java64
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestGetFileTime.java55
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestProcessBuilder.java218
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/DeleteResourceTest.java107
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/HbaseSaltPrefixerTest.java40
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtilTest.java72
-rw-r--r--ajsc-aai/src/test/java/org/openecomp/aai/workarounds/RemoveDME2QueryParamsTest.java92
-rw-r--r--ajsc-aai/src/test/resources/inmemory_titan.properties21
-rw-r--r--ajsc-aai/src/test/resources/log4j.properties3
-rw-r--r--ajsc-aai/src/test/resources/logback.xml288
-rw-r--r--ajsc-aai/src/test/resources/test_aaiconfig.properties94
-rw-r--r--annotations/.gitignore1
-rw-r--r--annotations/pom.xml83
-rw-r--r--annotations/src/main/java/org/openecomp/aai/annotations/Metadata.java47
-rw-r--r--pom.xml334
-rw-r--r--readme.md128
-rw-r--r--version.properties16
466 files changed, 89588 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..023bd8c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+.settings
+.project
+.classpath
+target/
+**/logs/
+bundleconfig-local/etc/auth/aai-client-cert.p12
+bundleconfig-local/etc/auth/tomcat_keystore
+bundleconfig-local/etc/logback.xml
+/.pydevproject
+/bin/
diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 0000000..32bbcba
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,23 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
diff --git a/aai-schema/.gitignore b/aai-schema/.gitignore
new file mode 100644
index 0000000..09e3bc9
--- /dev/null
+++ b/aai-schema/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/target/
diff --git a/aai-schema/pom.xml b/aai-schema/pom.xml
new file mode 100644
index 0000000..e6afc4f
--- /dev/null
+++ b/aai-schema/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>aai-service</artifactId>
+ <version>${openecomp.release}</version>
+ </parent>
+ <artifactId>aai-schema</artifactId>
+ <name>aai-schema</name>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}-${openecomp.release}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.jsonschema2pojo</groupId>
+ <artifactId>jsonschema2pojo-maven-plugin</artifactId>
+ <version>0.4.13</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-codegen-plugin</artifactId>
+ <version>${cxf.version}</version>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase/>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <configuration>
+ <skip>true</skip></configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>make-assembly-ajsc-arch-parent</id>
+ <phase></phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>gmaven-ajsc-arch-parent</id>
+ <phase/>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>jaxb2-maven-plugin</artifactId>
+ <version>2.2</version>
+ <executions>
+ <execution>
+ <id>xjc</id>
+ <phase></phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-schema-dependency</id>
+ <phase></phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/aai-schema/src/main/resources/aai_schema/aai_schema_v8.xsd b/aai-schema/src/main/resources/aai_schema/aai_schema_v8.xsd
new file mode 100644
index 0000000..ecbbd5b
--- /dev/null
+++ b/aai-schema/src/main/resources/aai_schema/aai_schema_v8.xsd
@@ -0,0 +1,3699 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://org.openecomp.aai.inventory/v8" xmlns:tns="http://org.openecomp.aai.inventory/v8" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ jaxb:version="2.1"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:extensionBindingPrefixes="annox">
+
+ <xs:element name="result-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="resource-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The specific type of node in the AAI graph")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-link" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The URL to the specific resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="search-results">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:result-data" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="search">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:search-results" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="update-node-key">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="key-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="key-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="action-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="action-type" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:action-data" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="update">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Serves a PATCH like function. Does not enforce concurrency control.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="update-node-type" type="xs:string"/>
+ <xs:element ref="tns:update-node-key" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="update-node-uri" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:action" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="key-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="key-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="key-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notify">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="event-id" type="xs:string"/>
+ <xs:element name="node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="event-trigger" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:key-data" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="selflink" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="actions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="APIs that are more action related than REST (e.g., notify, update).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:update" minOccurs="0"/>
+ <xs:element ref="tns:notify" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="relationship-key" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="A keyword provided by AAI to indicate an attribute.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="relationship-value" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Value of the attribute.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="related-to-property">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Key part of a key/value pair")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="property-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Value part of a key/value pair")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="related-to" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="A keyword provided by AAI to indicate type of node.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="related-link" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to the object in AAI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-data" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="tns:related-to-property" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:relationship" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volume-group">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Persistent block-level storage.",indexedProps="volume-group-name,vnf-type,heat-stack-id,volume-group-id",dependentOn="cloud-region",container="volume-groups")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="volume-group-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique ID of volume-group.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="volume-group-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of the volume group.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Heat stack id corresponding to this volume-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded and clients should expect changes to occur in the future to this field as SDC matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Orchestration status of this volume-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volume-groups">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of persistent block-level storage.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:volume-group" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volume">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Ephemeral Block storage volume.",indexedProps="volume-id",dependentOn="vserver",container="volumes")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="volume-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique ID of block storage volume relative to the vserver.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="volume-selflink" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volumes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of ephemeral Block storage volumes.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:volume" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-interface-ipv4-address-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="IPv4 Address Range",indexedProps="l3-interface-ipv4-address,vlan-id-inner,neutron-network-id,neutron-subnet-id",dependentOn="vlan,l-interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="l3-interface-ipv4-address" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="IP address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="l3-interface-ipv4-prefix-length" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Prefix length, 32 for single address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-floating" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indicator of fixed or floating address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Neutron network id of the interface that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Neutron id of subnet that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-interface-ipv6-address-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="IPv6 Address Range",indexedProps="l3-interface-ipv6-address,vlan-id-inner,neutron-network-id,neutron-subnet-id",dependentOn="vlan,l-interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="l3-interface-ipv6-address" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="IP address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="l3-interface-ipv6-prefix-length" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Prefix length, 128 for single address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-floating" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indicator of fixed or floating address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Neutron network id of the interface that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Neutron id of subnet that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Definition of vlan",indexedProps="vlan-interface,vlan-id-inner,vpn-id",uniqueProps="vpn-id",dependentOn="l-interface",container="vlans")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-interface" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="String that identifies the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used to describe (the service associated with) the vlan")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="backdoor-connection" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Whether customer is going to use this VLAN for backdoor connection to another customer premise device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="This indicates the customers VPN ID associated with this vlan")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlans">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:vlan" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l-interface">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Logical interfaces, e.g., a vnic.",indexedProps="macaddr,interface-id,interface-name,network-name",dependentOn="generic-vnf,p-interface,vserver,lag-interface",container="l-interfaces")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Name given to the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="E.g., CUSTOMER, UPLINK, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="v6-wan-link-ip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Questionably placed - v6 ip addr of this interface (is in vr-lan-interface from Mary B.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="ID of interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="macaddr" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="MAC address for the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of the network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Whether AAI should be managing this interface of not. Could have value like CUSTOMER")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:vlans" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l-interfaces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of logical interfaces.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:l-interface" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vserver">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Virtual Servers, aka virtual machine or VM.",nameProps="vserver-name",indexedProps="is-closed-loop-disabled,prov-status,vserver-name,vserver-id,in-maint,vserver-name2",searchable="vserver-name,vserver-id,vserver-name2",dependentOn="tenant",container="vservers")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vserver-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique identifier for this vserver relative to its tenant")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vserver-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of vserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vserver-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Alternative name of vserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vserver-selflink" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-closed-loop-disabled" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether closed loop function is enabled on this node")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:volumes" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vservers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of virtual Servers, aka virtual machines or VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vserver" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tenant">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Openstack tenant",nameProps="tenant-name",indexedProps="tenant-name,tenant-id",dependentOn="cloud-region",container="tenants")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="tenant-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique id relative to the cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tenant-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Readable name of tenant")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:vservers" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tenants">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of openstack tenants.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:tenant" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="flavor">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Openstack flavor.",nameProps="flavor-name",indexedProps="flavor-name,flavor-id",dependentOn="cloud-region",container="flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="flavor-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Flavor id, expected to be unique across cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Flavor name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-vcpus" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Number of CPUs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-ram" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Amount of memory")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-disk" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Disk space")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-ephemeral" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Amount of ephemeral disk space")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-swap" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="amount of swap space allocation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-is-public" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="whether flavor is available to all users or private to the tenant it was created in.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-selflink" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-disabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Boolean as to whether this flavor is no longer enabled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="flavors">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of openstack flavors.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:flavor" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="group-assignment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Openstack group-assignment used to store exclusivity groups (EG).",nameProps="group-name",indexedProps="group-id,group-type,group-name",dependentOn="cloud-region",container="group-assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="group-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Group id, expected to be unique across cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Group type - the type of group this instance refers to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Group name - name assigned to the group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Group description - description of the group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="group-assignments">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of openstack group assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:group-assignment" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="snapshot">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Openstack snapshot",nameProps="snapshot-name",uniqueProps="snapshot-id",indexedProps="application,snapshot-name,application-vendor,snapshot-id,application-version,prev-snapshot-id",dependentOn="cloud-region",container="snapshots")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="snapshot-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Snapshot id, this is the key UUID assoc associated in glance with the snapshots.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Snapshot name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-architecture" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Operating system architecture")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-os-distro" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The common name of the operating system distribution in lowercase")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-os-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The operating system version as specified by the distributor.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The application that the image instantiates.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The vendor of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The version of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prev-snapshot-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="This field contains the UUID of the previous snapshot (if any).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="snapshots">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of openstack snapshots")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:snapshot" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="metadatum">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Key/value pairs",indexedProps="metaname",dependentOn="tenant,image,service-instance,model",container="metadata")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="metaname" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true)</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="metaval" type="xs:string"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="metadata">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of metadatum (key/value pairs)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:metadatum" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="image">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Openstack image.",nameProps="image-name",indexedProps="application,image-name,application-vendor,image-id,application-version",dependentOn="cloud-region",container="images")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="image-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Image id, expected to be unique across cloud region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Image name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-architecture" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Operating system architecture.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-os-distro" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The common name of the operating system distribution in lowercase")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-os-version" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The operating system version as specified by the distributor.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The application that the image instantiates.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The vendor of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="The version of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-selflink" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="images">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collectio of Openstack images.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:image" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="availability-zone">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Availability zone, a collection of compute hosts/pservers",indexedProps="availability-zone-name",dependentOn="cloud-region",container="availability-zones")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="availability-zone-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Name of the availability zone. Unique across a cloud region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hypervisor-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Type of hypervisor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="State that indicates whether the availability zone should be used, etc. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="availability-zones">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of availability zones")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:availability-zone" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cloud-region">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="cloud-region designates an installation of a cloud cluster or region or instantiation. Cloud regions are uniquely identified by a composite key, cloud-owner + cloud-region-id. The format of the cloud-owner is vendor-cloudname.",indexedProps="cloud-owner,cloud-region-id,cloud-type,owner-defined-type",nameProps="owner-defined-type",container="cloud-regions",namespace="cloud-infrastructure")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="cloud-owner" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Identifies the vendor and cloud name. First part of composite key should be formatted as vendor-cloudname")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-region-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Identifier used by the vendor for the region. Second part of composite key")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Type of the cloud (e.g., openstack)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="owner-defined-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Cloud-owner defined type indicator")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-region-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Software version employed at the site")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="identity-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL of the keystone identity service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-zone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Zone where the cloud is homed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="complex-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="complex name for cloud-region instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:volume-groups" minOccurs="0"/>
+ <xs:element ref="tns:tenants" minOccurs="0"/>
+ <xs:element ref="tns:flavors" minOccurs="0"/>
+ <xs:element ref="tns:group-assignments" minOccurs="0"/>
+ <xs:element ref="tns:snapshots" minOccurs="0"/>
+ <xs:element ref="tns:images" minOccurs="0"/>
+ <xs:element ref="tns:availability-zones" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cloud-regions">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:cloud-region" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="p-interface">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Physical interface (e.g., nic)",indexedProps="interface-name",dependentOn="pserver,pnf",container="p-interfaces")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Name that identifies the physical interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Nature of the services and connectivity on this port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-identifier" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="CLEI or other specification for p-interface hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Role specification for p-interface hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indicates the physical properties of the interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="p-interfaces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of physical interfaces.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:p-interface" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lag-interface">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Link aggregate interface",indexedProps="interface-name",dependentOn="generic-vnf,pserver,pnf",container="lag-interfaces")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Name that identifies the link aggregate interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lag-interfaces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of link aggregate interfaces.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:lag-interface" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pserver">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Compute host whose hostname must be unique and must exactly match what is sent as a relationship to a vserver.",nameProps="pserver-name2",indexedProps="hostname,in-maint,pserver-id,pserver-name2",searchable="hostname,pserver-name2,pserver-id,ipv4-oam-address",container="pservers",namespace="cloud-infrastructure")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="hostname" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Value from executing hostname on the compute node.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ptnii-equip-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="PTNII name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="number-of-cpus" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Number of cpus")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="disk-in-gigabytes" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Disk size, in GBs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ram-in-megabytes" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="RAM size, in MBs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Equipment type. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Equipment vendor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Equipment model. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Fully-qualified domain name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pserver-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used to configure device, also used for troubleshooting and is IP used for traps generated by device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="serial-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Serial number, may be queried")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pserver-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="ID of Pserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="internet-topology" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="internet topology of Pserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pserver-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="alternative pserver name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="purpose" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="purpose of pserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:p-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pservers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of compute hosts.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:pserver" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cloud-infrastructure">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Namespace for cloud infrastructure.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:cloud-regions" minOccurs="0"/>
+ <xs:element ref="tns:pservers" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-instance">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Instance of a service",indexedProps="service-instance-id,persona-model-id,persona-model-version,widget-model-id,widget-model-version,service-instance-name,service-instance-location-id",nameProps="service-instance-name",searchable="service-instance-id",uniqueProps="service-instance-id",dependentOn="service-subscription",container="service-instances")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-instance-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this instance of a service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-instance-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="This field will store a name assigned to the service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model id for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model version for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary widget model. This maps directly to the AAI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-total" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indicates the total bandwidth to be used for this service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-up-wan1" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="indicates the upstream bandwidth this service will use on the WAN1 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-down-wan1" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="indicates the downstream bandwidth this service will use on the WAN1 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-up-wan2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="indicates the upstream bandwidth this service will use on the WAN2 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-down-wan2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="indicates the downstream bandwidth this service will use on the WAN2 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vhn-portal-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL customers will use to access the vHN Portal.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Operational status of the service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-instance-location-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="An identifier that customers assign to the location where this service is being used.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-instances">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of service instances")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service-instance" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-subscription">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Object that group service instances.",indexedProps="service-type",dependentOn="customer",container="service-subscriptions")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Value defined by orchestration to identify this service across OpenECOMP.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="temp-ub-sub-account-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="This property will be deleted from AAI in the near future. Only stop gap solution.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:service-instances" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-subscriptions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of objects that group service instances.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service-subscription" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="customer">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="customer identifiers to provide linkage back to BSS information.",nameProps="subscriber-name",indexedProps="subscriber-name,global-customer-id,subscriber-type",searchable="subscriber-name,global-customer-id",uniqueProps="global-customer-id,subscriber-name",alternateKeys1="subscriber-name",container="customers",namespace="business")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="global-customer-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Global customer id used across OpenECOMP to uniquely identify customer.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subscriber-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Subscriber name, an alternate way to retrieve a customer.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subscriber-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Subscriber type, a way to provide VID with only the INFRA customers.",defaultValue="CUST")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:service-subscriptions" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="customers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of customer identifiers to provide linkage back to BSS information.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:customer" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="business">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Namespace for business related constructs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:customers" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Stand-in for service model definitions. Likely to be deprecated in favor of models from SDC.",indexedProps="service-description,service-id",container="services",namespace="service-design-and-creation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="This gets defined by others to provide a unique ID for the service, we accept what is sent.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-description" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Description of the service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="service version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="services">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of service model definitions. Likely to be deprecated in favor of models from SDC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="element-choice-set">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="This is how we would capture constraints defining allowed sets of elements.",uniqueProps="element-choice-set-uuid",indexedProps="element-choice-set-uuid",allowDirectRead="true",allowDirectWrite="false",container="element-choice-sets")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="element-choice-set-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="element-choice-set-name" type="xs:string"/>
+ <xs:element name="cardinality" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:model-elements" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="element-choice-sets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:element-choice-set" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="constrained-element-set">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="This is how we would capture constraints defining allowed sets of elements.",uniqueProps="constrained-element-set-uuid",indexedProps="constrained-element-set-uuid",allowDirectRead="true",allowDirectWrite="false",container="constrained-element-sets")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="constrained-element-set-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="constraint-type" type="xs:string"/>
+ <xs:element name="check-type" type="xs:string"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:element-choice-sets" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="constrained-element-sets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:constrained-element-set" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-constraint">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="This is how we would capture constraints defining allowed sets of elements.",uniqueProps="model-constraint-uuid",indexedProps="model-constraint-uuid",allowDirectRead="true",allowDirectWrite="false",container="model-constraints")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-constraint-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="constrained-element-set-uuid-to-replace" type="xs:string"/>
+ <xs:element ref="tns:constrained-element-sets" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-constraints">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:model-constraint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-element">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Defines how other models combine to make up a higher-level model.",uniqueProps="model-element-uuid",indexedProps="model-element-uuid",allowDirectRead="true",allowDirectWrite="false",container="model-elements")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-element-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="new-data-del-flag" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indicates whether this element was created as part of instantiation from this model")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cardinality" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="How many of this type of element are required/allowed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="linkage-points" minOccurs="0">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Defines how other models combine to make up a higher-level model.",uniqueProps="model-element-uuid",indexedProps="model-element-uuid",allowDirectRead="true",allowDirectWrite="false",container="model-elements")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="linkage-point" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-elements" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Defines how other models combine to make up a higher-level model")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-constraints" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Describes new constraints on this model element that are not part of that model's definition")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-elements">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:model-element" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Subgraph definition provided by SDC to describe an inventory asset and its connections related to SDC models",nameProps="model-name,model-type",indexedProps="model-name-version-id,model-type,model-name,model-id,model-version",alternateKeys1="model-id,model-version",uniqueProps="model-name-version-id",container="models",namespace="service-design-and-creation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-name-version-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique identifier corresponding to one version of a model in SDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Type of the model, e.g., service, resource, widget, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of the model, which can change from version to version.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Invariant unique ID which does not change from version to version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Description")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-elements" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="models">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of subgraph definitions provided by SDC to describe the inventory assets and their connections related to SDC models")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:model" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="related-lookup">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="TBD",uniqueProps="related-lookup-uuid",indexedProps="related-lookup-uuid",allowDirectRead="true",allowDirectWrite="false",container="related-lookups")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="related-lookup-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="source-node-type" type="xs:string"/>
+ <xs:element name="source-node-property" type="xs:string"/>
+ <xs:element name="target-node-type" type="xs:string"/>
+ <xs:element name="target-node-property" type="xs:string"/>
+ <xs:element name="property-collect-list" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="related-lookups">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:related-lookup" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="property-constraint">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="TBD",uniqueProps="property-constraint-uuid",indexedProps="property-constraint-uuid",allowDirectRead="true",allowDirectWrite="false",container="property-constraints")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="property-constraint-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="constraint-type" type="xs:string"/>
+ <xs:element name="property-name" type="xs:string"/>
+ <xs:element name="property-value" type="xs:string"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="property-constraints">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:property-constraint" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-query-element">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="TBD",uniqueProps="named-query-element-uuid",indexedProps="named-query-element-uuid",allowDirectRead="true",allowDirectWrite="false",container="named-query-elements")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="named-query-element-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="property-collect-list" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-limit-desc" type="xs:string" minOccurs="0"/>
+ <xs:element name="do-not-output" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:named-query-elements" minOccurs="0"/>
+ <xs:element ref="tns:related-lookups" minOccurs="0"/>
+ <xs:element ref="tns:property-constraints" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-query-elements">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:named-query-element" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-query">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="TBD",nameProps="named-query-name",uniqueProps="named-query-uuid",indexedProps="named-query-uuid,named-query-name",container="named-queries",namespace="service-design-and-creation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="named-query-uuid" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true)</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="named-query-name" type="xs:string"/>
+ <xs:element name="named-query-version" type="xs:string"/>
+ <xs:element name="required-input-params" minOccurs="0">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="TBD",nameProps="named-query-name",uniqueProps="named-query-uuid",indexedProps="named-query-uuid,named-query-name",container="named-queries",namespace="service-design-and-creation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="required-input-param" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:named-query-elements" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-queries">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:named-query" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-design-and-creation">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Namespace for objects managed by SDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:services" minOccurs="0"/>
+ <xs:element ref="tns:models" minOccurs="0"/>
+ <xs:element ref="tns:named-queries" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="logical-link">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Logical links generally connect l-interfaces but are used to express logical connectivity between two points",indexedProps="link-name,persona-model-id,persona-model-version,widget-model-id,widget-model-version,link-id",uniqueProps="link-id",container="logical-links",namespace="network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="link-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="e.g., evc-name, or vnf-nameA_interface-nameA_vnf-nameZ_interface-nameZ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Type of logical link, e.g., evc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="v4, v6, or ds for dual stack (should be ip-version)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="routing-protocol" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="For example, static or BGP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model id for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model version for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary widget model. This maps directly to the AAI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indication of operational status of the logical link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indication of the network use of the logical link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Alias or alternate name (CLCI or D1 name).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="UUID of the logical-link, SDNC generates this.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="logical-links">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of logical connections")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:logical-link" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnfc">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(indexedProps="vnfc-name,prov-status,vnfc-type,vnfc-function-code,ipaddress-v4-oam-vip,in-maint,is-closed-loop-disabled,group-notation",container="vnfcs",namespace="network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnfc-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique ID of vnfc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnfc-function-code" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="function code")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnfc-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="prov status of this vnfc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by APP-C")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-oam-vip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Oam V4 vip address of this vnfc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-closed-loop-disabled" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether closed loop function is enabled on this node")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-notation" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Group notation of VNFC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnfcs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="virtual network components associated with a vserver from application controller.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vnfc" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="subnet">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(indexedProps="subnet-id,subnet-name",nameProps="subnet-name",uniqueProps="subnet-id",dependentOn="l3-network",container="subnets")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="subnet-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Subnet ID, should be UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name associated with the subnet.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Neutron id of this subnet")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="gateway-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="gateway ip address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-start-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="network start address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cidr-mask" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="cidr mask")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="ip version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-enabled" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="dhcp enabled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-start" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the start address reserved for use by dhcp")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-end" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the last address reserved for use by dhcp")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="subnets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:subnet" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ctag-assignment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(indexedProps="vlan-id-inner",dependentOn="l3-network",container="ctag-assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="id.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ctag-assignments">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:ctag-assignment" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="segmentation-assignment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Openstack segmentation assignment.",indexedProps="segmentation-id",dependentOn="l3-network",container="segmentation-assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="segmentation-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Route Table Reference id, UUID assigned to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="segmentation-assignments">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of openstack segmentation assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:segmentation-assignment" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-network">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Generic network definition",nameProps="network-name",indexedProps="heat-stack-id,network-uuid,service-id,network-id,network-name,persona-model-id,persona-model-version,widget-model-id,widget-model-version,contrail-network-fqdn",uniqueProps="network-id",container="l3-networks",namespace="network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Network ID, should be uuid. Unique across AAI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of the network, governed by some naming convention..")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Type of the network - who defines these values?")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Role the network plans - who defines these values?")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-technology" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Network technology - who defines these values?")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Neutron network id of this Interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-bound-to-vpn" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="Set to true if bound to VPN")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Unique identifier of service from SDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-role-instance" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="network role instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="contrail-network-fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Contrail FQDN for the network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model id for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model version for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary widget model. This maps directly to the AAI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="physical-network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name associated with the physical network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-provider-network" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not network is a provider network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-shared-network" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not network is a shared network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-external-network" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not network is an external network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:subnets" minOccurs="0"/>
+ <xs:element ref="tns:ctag-assignments" minOccurs="0"/>
+ <xs:element ref="tns:segmentation-assignments" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Relates to tenant (or is it a child of tenant)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-networks">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:l3-network" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vf-module">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="a deployment unit of VNFCs",indexedProps="vf-module-id,vf-module-name,heat-stack-id,persona-model-id,persona-model-version,widget-model-id,widget-model-version,contrail-service-instance-fqdn",dependentOn="generic-vnf",container="vf-modules")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vf-module-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique ID of vf-module.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-module-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of vf-module")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Heat stack id corresponding to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="orchestration status of this vf-module, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-base-vf-module" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is base vf module")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model id for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model version for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary widget model. This maps directly to the AAI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="contrail-service-instance-fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the Contrail unique ID for a service-instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vf-modules">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of vf-modules, a deployment unit of VNFCs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vf-module" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="generic-vnf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="General purpose VNF",nameProps="vnf-name",indexedProps="is-closed-loop-disabled,vnf-name2,vnf-type,heat-stack-id,in-maint,vnf-name,vnf-id,regional-resource-zone,prov-status,service-id,persona-model-id,persona-model-version,widget-model-id,widget-model-version",searchable="vnf-id,vnf-name,vnf-name2",uniqueProps="vnf-id",container="generic-vnfs",namespace="network",extendsFrom="vnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnf-id" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="Unique id of VNF. This is unique across the graph.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Alternate name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded and clients should expect changes to occur in the future to this field as SDC matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Unique identifier of service from SDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="regional-resource-zone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Regional way of organizing pservers, source of truth should define values")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="License key")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Client should send valid enumerated value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Orchestration status of this VNF, used by MSO.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="identifier of managed by customer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Address tail-f uses to configure generic-vnf, also used for troubleshooting and is IP used for traps generated by generic-vnf.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-loopback0-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="v4 Loopback0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nm-lan-v6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="v6 Loopback address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-v6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="v6 management address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vcpu" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="number of vcpus ordered for this instance of VNF, used for VNFs with no vservers/flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vcpu-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="units associated with vcpu, used for VNFs with no vservers/flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vmemory" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="number of GB of memory ordered for this instance of VNF, used for VNFs with no vservers/flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vmemory-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="units associated with vmemory, used for VNFs with no vservers/flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vdisk" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="number of vdisks ordered for this instance of VNF, used for VNFs with no vservers/flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vdisk-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="units associated with vdisk, used for VNFs with no vservers/flavors")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-closed-loop-disabled" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether closed loop function is enabled on this node")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="summary-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="details regarding the generic-vnf operation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="encrypted-access-flag" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="indicates whether generic-vnf access uses SSH")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="entitlement-assignment-group-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="UUID of the Entitlement group used for licensing VNFs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="entitlement-resource-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="UUID of the specific entitlement resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-assignment-group-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="UUID of the license assignment group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-key-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="UUID of the actual license resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model id for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC model version for this resource or service model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="captures the id of all the configuration used to customize the resource for the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary widget model. This maps directly to the AAI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="as-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="as-number of the VNF")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="regional-resource-subzone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="represents sub zone of the rr plane")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:vf-modules" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="generic-vnfs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of VNFs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:generic-vnf" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pnf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="PNF represents a physical network function.",indexedProps="pnf-name,orchestration-status",uniqueProps="pnf-name",container="pnfs",namespace="network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pnf-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="unique name of Physical Network Function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="name of Physical Network Function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-name2-source" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="source of name2")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="id of pnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Equipment type. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Equipment vendor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Equipment model. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="identifier of managed by customer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-oam" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="ipv4-oam-address with new naming convention for IP addresses")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sw-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="sw-version is the version of SW for the hosted application on the PNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="orchestration-status is the status of orchestration on the PNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="frame-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="ID of the physical frame (relay rack) where pnf is installed.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:p-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pnfs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of Physical Network Functions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:pnf" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="physical-link">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of physical connections, typically between p-interfaces",indexedProps="circuit-id,link-name",alternateKeys1="circuit-id",container="physical-links",namespace="network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="link-name" type="xs:string">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(isKey=true,description="e.g., hostnameA_p-connection_nameA_hostnameZ+p_connection-nameZ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="circuit-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Circuit it")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dual-mode" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Dual access mode (e.g., primary, secondary")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="To provide information on who manages this circuit. AAI or 3rd party transport provider")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-provider-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Name of the service Provider on this link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.openecomp.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="physical-links">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Collection of physical connections, typically between p-interfaces")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:physical-link" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Namespace for network inventory resources.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:logical-links" minOccurs="0"/>
+ <xs:element ref="tns:vnfcs" minOccurs="0"/>
+ <xs:element ref="tns:l3-networks" minOccurs="0"/>
+ <xs:element ref="tns:generic-vnfs" minOccurs="0"/>
+ <xs:element ref="tns:pnfs" minOccurs="0"/>
+ <xs:element ref="tns:physical-links" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="reserved-prop-names">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Internal map to define some reserved properties of a vertex",uniqueProps="aai-unique-key",indexedProps="aai-unique-key,source-of-truth,aai-node-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="last-mod-source-of-truth" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-created-ts" type="xs:unsignedInt" minOccurs="0"/>
+ <xs:element name="aai-unique-key" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-last-mod-ts" type="xs:unsignedInt" minOccurs="0"/>
+ <xs:element name="source-of-truth" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="edge-prop-names">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Internal map to define the properties of an edge and interpret the map EdgeRules",edgeInfo="edgeLabel,direction,multiplicityRule,isParent,usesResource,hasDelTarget,SVC-INFRA,SVC-INFRA-REV")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="edgeLabel" type="xs:string" minOccurs="0"/>
+ <xs:element name="direction" type="xs:string" minOccurs="0"/>
+ <xs:element name="multiplicityRule" type="xs:string" minOccurs="0"/>
+ <xs:element name="isParent" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="usesResource" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="hasDelTarget" type="xs:boolean" minOccurs="0"/>
+ <xs:element name="SVC-INFRA" type="xs:string" minOccurs="0"/>
+ <xs:element name="SVC-INFRA-REV" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="aai-internal">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:reserved-prop-names" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="tns:edge-prop-names" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:search" minOccurs="0"/>
+ <xs:element ref="tns:actions" minOccurs="0"/>
+ <xs:element ref="tns:cloud-infrastructure" minOccurs="0"/>
+ <xs:element ref="tns:business" minOccurs="0"/>
+ <xs:element ref="tns:service-design-and-creation" minOccurs="0"/>
+ <xs:element ref="tns:network" minOccurs="0"/>
+ <xs:element ref="tns:aai-internal" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-item-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-item">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="inventory-item-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="inventory-item-link" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:inventory-item-data" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="tns:tagged-inventory-item-list" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tagged-inventory-item-list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:inventory-item" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="start-node-filter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="include-node-filter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="include-node-type" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="secondary-filter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="filter-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notification-event-header">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0"/>
+ <xs:element name="timestamp" type="xs:string" minOccurs="0"/>
+ <xs:element name="source-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="domain" type="xs:string" minOccurs="0"/>
+ <xs:element name="sequence-number" type="xs:string" minOccurs="0"/>
+ <xs:element name="severity" type="xs:string" minOccurs="0"/>
+ <xs:element name="event-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="version" type="xs:string" minOccurs="0"/>
+ <xs:element name="action" type="xs:string" minOccurs="0"/>
+ <xs:element name="entity-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="top-entity-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="entity-link" type="xs:string" minOccurs="0"/>
+ <xs:element name="status" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notification-event">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="cambria.partition" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:notification-event-header" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="query-parameters">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="QueryParameters for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:named-query" minOccurs="0"/>
+ <xs:element ref="tns:model" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="instance-filter">
+ <xs:complexType>
+ <xs:sequence/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="instance-filters">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="InstanceFilters for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:instance-filter" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-and-named-query-search">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="ModelAndNamedQuerySearch holds query-parameters and instance-properties for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:query-parameters" minOccurs="0"/>
+ <xs:element ref="tns:instance-filters" minOccurs="0"/>
+ <xs:element name="top-node-type" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="properties">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Property holder for query properties or instance properties")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="extra-properties">
+ <xs:complexType>
+ <xs:sequence/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-response-item">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Inventory item for response list",container="inventory-response-items")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-name" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:extra-properties" minOccurs="0"/>
+ <xs:element ref="tns:inventory-response-items" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-response-items">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Container for inventory items in response list",container="response-list")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:inventory-response-item" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="response-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.openecomp.aai.annotations.Metadata(description="Response container for the results of a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:inventory-response-items" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="extra-property">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/aai-schema/src/main/resources/oxm/aai_oxm_v8.xml b/aai-schema/src/main/resources/oxm/aai_oxm_v8.xml
new file mode 100644
index 0000000..3ed2ea5
--- /dev/null
+++ b/aai-schema/src/main/resources/oxm/aai_oxm_v8.xml
@@ -0,0 +1,3076 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="inventory.aai.openecomp.org.v8" xml-mapping-metadata-complete="true">
+ <xml-schema element-form-default="QUALIFIED">
+ <xml-ns namespace-uri="http://org.openecomp.aai.inventory/v8" />
+ </xml-schema>
+ <java-types>
+ <java-type name="Inventory">
+ <xml-root-element name="inventory" />
+ <java-attributes>
+ <xml-element java-attribute="search" name="search" type="inventory.aai.openecomp.org.v8.Search" />
+ <xml-element java-attribute="actions" name="actions" type="inventory.aai.openecomp.org.v8.Actions" />
+ <xml-element java-attribute="cloudInfrastructure" name="cloud-infrastructure" type="inventory.aai.openecomp.org.v8.CloudInfrastructure" />
+ <xml-element java-attribute="business" name="business" type="inventory.aai.openecomp.org.v8.Business" />
+ <xml-element java-attribute="serviceDesignAndCreation" name="service-design-and-creation" type="inventory.aai.openecomp.org.v8.ServiceDesignAndCreation" />
+ <xml-element java-attribute="network" name="network" type="inventory.aai.openecomp.org.v8.Network" />
+ <xml-element java-attribute="aaiInternal" name="aai-internal" type="inventory.aai.openecomp.org.v8.AaiInternal" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Search">
+ <xml-root-element name="search" />
+ <java-attributes>
+ <xml-element java-attribute="searchResults" name="search-results" type="inventory.aai.openecomp.org.v8.SearchResults" />
+ </java-attributes>
+ </java-type>
+
+
+ <java-type name="TaggedInventoryItemList">
+ <xml-root-element name="tagged-inventory-item-list" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="inventoryItem" name="inventory-item" type="inventory.aai.openecomp.org.v8.InventoryItem" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="InventoryItem">
+ <xml-root-element name="inventory-item" />
+ <java-attributes>
+ <xml-element java-attribute="inventoryItemType" name="inventory-item-type" type="java.lang.String" />
+ <xml-element java-attribute="inventoryItemLink" name="inventory-item-link" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="inventoryItemData" name="inventory-item-data" type="inventory.aai.openecomp.org.v8.InventoryItemData" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="taggedInventoryItemList" name="tagged-inventory-item-list" type="inventory.aai.openecomp.org.v8.TaggedInventoryItemList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="InventoryItemData">
+ <xml-root-element name="inventory-item-data" />
+ <java-attributes>
+ <xml-element java-attribute="propertyName" name="property-name" type="java.lang.String" />
+ <xml-element java-attribute="propertyValue" name="property-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+
+ <java-type name="StartNodeFilter">
+ <xml-root-element name="start-node-filter" />
+ <java-attributes>
+ <xml-element java-attribute="propertyName" name="property-name" type="java.lang.String" />
+ <xml-element java-attribute="propertyValue" name="property-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="IncludeNodeFilter">
+ <xml-root-element name="include-node-filter" />
+ <java-attributes>
+ <xml-element java-attribute="includeNodeType" name="include-node-type" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="SecondaryFilter">
+ <xml-root-element name="secondary-filter" />
+ <java-attributes>
+ <xml-element java-attribute="propertyName" name="property-name" type="java.lang.String" />
+ <xml-element java-attribute="filterType" name="filter-type" type="java.lang.String" />
+ <xml-element java-attribute="propertyValue" name="property-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="SearchResults">
+ <xml-root-element name="search-results" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="resultData" name="result-data" type="inventory.aai.openecomp.org.v8.ResultData" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ResultData">
+ <xml-root-element name="result-data" />
+ <java-attributes>
+ <xml-element java-attribute="resourceType" name="resource-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The specific type of node in the AAI graph" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceLink" name="resource-link" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The URL to the specific resource" />
+ </xml-properties>
+ </xml-element>
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Actions">
+ <xml-properties>
+ <xml-property name="description" value="APIs that are more action related than REST (e.g., notify, update)." />
+ </xml-properties>
+ <xml-root-element name="actions" />
+ <java-attributes>
+ <xml-element java-attribute="update" name="update" type="inventory.aai.openecomp.org.v8.Update" />
+ <xml-element java-attribute="notify" name="notify" type="inventory.aai.openecomp.org.v8.Notify" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Update">
+ <xml-properties>
+ <xml-property name="description" value="Serves a PATCH like function. Does not enforce concurrency control." />
+ </xml-properties>
+ <xml-root-element name="update" />
+ <java-attributes>
+ <xml-element java-attribute="updateNodeType" name="update-node-type" required="true" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="updateNodeKey" name="update-node-key" type="inventory.aai.openecomp.org.v8.UpdateNodeKey" />
+ <xml-element java-attribute="updateNodeUri" name="update-node-uri" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="action" name="action" type="inventory.aai.openecomp.org.v8.Action" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Action">
+ <xml-root-element name="action" />
+ <java-attributes>
+ <xml-element java-attribute="actionType" name="action-type" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="actionData" name="action-data" type="inventory.aai.openecomp.org.v8.ActionData" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ActionData">
+ <xml-root-element name="action-data" />
+ <java-attributes>
+ <xml-element java-attribute="propertyName" name="property-name" type="java.lang.String" />
+ <xml-element java-attribute="propertyValue" name="property-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="UpdateNodeKey">
+ <xml-root-element name="update-node-key" />
+ <java-attributes>
+ <xml-element java-attribute="keyName" name="key-name" type="java.lang.String" />
+ <xml-element java-attribute="keyValue" name="key-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Notify">
+ <xml-root-element name="notify" />
+ <java-attributes>
+ <xml-element java-attribute="eventId" name="event-id" required="true" type="java.lang.String" />
+ <xml-element java-attribute="nodeType" name="node-type" type="java.lang.String" />
+ <xml-element java-attribute="eventTrigger" name="event-trigger" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="keyData" name="key-data" type="inventory.aai.openecomp.org.v8.KeyData" />
+ <xml-element java-attribute="selflink" name="selflink" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="KeyData">
+ <xml-root-element name="key-data" />
+ <java-attributes>
+ <xml-element java-attribute="keyName" name="key-name" type="java.lang.String" />
+ <xml-element java-attribute="keyValue" name="key-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="CloudInfrastructure">
+ <xml-properties>
+ <xml-property name="description" value="Namespace for cloud infrastructure." />
+ </xml-properties>
+ <xml-root-element name="cloud-infrastructure" />
+ <java-attributes>
+ <xml-element java-attribute="cloudRegions" name="cloud-regions" type="inventory.aai.openecomp.org.v8.CloudRegions" />
+ <xml-element java-attribute="pservers" name="pservers" type="inventory.aai.openecomp.org.v8.Pservers" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="CloudRegions">
+ <xml-root-element name="cloud-regions" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="cloudRegion" name="cloud-region" type="inventory.aai.openecomp.org.v8.CloudRegion" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="CloudRegion">
+ <xml-root-element name="cloud-region" />
+ <java-attributes>
+ <xml-element java-attribute="cloudOwner" name="cloud-owner" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Identifies the vendor and cloud name. First part of composite key should be formatted as vendor-cloudname" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="cloudRegionId" name="cloud-region-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Identifier used by the vendor for the region. Second part of composite key" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="cloudType" name="cloud-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Type of the cloud (e.g., openstack)" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ownerDefinedType" name="owner-defined-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Cloud-owner defined type indicator" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="cloudRegionVersion" name="cloud-region-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Software version employed at the site" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="identityUrl" name="identity-url" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL of the keystone identity service" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="cloudZone" name="cloud-zone" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Zone where the cloud is homed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="complexName" name="complex-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="complex name for cloud-region instance" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="volumeGroups" name="volume-groups" type="inventory.aai.openecomp.org.v8.VolumeGroups" />
+ <xml-element java-attribute="tenants" name="tenants" type="inventory.aai.openecomp.org.v8.Tenants" />
+ <xml-element java-attribute="flavors" name="flavors" type="inventory.aai.openecomp.org.v8.Flavors" />
+ <xml-element java-attribute="groupAssignments" name="group-assignments" type="inventory.aai.openecomp.org.v8.GroupAssignments" />
+ <xml-element java-attribute="snapshots" name="snapshots" type="inventory.aai.openecomp.org.v8.Snapshots" />
+ <xml-element java-attribute="images" name="images" type="inventory.aai.openecomp.org.v8.Images" />
+ <xml-element java-attribute="availabilityZones" name="availability-zones" type="inventory.aai.openecomp.org.v8.AvailabilityZones" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="cloud-region designates an installation of a cloud cluster or region or instantiation. Cloud regions are uniquely identified by a composite key, cloud-owner + cloud-region-id. The format of the cloud-owner is vendor-cloudname." />
+ <xml-property name="indexedProps" value="cloud-owner,cloud-region-id,cloud-type,owner-defined-type" />
+ <xml-property name="nameProps" value="owner-defined-type" />
+ <xml-property name="container" value="cloud-regions" />
+ <xml-property name="namespace" value="cloud-infrastructure" />
+ </xml-properties>
+ </java-type>
+ <java-type name="VolumeGroups">
+ <xml-properties>
+ <xml-property name="description" value="Collection of persistent block-level storage." />
+ </xml-properties>
+ <xml-root-element name="volume-groups" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="volumeGroup" name="volume-group" type="inventory.aai.openecomp.org.v8.VolumeGroup" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="VolumeGroup">
+ <xml-root-element name="volume-group" />
+ <java-attributes>
+ <xml-element java-attribute="volumeGroupId" name="volume-group-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique ID of volume-group." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="volumeGroupName" name="volume-group-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of the volume group." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="heatStackId" name="heat-stack-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Heat stack id corresponding to this volume-group" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vnfType" name="vnf-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded and clients should expect changes to occur in the future to this field as SDC matures." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Orchestration status of this volume-group" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Persistent block-level storage." />
+ <xml-property name="indexedProps" value="volume-group-name,vnf-type,heat-stack-id,volume-group-id" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="volume-groups" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="RelationshipList">
+ <xml-root-element name="relationship-list" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="relationship" name="relationship" type="inventory.aai.openecomp.org.v8.Relationship" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Relationship">
+ <xml-root-element name="relationship" />
+ <java-attributes>
+ <xml-element java-attribute="relatedTo" name="related-to" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="A keyword provided by AAI to indicate type of node." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relatedLink" name="related-link" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to the object in AAI." />
+ </xml-properties>
+ </xml-element>
+ <xml-element container-type="java.util.ArrayList" java-attribute="relationshipData" name="relationship-data" type="inventory.aai.openecomp.org.v8.RelationshipData" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="relatedToProperty" name="related-to-property" type="inventory.aai.openecomp.org.v8.RelatedToProperty" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="RelatedToProperty">
+ <xml-root-element name="related-to-property" />
+ <java-attributes>
+ <xml-element java-attribute="propertyKey" name="property-key" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Key part of a key/value pair" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="propertyValue" name="property-value" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Value part of a key/value pair" />
+ </xml-properties>
+ </xml-element>
+ </java-attributes>
+ </java-type>
+
+ <java-type name="RelationshipData">
+ <xml-root-element name="relationship-data" />
+ <java-attributes>
+ <xml-element java-attribute="relationshipKey" name="relationship-key" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="A keyword provided by AAI to indicate an attribute." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipValue" name="relationship-value" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Value of the attribute." />
+ </xml-properties>
+ </xml-element>
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Tenants">
+ <xml-properties>
+ <xml-property name="description" value="Collection of openstack tenants." />
+ </xml-properties>
+ <xml-root-element name="tenants" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="tenant" name="tenant" type="inventory.aai.openecomp.org.v8.Tenant" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Tenant">
+ <xml-root-element name="tenant" />
+ <java-attributes>
+ <xml-element java-attribute="tenantId" name="tenant-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique id relative to the cloud-region." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="tenantName" name="tenant-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Readable name of tenant" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vservers" name="vservers" type="inventory.aai.openecomp.org.v8.Vservers" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Openstack tenant" />
+ <xml-property name="nameProps" value="tenant-name" />
+ <xml-property name="indexedProps" value="tenant-name,tenant-id" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="tenants" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Vservers">
+ <xml-properties>
+ <xml-property name="description" value="Collection of virtual Servers, aka virtual machines or VMs." />
+ </xml-properties>
+ <xml-root-element name="vservers" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="vserver" name="vserver" type="inventory.aai.openecomp.org.v8.Vserver" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Vserver">
+ <xml-root-element name="vserver" />
+ <java-attributes>
+ <xml-element java-attribute="vserverId" name="vserver-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique identifier for this vserver relative to its tenant" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vserverName" name="vserver-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of vserver" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vserverName2" name="vserver-name2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Alternative name of vserver" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="provStatus" name="prov-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Trigger for operational monitoring of this resource by Service Assurance systems." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vserverSelflink" name="vserver-selflink" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="inMaint" name="in-maint" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs." />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="isClosedLoopDisabled" name="is-closed-loop-disabled" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="Used to indicate whether closed loop function is enabled on this node" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="volumes" name="volumes" type="inventory.aai.openecomp.org.v8.Volumes" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="lInterfaces" name="l-interfaces" type="inventory.aai.openecomp.org.v8.LInterfaces" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Virtual Servers, aka virtual machine or VM." />
+ <xml-property name="nameProps" value="vserver-name" />
+ <xml-property name="indexedProps" value="is-closed-loop-disabled,prov-status,vserver-name,vserver-id,in-maint,vserver-name2" />
+ <xml-property name="searchable" value="vserver-name,vserver-id,vserver-name2" />
+ <xml-property name="dependentOn" value="tenant" />
+ <xml-property name="container" value="vservers" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="LInterfaces">
+ <xml-properties>
+ <xml-property name="description" value="Collection of logical interfaces." />
+ </xml-properties>
+ <xml-root-element name="l-interfaces" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="lInterface" name="l-interface" type="inventory.aai.openecomp.org.v8.LInterface" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="LInterface">
+ <xml-root-element name="l-interface" />
+ <java-attributes>
+ <xml-element java-attribute="interfaceName" name="interface-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Name given to the interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="interfaceRole" name="interface-role" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="E.g., CUSTOMER, UPLINK, etc." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="v6WanLinkIp" name="v6-wan-link-ip" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Questionably placed - v6 ip addr of this interface (is in vr-lan-interface from Mary B." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="selflink" name="selflink" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="interfaceId" name="interface-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="ID of interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="macaddr" name="macaddr" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="MAC address for the interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkName" name="network-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of the network" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="managementOption" name="management-option" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Whether AAI should be managing this interface of not. Could have value like CUSTOMER" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlans" name="vlans" type="inventory.aai.openecomp.org.v8.Vlans" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv4AddressList" name="l3-interface-ipv4-address-list" type="inventory.aai.openecomp.org.v8.L3InterfaceIpv4AddressList" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv6AddressList" name="l3-interface-ipv6-address-list" type="inventory.aai.openecomp.org.v8.L3InterfaceIpv6AddressList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Logical interfaces, e.g., a vnic." />
+ <xml-property name="indexedProps" value="macaddr,interface-id,interface-name,network-name" />
+ <xml-property name="dependentOn" value="generic-vnf,p-interface,vserver,lag-interface" />
+ <xml-property name="container" value="l-interfaces" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="L3InterfaceIpv4AddressList">
+ <xml-root-element name="l3-interface-ipv4-address-list" />
+ <java-attributes>
+ <xml-element java-attribute="l3InterfaceIpv4Address" name="l3-interface-ipv4-address" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="IP address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="l3InterfaceIpv4PrefixLength" name="l3-interface-ipv4-prefix-length" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Prefix length, 32 for single address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanIdInner" name="vlan-id-inner" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Inner VLAN tag" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanIdOuter" name="vlan-id-outer" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Outer VLAN tag" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="isFloating" name="is-floating" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="description" value="Indicator of fixed or floating address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="neutronNetworkId" name="neutron-network-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Neutron network id of the interface that address belongs to" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="neutronSubnetId" name="neutron-subnet-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Neutron id of subnet that address belongs to" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="IPv4 Address Range" />
+ <xml-property name="indexedProps" value="l3-interface-ipv4-address,vlan-id-inner,neutron-network-id,neutron-subnet-id" />
+ <xml-property name="dependentOn" value="vlan,l-interface" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Vlans">
+ <xml-root-element name="vlans" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="vlan" name="vlan" type="inventory.aai.openecomp.org.v8.Vlan" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Vlan">
+ <xml-root-element name="vlan" />
+ <java-attributes>
+ <xml-element java-attribute="vlanInterface" name="vlan-interface" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="String that identifies the interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanIdInner" name="vlan-id-inner" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Inner VLAN tag" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanIdOuter" name="vlan-id-outer" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Outer VLAN tag" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedValue" name="speed-value" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the numeric part of the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedUnits" name="speed-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the units corresponding to the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanDescription" name="vlan-description" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used to describe (the service associated with) the vlan" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="backdoorConnection" name="backdoor-connection" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Whether customer is going to use this VLAN for backdoor connection to another customer premise device." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vpnId" name="vpn-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="This indicates the customers VPN ID associated with this vlan" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv4AddressList" name="l3-interface-ipv4-address-list" type="inventory.aai.openecomp.org.v8.L3InterfaceIpv4AddressList" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="l3InterfaceIpv6AddressList" name="l3-interface-ipv6-address-list" type="inventory.aai.openecomp.org.v8.L3InterfaceIpv6AddressList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Definition of vlan" />
+ <xml-property name="indexedProps" value="vlan-interface,vlan-id-inner,vpn-id" />
+ <xml-property name="uniqueProps" value="vpn-id" />
+ <xml-property name="dependentOn" value="l-interface" />
+ <xml-property name="container" value="vlans" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="L3InterfaceIpv6AddressList">
+ <xml-root-element name="l3-interface-ipv6-address-list" />
+ <java-attributes>
+ <xml-element java-attribute="l3InterfaceIpv6Address" name="l3-interface-ipv6-address" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="IP address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="l3InterfaceIpv6PrefixLength" name="l3-interface-ipv6-prefix-length" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Prefix length, 128 for single address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanIdInner" name="vlan-id-inner" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Inner VLAN tag" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vlanIdOuter" name="vlan-id-outer" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="Outer VLAN tag" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="isFloating" name="is-floating" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="description" value="Indicator of fixed or floating address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="neutronNetworkId" name="neutron-network-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Neutron network id of the interface that address belongs to" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="neutronSubnetId" name="neutron-subnet-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Neutron id of subnet that address belongs to" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="IPv6 Address Range" />
+ <xml-property name="indexedProps" value="l3-interface-ipv6-address,vlan-id-inner,neutron-network-id,neutron-subnet-id" />
+ <xml-property name="dependentOn" value="vlan,l-interface" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Volumes">
+ <xml-properties>
+ <xml-property name="description" value="Collection of ephemeral Block storage volumes." />
+ </xml-properties>
+ <xml-root-element name="volumes" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="volume" name="volume" type="inventory.aai.openecomp.org.v8.Volume" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Volume">
+ <xml-root-element name="volume" />
+ <java-attributes>
+ <xml-element java-attribute="volumeId" name="volume-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique ID of block storage volume relative to the vserver." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="volumeSelflink" name="volume-selflink" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Ephemeral Block storage volume." />
+ <xml-property name="indexedProps" value="volume-id" />
+ <xml-property name="dependentOn" value="vserver" />
+ <xml-property name="container" value="volumes" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Flavors">
+ <xml-properties>
+ <xml-property name="description" value="Collection of openstack flavors." />
+ </xml-properties>
+ <xml-root-element name="flavors" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="flavor" name="flavor" type="inventory.aai.openecomp.org.v8.Flavor" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Flavor">
+ <xml-root-element name="flavor" />
+ <java-attributes>
+ <xml-element java-attribute="flavorId" name="flavor-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Flavor id, expected to be unique across cloud-region." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorName" name="flavor-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Flavor name" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorVcpus" name="flavor-vcpus" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="Number of CPUs" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorRam" name="flavor-ram" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="Amount of memory" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorDisk" name="flavor-disk" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="Disk space" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorEphemeral" name="flavor-ephemeral" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="Amount of ephemeral disk space" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorSwap" name="flavor-swap" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="amount of swap space allocation" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorIsPublic" name="flavor-is-public" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="description" value="whether flavor is available to all users or private to the tenant it was created in." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorSelflink" name="flavor-selflink" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="flavorDisabled" name="flavor-disabled" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="description" value="Boolean as to whether this flavor is no longer enabled" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Openstack flavor." />
+ <xml-property name="nameProps" value="flavor-name" />
+ <xml-property name="indexedProps" value="flavor-name,flavor-id" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="flavors" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Snapshots">
+ <xml-properties>
+ <xml-property name="description" value="Collection of openstack snapshots" />
+ </xml-properties>
+ <xml-root-element name="snapshots" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="snapshot" name="snapshot" type="inventory.aai.openecomp.org.v8.Snapshot" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Snapshot">
+ <xml-root-element name="snapshot" />
+ <java-attributes>
+ <xml-element java-attribute="snapshotId" name="snapshot-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Snapshot id, this is the key UUID assoc associated in glance with the snapshots." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="snapshotName" name="snapshot-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Snapshot name" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="snapshotArchitecture" name="snapshot-architecture" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Operating system architecture" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="snapshotOsDistro" name="snapshot-os-distro" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The common name of the operating system distribution in lowercase" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="snapshotOsVersion" name="snapshot-os-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The operating system version as specified by the distributor." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="application" name="application" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The application that the image instantiates." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="applicationVendor" name="application-vendor" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The vendor of the application." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="applicationVersion" name="application-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The version of the application." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="snapshotSelflink" name="snapshot-selflink" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="prevSnapshotId" name="prev-snapshot-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="This field contains the UUID of the previous snapshot (if any)." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Openstack snapshot" />
+ <xml-property name="nameProps" value="snapshot-name" />
+ <xml-property name="uniqueProps" value="snapshot-id" />
+ <xml-property name="indexedProps" value="application,snapshot-name,application-vendor,snapshot-id,application-version,prev-snapshot-id" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="snapshots" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="GroupAssignments">
+ <xml-properties>
+ <xml-property name="description" value="Collection of openstack group assignments" />
+ </xml-properties>
+ <xml-root-element name="group-assignments" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="groupAssignment" name="group-assignment" type="inventory.aai.openecomp.org.v8.GroupAssignment" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="GroupAssignment">
+ <xml-root-element name="group-assignment" />
+ <java-attributes>
+ <xml-element java-attribute="groupId" name="group-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Group id, expected to be unique across cloud-region." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="groupType" name="group-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Group type - the type of group this instance refers to" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="groupName" name="group-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Group name - name assigned to the group" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="groupDescription" name="group-description" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Group description - description of the group" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Openstack group-assignment used to store exclusivity groups (EG)." />
+ <xml-property name="nameProps" value="group-name" />
+ <xml-property name="indexedProps" value="group-id,group-type,group-name" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="group-assignments" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Images">
+ <xml-properties>
+ <xml-property name="description" value="Collectio of Openstack images." />
+ </xml-properties>
+ <xml-root-element name="images" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="image" name="image" type="inventory.aai.openecomp.org.v8.Image" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Image">
+ <xml-root-element name="image" />
+ <java-attributes>
+ <xml-element java-attribute="imageId" name="image-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Image id, expected to be unique across cloud region" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="imageName" name="image-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Image name" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="imageArchitecture" name="image-architecture" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Operating system architecture." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="imageOsDistro" name="image-os-distro" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The common name of the operating system distribution in lowercase" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="imageOsVersion" name="image-os-version" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The operating system version as specified by the distributor." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="application" name="application" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The application that the image instantiates." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="applicationVendor" name="application-vendor" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The vendor of the application." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="applicationVersion" name="application-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="The version of the application." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="imageSelflink" name="image-selflink" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="metadata" name="metadata" type="inventory.aai.openecomp.org.v8.Metadata" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Openstack image." />
+ <xml-property name="nameProps" value="image-name" />
+ <xml-property name="indexedProps" value="application,image-name,application-vendor,image-id,application-version" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="images" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Metadata">
+ <xml-properties>
+ <xml-property name="description" value="Collection of metadatum (key/value pairs)" />
+ </xml-properties>
+ <xml-root-element name="metadata" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="metadatum" name="metadatum" type="inventory.aai.openecomp.org.v8.Metadatum" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Metadatum">
+ <xml-root-element name="metadatum" />
+ <java-attributes>
+ <xml-element java-attribute="metaname" name="metaname" required="true" type="java.lang.String" xml-key="true" />
+ <xml-element java-attribute="metaval" name="metaval" required="true" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Key/value pairs" />
+ <xml-property name="indexedProps" value="metaname" />
+ <xml-property name="dependentOn" value="tenant,image,service-instance,model" />
+ <xml-property name="container" value="metadata" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Pservers">
+ <xml-properties>
+ <xml-property name="description" value="Collection of compute hosts." />
+ </xml-properties>
+ <xml-root-element name="pservers" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="pserver" name="pserver" type="inventory.aai.openecomp.org.v8.Pserver" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Pserver">
+ <xml-root-element name="pserver" />
+ <java-attributes>
+ <xml-element java-attribute="hostname" name="hostname" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Value from executing hostname on the compute node." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ptniiEquipName" name="ptnii-equip-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="PTNII name" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="numberOfCpus" name="number-of-cpus" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="Number of cpus" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="diskInGigabytes" name="disk-in-gigabytes" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="Disk size, in GBs" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ramInMegabytes" name="ram-in-megabytes" type="java.lang.Integer">
+ <xml-properties>
+ <xml-property name="description" value="RAM size, in MBs" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipType" name="equip-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Equipment type. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipVendor" name="equip-vendor" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Equipment vendor. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipModel" name="equip-model" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Equipment model. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="fqdn" name="fqdn" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Fully-qualified domain name" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="pserverSelflink" name="pserver-selflink" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipv4OamAddress" name="ipv4-oam-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used to configure device, also used for troubleshooting and is IP used for traps generated by device." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serialNumber" name="serial-number" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Serial number, may be queried" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="pserverId" name="pserver-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="ID of Pserver" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="internetTopology" name="internet-topology" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="internet topology of Pserver" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="inMaint" name="in-maint" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="pserverName2" name="pserver-name2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="alternative pserver name" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="purpose" name="purpose" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="purpose of pserver" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="pInterfaces" name="p-interfaces" type="inventory.aai.openecomp.org.v8.PInterfaces" />
+ <xml-element java-attribute="lagInterfaces" name="lag-interfaces" type="inventory.aai.openecomp.org.v8.LagInterfaces" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Compute host whose hostname must be unique and must exactly match what is sent as a relationship to a vserver." />
+ <xml-property name="nameProps" value="pserver-name2" />
+ <xml-property name="indexedProps" value="hostname,in-maint,pserver-id,pserver-name2" />
+ <xml-property name="searchable" value="hostname,pserver-name2,pserver-id,ipv4-oam-address" />
+ <xml-property name="container" value="pservers" />
+ <xml-property name="namespace" value="cloud-infrastructure" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="PInterfaces">
+ <xml-properties>
+ <xml-property name="description" value="Collection of physical interfaces." />
+ </xml-properties>
+ <xml-root-element name="p-interfaces" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="pInterface" name="p-interface" type="inventory.aai.openecomp.org.v8.PInterface" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="PInterface">
+ <xml-root-element name="p-interface" />
+ <java-attributes>
+ <xml-element java-attribute="interfaceName" name="interface-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Name that identifies the physical interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedValue" name="speed-value" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the numeric part of the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedUnits" name="speed-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the units corresponding to the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="portDescription" name="port-description" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Nature of the services and connectivity on this port." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipmentIdentifier" name="equipment-identifier" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="CLEI or other specification for p-interface hardware." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="interfaceRole" name="interface-role" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Role specification for p-interface hardware." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="interfaceType" name="interface-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Indicates the physical properties of the interface." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="lInterfaces" name="l-interfaces" type="inventory.aai.openecomp.org.v8.LInterfaces" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Physical interface (e.g., nic)" />
+ <xml-property name="indexedProps" value="interface-name" />
+ <xml-property name="dependentOn" value="pserver,pnf" />
+ <xml-property name="container" value="p-interfaces" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="LagInterfaces">
+ <xml-properties>
+ <xml-property name="description" value="Collection of link aggregate interfaces." />
+ </xml-properties>
+ <xml-root-element name="lag-interfaces" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="lagInterface" name="lag-interface" type="inventory.aai.openecomp.org.v8.LagInterface" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="LagInterface">
+ <xml-root-element name="lag-interface" />
+ <java-attributes>
+ <xml-element java-attribute="interfaceName" name="interface-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Name that identifies the link aggregate interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedValue" name="speed-value" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the numeric part of the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedUnits" name="speed-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the units corresponding to the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="lInterfaces" name="l-interfaces" type="inventory.aai.openecomp.org.v8.LInterfaces" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Link aggregate interface" />
+ <xml-property name="indexedProps" value="interface-name" />
+ <xml-property name="dependentOn" value="generic-vnf,pserver,pnf" />
+ <xml-property name="container" value="lag-interfaces" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="AvailabilityZones">
+ <xml-properties>
+ <xml-property name="description" value="Collection of availability zones" />
+ </xml-properties>
+ <xml-root-element name="availability-zones" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="availabilityZone" name="availability-zone" type="inventory.aai.openecomp.org.v8.AvailabilityZone" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="AvailabilityZone">
+ <xml-root-element name="availability-zone" />
+ <java-attributes>
+ <xml-element java-attribute="availabilityZoneName" name="availability-zone-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Name of the availability zone. Unique across a cloud region" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="hypervisorType" name="hypervisor-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Type of hypervisor. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="operationalState" name="operational-state" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="State that indicates whether the availability zone should be used, etc. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Availability zone, a collection of compute hosts/pservers" />
+ <xml-property name="indexedProps" value="availability-zone-name" />
+ <xml-property name="dependentOn" value="cloud-region" />
+ <xml-property name="container" value="availability-zones" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Business">
+ <xml-properties>
+ <xml-property name="description" value="Namespace for business related constructs" />
+ </xml-properties>
+ <xml-root-element name="business" />
+ <java-attributes>
+ <xml-element java-attribute="customers" name="customers" type="inventory.aai.openecomp.org.v8.Customers" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Customers">
+ <xml-properties>
+ <xml-property name="description" value="Collection of customer identifiers to provide linkage back to BSS information." />
+ </xml-properties>
+ <xml-root-element name="customers" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="customer" name="customer" type="inventory.aai.openecomp.org.v8.Customer" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Customer">
+ <xml-root-element name="customer" />
+ <java-attributes>
+ <xml-element java-attribute="globalCustomerId" name="global-customer-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Global customer id used across OpenECOMP to uniquely identify customer." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="subscriberName" name="subscriber-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Subscriber name, an alternate way to retrieve a customer." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="subscriberType" name="subscriber-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Subscriber type, a way to provide VID with only the INFRA customers." />
+ <xml-property name="defaultValue" value="CUST" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceSubscriptions" name="service-subscriptions" type="inventory.aai.openecomp.org.v8.ServiceSubscriptions" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="customer identifiers to provide linkage back to BSS information." />
+ <xml-property name="nameProps" value="subscriber-name" />
+ <xml-property name="indexedProps" value="subscriber-name,global-customer-id,subscriber-type" />
+ <xml-property name="searchable" value="subscriber-name,global-customer-id" />
+ <xml-property name="uniqueProps" value="global-customer-id,subscriber-name" />
+ <xml-property name="alternateKeys1" value="subscriber-name" />
+ <xml-property name="container" value="customers" />
+ <xml-property name="namespace" value="business" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="ServiceSubscriptions">
+ <xml-properties>
+ <xml-property name="description" value="Collection of objects that group service instances." />
+ </xml-properties>
+ <xml-root-element name="service-subscriptions" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="serviceSubscription" name="service-subscription" type="inventory.aai.openecomp.org.v8.ServiceSubscription" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ServiceSubscription">
+ <xml-root-element name="service-subscription" />
+ <java-attributes>
+ <xml-element java-attribute="serviceType" name="service-type" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Value defined by orchestration to identify this service across OpenECOMP." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="tempUbSubAccountId" name="temp-ub-sub-account-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="This property will be deleted from AAI in the near future. Only stop gap solution." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceInstances" name="service-instances" type="inventory.aai.openecomp.org.v8.ServiceInstances">
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Object that group service instances." />
+ <xml-property name="indexedProps" value="service-type" />
+ <xml-property name="dependentOn" value="customer" />
+ <xml-property name="container" value="service-subscriptions" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="ServiceInstances">
+ <xml-properties>
+ <xml-property name="description" value="Collection of service instances" />
+ </xml-properties>
+ <xml-root-element name="service-instances" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="serviceInstance" name="service-instance" type="inventory.aai.openecomp.org.v8.ServiceInstance" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ServiceInstance">
+ <xml-root-element name="service-instance" />
+ <java-attributes>
+ <xml-element java-attribute="serviceInstanceId" name="service-instance-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Uniquely identifies this instance of a service" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceInstanceName" name="service-instance-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="This field will store a name assigned to the service-instance." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelId" name="persona-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model id for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelVersion" name="persona-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model version for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelId" name="widget-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary widget model. This maps directly to the AAI widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelVersion" name="widget-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="bandwidthTotal" name="bandwidth-total" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Indicates the total bandwidth to be used for this service." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="bandwidthUpWan1" name="bandwidth-up-wan1" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="indicates the upstream bandwidth this service will use on the WAN1 port of the physical device." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="bandwidthDownWan1" name="bandwidth-down-wan1" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="indicates the downstream bandwidth this service will use on the WAN1 port of the physical device." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="bandwidthUpWan2" name="bandwidth-up-wan2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="indicates the upstream bandwidth this service will use on the WAN2 port of the physical device." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="bandwidthDownWan2" name="bandwidth-down-wan2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="indicates the downstream bandwidth this service will use on the WAN2 port of the physical device." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vhnPortalUrl" name="vhn-portal-url" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL customers will use to access the vHN Portal." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="operationalStatus" name="operational-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Operational status of the service-instance." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceInstanceLocationId" name="service-instance-location-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="An identifier that customers assign to the location where this service is being used." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="metadata" name="metadata" type="inventory.aai.openecomp.org.v8.Metadata" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Instance of a service" />
+ <xml-property name="indexedProps" value="service-instance-id,persona-model-id,persona-model-version,widget-model-id,widget-model-version,service-instance-name,service-instance-location-id" />
+ <xml-property name="nameProps" value="service-instance-name" />
+ <xml-property name="searchable" value="service-instance-id" />
+ <xml-property name="uniqueProps" value="service-instance-id" />
+ <xml-property name="dependentOn" value="service-subscription" />
+ <xml-property name="container" value="service-instances" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="ServiceDesignAndCreation">
+ <xml-properties>
+ <xml-property name="description" value="Namespace for objects managed by SDC" />
+ </xml-properties>
+ <xml-root-element name="service-design-and-creation" />
+ <java-attributes>
+ <xml-element java-attribute="services" name="services" type="inventory.aai.openecomp.org.v8.Services" />
+ <xml-element java-attribute="models" name="models" type="inventory.aai.openecomp.org.v8.Models" />
+ <xml-element java-attribute="namedQueries" name="named-queries" type="inventory.aai.openecomp.org.v8.NamedQueries" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Network">
+ <xml-properties>
+ <xml-property name="description" value="Namespace for network inventory resources." />
+ </xml-properties>
+ <xml-root-element name="network" />
+ <java-attributes>
+ <xml-element java-attribute="logicalLinks" name="logical-links" type="inventory.aai.openecomp.org.v8.LogicalLinks" />
+ <xml-element java-attribute="vnfcs" name="vnfcs" type="inventory.aai.openecomp.org.v8.Vnfcs" />
+ <xml-element java-attribute="l3Networks" name="l3-networks" type="inventory.aai.openecomp.org.v8.L3Networks" />
+ <xml-element java-attribute="genericVnfs" name="generic-vnfs" type="inventory.aai.openecomp.org.v8.GenericVnfs" />
+ <xml-element java-attribute="pnfs" name="pnfs" type="inventory.aai.openecomp.org.v8.Pnfs" />
+ <xml-element java-attribute="physicalLinks" name="physical-links" type="inventory.aai.openecomp.org.v8.PhysicalLinks" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="LogicalLinks">
+ <xml-properties>
+ <xml-property name="description" value="Collection of logical connections" />
+ </xml-properties>
+ <xml-root-element name="logical-links" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="logicalLink" name="logical-link" type="inventory.aai.openecomp.org.v8.LogicalLink" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="LogicalLink">
+ <xml-root-element name="logical-link" />
+ <java-attributes>
+ <xml-element java-attribute="linkName" name="link-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="e.g., evc-name, or vnf-nameA_interface-nameA_vnf-nameZ_interface-nameZ" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="linkType" name="link-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Type of logical link, e.g., evc" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedValue" name="speed-value" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the numeric part of the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedUnits" name="speed-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the units corresponding to the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipVersion" name="ip-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="v4, v6, or ds for dual stack (should be ip-version)" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="routingProtocol" name="routing-protocol" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="For example, static or BGP" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelId" name="persona-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model id for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelVersion" name="persona-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model version for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelId" name="widget-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary widget model. This maps directly to the AAI widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelVersion" name="widget-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="operationalStatus" name="operational-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Indication of operational status of the logical link." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="linkRole" name="link-role" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Indication of the network use of the logical link." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="linkName2" name="link-name2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Alias or alternate name (CLCI or D1 name)." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="linkId" name="link-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="UUID of the logical-link, SDNC generates this." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Logical links generally connect l-interfaces but are used to express logical connectivity between two points" />
+ <xml-property name="indexedProps" value="link-name,persona-model-id,persona-model-version,widget-model-id,widget-model-version,link-id" />
+ <xml-property name="uniqueProps" value="link-id" />
+ <xml-property name="container" value="logical-links" />
+ <xml-property name="namespace" value="network" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Vnfcs">
+ <xml-properties>
+ <xml-property name="description" value="virtual network components associated with a vserver from application controller." />
+ </xml-properties>
+ <xml-root-element name="vnfcs" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="vnfc" name="vnfc" type="inventory.aai.openecomp.org.v8.Vnfc" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Vnfc">
+ <xml-root-element name="vnfc" />
+ <java-attributes>
+ <xml-element java-attribute="vnfcName" name="vnfc-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique ID of vnfc." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vnfcFunctionCode" name="vnfc-function-code" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="function code" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vnfcType" name="vnfc-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="type" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="provStatus" name="prov-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="prov status of this vnfc" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Orchestration status of this VNF, mastered by APP-C" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipaddressV4OamVip" name="ipaddress-v4-oam-vip" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Oam V4 vip address of this vnfc" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="inMaint" name="in-maint" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="isClosedLoopDisabled" name="is-closed-loop-disabled" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="used to indicate whether closed loop function is enabled on this node" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="groupNotation" name="group-notation" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Group notation of VNFC" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="indexedProps" value="vnfc-name,prov-status,vnfc-type,vnfc-function-code,ipaddress-v4-oam-vip,in-maint,is-closed-loop-disabled,group-notation" />
+ <xml-property name="container" value="vnfcs" />
+ <xml-property name="namespace" value="network" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="L3Networks">
+ <xml-root-element name="l3-networks" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="l3Network" name="l3-network" type="inventory.aai.openecomp.org.v8.L3Network" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="L3Network">
+ <xml-root-element name="l3-network" />
+ <java-attributes>
+ <xml-element java-attribute="networkId" name="network-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Network ID, should be uuid. Unique across AAI." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkName" name="network-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of the network, governed by some naming convention.." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkType" name="network-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Type of the network - who defines these values?" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkRole" name="network-role" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Role the network plans - who defines these values?" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkTechnology" name="network-technology" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Network technology - who defines these values?" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="neutronNetworkId" name="neutron-network-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Neutron network id of this Interface" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="isBoundToVpn" name="is-bound-to-vpn" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="Set to true if bound to VPN" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceId" name="service-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Unique identifier of service from SDC" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkRoleInstance" name="network-role-instance" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="network role instance" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Orchestration status of this VNF, mastered by MSO" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="heatStackId" name="heat-stack-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Heat stack id corresponding to this instance, managed by MSO" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="msoCatalogKey" name="mso-catalog-key" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Corresponds to the SDN-C catalog id used to configure this VCE" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="contrailNetworkFqdn" name="contrail-network-fqdn" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Contrail FQDN for the network" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelId" name="persona-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model id for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelVersion" name="persona-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model version for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelId" name="widget-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary widget model. This maps directly to the AAI widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelVersion" name="widget-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="physicalNetworkName" name="physical-network-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name associated with the physical network." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="isProviderNetwork" name="is-provider-network" required="true" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="boolean indicatating whether or not network is a provider network." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="isSharedNetwork" name="is-shared-network" required="true" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="boolean indicatating whether or not network is a shared network." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="isExternalNetwork" name="is-external-network" required="true" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="boolean indicatating whether or not network is an external network." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="subnets" name="subnets" type="inventory.aai.openecomp.org.v8.Subnets" />
+ <xml-element java-attribute="ctagAssignments" name="ctag-assignments" type="inventory.aai.openecomp.org.v8.CtagAssignments" />
+ <xml-element java-attribute="segmentationAssignments" name="segmentation-assignments" type="inventory.aai.openecomp.org.v8.SegmentationAssignments" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" >
+ <xml-properties>
+ <xml-property name="description" value="Relates to tenant (or is it a child of tenant)" />
+ </xml-properties>
+ </xml-element>
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Generic network definition" />
+ <xml-property name="nameProps" value="network-name" />
+ <xml-property name="indexedProps" value="heat-stack-id,network-uuid,service-id,network-id,network-name,persona-model-id,persona-model-version,widget-model-id,widget-model-version,contrail-network-fqdn" />
+ <xml-property name="uniqueProps" value="network-id" />
+ <xml-property name="container" value="l3-networks" />
+ <xml-property name="namespace" value="network" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="CtagAssignments">
+ <xml-root-element name="ctag-assignments" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="ctagAssignment" name="ctag-assignment" type="inventory.aai.openecomp.org.v8.CtagAssignment" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="CtagAssignment">
+ <xml-root-element name="ctag-assignment" />
+ <java-attributes>
+ <xml-element java-attribute="vlanIdInner" name="vlan-id-inner" required="true" type="java.lang.Long" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="id." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="indexedProps" value="vlan-id-inner" />
+ <xml-property name="dependentOn" value="l3-network" />
+ <xml-property name="container" value="ctag-assignments" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Subnets">
+ <xml-root-element name="subnets" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="subnet" name="subnet" type="inventory.aai.openecomp.org.v8.Subnet" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Subnet">
+ <xml-root-element name="subnet" />
+ <java-attributes>
+ <xml-element java-attribute="subnetId" name="subnet-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Subnet ID, should be UUID." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="subnetName" name="subnet-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name associated with the subnet." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="neutronSubnetId" name="neutron-subnet-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Neutron id of this subnet" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="gatewayAddress" name="gateway-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="gateway ip address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="networkStartAddress" name="network-start-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="network start address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="cidrMask" name="cidr-mask" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="cidr mask" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipVersion" name="ip-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="ip version" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Orchestration status of this VNF, mastered by MSO" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="dhcpEnabled" name="dhcp-enabled" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="dhcp enabled" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="dhcpStart" name="dhcp-start" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the start address reserved for use by dhcp" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="dhcpEnd" name="dhcp-end" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the last address reserved for use by dhcp" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="indexedProps" value="subnet-id,subnet-name" />
+ <xml-property name="nameProps" value="subnet-name" />
+ <xml-property name="uniqueProps" value="subnet-id" />
+ <xml-property name="dependentOn" value="l3-network" />
+ <xml-property name="container" value="subnets" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="GenericVnfs">
+ <xml-properties>
+ <xml-property name="description" value="Collection of VNFs" />
+ </xml-properties>
+ <xml-root-element name="generic-vnfs" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="genericVnf" name="generic-vnf" type="inventory.aai.openecomp.org.v8.GenericVnf" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="GenericVnf">
+ <xml-root-element name="generic-vnf" />
+ <java-attributes>
+ <xml-element java-attribute="vnfId" name="vnf-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique id of VNF. This is unique across the graph." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vnfName" name="vnf-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of VNF." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vnfName2" name="vnf-name2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Alternate name of VNF." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vnfType" name="vnf-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded and clients should expect changes to occur in the future to this field as SDC matures." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceId" name="service-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Unique identifier of service from SDC" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="regionalResourceZone" name="regional-resource-zone" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Regional way of organizing pservers, source of truth should define values" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="provStatus" name="prov-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Trigger for operational monitoring of this resource by Service Assurance systems." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="operationalState" name="operational-state" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Indicator for whether the resource is considered operational" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="licenseKey" name="license-key" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="License key" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipmentRole" name="equipment-role" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Client should send valid enumerated value" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Orchestration status of this VNF, used by MSO." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="heatStackId" name="heat-stack-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Heat stack id corresponding to this instance, managed by MSO" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="msoCatalogKey" name="mso-catalog-key" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Corresponds to the SDN-C catalog id used to configure this VCE" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="managementOption" name="management-option" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="identifier of managed by customer" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipv4OamAddress" name="ipv4-oam-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Address tail-f uses to configure generic-vnf, also used for troubleshooting and is IP used for traps generated by generic-vnf." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipv4Loopback0Address" name="ipv4-loopback0-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="v4 Loopback0 address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="nmLanV6Address" name="nm-lan-v6-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="v6 Loopback address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="managementV6Address" name="management-v6-address" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="v6 management address" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vcpu" name="vcpu" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="number of vcpus ordered for this instance of VNF, used for VNFs with no vservers/flavors" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vcpuUnits" name="vcpu-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="units associated with vcpu, used for VNFs with no vservers/flavors" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vmemory" name="vmemory" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="number of GB of memory ordered for this instance of VNF, used for VNFs with no vservers/flavors" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vmemoryUnits" name="vmemory-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="units associated with vmemory, used for VNFs with no vservers/flavors" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vdisk" name="vdisk" type="java.lang.Long">
+ <xml-properties>
+ <xml-property name="description" value="number of vdisks ordered for this instance of VNF, used for VNFs with no vservers/flavors" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vdiskUnits" name="vdisk-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="units associated with vdisk, used for VNFs with no vservers/flavors" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="inMaint" name="in-maint" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs." />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="isClosedLoopDisabled" name="is-closed-loop-disabled" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="used to indicate whether closed loop function is enabled on this node" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="summaryStatus" name="summary-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="details regarding the generic-vnf operation" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="encryptedAccessFlag" name="encrypted-access-flag" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="description" value="indicates whether generic-vnf access uses SSH" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="entitlementAssignmentGroupUuid" name="entitlement-assignment-group-uuid" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="UUID of the Entitlement group used for licensing VNFs" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="entitlementResourceUuid" name="entitlement-resource-uuid" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="UUID of the specific entitlement resource" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="licenseAssignmentGroupUuid" name="license-assignment-group-uuid" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="UUID of the license assignment group" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="licenseKeyUuid" name="license-key-uuid" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="UUID of the actual license resource" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelId" name="persona-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model id for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelVersion" name="persona-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model version for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelCustomizationId" name="persona-model-customization-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="captures the id of all the configuration used to customize the resource for the service." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelId" name="widget-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary widget model. This maps directly to the AAI widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelVersion" name="widget-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="asNumber" name="as-number" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="as-number of the VNF" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="regionalResourceSubzone" name="regional-resource-subzone" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="represents sub zone of the rr plane" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="lInterfaces" name="l-interfaces" type="inventory.aai.openecomp.org.v8.LInterfaces" />
+ <xml-element java-attribute="lagInterfaces" name="lag-interfaces" type="inventory.aai.openecomp.org.v8.LagInterfaces" />
+ <xml-element java-attribute="vfModules" name="vf-modules" type="inventory.aai.openecomp.org.v8.VfModules" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="General purpose VNF" />
+ <xml-property name="nameProps" value="vnf-name" />
+ <xml-property name="indexedProps" value="is-closed-loop-disabled,vnf-name2,vnf-type,heat-stack-id,in-maint,vnf-name,vnf-id,regional-resource-zone,prov-status,service-id,persona-model-id,persona-model-version,widget-model-id,widget-model-version" />
+ <xml-property name="searchable" value="vnf-id,vnf-name,vnf-name2" />
+ <xml-property name="uniqueProps" value="vnf-id" />
+ <xml-property name="container" value="generic-vnfs" />
+ <xml-property name="namespace" value="network" />
+ <xml-property name="extends" value="vnf" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="VfModules">
+ <xml-properties>
+ <xml-property name="description" value="Collection of vf-modules, a deployment unit of VNFCs" />
+ </xml-properties>
+ <xml-root-element name="vf-modules" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="vfModule" name="vf-module" type="inventory.aai.openecomp.org.v8.VfModule" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="VfModule">
+ <xml-root-element name="vf-module" />
+ <java-attributes>
+ <xml-element java-attribute="vfModuleId" name="vf-module-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique ID of vf-module." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="vfModuleName" name="vf-module-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of vf-module" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="heatStackId" name="heat-stack-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Heat stack id corresponding to this instance." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="orchestration status of this vf-module, mastered by MSO" />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="isBaseVfModule" name="is-base-vf-module" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="used to indicate whether or not this object is base vf module" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelId" name="persona-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model id for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="personaModelVersion" name="persona-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC model version for this resource or service model." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelId" name="widget-model-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary widget model. This maps directly to the AAI widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="widgetModelVersion" name="widget-model-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the SDC data dictionary version of the widget model.This maps directly to the AAI version of the widget." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="contrailServiceInstanceFqdn" name="contrail-service-instance-fqdn" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="the Contrail unique ID for a service-instance" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="a deployment unit of VNFCs" />
+ <xml-property name="indexedProps" value="vf-module-id,vf-module-name,heat-stack-id,persona-model-id,persona-model-version,widget-model-id,widget-model-version,contrail-service-instance-fqdn" />
+ <xml-property name="dependentOn" value="generic-vnf" />
+ <xml-property name="container" value="vf-modules" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Pnfs">
+ <xml-properties>
+ <xml-property name="description" value="Collection of Physical Network Functions." />
+ </xml-properties>
+ <xml-root-element name="pnfs" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="pnf" name="pnf" type="inventory.aai.openecomp.org.v8.Pnf" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Pnf">
+ <xml-root-element name="pnf" />
+ <java-attributes>
+ <xml-element java-attribute="pnfName" name="pnf-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="unique name of Physical Network Function." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="pnfName2" name="pnf-name2" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="name of Physical Network Function." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="pnfName2Source" name="pnf-name2-source" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="source of name2" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="pnfId" name="pnf-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="id of pnf" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipType" name="equip-type" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Equipment type. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipVendor" name="equip-vendor" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Equipment vendor. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="equipModel" name="equip-model" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Equipment model. Source of truth should define valid values." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="managementOption" name="management-option" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="identifier of managed by customer" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="ipaddressV4Oam" name="ipaddress-v4-oam" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="ipv4-oam-address with new naming convention for IP addresses" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="swVersion" name="sw-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="sw-version is the version of SW for the hosted application on the PNF." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="orchestrationStatus" name="orchestration-status" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="orchestration-status is the status of orchestration on the PNF." />
+ </xml-properties>
+ </xml-element>
+ <xml-element default-value="false" required="true" java-attribute="inMaint" name="in-maint" type="java.lang.Boolean">
+ <xml-properties>
+ <xml-property name="defaultValue" value="false"/>
+ <xml-property name="description" value="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="frameId" name="frame-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="ID of the physical frame (relay rack) where pnf is installed." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ <xml-element java-attribute="pInterfaces" name="p-interfaces" type="inventory.aai.openecomp.org.v8.PInterfaces" />
+ <xml-element java-attribute="lagInterfaces" name="lag-interfaces" type="inventory.aai.openecomp.org.v8.LagInterfaces" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="PNF represents a physical network function." />
+ <xml-property name="indexedProps" value="pnf-name,orchestration-status" />
+ <xml-property name="uniqueProps" value="pnf-name" />
+ <xml-property name="container" value="pnfs" />
+ <xml-property name="namespace" value="network" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="PhysicalLinks">
+ <xml-properties>
+ <xml-property name="description" value="Collection of physical connections, typically between p-interfaces" />
+ </xml-properties>
+ <xml-root-element name="physical-links" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="physicalLink" name="physical-link" type="inventory.aai.openecomp.org.v8.PhysicalLink" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="PhysicalLink">
+ <xml-root-element name="physical-link" />
+ <java-attributes>
+ <xml-element java-attribute="linkName" name="link-name" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="e.g., hostnameA_p-connection_nameA_hostnameZ+p_connection-nameZ" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedValue" name="speed-value" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the numeric part of the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="speedUnits" name="speed-units" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Captures the units corresponding to the speed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="circuitId" name="circuit-id" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Circuit it" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="dualMode" name="dual-mode" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Dual access mode (e.g., primary, secondary" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="managementOption" name="management-option" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="To provide information on who manages this circuit. AAI or 3rd party transport provider" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceProviderName" name="service-provider-name" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of the service Provider on this link." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Collection of physical connections, typically between p-interfaces" />
+ <xml-property name="indexedProps" value="circuit-id,link-name" />
+ <xml-property name="alternateKeys1" value="circuit-id" />
+ <xml-property name="container" value="physical-links" />
+ <xml-property name="namespace" value="network" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="NotificationEvent">
+ <xml-root-element name="notification-event" />
+ <java-attributes>
+ <xml-element java-attribute="cambriaPartition" name="cambria.partition" type="java.lang.String" />
+ <xml-element java-attribute="eventHeader" name="event-header" type="inventory.aai.openecomp.org.v8.NotificationEventHeader" />
+ <xml-any-element java-attribute="entity" />
+ </java-attributes>
+ </java-type>
+ <java-type name="NotificationEventHeader">
+ <xml-root-element name="notification-event-header" />
+ <java-attributes>
+ <xml-element java-attribute="id" name="id" type="java.lang.String" />
+ <xml-element java-attribute="timestamp" name="timestamp" type="java.lang.String" />
+ <xml-element java-attribute="sourceName" name="source-name" type="java.lang.String" />
+ <xml-element java-attribute="domain" name="domain" type="java.lang.String" />
+ <xml-element java-attribute="sequenceNumber" name="sequence-number" type="java.lang.String" />
+ <xml-element java-attribute="severity" name="severity" type="java.lang.String" />
+ <xml-element java-attribute="eventType" name="event-type" type="java.lang.String" />
+ <xml-element java-attribute="version" name="version" type="java.lang.String" />
+ <xml-element java-attribute="action" name="action" type="java.lang.String" />
+ <xml-element java-attribute="entityType" name="entity-type" type="java.lang.String" />
+ <xml-element java-attribute="topEntityType" name="top-entity-type" type="java.lang.String" />
+ <xml-element java-attribute="entityLink" name="entity-link" type="java.lang.String" />
+ <xml-element java-attribute="status" name="status" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="AaiInternal">
+ <xml-root-element name="aai-internal" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="reservedPropNames" name="reserved-prop-names" type="inventory.aai.openecomp.org.v8.ReservedPropNames" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="edgePropNames" name="edge-prop-names" type="inventory.aai.openecomp.org.v8.EdgePropNames" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ReservedPropNames">
+ <xml-properties>
+ <xml-property name="description" value="Internal map to define some reserved properties of a vertex" />
+ <xml-property name="uniqueProps" value="aai-unique-key" />
+ <xml-property name="indexedProps" value="aai-unique-key,source-of-truth,aai-node-type" />
+ </xml-properties>
+ <xml-root-element name="reserved-prop-names" />
+ <java-attributes>
+ <xml-element java-attribute="lastModSourceOfTruth" name="last-mod-source-of-truth" type="java.lang.String" />
+ <xml-element java-attribute="aaiNodeType" name="aai-node-type" type="java.lang.String" />
+ <xml-element java-attribute="aaiCreatedTs" name="aai-created-ts" type="java.lang.Long" />
+ <xml-element java-attribute="aaiUniqueKey" name="aai-unique-key" type="java.lang.String" />
+ <xml-element java-attribute="aaiLastModTs" name="aai-last-mod-ts" type="java.lang.Long" />
+ <xml-element java-attribute="sourceOfTruth" name="source-of-truth" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="EdgePropNames">
+ <!-- NOTE that the names of these properties are not consistent and are in mixed case and hyphen case for now -->
+ <xml-properties>
+ <xml-property name="description" value="Internal map to define the properties of an edge and interpret the map EdgeRules" />
+ <xml-property name="edgeInfo" value="edgeLabel,direction,multiplicityRule,isParent,usesResource,hasDelTarget,SVC-INFRA,SVC-INFRA-REV" />
+ </xml-properties>
+ <xml-root-element name="edge-prop-names" />
+ <java-attributes>
+ <xml-element java-attribute="edgeLabel" name="edgeLabel" type="java.lang.String" />
+ <xml-element java-attribute="direction" name="direction" type="java.lang.String" />
+ <xml-element java-attribute="multiplicityRule" name="multiplicityRule" type="java.lang.String" />
+ <xml-element java-attribute="isParent" name="isParent" type="java.lang.Boolean" />
+ <xml-element java-attribute="usesResource" name="usesResource" type="java.lang.Boolean" />
+ <xml-element java-attribute="hasDelTarget" name="hasDelTarget" type="java.lang.Boolean" />
+ <xml-element java-attribute="SVC-INFRA" name="SVC-INFRA" type="java.lang.String" />
+ <xml-element java-attribute="SVC-INFRA-REV" name="SVC-INFRA-REV" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Services">
+ <xml-properties>
+ <xml-property name="description" value="Collection of service model definitions. Likely to be deprecated in favor of models from SDC."/>
+ </xml-properties>
+ <xml-root-element name="services" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="service" name="service" type="inventory.aai.openecomp.org.v8.Service" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Service">
+ <xml-root-element name="service" />
+ <java-attributes>
+ <xml-element java-attribute="serviceId" name="service-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="This gets defined by others to provide a unique ID for the service, we accept what is sent." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceDescription" name="service-description" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Description of the service" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceSelflink" name="service-selflink" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="URL to endpoint where AAI can get more details" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="serviceVersion" name="service-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="service version" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Stand-in for service model definitions. Likely to be deprecated in favor of models from SDC." />
+ <xml-property name="indexedProps" value="service-description,service-id" />
+ <xml-property name="container" value="services" />
+ <xml-property name="namespace" value="service-design-and-creation" />
+ </xml-properties>
+ </java-type>
+
+ <java-type name="Models">
+ <xml-properties>
+ <xml-property name="description" value="Collection of subgraph definitions provided by SDC to describe the inventory assets and their connections related to SDC models" />
+ </xml-properties>
+ <xml-root-element name="models" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="model" name="model" type="inventory.aai.openecomp.org.v8.Model" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Model">
+ <xml-properties>
+ <xml-property name="description" value="Subgraph definition provided by SDC to describe an inventory asset and its connections related to SDC models" />
+ <xml-property name="nameProps" value="model-name,model-type" />
+ <xml-property name="indexedProps" value="model-name-version-id,model-type,model-name,model-id,model-version" />
+ <xml-property name="alternateKeys1" value="model-id,model-version" />
+ <xml-property name="uniqueProps" value="model-name-version-id" />
+ <xml-property name="container" value="models" />
+ <xml-property name="namespace" value="service-design-and-creation" />
+ </xml-properties>
+ <xml-root-element name="model" />
+ <java-attributes>
+ <xml-element java-attribute="modelNameVersionId" name="model-name-version-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Unique identifier corresponding to one version of a model in SDC" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelType" name="model-type" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Type of the model, e.g., service, resource, widget, etc." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelName" name="model-name" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Name of the model, which can change from version to version." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelId" name="model-id" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Invariant unique ID which does not change from version to version" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelVersion" name="model-version" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Version" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelDescription" name="model-description" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Description" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelElements" name="model-elements" type="inventory.aai.openecomp.org.v8.ModelElements" />
+ <xml-element java-attribute="metadata" name="metadata" type="inventory.aai.openecomp.org.v8.Metadata" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ModelElements">
+ <xml-root-element name="model-elements" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="modelElement" name="model-element" type="inventory.aai.openecomp.org.v8.ModelElement" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ModelElement">
+ <xml-properties>
+ <xml-property name="description" value="Defines how other models combine to make up a higher-level model." />
+ <xml-property name="uniqueProps" value="model-element-uuid" />
+ <xml-property name="indexedProps" value="model-element-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="model-elements" />
+ </xml-properties>
+ <xml-root-element name="model-element" />
+ <java-attributes>
+ <xml-element java-attribute="modelElementUuid" name="model-element-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="newDataDelFlag" name="new-data-del-flag" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Indicates whether this element was created as part of instantiation from this model" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="cardinality" name="cardinality" required="true" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="How many of this type of element are required/allowed" />
+ </xml-properties>
+ </xml-element>
+ <xml-element container-type="java.util.ArrayList" java-attribute="linkagePoints" name="linkage-point" type="java.lang.String">
+ <xml-element-wrapper name="linkage-points" />
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Used for optimistic concurrency. Must be empty on create, valid on update and delete." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelElements" name="model-elements" type="inventory.aai.openecomp.org.v8.ModelElements">
+ <xml-properties>
+ <xml-property name="description" value="Defines how other models combine to make up a higher-level model" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="modelConstraints" name="model-constraints" type="inventory.aai.openecomp.org.v8.ModelConstraints">
+ <xml-properties>
+ <xml-property name="description" value="Describes new constraints on this model element that are not part of that model's definition" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ModelConstraints">
+ <xml-root-element name="model-constraints" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="modelConstraint" name="model-constraint" type="inventory.aai.openecomp.org.v8.ModelConstraint" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ModelConstraint">
+ <xml-properties>
+ <xml-property name="description" value="This is how we would capture constraints defining allowed sets of elements." />
+ <xml-property name="uniqueProps" value="model-constraint-uuid" />
+ <xml-property name="indexedProps" value="model-constraint-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="model-constraints" />
+ </xml-properties>
+ <xml-root-element name="model-constraint" />
+ <java-attributes>
+ <xml-element java-attribute="modelConstraintUuid" name="model-constraint-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="constrainedElementSetUuidToReplace" name="constrained-element-set-uuid-to-replace" required="true" type="java.lang.String" />
+ <xml-element java-attribute="constrainedElementSets" name="constrained-element-sets" type="inventory.aai.openecomp.org.v8.ConstrainedElementSets" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ConstrainedElementSets">
+ <xml-root-element name="constrained-element-sets" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="constrainedElementSet" name="constrained-element-set" type="inventory.aai.openecomp.org.v8.ConstrainedElementSet" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ConstrainedElementSet">
+ <xml-properties>
+ <xml-property name="description" value="This is how we would capture constraints defining allowed sets of elements." />
+ <xml-property name="uniqueProps" value="constrained-element-set-uuid" />
+ <xml-property name="indexedProps" value="constrained-element-set-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="constrained-element-sets" />
+ </xml-properties>
+ <xml-root-element name="constrained-element-set" />
+ <java-attributes>
+ <xml-element java-attribute="constrainedElementSetUuid" name="constrained-element-set-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="constraintType" name="constraint-type" required="true" type="java.lang.String" />
+ <xml-element java-attribute="checkType" name="check-type" required="true" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String" />
+ <xml-element java-attribute="elementChoiceSets" name="element-choice-sets" type="inventory.aai.openecomp.org.v8.ElementChoiceSets" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ElementChoiceSets">
+ <xml-root-element name="element-choice-sets" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="elementChoiceSet" name="element-choice-set" type="inventory.aai.openecomp.org.v8.ElementChoiceSet" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ElementChoiceSet">
+ <xml-properties>
+ <xml-property name="description" value="This is how we would capture constraints defining allowed sets of elements." />
+ <xml-property name="uniqueProps" value="element-choice-set-uuid" />
+ <xml-property name="indexedProps" value="element-choice-set-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="element-choice-sets" />
+ </xml-properties>
+ <xml-root-element name="element-choice-set" />
+ <java-attributes>
+ <xml-element java-attribute="elementChoiceSetUuid" name="element-choice-set-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="elementChoiceSetName" name="element-choice-set-name" required="true" type="java.lang.String" />
+ <xml-element java-attribute="cardinality" name="cardinality" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String" />
+ <xml-element java-attribute="modelElements" name="model-elements" type="inventory.aai.openecomp.org.v8.ModelElements" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="NamedQueries">
+ <xml-root-element name="named-queries" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="namedQuery" name="named-query" type="inventory.aai.openecomp.org.v8.NamedQuery" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="NamedQuery">
+ <xml-properties>
+ <xml-property name="description" value="TBD" />
+ <xml-property name="nameProps" value="named-query-name" />
+ <xml-property name="uniqueProps" value="named-query-uuid" />
+ <xml-property name="indexedProps" value="named-query-uuid,named-query-name" />
+ <xml-property name="container" value="named-queries" />
+ <xml-property name="namespace" value="service-design-and-creation" />
+ </xml-properties>
+ <xml-root-element name="named-query" />
+ <java-attributes>
+ <xml-element java-attribute="namedQueryUuid" name="named-query-uuid" required="true" type="java.lang.String" xml-key="true" />
+ <xml-element java-attribute="namedQueryName" name="named-query-name" required="true" type="java.lang.String" />
+ <xml-element java-attribute="namedQueryVersion" name="named-query-version" required="true" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="requiredInputParams" name="required-input-param" type="java.lang.String">
+ <xml-element-wrapper name="required-input-params" />
+ </xml-element>
+ <xml-element java-attribute="description" name="description" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String" />
+ <xml-element java-attribute="namedQueryElements" name="named-query-elements" type="inventory.aai.openecomp.org.v8.NamedQueryElements" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="NamedQueryElements">
+ <xml-root-element name="named-query-elements" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="namedQueryElement" name="named-query-element" type="inventory.aai.openecomp.org.v8.NamedQueryElement" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="NamedQueryElement">
+ <xml-properties>
+ <xml-property name="description" value="TBD" />
+ <xml-property name="uniqueProps" value="named-query-element-uuid" />
+ <xml-property name="indexedProps" value="named-query-element-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="named-query-elements" />
+ </xml-properties>
+ <xml-root-element name="named-query-element" />
+ <java-attributes>
+ <xml-element java-attribute="namedQueryElementUuid" name="named-query-element-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element container-type="java.util.ArrayList" java-attribute="propertyCollectList" name="property-collect-list" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String" />
+ <xml-element java-attribute="propertyLimitDesc" name="property-limit-desc" type="java.lang.String" />
+ <xml-element java-attribute="doNotOutput" name="do-not-output" type="java.lang.String" />
+ <xml-element java-attribute="namedQueryElements" name="named-query-elements" type="inventory.aai.openecomp.org.v8.NamedQueryElements" />
+ <xml-element java-attribute="relatedLookups" name="related-lookups" type="inventory.aai.openecomp.org.v8.RelatedLookups" />
+ <xml-element java-attribute="propertyConstraints" name="property-constraints" type="inventory.aai.openecomp.org.v8.PropertyConstraints" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="RelatedLookups">
+ <xml-root-element name="related-lookups" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="relatedLookup" name="related-lookup" type="inventory.aai.openecomp.org.v8.RelatedLookup" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="RelatedLookup">
+ <xml-properties>
+ <xml-property name="description" value="TBD" />
+ <xml-property name="uniqueProps" value="related-lookup-uuid" />
+ <xml-property name="indexedProps" value="related-lookup-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="related-lookups" />
+ </xml-properties>
+ <xml-root-element name="related-lookup" />
+ <java-attributes>
+ <xml-element java-attribute="relatedLookupUuid" name="related-lookup-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="sourceNodeType" name="source-node-type" required="true" type="java.lang.String" />
+ <xml-element java-attribute="sourceNodeProperty" name="source-node-property" required="true" type="java.lang.String" />
+ <xml-element java-attribute="targetNodeType" name="target-node-type" required="true" type="java.lang.String" />
+ <xml-element java-attribute="targetNodeProperty" name="target-node-property" required="true" type="java.lang.String" />
+ <xml-element container-type="java.util.ArrayList" java-attribute="propertyCollectList" name="property-collect-list" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String" />
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="PropertyConstraints">
+ <xml-root-element name="property-constraints" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="propertyConstraint" name="property-constraint" type="inventory.aai.openecomp.org.v8.PropertyConstraint" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="PropertyConstraint">
+ <xml-properties>
+ <xml-property name="description" value="TBD" />
+ <xml-property name="uniqueProps" value="property-constraint-uuid" />
+ <xml-property name="indexedProps" value="property-constraint-uuid" />
+ <xml-property name="allowDirectRead" value="true" />
+ <xml-property name="allowDirectWrite" value="false" />
+ <xml-property name="container" value="property-constraints" />
+ </xml-properties>
+ <xml-root-element name="property-constraint" />
+ <java-attributes>
+ <xml-element java-attribute="propertyConstraintUuid" name="property-constraint-uuid" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="autoGenerateUuid" value="true" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="constraintType" name="constraint-type" required="true" type="java.lang.String" />
+ <xml-element java-attribute="property-name" name="property-name" required="true" type="java.lang.String" />
+ <xml-element java-attribute="property-value" name="property-value" required="true" type="java.lang.String" />
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ModelAndNamedQuerySearch">
+ <xml-properties>
+ <xml-property name="description" value="ModelAndNamedQuerySearch holds query-parameters and instance-properties for performing a named-query or model query" />
+ </xml-properties>
+ <xml-root-element name="model-and-named-query-search" />
+ <java-attributes>
+ <xml-element java-attribute="queryParameters" name="query-parameters" type="inventory.aai.openecomp.org.v8.QueryParameters" />
+ <xml-element java-attribute="instanceFilters" name="instance-filters" type="inventory.aai.openecomp.org.v8.InstanceFilters" />
+ <xml-element java-attribute="topNodeType" name="top-node-type" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="QueryParameters">
+ <xml-properties>
+ <xml-property name="description" value="QueryParameters for performing a named-query or model query" />
+ </xml-properties>
+ <xml-root-element name="query-parameters" />
+ <java-attributes>
+ <xml-element java-attribute="namedQuery" name="named-query" type="inventory.aai.openecomp.org.v8.NamedQuery" />
+ <xml-element java-attribute="model" name="model" type="inventory.aai.openecomp.org.v8.Model" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="InstanceFilters">
+ <xml-properties>
+ <xml-property name="description" value="InstanceFilters for performing a named-query or model query" />
+ </xml-properties>
+ <xml-root-element name="instance-filters" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="instanceFilter" name="instance-filter" type="inventory.aai.openecomp.org.v8.InstanceFilter" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="InstanceFilter">
+ <xml-properties>
+ <xml-property name="description" value="InstanceFilter for performing a named-query or model query" />
+ <xml-property name="container" value="instance-filters" />
+ </xml-properties>
+ <xml-root-element name="instance-filter" />
+ <java-attributes>
+ <xml-any-element container-type="java.util.ArrayList" java-attribute="any" lax="true" name="any" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="Properties">
+ <xml-properties>
+ <xml-property name="description" value="Property holder for query properties or instance properties" />
+ </xml-properties>
+ <xml-root-element name="properties" />
+ <java-attributes>
+ <xml-element java-attribute="propertyName" name="property-name" type="java.lang.String" />
+ <xml-element java-attribute="propertyValue" name="property-value" type="java.lang.String" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ResponseList">
+ <xml-properties>
+ <xml-property name="description" value="Response container for the results of a named-query or model query" />
+ </xml-properties>
+ <xml-root-element name="response-list" />
+ <java-attributes>
+ <xml-element java-attribute="inventoryResponseItems" name="inventory-response-items" type="inventory.aai.openecomp.org.v8.InventoryResponseItems" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="InventoryResponseItems">
+ <xml-properties>
+ <xml-property name="description" value="Container for inventory items in response list" />
+ <xml-property name="container" value="response-list" />
+ </xml-properties>
+ <xml-root-element name="inventory-response-items" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="inventoryResponseItem" name="inventory-response-item" type="inventory.aai.openecomp.org.v8.InventoryResponseItem" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="InventoryResponseItem">
+ <xml-properties>
+ <xml-property name="description" value="Inventory item for response list" />
+ <xml-property name="container" value="inventory-response-items" />
+ </xml-properties>
+ <xml-root-element name="inventory-response-item" />
+ <java-attributes>
+ <xml-element java-attribute="modelName" name="model-name" type="java.lang.String" />
+ <xml-any-element java-attribute="item" />
+ <xml-element java-attribute="extraProperties" name="extra-properties" type="inventory.aai.openecomp.org.v8.ExtraProperties" />
+ <xml-element java-attribute="inventoryResponseItems" name="inventory-response-items" type="inventory.aai.openecomp.org.v8.InventoryResponseItems" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ExtraProperties">
+ <xml-properties>
+ <xml-property name="description" value="Extra properties for inventory item for response list" />
+ </xml-properties>
+ <xml-root-element name="extra-properties" />
+ <java-attributes>
+ <xml-any-element container-type="java.util.ArrayList" java-attribute="extraProperty" name="extra-property" type="inventory.aai.openecomp.org.v8.ExtraProperty" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="ExtraProperty">
+ <xml-root-element name="extra-property" />
+ <java-attributes>
+ <xml-element java-attribute="propertyName" name="property-name" type="java.lang.String" />
+ <xml-any-element java-attribute="propertyValue" lax="true" name="property-value" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="SegmentationAssignments">
+ <xml-properties>
+ <xml-property name="description" value="Collection of openstack segmentation assignments" />
+ </xml-properties>
+ <xml-root-element name="segmentation-assignments" />
+ <java-attributes>
+ <xml-element container-type="java.util.ArrayList" java-attribute="segmentationAssignment" name="segmentation-assignment" type="inventory.aai.openecomp.org.v8.SegmentationAssignment" />
+ </java-attributes>
+ </java-type>
+
+ <java-type name="SegmentationAssignment">
+ <xml-root-element name="segmentation-assignment" />
+ <java-attributes>
+ <xml-element java-attribute="segmentationId" name="segmentation-id" required="true" type="java.lang.String" xml-key="true">
+ <xml-properties>
+ <xml-property name="description" value="Route Table Reference id, UUID assigned to this instance." />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="resourceVersion" name="resource-version" type="java.lang.String">
+ <xml-properties>
+ <xml-property name="description" value="Concurrency value" />
+ </xml-properties>
+ </xml-element>
+ <xml-element java-attribute="relationshipList" name="relationship-list" type="inventory.aai.openecomp.org.v8.RelationshipList" />
+ </java-attributes>
+ <xml-properties>
+ <xml-property name="description" value="Openstack segmentation assignment." />
+ <xml-property name="indexedProps" value="segmentation-id" />
+ <xml-property name="dependentOn" value="l3-network" />
+ <xml-property name="container" value="segmentation-assignments" />
+ </xml-properties>
+ </java-type>
+
+ </java-types>
+</xml-bindings>
diff --git a/ajsc-aai/.gitignore b/ajsc-aai/.gitignore
new file mode 100644
index 0000000..2a36faf
--- /dev/null
+++ b/ajsc-aai/.gitignore
@@ -0,0 +1,7 @@
+.settings
+target/
+**/logs/
+bundleconfig-local/etc/oxm
+bundleconfig-local/etc/logback.xml
+/.pydevproject
+/test_csvWriter.csv
diff --git a/ajsc-aai/ajsc-shared-config/README.txt b/ajsc-aai/ajsc-shared-config/README.txt
new file mode 100644
index 0000000..a82eb64
--- /dev/null
+++ b/ajsc-aai/ajsc-shared-config/README.txt
@@ -0,0 +1,6 @@
+The ajsc-shared-config folder is included in the service project to provide the functionality of the AJSC_SHARED_CONFIG
+location that will exist in CSI envs. This includes the logback.xml for logging configurations, and some csm related
+artifacts necessary for proper functionality of the csm framework within the CSI env. Within the 2 profiles that can
+be utilized to run the AJSC locally, "runLocal" and "runAjsc", the system propery, "AJSC_SHARED_CONFIG", has been set
+to point to this directory. The files in this folder will NOT be copied/moved anywhere within the AJSC SWM package. These
+files will already be in existence within the CSI env. \ No newline at end of file
diff --git a/ajsc-aai/ajsc-shared-config/etc/aft.properties b/ajsc-aai/ajsc-shared-config/etc/aft.properties
new file mode 100644
index 0000000..b2f86bc
--- /dev/null
+++ b/ajsc-aai/ajsc-shared-config/etc/aft.properties
@@ -0,0 +1,7 @@
+#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+# Flow test 319
+# The DEFAULT setup for this file is for deployment to soa cloud node which will use the "bundleconfig/etc/spm2.jks" location
+# For Testing Locally, you can set the system property, csiEnable=true, found within bundleconfig-local/etc/sysprops/sys-props.properties
+# and switch com.att.aft.keyStore and com.att.aft.trustStore values commented out below to "ajsc-shared-config/etc/spm2.jks"
+
+#replace proper values for the dummy values.
diff --git a/ajsc-aai/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml b/ajsc-aai/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml
new file mode 100644
index 0000000..4ebe2db
--- /dev/null
+++ b/ajsc-aai/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml
@@ -0,0 +1,87 @@
+<!--
+ Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+-->
+<configuration scan="true" scanPeriod="3 seconds" debug="true">
+ <property name="logDirectory" value="${AJSC_HOME}/log" />
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>ERROR</level>
+ </filter>
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n
+ </pattern>
+ </encoder>
+ </appender>
+
+ <appender name="INFO"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>DEBUG</level>
+ </filter>
+ <file>${logDirectory}/info_ajsc.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/info_ajsc.%i.log.zip
+ </fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+ <appender name="ERROR"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>ERROR</level>
+ </filter>
+ <file>${logDirectory}/error_ajsc.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/error_ajsc.%i.log.zip
+ </fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n"</pattern> -->
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="AJSC-AUDIT" class="ch.qos.logback.classic.net.SyslogAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ <syslogHost>localhost</syslogHost>
+ <facility>USER</facility>
+ <!-- Note the colon character below - it is important part of "TAG" message
+ format You need a colon to determine where the TAG field ends and the CONTENT
+ begins -->
+ <suffixPattern>AJSC_AUDIT: [%thread] [%logger] %msg</suffixPattern>
+ </appender>
+ <appender name="CONTROLLER-AUDIT" class="ch.qos.logback.classic.net.SyslogAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ <syslogHost>localhost</syslogHost>
+ <facility>USER</facility>
+ <!-- Note the colon character below - it is important part of "TAG" message
+ format You need a colon to determine where the TAG field ends and the CONTENT
+ begins -->
+ <suffixPattern>AJSC_AUDIT: [%thread] [%logger] mdc:[%mdc] %msg
+ </suffixPattern>
+ </appender>
+
+ <root level="off">
+ <appender-ref ref="ERROR" />
+ <appender-ref ref="INFO" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
diff --git a/ajsc-aai/ajsc-shared-config/etc/localhost-access-logback.xml b/ajsc-aai/ajsc-shared-config/etc/localhost-access-logback.xml
new file mode 100644
index 0000000..9401a9f
--- /dev/null
+++ b/ajsc-aai/ajsc-shared-config/etc/localhost-access-logback.xml
@@ -0,0 +1,38 @@
+<configuration>
+ <appender name="ACCESS"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${AJSC_HOME}/logs/ajsc-jetty/localhost_access.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${AJSC_HOME}/logs/ajsc-jetty/localhost_access.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder class="org.openecomp.aai.util.CustomLogPatternLayoutEncoder">
+ <Pattern>%a %u %z [%t] "%m %U" %s %b %y</Pattern>
+ </encoder>
+ </appender>
+ <appender-ref ref="ACCESS" />
+</configuration>
+
+<!--
+%a - Remote IP address
+%A - Local IP address
+%b - Bytes sent, excluding HTTP headers, or '-' if no bytes were sent
+%B - Bytes sent, excluding HTTP headers
+%h - Remote host name
+%H - Request protocol
+%l - Remote logical username from identd (always returns '-')
+%m - Request method
+%p - Local port
+%q - Query string (prepended with a '?' if it exists, otherwise an empty string
+%r - First line of the request
+%s - HTTP status code of the response
+%S - User session ID
+%t - Date and time, in Common Log Format format
+%u - Remote user that was authenticated
+%U - Requested URL path
+%v - Local server name
+%I - current request thread name (can compare later with stacktraces)
+
+%z - Custom pattern that parses the cert for the subject
+%y - Custom pattern determines rest or dme2
+ --> \ No newline at end of file
diff --git a/ajsc-aai/ajsc-shared-config/etc/logback.xml b/ajsc-aai/ajsc-shared-config/etc/logback.xml
new file mode 100644
index 0000000..103f38f
--- /dev/null
+++ b/ajsc-aai/ajsc-shared-config/etc/logback.xml
@@ -0,0 +1,296 @@
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+ <contextName>${module.ajsc.namespace.name}</contextName>
+ <jmxConfigurator />
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>ERROR</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="METRIC" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/metrics.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncMETRIC" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <appender-ref ref="METRIC" />
+ </appender>
+
+ <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/debug.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncDEBUG" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <appender-ref ref="DEBUG" />
+ </appender>
+
+ <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <file>${logDirectory}/rest/error.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncERROR" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <appender-ref ref="ERROR" />
+ </appender>
+
+ <appender name="AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/rest/audit.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/audit.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+ <appender name="asyncAUDIT" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <appender-ref ref="AUDIT" />
+ </appender>
+
+ <appender name="dmaapAAIWorkloadConsumer" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/dmaapAAIWorkloadConsumer/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dmaapAAIWorkloadConsumer/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="dmaapAAIWorkloadConsumerdebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/dmaapAAIWorkloadConsumer/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dmaapAAIWorkloadConsumer/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+ <appender name="dmaapAAIWorkloadConsumermetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/dmaapAAIWorkloadConsumer/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dmaapAAIWorkloadConsumer/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <!-- Spring related loggers -->
+ <logger name="org.springframework" level="WARN" />
+ <logger name="org.springframework.beans" level="WARN" />
+ <logger name="org.springframework.web" level="WARN" />
+ <logger name="com.blog.spring.jms" level="WARN" />
+
+ <!-- AJSC Services (bootstrap services) -->
+ <logger name="ajsc" level="WARN" />
+ <logger name="ajsc.RouteMgmtService" level="WARN" />
+ <logger name="ajsc.ComputeService" level="WARN" />
+ <logger name="ajsc.VandelayService" level="WARN" />
+ <logger name="ajsc.FilePersistenceService" level="WARN" />
+ <logger name="ajsc.UserDefinedJarService" level="WARN" />
+ <logger name="ajsc.UserDefinedBeansDefService" level="WARN" />
+ <logger name="ajsc.LoggingConfigurationService" level="WARN" />
+
+ <!-- AJSC related loggers (DME2 Registration, csi logging, restlet, servlet logging) -->
+ <logger name="ajsc.utils" level="WARN" />
+ <logger name="ajsc.utils.DME2Helper" level="WARN" />
+ <logger name="ajsc.filters" level="WARN" />
+ <logger name="ajsc.beans.interceptors" level="WARN" />
+ <logger name="ajsc.restlet" level="WARN" />
+ <logger name="ajsc.servlet" level="WARN" />
+ <logger name="com.att.ajsc" level="WARN" />
+
+ <!-- Other Loggers that may help troubleshoot -->
+ <logger name="net.sf" level="WARN" />
+ <logger name="org.apache.commons.httpclient" level="WARN" />
+ <logger name="org.apache.commons" level="WARN" />
+ <logger name="org.apache.coyote" level="WARN" />
+ <logger name="org.apache.jasper" level="WARN" />
+
+ <!-- Camel Related Loggers (including restlet/servlet/jaxrs/cxf logging. May aid in troubleshooting) -->
+ <logger name="org.apache.camel" level="WARN" />
+ <logger name="org.apache.cxf" level="WARN" />
+ <logger name="org.apache.camel.processor.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.jaxrs.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.service" level="WARN" />
+ <logger name="org.restlet" level="WARN" />
+ <logger name="org.apache.camel.component.restlet" level="WARN" />
+
+ <!-- logback internals logging -->
+ <logger name="ch.qos.logback.classic" level="WARN" />
+ <logger name="ch.qos.logback.core" level="WARN" />
+
+ <!-- logback jms appenders & loggers definition starts here -->
+ <appender name="auditLogs" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter"/>
+ <file>${logDirectory}/perf-audit/Audit-${lrmRVer}-${lrmRO}-${Pid}.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/perf-audit/Audit-${lrmRVer}-${lrmRO}-${Pid}.%i.log.zip</fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+ <appender name="perfLogs" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter"/>
+ <file>${logDirectory}/perf-audit/Perform-${lrmRVer}-${lrmRO}-${Pid}.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+ <fileNamePattern>${logDirectory}/perf-audit/Perform-${lrmRVer}-${lrmRO}-${Pid}.%i.log.zip</fileNamePattern>
+ <minIndex>1</minIndex>
+ <maxIndex>9</maxIndex>
+ </rollingPolicy>
+ <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+<!-- <if condition='property("JMS_BROKER").contains("WMQ")'>
+ <then>
+ <appender name="Audit-Record-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName" value="${JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME}" />
+ <param name="ProviderURL" value="${JMS_WMQ_PROVIDER_URL}" />
+ <param name="DestinationName" value="${JMS_WMQ_AUDIT_DESTINATION_NAME}" />
+ <param name="ConnectionFactoryName" value="${JMS_WMQ_CONNECTION_FACTORY_NAME}" />
+ </appender>
+ <appender name="Performance-Tracker-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName" value="${JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME}" />
+ <param name="ProviderURL" value="${JMS_WMQ_PROVIDER_URL}" />
+ <param name="DestinationName" value="${JMS_WMQ_PERF_DESTINATION_NAME}" />
+ <param name="ConnectionFactoryName" value="${JMS_WMQ_CONNECTION_FACTORY_NAME}" />
+ </appender>
+ </then>
+ <else> -->
+ <!-- logback jms appenders definition starts here -->
+<!-- <appender name="Audit-Record-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName" value="com.tibco.tibjms.naming.TibjmsInitialContextFactory" />
+ <param name="ProviderURL" value="${JMS_TIBCO_PROVIDER_URL}" />
+ <param name="userName" value="${JMS_LOGGER_USER_NAME}" />
+ <param name="password" value="${JMS_LOGGER_PASSWORD}" />
+ <QueueBindingName>${JMS_LOGGER_AUDIT_QUEUE_BINDING}</QueueBindingName>
+ </appender>
+ <appender name="Performance-Tracker-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName" value="com.tibco.tibjms.naming.TibjmsInitialContextFactory" />
+ <param name="ProviderURL" value="${JMS_TIBCO_PROVIDER_URL}" />
+ <param name="userName" value="${JMS_LOGGER_USER_NAME}" />
+ <param name="password" value="${JMS_LOGGER_PASSWORD}" />
+ <QueueBindingName>${JMS_LOGGER_PERF_QUEUE_BINDING}</QueueBindingName>
+ </appender>
+ </else>
+ </if> -->
+ <appender name="ASYNC-audit" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <discardingThreshold>0</discardingThreshold>
+ <appender-ref ref="Audit-Record-Queue" />
+ </appender>
+ <logger name="AuditRecord" level="INFO" additivity="false">
+ <appender-ref ref="ASYNC-audit" />
+ <appender-ref ref="auditLogs" />
+ </logger>
+ <logger name="AuditRecord_DirectCall" level="INFO" additivity="false">
+ <appender-ref ref="ASYNC-audit" />
+ <appender-ref ref="auditLogs" />
+ </logger>
+ <appender name="ASYNC-perf" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <discardingThreshold>0</discardingThreshold>
+ <appender-ref ref="Performance-Tracker-Queue" />
+ </appender>
+ <logger name="PerfTrackerRecord" level="INFO" additivity="false">
+ <appender-ref ref="ASYNC-perf" />
+ <appender-ref ref="perfLogs" />
+ </logger>
+ <!-- logback jms appenders & loggers definition ends here -->
+
+ <logger name="org.openecomp.aai.dmaap" level="DEBUG" additivity="false">
+ <appender-ref ref="dmaapAAIWorkloadConsumer" />
+ <appender-ref ref="dmaapAAIWorkloadConsumerdebug" />
+ <appender-ref ref="dmaapAAIWorkloadConsumermetric" />
+ </logger>
+
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="asyncDEBUG" />
+ <appender-ref ref="asyncERROR" />
+ <appender-ref ref="asyncMETRIC" />
+ </logger>
+ <logger name="org.openecomp.aai.AUDITLOGGER" level="INFO" additivity="false">
+ <appender-ref ref="asyncAUDIT" />
+ </logger>
+
+ <logger name="org.apache" level="WARN" />
+ <logger name="org.zookeeper" level="WARN" />
+ <logger name="com.thinkaurelius" level="WARN" />
+
+ <!-- ============================================================================ -->
+ <!-- General EELF logger -->
+ <!-- ============================================================================ -->
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="asyncDEBUG" />
+ <appender-ref ref="asyncERROR" />
+ <appender-ref ref="asyncMETRIC" />
+ <appender-ref ref="asyncAUDIT" />
+ </logger>
+
+ <root level="WARN">
+ <appender-ref ref="asyncDEBUG" />
+ <appender-ref ref="asyncERROR" />
+ <appender-ref ref="asyncMETRIC" />
+ <appender-ref ref="asyncAUDIT" />
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/ajsc/pom.xml b/ajsc-aai/ajsc/pom.xml
new file mode 100644
index 0000000..deb43c8
--- /dev/null
+++ b/ajsc-aai/ajsc/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>ajsc-aai</artifactId>
+ <version>${openecomp.release}</version>
+ </parent>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>ajsc</artifactId>
+ <name>ajsc</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ajsc-aai/antBuild/build.xml b/ajsc-aai/antBuild/build.xml
new file mode 100644
index 0000000..76c7df9
--- /dev/null
+++ b/ajsc-aai/antBuild/build.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+-->
+<project>
+ <target name="runLocal">
+ <java dir="${basedir}" fork="yes" newenvironment="true"
+ failonerror="true" classname="com.att.ajsc.runner.Runner">
+ <classpath
+ path="${classpath}:${basedir}/ajsc-shared-config/etc:${runAjscHome}/lib/ajsc-runner-${ajscRuntimeVersion}.jar" />
+
+ <!-- Windows Users may need to add a jvmarg arg to create a temp directory
+ properly. -->
+ <!-- <jvmarg value="-Djava.io.tmpdir=C:/yourTempDirectory"/> -->
+
+ <!-- Uncomment the following 2 jvmarg values to enable Remote Debugging.
+ -->
+ <!-- <jvmarg value="-Xdebug" /> -->
+ <!-- <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5432"
+ /> -->
+
+ <jvmarg value="-XX:MaxPermSize=512m" />
+ <jvmarg value="-Xmx1024m" />
+
+ <!-- Main ajsc Variables below (Variables necessary for proper startup
+ of AJSC) -->
+ <env key="AJSC_HOME" value="${runAjscHome}" />
+ <sysproperty key="AJSC_HOME" value="${runAjscHome}" />
+ <!-- you may specify any external location for AJSC_CONF_HOME where etc
+ folder & all other configs can be found under it. If not specified, it will
+ default to AJSC_HOME -->
+ <sysproperty key="AJSC_CONF_HOME" value="${basedir}/bundleconfig-local" />
+ <sysproperty key="AJSC_SHARED_CONFIG" value="${basedir}/ajsc-shared-config" />
+
+ <!-- Location of logback.xml file used for logging configurations. Please,
+ note, when deploying a service to either CSI or NON-CSI environment, this
+ system property will be set in sys-props.properties file. We are setting
+ it here for running locally due to the ease of use of maven variable for
+ basedir. -->
+ <sysproperty key="logback.configurationFile"
+ value="${basedir}/ajsc-shared-config/etc/logback.xml" />
+
+ <!-- Setting system properties for the AJSC external libs and properties
+ folders below. When deploying to a node, these properties will be set within
+ the bundleconfig/etc/sysprops/sys-props.properties file. However, when running
+ locally, the ${basedir} substitution works more efficiently in this manner. -->
+ <sysproperty key="AJSC_EXTERNAL_LIB_FOLDERS" value="${basedir}/target/commonLibs" />
+ <sysproperty key="AJSC_EXTERNAL_PROPERTIES_FOLDERS"
+ value="${basedir}/ajsc-shared-config/etc" />
+
+ <!-- End of Main ajsc Variables below (Variables necessary for proper
+ startup of AJSC) -->
+
+ <!-- Uncomment the following line to add oauthentication to your Service -->
+ <!-- <sysproperty key="spring.profiles.active" value="oauth" /> -->
+
+ <!-- If using Cassandra as Database, Enter the ip/host and port below
+ based on your known configuration -->
+ <!-- <sysproperty key="cassandra.ip" value="hostname" /> -->
+ <!-- <sysproperty key="cassandra.port" value="9042" /> -->
+
+ <!-- The APP_SERVLET_URL_PATTERN variable is defaulted to "/services"
+ within the initial configuration of the AJSC. If you are changing the CamelServlet
+ Filter within the ajsc-override-web.xml, you should use that url-pattern
+ here. This is necessary to properly register your service with dme2. An empty
+ value, "", is used when NO value is wanted (url-pattern would be /* for CamelServlet
+ Filter) -->
+ <!-- As of 4.5.1, this property is no longer needed -->
+ <!-- <sysproperty key="APP_SERVLET_URL_PATTERN" value="/services" /> -->
+
+ <!-- GRM/DME2 System Properties below -->
+ <sysproperty key="AJSC_SERVICE_NAMESPACE" value="${module.ajsc.namespace.name}" />
+ <sysproperty key="AJSC_SERVICE_VERSION" value="${module.ajsc.namespace.version}" />
+ <sysproperty key="SOACLOUD_SERVICE_VERSION" value="${project.version}" />
+ <!-- End of GRM/DME2 System Property Variables -->
+
+ <!-- The following server.port variable was necessary for the proper registration
+ of the AJSC to dme2. This value may still need to be used if the Developer
+ is hardcoding their port (example: 8080). Then, the server.port value="8080".
+ The default functionality for the AJSC is to use EPHEMERAL ports. In this
+ case, you do NOT need to set the server.port value. The AJSC will find the
+ proper port value and register to dme2 correctly -->
+ <!-- <sysproperty key="server.port" value="${serverPort}" /> -->
+
+ <!-- Command Line Arguments to add to the java command. Here, you can
+ specify the port as well as the Context you want your service to run in.
+ Use context=/ to run in an unnamed Context (Root Context). The default configuration
+ of the AJSC is to run under the /ajsc Context. Setting the port here can
+ aid during the development phase of your service. However, you can leave
+ this argument out entirely, and the AJSC will default to using an Ephemeral
+ port. -->
+ <arg line="context=/ port=${serverPort} sslport=${sslport}" />
+ </java>
+ </target>
+ <target name="prep_home_directory_for_swm_pkgcreate">
+
+<!-- ********* GENERATE CADI KEY AND ENCRYPTED PASSWORD ***********
+
+ Uncomment the following if your cadi key get corrupted , It would
+ generate the Cadi key and password in the package phase and keep the key
+ in the 'src/main/config/ajscKey' and password in the bottom of cadi.properties(you
+ need to modify the 'aaf_pass' variable with this value . Plese modify the
+ template.cadi.properties as well before uploading to SOA node
+-->
+
+<!--
+ <java jar="${basedir}/target/userjars/cadi-core-1.2.5.jar" fork="true">
+ <arg value="keygen" /> <arg value="src/main/config/ajscKey" />
+ </java>
+
+ <echo>***Cadi Key file generated ****</echo>
+
+ <java jar="${basedir}/target/userjars/cadi-core-1.2.5.jar"
+ fork="true" append="true" output="${basedir}/src/main/config/cadi.properties">
+ <arg value="digest" /> <arg value="ajscRocks!" /> <arg value="src/main/config/ajscKey"
+ />
+ </java>
+
+-->
+
+
+
+ <!-- These tasks are copying contents from the installHomeDirectory into
+ the eventual $AJSC_HOME directory for running locally and soa cloud installation -->
+ <echo message="ENTERING 'prep_home_directory_for_swm_pkgcreate' ant tasks" />
+
+ <!-- Please, NOTE: The ajsc-archetype is setup for a default CSI Env deployment.
+ If you are deploying to a CSI Env, you should NOT have to change anything
+ within this build file. However, if you are NOT deploying to a CSI Env, you
+ should comment OUT the CSI related portion of this build.xml. -->
+
+ <!-- The following code snippet is copying the bundleconfig-csi directory
+ to the proper installation/bundleconfig directory used in CSI envs. If you
+ are NOT installing to a CSI node, you should comment out (or delete) the
+ following snippet, and uncomment the NON-CSI copy task to copy EVERYTHING
+ to the installation/bundleconfig directory. -->
+
+ <!-- CSI related bundleconfig copy task. If you are NOT deploying to a
+ CSI Env, please COMMENT OUT or delete the following copy task code snippet. -->
+ <!--<copy toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/bundleconfig"
+ failonerror="true"> <fileset dir="${basedir}/bundleconfig-csi" /> </copy> -->
+ <!-- End of CSI related bundleconfig copy task -->
+
+ <!-- NOTE: If you are NOT deploying to CSI environment, and you are NOT
+ using an AJSC_SHARED_CONFIG location on a node, you should go ahead and copy
+ EVERYTHING from bundleconfig and ajsc-shared-config (logback.xml) directory
+ to utilize proper logging from logback.xml. Simply, uncomment the following
+ code snippet below to copy EVERYTHING and comment out the CSI related build
+ script above. -->
+ <!-- NON-CSI related build copy task. Please, uncomment the following code
+ snippet to deploy the proper artifacts to a NON-CSI Env. -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/bundleconfig"
+ failonerror="true">
+ <fileset dir="${basedir}/bundleconfig-local" includes="**/**" />
+ </copy>
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/bundleconfig/etc"
+ failonerror="true">
+ <fileset dir="${basedir}/ajsc-shared-config/etc" includes="**/**" />
+ </copy>
+ <!-- End of NON-CSI related build copy task. -->
+
+ <!-- Copying any zips (deployment packages) to $AJSC_HOME/services for
+ auto-deployment -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/services"
+ failonerror="false">
+ <fileset dir="${basedir}/services" includes="*.zip" />
+ </copy>
+
+ <!-- Copying runtimeEnvironment zip file to $AJSC_HOME/runtime and renaming
+ runtimeEnvironment.zip for proper auto-deployment of ajsc services. -->
+ <!-- <copy
+ tofile="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/runtime/runtimeEnvironment.zip">
+ <fileset dir="target" includes="*-runtimeEnvironment.zip" />
+ </copy>
+-->
+ <!-- Copying dependencies from the service project (not provided by AJSC
+ Container) to the $AJSC_HOME/extJars folder to be accessible on the classpath -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extJars"
+ failonerror="false">
+ <fileset dir="target/userjars" includes="*" />
+ </copy>
+
+ <!-- extApps directory MUST be created for ajsc-runner to run correctly,
+ even if empty. DO NOT REMOVE!!! -->
+ <!-- extApps directory created to deploy other war files on startup or
+ hot deploy War files after ajsc starts up. -->
+ <mkdir
+ dir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extApps" />
+
+ <!-- Copying any extra wars to $AJSC_HOME/extApps to be deployed within
+ AJSC -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extApps"
+ failonerror="false">
+ <fileset dir="${basedir}/src/main/resources/extApps"
+ includes="*" />
+ </copy>
+
+ <!-- staticContent folder is for serving static content within an ajsc
+ service. Any static content to be served will be copyied to the ultimate
+ $AJSC_HOME/staticContent folder and can be served with the
+ camel component. -->
+ <!-- Uncomment the following snippet to copy items from staticContent folder
+ to ultimate $AJSC_HOME/staticConent -->
+ <!-- <copy toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/staticContent"
+ failonerror="false"> <fileset dir="${basedir}/staticContent" includes="**/**"
+ /> </copy> -->
+
+ <!-- Copying extra jar files that have been labeled as dependencies in
+ service project to /extJars folder to be made available on the classpath
+ for your service -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/extJars"
+ failonerror="false">
+ <fileset dir="target" includes="*.jar" />
+ </copy>
+
+ <!-- Copying deployment packages created within the project to the $AJSC_HOME/services
+ folder to be auto deployed. -->
+ <copy
+ toDir="${basedir}/target/swm/package/nix/dist_files${distFilesRoot}/services">
+ <fileset dir="target" includes="*.zip" excludes="*-runtimeEnvironment.zip" />
+ </copy>
+
+ <echo message="EXITING 'prep_assembly_output_for_swm_plugin' ant tasks" />
+ </target>
+</project> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/README.txt b/ajsc-aai/bundleconfig-local/README.txt
new file mode 100644
index 0000000..e5c95b6
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/README.txt
@@ -0,0 +1,10 @@
+The bundleconfig-local directory contains the necessary configuration files to be used for running locally. When running
+locally, the "mvn -N -P runLocal" or the "mvn -N -P runAjsc" profiles will be using this bundleconfig-local directory as the AJSC_CONF
+directory. When deploying to a CSI env, the bundleconfig-csi directory will be copied to the ultimate installation/bundleconfig
+directory and will be used for your AJSC service once installed. If you are not deploying to a CSI env, please look at the
+antBuild/build.xml file for help in some simple copying of the appropriate folders/files for a NON-CSI env.
+
+
+The ajsc-shared-config directory houses the shared configurations that will be used in CSI envs. This includes the logging
+functionality of the logback.xml and some csm related artifacts that may be necessary to use while running locally.
+When running locally, the system property, "AJSC_SHARED_CONFIG", will point to this location to utilize the logback.xml. \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/RELEASE_NOTES.txt b/ajsc-aai/bundleconfig-local/RELEASE_NOTES.txt
new file mode 100644
index 0000000..a567d9b
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/RELEASE_NOTES.txt
@@ -0,0 +1 @@
+Place Release Notes here to provide updated Release information for CSTEM to better help manage your service in the CSI environment. \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/AAFUserRoles.properties b/ajsc-aai/bundleconfig-local/etc/appprops/AAFUserRoles.properties
new file mode 100644
index 0000000..1929351
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/AAFUserRoles.properties
@@ -0,0 +1,5 @@
+#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+
+#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.
+
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/Introscope.properties b/ajsc-aai/bundleconfig-local/etc/appprops/Introscope.properties
new file mode 100644
index 0000000..319381e
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/Introscope.properties
@@ -0,0 +1,8 @@
+#CSI environment uses the Introscope java agent for monitoring services. The AJSC has provided an implementation class that
+#provides basic information to the Introscope Enterprise Manager for each http request/response.
+
+introscopeEventClass=com.att.ajsc.introscope.IntroscopeEventNotifierImpl
+serviceName=N/A
+conversationId=N/A
+uniqueID=N/A
+userID=N/A
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties b/ajsc-aai/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties
new file mode 100644
index 0000000..08ffefa
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties
@@ -0,0 +1,3 @@
+#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+#This properties file is for defining any PostProcessorInterceptors that have been created for your AJSC service.
+
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties b/ajsc-aai/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties
new file mode 100644
index 0000000..1383071
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties
@@ -0,0 +1,4 @@
+#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+#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/ajsc-aai/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties b/ajsc-aai/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties
new file mode 100644
index 0000000..0d294ed
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties
@@ -0,0 +1,29 @@
+TransportType=DME2
+Latitude=47.778998
+Longitude=-122.182883
+Version=1.0
+ServiceName=dmaap-v1-host/events
+Environment=TEST
+Partner=BOT_R
+routeOffer=MR1
+SubContextPath=/
+Protocol=https
+MethodType=POST
+username=
+password=
+contenttype=application/json
+host=
+topic=
+partition=AAI_WORKLOAD
+maxBatchSize=100
+maxAgeMs=250
+AFT_DME2_EXCHANGE_REQUEST_HANDLERS=
+AFT_DME2_EXCHANGE_REPLY_HANDLERS=
+AFT_DME2_REQ_TRACE_ON=true
+AFT_ENVIRONMENT=AFTUAT
+AFT_DME2_EP_CONN_TIMEOUT=15000
+AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000
+AFT_DME2_EP_READ_TIMEOUT_MS=50000
+sessionstickinessrequired=NO
+DME2preferredRouterFilePath=preferredRoute.txt
+MessageSentThreadOccurance=50 \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadConsumer.properties b/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadConsumer.properties
new file mode 100644
index 0000000..8f03f83
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadConsumer.properties
@@ -0,0 +1,30 @@
+TransportType=DME2
+Latitude=47.778998
+Longitude=-122.182883
+Version=1.0
+ServiceName=
+Environment=TEST
+Partner=BOT_R
+routeOffer=MR1
+SubContextPath=/
+Protocol=http
+MethodType=GET
+username=
+password=
+contenttype=application/json
+host=
+topic=
+group=aaiConsumer
+id=dev
+timeout=15000
+limit=1000
+filter=
+AFT_DME2_EXCHANGE_REQUEST_HANDLERS=
+AFT_DME2_EXCHANGE_REPLY_HANDLERS=
+AFT_DME2_REQ_TRACE_ON=true
+AFT_ENVIRONMENT=AFTUAT
+AFT_DME2_EP_CONN_TIMEOUT=15000
+AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000
+AFT_DME2_EP_READ_TIMEOUT_MS=50000
+sessionstickinessrequired=no
+DME2preferredRouterFilePath=preferredRoute.txt \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadPublisher.properties b/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadPublisher.properties
new file mode 100644
index 0000000..372268a
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadPublisher.properties
@@ -0,0 +1,29 @@
+TransportType=DME2
+Latitude=47.778998
+Longitude=-122.182883
+Version=1.0
+ServiceName=
+Environment=TEST
+Partner=BOT_R
+routeOffer=MR1
+SubContextPath=/
+Protocol=http
+MethodType=POST
+username=
+password=
+contenttype=application/json
+host=
+topic=
+partition=AAI_WORKLOAD
+maxBatchSize=100
+maxAgeMs=250
+AFT_DME2_EXCHANGE_REQUEST_HANDLERS=
+AFT_DME2_EXCHANGE_REPLY_HANDLERS=
+AFT_DME2_REQ_TRACE_ON=true
+AFT_ENVIRONMENT=AFTUAT
+AFT_DME2_EP_CONN_TIMEOUT=15000
+AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000
+AFT_DME2_EP_READ_TIMEOUT_MS=50000
+sessionstickinessrequired=NO
+DME2preferredRouterFilePath=preferredRoute.txt
+MessageSentThreadOccurance=50 \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadStatusPublisher.properties b/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadStatusPublisher.properties
new file mode 100644
index 0000000..49db340
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/aaiWorkloadStatusPublisher.properties
@@ -0,0 +1,29 @@
+TransportType=DME2
+Latitude=47.778998
+Longitude=-122.182883
+Version=1.0
+ServiceName=
+Environment=TEST
+Partner=BOT_R
+routeOffer=MR1
+SubContextPath=/
+Protocol=http
+MethodType=POST
+username=
+password=
+contenttype=application/json
+host=
+topic=
+partition=AAI_WORKLOAD_STATUS
+maxBatchSize=100
+maxAgeMs=250
+AFT_DME2_EXCHANGE_REQUEST_HANDLERS=
+AFT_DME2_EXCHANGE_REPLY_HANDLERS=
+AFT_DME2_REQ_TRACE_ON=true
+AFT_ENVIRONMENT=AFTUAT
+AFT_DME2_EP_CONN_TIMEOUT=15000
+AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000
+AFT_DME2_EP_READ_TIMEOUT_MS=50000
+sessionstickinessrequired=NO
+DME2preferredRouterFilePath=preferredRoute.txt
+MessageSentThreadOccurance=50 \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/aaiconfig.properties b/ajsc-aai/bundleconfig-local/etc/appprops/aaiconfig.properties
new file mode 100644
index 0000000..b1b23fe
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/aaiconfig.properties
@@ -0,0 +1,95 @@
+####################################################################
+# REMEMBER TO THINK ABOUT ENVIRONMENTAL DIFFERENCES AND CHANGE THE
+# TEMPLATE AND *ALL* DATAFILES
+####################################################################
+
+aai.config.checktime=1000
+
+# this could come from siteconfig.pl?
+aai.config.nodename=AutomaticallyOverwritten
+
+aai.logging.hbase.interceptor=false
+aai.logging.hbase.enabled=false
+aai.logging.hbase.logrequest=false
+aai.logging.hbase.logresponse=false
+
+aai.logging.trace.enabled=true
+aai.logging.trace.logrequest=false
+aai.logging.trace.logresponse=false
+
+
+aai.tools.enableBasicAuth=true
+aai.tools.username=AAI
+aai.tools.password=AAI
+
+aai.server.url.base=https://localhost:8443/aai/
+aai.server.url=https://localhost:8443/aai/v8/
+aai.global.callback.url=https://localhost:8443/aai/
+
+aai.auth.cspcookies_on=false
+aai.truststore.filename=aai_keystore
+aai.truststore.passwd.x=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
+
+# the following parameters are not reloaded automatically and require a manual bounce
+storage.backend=inmemory
+storage.hostname=localhost
+
+#schema.default=none
+storage.lock.wait-time=300
+storage.hbase.table=aaigraph.dev
+storage.hbase.ext.zookeeper.znode.parent=/hbase
+# Setting db-cache to false ensure the fastest propagation of changes across servers
+cache.db-cache = false
+#cache.db-cache-clean-wait = 20
+#cache.db-cache-time = 180000
+#cache.db-cache-size = 0.5
+
+# for transaction log
+hbase.table.name=aailogging.dev
+hbase.table.timestamp.format=YYYYMMdd-HH:mm:ss:SSS
+hbase.zookeeper.quorum=localhost
+hbase.zookeeper.property.clientPort=2181
+hbase.zookeeper.znode.parent=/hbase
+hbase.column.ttl.days=15
+
+
+# single primary server
+aai.primary.filetransfer.serverlist=localhost
+aai.primary.filetransfer.primarycheck=echo:8443/aai/util/echo
+aai.primary.filetransfer.pingtimeout=5000
+aai.primary.filetransfer.pingcount=5
+
+#rsync properties
+aai.rsync.command=rsync
+aai.rsync.options.list=-v|-t
+aai.rsync.remote.user=aaiadmin
+aai.rsync.enabled=y
+
+
+aai.notification.current.version=v8
+aai.notificationEvent.default.status=UNPROCESSED
+aai.notificationEvent.default.eventType=AAI-EVENT
+aai.notificationEvent.default.domain=devINT1
+aai.notificationEvent.default.sourceName=aai
+aai.notificationEvent.default.sequenceNumber=0
+aai.notificationEvent.default.severity=NORMAL
+aai.notificationEvent.default.version=v8
+# This one lets us enable/disable resource-version checking on updates/deletes
+aai.resourceversion.enableflag=true
+aai.logging.maxStackTraceEntries=10
+aai.default.api.version=v8
+
+
+# Used by Model-processing code
+aai.model.delete.sleep.per.vtx.msec=500
+aai.model.query.resultset.maxcount=30
+aai.model.query.timeout.sec=90
+
+# Used by Data Grooming
+aai.grooming.default.max.fix=150
+aai.grooming.default.sleep.minutes=7
+
+aai.model.proc.max.levels=50
+aai.edgeTag.proc.max.levels=50
+
+aai.dmaap.workload.enableEventProcessing=true
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/app-intercepts.properties b/ajsc-aai/bundleconfig-local/etc/appprops/app-intercepts.properties
new file mode 100644
index 0000000..d024956
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/app-intercepts.properties
@@ -0,0 +1,8 @@
+#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+
+#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=ajsctestservice.JaxrsEchoService,packagename.class1name,packagename.class2name
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/createDBSchema-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/createDBSchema-logback.xml
new file mode 100644
index 0000000..de1a168
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/createDBSchema-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="createDBSchema" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/createDBSchema/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/createDBSchema/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="createDBSchemadebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/createDBSchema/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/createDBSchema/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="createDBSchemametric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/createDBSchema/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/createDBSchema/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="createDBSchema"/>
+ <appender-ref ref="createDBSchemadebug"/>
+ <appender-ref ref="createDBSchemametric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/dataGrooming-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/dataGrooming-logback.xml
new file mode 100644
index 0000000..cc2920b
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/dataGrooming-logback.xml
@@ -0,0 +1,108 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="dataGrooming" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/dataGrooming/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dataGrooming/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="dataGroomingdebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/dataGrooming/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dataGrooming/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="dataGroomingmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/dataGrooming/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dataGrooming/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="com.sun.jersey.api.client" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="org.eclipse.jetty.util.log" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+ <logger name="java.net" level="WARN" additivity="false">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="dataGrooming"/>
+ <appender-ref ref="dataGroomingdebug"/>
+ <appender-ref ref="dataGroomingmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/dataSnapshot-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/dataSnapshot-logback.xml
new file mode 100644
index 0000000..580fd33
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/dataSnapshot-logback.xml
@@ -0,0 +1,108 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="dataSnapshot" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/dataSnapshot/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dataSnapshot/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="dataSnapshotdebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/dataSnapshot/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dataSnapshot/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="dataSnapshotmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/dataSnapshot/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/dataSnapshot/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="com.sun.jersey.api.client" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="org.eclipse.jetty.util.log" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+ <logger name="java.net" level="WARN" additivity="false">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="dataSnapshot"/>
+ <appender-ref ref="dataSnapshotdebug"/>
+ <appender-ref ref="dataSnapshotmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/default-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/default-logback.xml
new file mode 100644
index 0000000..0dc841d
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/default-logback.xml
@@ -0,0 +1,20 @@
+<configuration debug="false">
+ <property name="defaultPattern" value="%d{MM/dd-HH:mm:ss.SSS}|%logger|%X{RequestId}|%X{ServiceInstanceId}|%thread|%X{ServiceName}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{RemoteHost}|%X{Timer}|%msg%n" />
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>${defaultPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN"/>
+ <logger name="org.apache.zookeeper" level="WARN"/>
+ <logger name="org.apache.hadoop" level="WARN"/>
+ <logger name="com.thinkaurelius" level="WARN"/>
+ <logger name="ch.qos.logback.classic" level="WARN" />
+ <logger name="ch.qos.logback.core" level="WARN" />
+
+ <root level="INFO">
+ <appender-ref ref="STDOUT"/>
+ </root>
+</configuration>
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/deltool-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/deltool-logback.xml
new file mode 100644
index 0000000..18fa8de
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/deltool-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="delTool" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/delTool/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/delTool/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="delTooldebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/delTool/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/delTool/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="delToolmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/delTool/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/delTool/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="delTool"/>
+ <appender-ref ref="delTooldebug"/>
+ <appender-ref ref="delToolmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/error.properties b/ajsc-aai/bundleconfig-local/etc/appprops/error.properties
new file mode 100644
index 0000000..1516471
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/error.properties
@@ -0,0 +1,128 @@
+# Adding comment trying to trigger a build
+#------------------------------------------------------------------------------- ----------
+#Key=Disposition:Category:Severity:Error Code:HTTP ResponseCode:RESTError Code:Error Message
+#------------------------------------------------------------------------------- ----------
+# testing code, please don't change unless error utility source code changes
+AAI_TESTING=5:2:WARN:0000:400:0001:Error code for testing
+
+# General success
+AAI_0000=0:0:INFO:0000:200:0000:Success
+
+# health check success
+AAI_0001=0:0:INFO:0001:200:0001:Success X-FromAppId=%1 X-TransactionId=%2
+AAI_0002=0:0:INFO:0002:200:0001:Successful health check
+
+# Success with additional info
+AAI_0003=0:3:INFO:0003:202:0003:Success with additional info performing %1 on %2. Added %3 with key %4
+AAI_0004=0:3:INFO:0004:202:0003:Added prerequisite object to db
+
+#--- aairest: 3000-3299
+# svc errors
+AAI_3000=5:2:INFO:3000:400:3000:Invalid input performing %1 on %2
+AAI_3001=5:6:INFO:3001:404:3001:Resource not found for %1 using id %2
+AAI_3002=5:1:WARN:3002:400:3002:Error writing output performing %1 on %2
+AAI_3003=5:1:WARN:3003:400:3003:Failed to make edge to missing target node of type %3 with keys %4 performing %1 on %2
+AAI_3005=5:6:WARN:3005:404:3001:Node cannot be directly accessed for read, must be accessed via ancestor(s)
+AAI_3006=5:6:WARN:3006:404:3001:Node cannot be directly accessed for write, must be accessed via ancestor(s)
+AAI_3007=5:6:INFO:3007:410:3007:This version (%1) of the API is retired, please migrate to %2
+AAI_3008=5:6:ERROR:3008:400:3008:URI is not encoded in UTF-8
+AAI_3009=5:6:ERROR:3009:400:3002:Malformed URL
+# pol errors
+AAI_3100=5:1:WARN:3100:400:3100:Unsupported operation %1
+AAI_3101=5:1:WARN:3101:403:3101:Attempt by client %1 to execute API %2
+AAI_3102=5:1:WARN:3102:400:3102:Error parsing input performing %1 on %2
+AAI_3300=5:1:WARN:3300:403:3300:Unauthorized
+AAI_3301=5:1:WARN:3301:401:3301:Stale credentials
+AAI_3302=5:1:WARN:3302:401:3301:Not authenticated
+
+#--- aaigen: 4000-4099
+AAI_4000=5:4:ERROR:4000:500:3002:Internal Error
+AAI_4001=5:4:FATAL:4001:500:3002:Configuration file not found
+AAI_4002=5:4:FATAL:4002:500:3002:Error reading Configuration file
+AAI_4003=5:4:ERROR:4003:500:3002:Error writing to log file
+AAI_4004=5:4:FATAL:4004:500:3002:Error reading/parsing the error properties file
+AAI_4005=5:4:FATAL:4005:500:3002:Missing or invalid configuration parameter
+AAI_4006=5:4:FATAL:4006:500:3002:Unexpected error in service
+AAI_4007=5:4:ERROR:4007:500:3102:Input parsing error
+AAI_4008=5:4:ERROR:4008:500:3002:Output parsing error
+AAI_4009=4:0:ERROR:4009:400:3000:Invalid X-FromAppId in header
+AAI_4010=4:0:ERROR:4010:400:3000:Invalid X-TransactionId in header
+AAI_4011=5:4:ERROR:4011:500:3002:Missing data for REST error response
+AAI_4012=5:4:ERROR:4012:500:3002:Bad rule data in RestRules
+AAI_4013=5:4:ERROR:4013:500:3002:Error connecting to AAI REST API
+AAI_4014=4:0:ERROR:4014:400:3000:Invalid Accept header
+AAI_4015=4:0:ERROR:4015:400:3000:You must provide at least one indexed property
+AAI_4016=4:0:ERROR:4016:400:3000:The depth parameter must be a number or the string "all"
+AAI_4017=5:2:INFO:4017:400:3000:Could not set property
+#--- aaidbmap: 5101-5199
+AAI_5101=5:4:FATAL:5101:500:3002:Could not connect to database
+AAI_5102=5:4:FATAL:5102:500:3002:Graph database is null after open
+AAI_5103=5:4:ERROR:5103:500:3002:Unexpected error during commit
+AAI_5104=5:4:ERROR:5104:500:3002:Unexpected error during rollback
+AAI_5105=5:4:ERROR:5105:500:3002:Unexpected error reading/updating database
+AAI_5106=5:4:WARN:5106:404:3001:Node not found
+AAI_5107=5:2:WARN:5107:400:3000:Required information missing
+AAI_5108=5:2:WARN:5108:200:0:Unexpected information in request being ignored
+
+#--- aaidbgen: 6101-6199
+AAI_6101=5:4:ERROR:6101:500:3002:null TitanGraph object passed
+AAI_6102=5:4:WARN:6102:400:3000:Passed-in property is not valid for this nodeType
+AAI_6103=5:4:WARN:6103:400:3000:Required Node-property not found in input data
+AAI_6104=5:4:WARN:6104:400:3000:Required Node-property was passed with no data
+AAI_6105=5:4:WARN:6105:400:3000:Node-Key-Property not defined in DbMaps
+AAI_6106=5:4:WARN:6106:400:3000:Passed-in property is not valid for this edgeType
+AAI_6107=5:4:WARN:6107:400:3000:Required Edge-property not found in input data
+AAI_6108=5:4:WARN:6108:400:3000:Required Edge-property was passed with no data
+AAI_6109=5:4:WARN:6109:400:3000:Bad dependent Node value
+AAI_6110=5:4:ERROR:6110:400:3100:Node cannot be deleted
+AAI_6111=5:4:ERROR:6111:400:3000:JSON processing error
+AAI_6112=5:4:ERROR:6112:400:3000:More than one node found by getUniqueNode()
+AAI_6114=5:4:INFO:6114:404:3001:Node Not Found
+AAI_6115=5:4:ERROR:6115:400:3000:Unrecognized NodeType
+AAI_6116=5:4:ERROR:6116:400:3000:Unrecognized Property
+AAI_6117=5:4:ERROR:6117:400:3000:Uniqueness constraint violated
+AAI_6118=5:4:ERROR:6118:400:3000:Required Field not passed.
+AAI_6120=5:4:ERROR:6120:400:3000:Bad Parameter Passed
+AAI_6121=5:4:ERROR:6121:400:3000:Problem with internal AAI reference data
+AAI_6122=5:4:ERROR:6122:400:3000:Data Set not complete in DB for this request
+AAI_6123=5:4:ERROR:6123:500:3000:Bad Data found by DataGrooming Tool - Investigate
+AAI_6124=5:4:ERROR:6124:500:3000:File read/write error
+AAI_6125=5:4:WARN:6125:500:3000:Problem Pulling Data Set
+AAI_6126=5:4:ERROR:6126:400:3000:Edge cannot be deleted
+AAI_6127=5:4:INFO:6127:404:3001:Edge Not Found
+AAI_6128=5:4:INFO:6128:500:3000:Unexpected error
+AAI_6129=5:4:INFO:6129:404:3003:Error making edge to target node
+AAI_6130=5:4:WARN:6130:412:3000:Precondition Required
+AAI_6131=5:4:WARN:6131:412:3000:Precondition Failed
+AAI_6132=5:4:WARN:6132:400:3000:Bad Model Definition
+AAI_6133=5:4:WARN:6133:400:3000:Bad Named Query Definition
+AAI_6134=5:4:ERROR:6134:413:6134:Could not persist transaction to storage back end. Exhausted retry amount
+AAI_6135=5:4:WARN:6135:412:3000:Resource version specified on create
+AAI_6136=5:4:ERROR:6136:400:3000:Object cannot hold multiple items
+AAI_6137=5:4:ERROR:6137:400:3000:Cannot perform writes on multiple vertices
+AAI_6138=5:4:ERROR:6138:400:3000:Cannot delete multiple vertices
+AAI_6139=5:4:ERROR:6139:404:3000:Attempted to add edge to vertex that does not exist
+AAI_6140=5:4:ERROR:6140:400:3000:Edge multiplicity violated
+AAI_6141=5:4:WARN:6141:400:3000:Please Refine Query
+AAI_6142=5:4:INFO:6142:400:3000:Retrying transaction
+AAI_6143=5:4:INFO:6143:400:3000:Ghost vertex found
+AAI_6144=5:4:WARN:6144:400:3000:Cycle found in graph
+AAI_6145=5:4:ERROR:6145:400:3000:Cannot create a nested/containment edge via relationship
+
+#--- aai csvp: 7101-7199
+AAI_7115=5:4:ERROR:7115:500:3002:Unexpected error
+AAI_7116=5:4:ERROR:7116:500:3002:Request error
+AAI_7117=5:4:ERROR:7117:500:3002:Error in get http client object
+
+
+
+#--- NotificationEvent
+AAI_7350=5:4:ERROR:7305:500:3002:Notification event creation failed
+
+#--- aairestctlr: 7401-7499
+AAI_7401=5:4:ERROR:7401:500:3002:Error connecting to AAI REST API
+AAI_7402=5:4:ERROR:7402:500:3002:Unexpected error
+AAI_7403=5:4:WARN:7403:400:3001:Request error
+AAI_7404=5:4:INFO:7404:404:3001:Node not found
+
+
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/getres-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/getres-logback.xml
new file mode 100644
index 0000000..559db42
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/getres-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="getTool" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/getTool/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/getTool/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="getTooldebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/getTool/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/getTool/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="getToolmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/getTool/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/getTool/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="getTool"/>
+ <appender-ref ref="getTooldebug"/>
+ <appender-ref ref="getToolmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/logging.properties b/ajsc-aai/bundleconfig-local/etc/appprops/logging.properties
new file mode 100644
index 0000000..e029cc4
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/logging.properties
@@ -0,0 +1,128 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+
+.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# this is where we will limit logging on components
+org.apache.hadoop.level=WARNING
+org.apache.zookeeper.level=WARNING
+org.reflections.level=WARNING
+com.thinkaurelius.level=WARNING
+
+1catalina.org.apache.juli.FileHandler.level = FINE
+1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+1catalina.org.apache.juli.FileHandler.prefix = catalina.
+
+2localhost.org.apache.juli.FileHandler.level = FINE
+2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+2localhost.org.apache.juli.FileHandler.prefix = localhost.
+
+3manager.org.apache.juli.FileHandler.level = FINE
+3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+3manager.org.apache.juli.FileHandler.prefix = manager.
+
+4host-manager.org.apache.juli.FileHandler.level = FINE
+4host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+4host-manager.org.apache.juli.FileHandler.prefix = host-manager.
+
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
+
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler
+
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler
+
+# For example, set the org.apache.catalina.util.LifecycleBase logger to log
+# each component that extends LifecycleBase changing state:
+#org.apache.catalina.util.LifecycleBase.level = FINE
+
+# To see debug messages in TldLocationsCache, uncomment the following line:
+#org.apache.jasper.compiler.TldLocationsCache.level = FINE
+
+
+################################
+# OpenEJB/TomEE specific loggers
+################################
+#
+# ACTIVATE LEVEL/HANDLERS YOU WANT
+# IF YOU ACTIVATE 5tomee.org.apache.juli.FileHandler
+# ADD IT TO handlers LINE LIKE:
+#
+# handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+#
+# LEVELS:
+# =======
+#
+# OpenEJB.level = WARNING
+# OpenEJB.options.level = INFO
+# OpenEJB.server.level = INFO
+# OpenEJB.startup.level = INFO
+# OpenEJB.startup.service.level = WARNING
+# OpenEJB.startup.config.level = INFO
+# OpenEJB.hsql.level = INFO
+# CORBA-Adapter.level = WARNING
+# Transaction.level = WARNING
+# org.apache.activemq.level = SEVERE
+# org.apache.geronimo.level = SEVERE
+# openjpa.level = WARNING
+# OpenEJB.cdi.level = INFO
+# org.apache.webbeans.level = INFO
+# org.apache.openejb.level = FINE
+#
+# HANDLERS:
+# =========
+#
+# OpenEJB.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.options.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.server.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.startup.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.startup.service.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.startup.config.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.hsql.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# CORBA-Adapter.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# Transaction.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# org.apache.activemq.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# org.apache.geronimo.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# openjpa.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# OpenEJB.cdi.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# org.apache.webbeans.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+# org.apache.openejb.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+#
+# TOMEE HANDLER SAMPLE:
+# =====================
+#
+# 5tomee.org.apache.juli.FileHandler.level = FINEST
+# 5tomee.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+# 5tomee.org.apache.juli.FileHandler.prefix = tomee.
+
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/methodMapper.properties b/ajsc-aai/bundleconfig-local/etc/appprops/methodMapper.properties
new file mode 100644
index 0000000..0708c3a
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/methodMapper.properties
@@ -0,0 +1,2 @@
+{"ActiveAndAvailableInventory-CloudNetwork": [
+]} \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/posttool-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/posttool-logback.xml
new file mode 100644
index 0000000..53b94b8
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/posttool-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="postTool" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/postTool/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/postTool/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="postTooldebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/postTool/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/postTool/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="postToolmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/postTool/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/postTool/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="postTool"/>
+ <appender-ref ref="postTooldebug"/>
+ <appender-ref ref="postToolmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/preferredRoute.txt b/ajsc-aai/bundleconfig-local/etc/appprops/preferredRoute.txt
new file mode 100644
index 0000000..662b0aa
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/preferredRoute.txt
@@ -0,0 +1 @@
+preferredRouteKey=MR1 \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/puttool-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/puttool-logback.xml
new file mode 100644
index 0000000..e0b69a3
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/puttool-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="putTool" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/putTool/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/putTool/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="putTooldebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/putTool/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/putTool/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="putToolmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/putTool/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/putTool/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="putTool"/>
+ <appender-ref ref="putTooldebug"/>
+ <appender-ref ref="putToolmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/rshiptool-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/rshiptool-logback.xml
new file mode 100644
index 0000000..03328eb
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/rshiptool-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="rshipTool" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/rshipTool/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rshipTool/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="rshipTooldebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/rshipTool/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rshipTool/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="rshipToolmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/rshipTool/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rshipTool/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="rshipTool"/>
+ <appender-ref ref="rshipTooldebug"/>
+ <appender-ref ref="rshipToolmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/schemaMod-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/schemaMod-logback.xml
new file mode 100644
index 0000000..5240ae6
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/schemaMod-logback.xml
@@ -0,0 +1,62 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="schemaModlog" class="ch.qos.logback.classic.sift.SiftingAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <!-- This is MDC value -->
+ <!-- We will assign a value to 'logFilenameAppender' via Java code -->
+ <discriminator>
+ <key>logFilenameAppender</key>
+ <defaultValue>undefined</defaultValue>
+ </discriminator>
+ <sift>
+ <!-- A standard RollingFileAppender, the log file is based on 'logFileName'
+ at runtime -->
+ <appender name="FILE-${logFilenameAppender}"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/schemaMod/${logFilenameAppender}.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/schemaMod/${logFilenameAppender}.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%m%n</pattern>
+ </encoder>
+ </appender>
+ </sift>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="org.apache.zookeeper" level="ERROR" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="org.apache.hadoop" level="ERROR" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="schemaModlog" />
+ </logger>
+
+
+ <root level="INFO">
+ <appender-ref ref="schemaModlog" />
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/uniquePropertyCheck-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/uniquePropertyCheck-logback.xml
new file mode 100644
index 0000000..78fa8c3
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/uniquePropertyCheck-logback.xml
@@ -0,0 +1,62 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="uniquePropertyChecklog" class="ch.qos.logback.classic.sift.SiftingAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <!-- This is MDC value -->
+ <!-- We will assign a value to 'logFilenameAppender' via Java code -->
+ <discriminator>
+ <key>logFilenameAppender</key>
+ <defaultValue>undefined</defaultValue>
+ </discriminator>
+ <sift>
+ <!-- A standard RollingFileAppender, the log file is based on 'logFileName'
+ at runtime -->
+ <appender name="FILE-${logFilenameAppender}"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/uniquePropertyCheck/${logFilenameAppender}.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/uniquePropertyCheck/${logFilenameAppender}.log.%d{yyyy-MM-dd}
+ </fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%m%n</pattern>
+ </encoder>
+ </appender>
+ </sift>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="org.apache.zookeeper" level="ERROR" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="org.apache.hadoop" level="ERROR" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </logger>
+
+
+ <root level="INFO">
+ <appender-ref ref="uniquePropertyChecklog" />
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/appprops/updtool-logback.xml b/ajsc-aai/bundleconfig-local/etc/appprops/updtool-logback.xml
new file mode 100644
index 0000000..ee8288e
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/appprops/updtool-logback.xml
@@ -0,0 +1,93 @@
+<configuration>
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <appender name="updTool" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ </filter>
+ <File>${logDirectory}/updTool/error.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/updTool/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="updTooldebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/updTool/debug.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/updTool/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="updToolmetric" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <File>${logDirectory}/updTool/metrics.log</File>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/updTool/metrics.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.reflections" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="org.apache.zookeeper" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="org.apache.hadoop" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="com.thinkaurelius" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.classic" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="ch.qos.logback.core" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="com.att.eelf" level="WARN" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+ <logger name="org.openecomp.aai" level="INFO" additivity="false">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </logger>
+
+ <root level="INFO">
+ <appender-ref ref="updTool"/>
+ <appender-ref ref="updTooldebug"/>
+ <appender-ref ref="updToolmetric"/>
+ </root>
+</configuration> \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/auth/aai_keystore b/ajsc-aai/bundleconfig-local/etc/auth/aai_keystore
new file mode 100644
index 0000000..3eef135
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/auth/aai_keystore
Binary files differ
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/addmanualdata/README b/ajsc-aai/bundleconfig-local/etc/scriptdata/addmanualdata/README
new file mode 100644
index 0000000..defac35
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/addmanualdata/README
@@ -0,0 +1,30 @@
+to add manual data, two files will be populated in the release directory under this folder.
+If the release directory does not exist, create it.
+
+The addManualData.sh script requires the release to be passed
+as a parameter. It finds and applies manual data changes under
+the release folder matching the parameter.
+
+This script is expected to be run for each installation. The script uses
+the PutTool, and flags the put to ignore 412 errors produced
+when the resource already exists.
+
+100-<file>.txt will contain the resource to be put.
+100-<file>.json will be the json file passed to the PutTool.
+
+
+bundleconfig/etc/scriptdata/addmanualdata/v8/<file>.txt
+bundleconfig/etc/scriptdata/addmanualdata/v8/<file>.json
+
+Example
+
+XYZ.txt
+business/customers/customer/21014aa2-526b-11e6-beb8-9e71128cae77/service-subscriptions/service-subscription/XYZ
+
+XYZ.json
+{
+ "service-type": "XYZ"
+}
+
+
+
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/closed-loop-named-query-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/closed-loop-named-query-1.0.json
new file mode 100644
index 0000000..c9b463e
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/closed-loop-named-query-1.0.json
@@ -0,0 +1,78 @@
+{
+ "named-query-uuid" : "4ff56a54-9e3f-46b7-a337-07a1d3c6b469",
+ "named-query-name" : "closed-loop-named-query",
+ "named-query-version" : "1.0",
+ "description" : "Named Query - For closed loop flow",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "2a160989-b202-47dd-874b-4a0f275998f7"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "abcc54bc-bb74-49dc-9043-7f7171707545"
+ } ]
+ } ]
+ }
+ }, {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "c00563ae-812b-4e62-8330-7c4d0f47088a"
+ } ]
+ } ]
+ }
+ }, {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "46b92144-923a-4d20-b85a-3cbd847668a9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "8ecb2c5d-7176-4317-a255-26274edfdd53"
+ } ]
+ } ]
+ }
+ } ]
+ }
+} \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json
new file mode 100644
index 0000000..db8d7a5
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json
@@ -0,0 +1,98 @@
+{
+ "named-query-uuid" : "ed0a0f5b-cf79-4784-88b2-911cd726cd3d",
+ "named-query-name" : "get-component-list",
+ "named-query-version" : "1.0",
+ "description" : "Named Query - Get Component List",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "9111f20f-e680-4001-b83f-19a2fc23bfc1"
+ } ]
+ } ]
+ }
+ }, {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "99d44c90-1f61-4418-b9a6-56586bf38c79"
+ } ]
+ } ]
+ }
+ }, {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "9111f20f-e680-4001-b83f-19a2fc23bfc1"
+ } ]
+ } ]
+ }
+ }, {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "8ecb2c5d-7176-4317-a255-26274edfdd53"
+ } ]
+ } ]
+ }
+ }, {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "99d44c90-1f61-4418-b9a6-56586bf38c79"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "c00563ae-812b-4e62-8330-7c4d0f47088a"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "46b92144-923a-4d20-b85a-3cbd847668a9"
+ } ]
+ } ]
+ }
+ } ]
+ }
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceModel-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceModel-1.0.json
new file mode 100644
index 0000000..aaee8d9
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceModel-1.0.json
@@ -0,0 +1,72 @@
+{
+ "named-query-uuid" : "3fb4d3d3-36c1-4162-9fe9-3e2c68a9da81",
+ "named-query-name" : "getServiceInstanceModel-1.0",
+ "named-query-version" : "1.0",
+ "description" : "Named query - Get service instance model",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "related-lookups" : {
+ "related-lookup" : [ {
+ "source-node-type" : "vf-module",
+ "source-node-property" : "persona-model-id",
+ "target-node-type" : "model",
+ "target-node-property" : "model-id",
+ "property-collect-list" : [ "model-name-version-id", "model-type", "model-name", "model-id", "model-version" ]
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "c00563ae-812b-4e62-8330-7c4d0f47088a"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "related-lookups" : {
+ "related-lookup" : [ {
+ "source-node-type" : "generic-vnf",
+ "source-node-property" : "persona-model-id",
+ "target-node-type" : "model",
+ "target-node-property" : "model-id",
+ "property-collect-list" : [ "model-name-version-id", "model-type", "model-name", "model-id", "model-version" ]
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "related-lookups" : {
+ "related-lookup" : [ {
+ "source-node-type" : "service-instance",
+ "source-node-property" : "persona-model-id",
+ "target-node-type" : "model",
+ "target-node-property" : "model-id",
+ "property-collect-list" : [ "model-name-version-id", "model-type", "model-name", "model-id", "model-version" ]
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "46b92144-923a-4d20-b85a-3cbd847668a9"
+ } ]
+ } ]
+ }
+ } ]
+ }
+} \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json
new file mode 100644
index 0000000..b013388
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json
@@ -0,0 +1,126 @@
+{
+ "named-query-uuid" : "5aaae840-ca96-4e5f-9308-58883564a80f",
+ "named-query-name" : "get-service-instance-summary",
+ "named-query-version" : "1.0",
+ "description" : "Named Query - Get Service Instance Summary",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "property-collect-list" : [ "service-instance-id", "service-instance-name", "operational-status" ],
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "do-not-output" : "true",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "property-collect-list" : [ "cloud-region-id" ],
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "2a160989-b202-47dd-874b-4a0f275998f7"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "9111f20f-e680-4001-b83f-19a2fc23bfc1"
+ } ]
+ } ]
+ }
+ }, {
+ "property-collect-list" : [ "service-type" ],
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "property-collect-list" : [ "global-customer-id", "subscriber-name" ],
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "d4df5c27-98a1-4812-a8aa-c17f055b7a3f"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "5e68299a-79f2-4bfb-8fbc-2bae877a2459"
+ } ]
+ } ]
+ }
+ }, {
+ "do-not-output" : "true",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "do-not-output" : "true",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "do-not-output" : "true",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "property-collect-list" : [ "cloud-region-id" ],
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "2a160989-b202-47dd-874b-4a0f275998f7"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "abcc54bc-bb74-49dc-9043-7f7171707545"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "8ecb2c5d-7176-4317-a255-26274edfdd53"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "46b92144-923a-4d20-b85a-3cbd847668a9"
+ } ]
+ } ]
+ }
+ } ]
+ }
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getVserver-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getVserver-1.0.json
new file mode 100644
index 0000000..624a4ec
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/named-query-json/getVserver-1.0.json
@@ -0,0 +1,105 @@
+{
+ "named-query-uuid" : "f199cb88-5e69-4b1f-93e0-6f257877d066",
+ "named-query-name" : "getVserver-1.0",
+ "named-query-version" : "1.0",
+ "description" : "Named query - Get vserver",
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "2a160989-b202-47dd-874b-4a0f275998f7"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "abcc54bc-bb74-49dc-9043-7f7171707545"
+ } ]
+ } ]
+ }
+ }, {
+ "named-query-elements" : {
+ "named-query-element" : [ {
+ "related-lookups" : {
+ "related-lookup" : [ {
+ "source-node-type" : "vf-module",
+ "source-node-property" : "persona-model-id",
+ "target-node-type" : "model",
+ "target-node-property" : "model-id",
+ "property-collect-list" : [ "model-name-version-id", "model-type", "model-name", "model-id", "model-version" ]
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "c00563ae-812b-4e62-8330-7c4d0f47088a"
+ } ]
+ } ]
+ }
+ }, {
+ "related-lookups" : {
+ "related-lookup" : [ {
+ "source-node-type" : "service-instance",
+ "source-node-property" : "persona-model-id",
+ "target-node-type" : "model",
+ "target-node-property" : "model-id",
+ "property-collect-list" : [ "model-name-version-id", "model-type", "model-name", "model-id", "model-version" ]
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "46b92144-923a-4d20-b85a-3cbd847668a9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "related-lookups" : {
+ "related-lookup" : [ {
+ "source-node-type" : "generic-vnf",
+ "source-node-property" : "persona-model-id",
+ "target-node-type" : "model",
+ "target-node-property" : "model-id",
+ "property-collect-list" : [ "model-name-version-id", "model-type", "model-name", "model-id", "model-version" ]
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9"
+ } ]
+ } ]
+ }
+ } ]
+ },
+ "relationship-list" : {
+ "relationship" : [ {
+ "related-to" : "model",
+ "relationship-data" : [ {
+ "relationship-key" : "model.model-name-version-id",
+ "relationship-value" : "8ecb2c5d-7176-4317-a255-26274edfdd53"
+ } ]
+ } ]
+ }
+ } ]
+ }
+} \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/resource-model-json/000-README b/ajsc-aai/bundleconfig-local/etc/scriptdata/resource-model-json/000-README
new file mode 100644
index 0000000..9647972
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/resource-model-json/000-README
@@ -0,0 +1,10 @@
+Add resource models here in the order you want them to be added to the graph.
+
+Recommended that they are spaced by 10's.
+
+So, if you are adding a resource model it should be:
+
+100-ipe-resource-model-1.0.json
+110-vBgf-resource-model-1.0.json
+
+This will allow others to insert models between existing models. \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/schemamods/README b/ajsc-aai/bundleconfig-local/etc/scriptdata/schemamods/README
new file mode 100644
index 0000000..84196db
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/schemamods/README
@@ -0,0 +1,18 @@
+And to add a schemamod for a release, a file containing one or more schemaMod parameter lines is created.
+If the directory for that release does not exist, add it
+
+The doSchemaMods.sh script requires the release to be passed
+as a parameter. It finds and applies schemamods under
+the release folder matching the parameter.
+
+This script is expected to be run for each installation.
+
+e.g.
+
+bundleconfig/etc/scriptdata/schemamods/v8/100-subscriber-name.txt
+
+and
+
+100-subscriber-name.txt will have
+
+subscriber-name String index true
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/service-model-json/000-README b/ajsc-aai/bundleconfig-local/etc/scriptdata/service-model-json/000-README
new file mode 100644
index 0000000..bb30e02
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/service-model-json/000-README
@@ -0,0 +1,10 @@
+Add service models here in the order you want them to be added to the graph.
+
+Recommended that they are spaced by 10's.
+
+So, if you are adding a resource model it should be:
+
+100-connector-service-model-1.0.json
+110-service-instance-service-model-1.0.json
+
+This will allow others to insert models between existing models. \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json
new file mode 100644
index 0000000..db4e5a9
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "6c092fb1-21b2-456b-9e01-67fb4de1896e",
+ "model-type" : "widget",
+ "model-name" : "availability-zone",
+ "model-id" : "61b88c01-d819-41c0-8e21-7fd7ba47148e",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json
new file mode 100644
index 0000000..f19699c
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "2a160989-b202-47dd-874b-4a0f275998f7",
+ "model-type" : "widget",
+ "model-name" : "cloud-region",
+ "model-id" : "425b2158-e51d-4509-9945-dad4556474a3",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json
new file mode 100644
index 0000000..1d12013
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "44e5cb1f-0938-41aa-b766-d4595109fe89",
+ "model-type" : "widget",
+ "model-name" : "ctag-assignment",
+ "model-id" : "fcb8d46b-b656-4ad6-8fa4-22cef74b443f",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json
new file mode 100644
index 0000000..be56c01
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "d4df5c27-98a1-4812-a8aa-c17f055b7a3f",
+ "model-type" : "widget",
+ "model-name" : "customer",
+ "model-id" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json
new file mode 100644
index 0000000..1559e65
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "36200fb5-f251-4f5d-a520-7c5ad5c2cd4b",
+ "model-type" : "widget",
+ "model-name" : "flavor",
+ "model-id" : "bace8d1c-a261-4041-9e37-823117415d0f",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json
new file mode 100644
index 0000000..7a8bcb3
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9",
+ "model-type" : "widget",
+ "model-name" : "generic-vnf",
+ "model-id" : "acc6edd8-a8d4-4b93-afaa-0994068be14c",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json
new file mode 100644
index 0000000..f0a6b25
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "fe578080-ce19-4604-8760-fc264fbb2565",
+ "model-type" : "widget",
+ "model-name" : "group-assignment",
+ "model-id" : "7cc05f25-7ba2-42b7-a237-c5662a1689e1",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json
new file mode 100644
index 0000000..31a04a0
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "f6a038c2-820c-42ba-8c2b-375e24e8f932",
+ "model-type" : "widget",
+ "model-name" : "image",
+ "model-id" : "3f4c7204-739b-4bbb-87a7-8a6856439c90",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json
new file mode 100644
index 0000000..4660e5a
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "a32613fd-18b9-459e-aab8-fffb3912966a",
+ "model-type" : "widget",
+ "model-name" : "l-interface",
+ "model-id" : "cea0a982-8d55-4093-921e-418fbccf7060",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json
new file mode 100644
index 0000000..660e9a0
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "41e76b6f-1e06-4fd4-82cd-81c50fc4574b",
+ "model-type" : "widget",
+ "model-name" : "l3-interface-ipv4-address-list",
+ "model-id" : "aad85df2-09be-40fa-b867-16415e4e10e2",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json
new file mode 100644
index 0000000..d84a247
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "d040621d-541a-477b-bb1b-a2b61b14e295",
+ "model-type" : "widget",
+ "model-name" : "l3-interface-ipv6-address-list",
+ "model-id" : "82966045-43ee-4982-8307-7e9610866140",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json
new file mode 100644
index 0000000..bbcbcd2
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "9111f20f-e680-4001-b83f-19a2fc23bfc1",
+ "model-type" : "widget",
+ "model-name" : "l3-network",
+ "model-id" : "3d560d81-57d0-438b-a2a1-5334dba0651a",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json
new file mode 100644
index 0000000..938ddd6
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "ce95f7c3-b61b-4758-ae9e-7e943b1c103d",
+ "model-type" : "widget",
+ "model-name" : "lag-interface",
+ "model-id" : "e0ee9bde-c1fc-4651-a95d-8e0597bf7d70",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json
new file mode 100644
index 0000000..f2e9bca
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "a1481a38-f8ba-4ae4-bdf1-06c2c6af4c54",
+ "model-type" : "widget",
+ "model-name" : "logical-link",
+ "model-id" : "fe012535-2c31-4a39-a739-612374c638a0",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json
new file mode 100644
index 0000000..a630880
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "d2cdb2d0-fc1f-4a57-a89e-591b1c4e3754",
+ "model-type" : "widget",
+ "model-name" : "p-interface",
+ "model-id" : "94043c37-4e73-439c-a790-0fdd697924cd",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json
new file mode 100644
index 0000000..54cc74b
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "9c523936-95b4-4d7f-9f53-6bdfe0cf2c05",
+ "model-type" : "widget",
+ "model-name" : "physical-link",
+ "model-id" : "c822d81f-822f-4304-9623-1025b53da568",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json
new file mode 100644
index 0000000..f6b0b92
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "e9f1fa7d-c839-418a-9601-03dc0d2ad687",
+ "model-type" : "widget",
+ "model-name" : "pnf",
+ "model-id" : "862b25a1-262a-4961-bdaa-cdc55d69785a",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json
new file mode 100644
index 0000000..6175213
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "72f0d495-bc27-4653-9e1a-eef76bd34bc9",
+ "model-type" : "widget",
+ "model-name" : "pserver",
+ "model-id" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json
new file mode 100644
index 0000000..f9537a6
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "c5171ae0-44fb-4c04-b482-d56702241a44",
+ "model-type" : "widget",
+ "model-name" : "segmentation-assignment",
+ "model-id" : "6e814aee-46e1-4583-a9d4-0049bfd2b59b",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json
new file mode 100644
index 0000000..a3b9f53
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "46b92144-923a-4d20-b85a-3cbd847668a9",
+ "model-type" : "widget",
+ "model-name" : "service-instance",
+ "model-id" : "82194af1-3c2c-485a-8f44-420e22a9eaa4",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json
new file mode 100644
index 0000000..6019b83
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "5e68299a-79f2-4bfb-8fbc-2bae877a2459",
+ "model-type" : "widget",
+ "model-name" : "service-subscription",
+ "model-id" : "2e1a602a-acd8-4f78-94ff-618b802a303b",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json
new file mode 100644
index 0000000..d5a4d7e
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "962a7c8b-687f-4d32-a775-fe098e214bcd",
+ "model-type" : "widget",
+ "model-name" : "snapshot",
+ "model-id" : "24de00ef-aead-4b52-995b-0adf8d4bd90d",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json
new file mode 100644
index 0000000..935d2cc
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "f902a6bc-6be4-4fe5-8458-a6ec0056b374",
+ "model-type" : "widget",
+ "model-name" : "subnet",
+ "model-id" : "1b2c9ba7-e449-4831-ba15-3073672f5ef2",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json
new file mode 100644
index 0000000..3518f9d
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "abcc54bc-bb74-49dc-9043-7f7171707545",
+ "model-type" : "widget",
+ "model-name" : "tenant",
+ "model-id" : "97c26c99-6870-44c1-8a07-1d900d3f4ce6",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json
new file mode 100644
index 0000000..cb29f36
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "c00563ae-812b-4e62-8330-7c4d0f47088a",
+ "model-type" : "widget",
+ "model-name" : "vf-module",
+ "model-id" : "ef86f9c5-2165-44f3-8fc3-96018b609ea5",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json
new file mode 100644
index 0000000..0426c6b
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "257d88a5-a269-4c35-944f-aca04fbdb791",
+ "model-type" : "widget",
+ "model-name" : "vlan",
+ "model-id" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json
new file mode 100644
index 0000000..df9ee2f
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "5761e0a7-c6df-4d8a-9ebd-b8f445054dec",
+ "model-type" : "widget",
+ "model-name" : "vnfc",
+ "model-id" : "96129eb9-f0de-4e05-8af2-73146473f766",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json
new file mode 100644
index 0000000..a461a1c
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "0fbe2e8f-4d91-4415-a772-88387049b38d",
+ "model-type" : "widget",
+ "model-name" : "volume",
+ "model-id" : "ddd739b4-2b25-46c4-affc-41a32af5cc42",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json
new file mode 100644
index 0000000..4680c14
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "99d44c90-1f61-4418-b9a6-56586bf38c79",
+ "model-type" : "widget",
+ "model-name" : "volume-group",
+ "model-id" : "fcec1b02-b2d0-4834-aef8-d71be04717dd",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json
new file mode 100644
index 0000000..8981b5e
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json
@@ -0,0 +1,7 @@
+{
+ "model-name-version-id" : "8ecb2c5d-7176-4317-a255-26274edfdd53",
+ "model-type" : "widget",
+ "model-name" : "vserver",
+ "model-id" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7",
+ "model-version" : "1.0"
+}
diff --git a/ajsc-aai/bundleconfig-local/etc/sysprops/sys-props.properties b/ajsc-aai/bundleconfig-local/etc/sysprops/sys-props.properties
new file mode 100644
index 0000000..37ec126
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/sysprops/sys-props.properties
@@ -0,0 +1,112 @@
+#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
+
+#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
+
+# 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=<Your network IP address>
+
+#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
+
+#Enable/disable endpoint level logging (values=true/false). This can be disabled during local development
+endpointLogging=false
+
+#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=10
+AJSC_JETTY_ThreadCount_MAX=500
+AJSC_JETTY_IDLETIME_MAX=60000
+AJSC_JETTY_BLOCKING_QUEUE_SIZE=100
+
+#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
+
+#File Monitor configurations
+ssf_filemonitor_polling_interval=5
+ssf_filemonitor_threadpool_size=10
+
+#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:1vn21ugu1saj1v9i1v941sar1ugw1vo0
+KEY_MANAGER_PASSWORD=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
diff --git a/ajsc-aai/bundleconfig-local/etc/sysprops/template.sys-props.properties b/ajsc-aai/bundleconfig-local/etc/sysprops/template.sys-props.properties
new file mode 100644
index 0000000..b760b64
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/etc/sysprops/template.sys-props.properties
@@ -0,0 +1,92 @@
+#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. Upon SOA cloud install, all of the "double underscore" variables will be replaced by SWM node variables.
+
+#For Cadi Authorization, use value="authentication-scheme-1"
+CadiAuthN=__AJSC_CADI_AUTHN__
+
+#For Basic Authorization, use value="authentication-scheme-1"
+authN=__AJSC_AUTH_SCHEME__
+
+#Persistence used for AJSC meta-data storage. For most environments, "file" should be used.
+ajscPersistence=__AJSC_PERSISTENCE__
+
+#Configure externalized logback location
+logback.configurationFile=__LOGBACK_CONFIG_FILE__
+
+# If using hawtio for local development, these properties will allow for faster server startup and usage for local development.
+# You may wish to deploy hawtio.war to dev/test environments to help debugging as well, but should not be used in PROD env.
+hawtio.authenticationEnabled=__HAWTIO_AUTHENTICATION_ENABLED__
+hawtio.config.pullOnStartup=__HAWTIO_CONFIG_PULLONSTARTUP__
+
+#Removes the extraneous restlet console output
+org.restlet.engine.loggerFacadeClass=org.restlet.ext.slf4j.Slf4jLoggerFacade
+
+#Enable/disable SSL (values=true/false).
+enableSSL=__AJSC_ENABLE_SSL__
+
+#Enable/disable EJB Container
+ENABLE_EJB=__ENABLE_EJB__
+
+#Enable/disable OSGI
+isOSGIEnable=__OSGI_ENABLE__
+
+#Enable/disable endpoint level logging (values=true/false).
+endpointLogging=__END_POINT_LEVEL_LOGGING__
+
+#SOA_CLOUD_ENV is used to register your service with dme2 (values=true/false).
+SOA_CLOUD_ENV=__SOA_CLOUD_ENV__
+
+#Jetty Container ThreadCount Configuration Variables
+AJSC_JETTY_ThreadCount_MAX=__AJSC_JETTY_ThreadCount_MAX__
+AJSC_JETTY_ThreadCount_MIN=__AJSC_JETTY_ThreadCount_MIN__
+AJSC_JETTY_IDLETIME_MAX=__AJSC_JETTY_IDLETIME_MAX__
+AJSC_SERVICE_NAMESPACE=__AJSC_SERVICE_NAMESPACE__
+AJSC_SERVICE_VERSION=__AJSC_SERVICE_VERSION__
+AJSC_JETTY_BLOCKING_QUEUE_SIZE=100
+
+#Camel Context level default threadPool Profile configuration
+CAMEL_POOL_SIZE=__CAMEL_POOL_SIZE__
+CAMEL_MAX_POOL_SIZE=__CAMEL_MAX_POOL_SIZE__
+CAMEL_KEEP_ALIVE_TIME=__CAMEL_KEEP_ALIVE_TIME__
+CAMEL_MAX_QUEUE_SIZE=__CAMEL_MAX_QUEUE_SIZE__
+
+#File Monitor configurations
+ssf_filemonitor_polling_interval=__AJSC_SSF_FILE_MONITOR_POLLING_INTERVAL__
+ssf_filemonitor_threadpool_size=__AJSC_SSF_FILE_MONITOR_THREAD_POOL_SIZE__
+
+#GRM/DME2 System Properties below
+AFT_DME2_CONN_IDLE_TIMEOUTMS=__AFT_DME2_CONN_IDLE_TIMEOUTMS__
+AJSC_ENV=__AJSC_ENV__
+SOACLOUD_NAMESPACE=__SOA_CLOUD_NAMESPACE__
+SOACLOUD_ENV_CONTEXT=__SCLD_ENV__
+SOACLOUD_PROTOCOL=__SOACLOUD_PROTOCOL__
+SOACLOUD_ROUTE_OFFER=__AAIENV__
+sslport=__AJSC_SSL_PORT__
+server.port=__AJSC_SVC_PORT__
+AFT_LATITUDE=__LATITUDE__
+AFT_LONGITUDE=__LONGITUDE__
+AFT_ENVIRONMENT=__AFT_ENVIRONMENT__
+
+#Restlet Component Properties
+RESTLET_COMPONENT_CONTROLLER_DAEMON=__RESTLET_COMPONENT_CONTROLLER_DAEMON__
+RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS=__RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS__
+RESTLET_COMPONENT_INBOUND_BUFFER_SIZE=__RESTLET_COMPONENT_INBOUND_BUFFER_SIZE__
+RESTLET_COMPONENT_MIN_THREADS=__RESTLET_COMPONENT_MIN_THREADS__
+RESTLET_COMPONENT_MAX_THREADS=__RESTLET_COMPONENT_MAX_THREADS__
+RESTLET_COMPONENT_LOW_THREADS=__RESTLET_COMPONENT_LOW_THREADS__
+RESTLET_COMPONENT_MAX_QUEUED=__RESTLET_COMPONENT_MAX_QUEUED__
+RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST=__RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST__
+RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS=__RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS__
+RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE=__RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE__
+RESTLET_COMPONENT_PERSISTING_CONNECTIONS=__RESTLET_COMPONENT_PERSISTING_CONNECTIONS__
+RESTLET_COMPONENT_PIPELINING_CONNECTIONS=__RESTLET_COMPONENT_PIPELINING_CONNECTIONS__
+RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS=__RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS__
+RESTLET_COMPONENT_USE_FORWARDED_HEADER=__RESTLET_COMPONENT_USE_FORWARDED_HEADER__
+RESTLET_COMPONENT_REUSE_ADDRESS=__RESTLET_COMPONENT_REUSE_ADDRESS__
+
+AJSC_EXTERNAL_LIB_FOLDERS=__CSM_LIB__|__DME2_LIB__|__AJSC_EXTERNAL_LIB_FOLDERS__
+AJSC_EXTERNAL_PROPERTIES_FOLDERS=__AJSC_SHARED_CONFIG__|__AJSC_EXTERNAL_PROPERTIES_FOLDERS__
+
+KEY_STORE_PASSWORD=__KEY_STORE_PASSWORD__
+KEY_MANAGER_PASSWORD=__KEY_MANAGER_PASSWORD__ \ No newline at end of file
diff --git a/ajsc-aai/bundleconfig-local/swm-var-ajsc.txt b/ajsc-aai/bundleconfig-local/swm-var-ajsc.txt
new file mode 100644
index 0000000..9d4464e
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/swm-var-ajsc.txt
@@ -0,0 +1,3 @@
+#This file is for SWM node variable default replacement. SWM node variables will already exist on CSI nodes. This file is used
+#for dev teams to override the default SWM node variables. The examples given are meant to be just that: EXAMPLES. Please,
+#REMOVE/DELETE/ADD/MODIFY these values for YOUR SWM package based on the needs of your project.
diff --git a/ajsc-aai/bundleconfig-local/symlinks.txt b/ajsc-aai/bundleconfig-local/symlinks.txt
new file mode 100644
index 0000000..70f2c0d
--- /dev/null
+++ b/ajsc-aai/bundleconfig-local/symlinks.txt
@@ -0,0 +1,6 @@
+#This file provides the definitions of sym-links to CSTEM that will be used by your project once installed on a CSI node.
+
+link_jre=ajsc-shared-config
+link_csi-csm=ajsc-shared-config
+link_csi-dme=ajsc-shared-config
+link_introscope=ajsc-shared-config
diff --git a/ajsc-aai/pom.xml b/ajsc-aai/pom.xml
new file mode 100644
index 0000000..950ce05
--- /dev/null
+++ b/ajsc-aai/pom.xml
@@ -0,0 +1,625 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>aai-service</artifactId>
+ <version>${openecomp.release}</version>
+ </parent>
+ <artifactId>ajsc-aai</artifactId>
+ <name>ajsc</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <dockerLocation>${basedir}/target/swm/package/nix/dist_files/</dockerLocation>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <docker.login></docker.login>
+ <docker.password></docker.password>
+ <docker.registry>${docker_registry}</docker.registry>
+ </properties>
+ <dependencies>
+ <!-- AJSC related dependencies -->
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-core</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- For dom4j dependency ONLY! - If deploying to CSI env, remove "provided"
+ scope. In CSI env, this jar MUST be included within service project's swm
+ package -->
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+ <!-- eelf dependency -->
+<dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>0.0.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-maven-plugin</artifactId>
+ <version>0.0.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.1.7</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.1.7</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-access</artifactId>
+ <version>1.1.7</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.codehaus.janino</groupId>
+ <artifactId>janino</artifactId>
+ <version>2.7.8</version>
+ </dependency>
+
+
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>jdk.tools</groupId>
+ <artifactId>jdk.tools</artifactId>
+ <version>1.8.0_101</version>
+ <scope>system</scope>
+ <systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>16.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.thinkaurelius.titan</groupId>
+ <artifactId>titan-core</artifactId>
+ <version>1.0.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.thinkaurelius.titan</groupId>
+ <artifactId>titan-hbase</artifactId>
+ <version>1.0.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tinkerpop</groupId>
+ <artifactId>tinkerpop</artifactId>
+ <version>3.1.0-incubating</version>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-client</artifactId>
+ <version>1.0.2</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>log4j</artifactId>
+ <groupId>log4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-protocol</artifactId>
+ <version>1.0.2</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>log4j</artifactId>
+ <groupId>log4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-common</artifactId>
+ <version>1.0.2</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>log4j</artifactId>
+ <groupId>log4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-servlet</artifactId>
+ <version>3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <version>3.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-json</artifactId>
+ <version>1.18</version>
+ </dependency>
+ <dependency>
+ <groupId>jivesoftware</groupId>
+ <artifactId>smack</artifactId>
+ <version>3.0.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <version>2.1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.18</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>4.2.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws</artifactId>
+ <version>1.5.2</version>
+ <!--<version>2.1.3-RELEASE</version> -->
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>4.2.5.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.10.19</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.beust</groupId>
+ <artifactId>jcommander</artifactId>
+ <version>1.48</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ </dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>2.3.14</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-core</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-xjc</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>eclipselink</artifactId>
+ <version>2.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>org.eclipse.persistence.moxy</artifactId>
+ <version>2.6.2</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-javaagent</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule-agent</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.fge</groupId>
+ <artifactId>json-patch</artifactId>
+ <version>1.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.javatuples</groupId>
+ <artifactId>javatuples</artifactId>
+ <version>1.2</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.7</version>
+ </dependency>
+ <dependency>
+ <groupId>com.att.nsa</groupId>
+ <artifactId>dmaapClient</artifactId>
+ <version>0.2.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>activemq-broker</artifactId>
+ <version>5.12.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>annotations</artifactId>
+ <version>${openecomp.release}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>aai</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.7</version>
+ <executions>
+ <execution>
+ <id>copy-docker-file</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${dockerLocation}</outputDirectory>
+ <overwrite>true</overwrite>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/resources/docker</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy-commonlibs-file</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${dockerLocation}/commonLibs</outputDirectory>
+ <overwrite>true</overwrite>
+ <resources>
+ <resource>
+ <directory>${basedir}/target/commonLibs</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.spotify</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>0.4.11</version>
+ <configuration>
+ <verbose>true</verbose>
+ <registry>${docker.registry}</registry>
+ <authConfig>
+ <username>${docker.login}</username>
+ <password>${docker.password}</password>
+ </authConfig>
+ <imageName>${docker.registry}/${project.artifactId}</imageName>
+ <dockerDirectory>${dockerLocation}</dockerDirectory>
+ <serverId>docker-hub</serverId>
+ <registryUrl>http://${docker.registry}</registryUrl>
+ <imageTags>
+ <imageTag>${docker_imageversion}</imageTag>
+ <imageTag>latest</imageTag>
+ </imageTags>
+ <forceTags>true</forceTags>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <version>0.13.1</version>
+ <executions>
+ <execution>
+ <id>gen-xjc</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <extension>true</extension>
+ <args>
+ <arg>-Xannotate</arg>
+ </args>
+ <generateDirectory>target/generated-sources</generateDirectory>
+ <schemaDirectory>src/main/aai_schema</schemaDirectory>
+ <bindingDirectory>src/main/xjb</bindingDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-annotate</artifactId>
+ <version>1.0.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics</artifactId>
+ <version>1.11.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-runtime</artifactId>
+ <version>1.11.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-tools</artifactId>
+ <version>1.11.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>annotations</artifactId>
+ <version>${openecomp.release}</version>
+ </plugin>
+ </plugins>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jsonschema2pojo</groupId>
+ <artifactId>jsonschema2pojo-maven-plugin</artifactId>
+ <version>0.4.13</version>
+ <configuration>
+ <sourceType>jsonschema</sourceType>
+ <sourceDirectory>src/main/resources/json</sourceDirectory>
+ <outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
+ <annotationStyle>jackson2</annotationStyle>
+ <generateBuilders>true</generateBuilders>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <id>aai-custom-jar</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>org/openecomp/aai/util/**/*</include>
+ </includes>
+ <finalName>aai-custom</finalName>
+ </configuration>
+ </execution>
+ <execution>
+ <id>aai-logging-jar</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>org/openecomp/aai/logging/**/*</include>
+ </includes>
+ <finalName>aai-logging</finalName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.5.1</version>
+ <executions>
+ <execution>
+ <id>copy-agent</id>
+ <phase>process-test-classes</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-javaagent</artifactId>
+ <version>1.6.2</version>
+ <outputDirectory>${project.build.directory}/agents</outputDirectory>
+ <destFileName>powermock-javaagent.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-schema-dependency</id>
+ <phase>initialize</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>aai-schema</artifactId>
+ <version>${openecomp.release}</version>
+ <outputDirectory>bundleconfig-local/etc</outputDirectory>
+ <includes>oxm/*.xml</includes>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>aai-schema</artifactId>
+ <version>${openecomp.release}</version>
+ <outputDirectory>src/main</outputDirectory>
+ <includes>aai_schema/*.xsd</includes>
+ </artifactItem>
+ </artifactItems>
+ <!-- other configurations here -->
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.12.4</version>
+ <configuration>
+ <reuseForks>false</reuseForks>
+ <argLine>-javaagent:${project.build.directory}/agents/powermock-javaagent.jar
+ -noverify</argLine>
+ <systemPropertyVariables>
+ <AJSC_HOME>.</AJSC_HOME>
+ <BUNDLECONFIG_DIR>bundleconfig-local</BUNDLECONFIG_DIR>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <profiles>
+ <!-- Use this profile to run the AJSC locally. This profile can be successfully
+ shutdown WITHIN eclipse even in a Windows environment. Debugging is also
+ available with this profile. -->
+ <profile>
+ <id>passwordGenerator</id>
+ <build>
+ <defaultGoal>initialize</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <phase>initialize</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <mainClass>org.eclipse.jetty.util.security.Password</mainClass>
+ <arguments>
+ <argument>user</argument>
+ <argument>changeit</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>java</executable>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ </profiles>
+</project>
diff --git a/ajsc-aai/services/README.txt b/ajsc-aai/services/README.txt
new file mode 100644
index 0000000..c20898d
--- /dev/null
+++ b/ajsc-aai/services/README.txt
@@ -0,0 +1,8 @@
+Place any Deployment Packages (zips) in this folder to be deployed with your service.
+This can be used for importing older Nimbus deployment packages to the AJSC. Not all
+prior Nimbus services are available and therefore, not ALL former Nimbus deployment
+packages will convert directly to AJSC. However, for Service Development, you may create
+other Services (Deployment Packages) as separate services and test by themselves. Then,
+simply take the created zip (deployment package) of the service and place in THIS services folder for it
+to be deployed within this AJSC Container. This folder will be copied to the ultimate AJSC_HOME/services
+folder from which all services are deployed. \ No newline at end of file
diff --git a/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml
new file mode 100644
index 0000000..8b5c5c5
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+<!-- <bean
+ class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
+
+ <bean id="ServicePropertiesListener" class="org.openecomp.aai.ajsc_aai.filemonitor.ServicePropertiesListener" />
+
+ <bean id="ServicePropertiesMap" class="org.openecomp.aai.ajsc_aai.filemonitor.ServicePropertiesMap" />
+
+ <bean id="ServicePropertyService" class="org.openecomp.aai.ajsc_aai.filemonitor.ServicePropertyService">
+ <property name="loadOnStartup" value="false" />
+ <property name="fileChangedListener" ref="ServicePropertiesListener" />
+ <property name="filePropertiesMap" ref="ServicePropertiesMap" />
+ <property name="ssfFileMonitorPollingInterval" value="15" />
+ <property name="ssfFileMonitorThreadpoolSize" value="10" />
+ </bean> -->
+</beans>
diff --git a/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy
new file mode 100644
index 0000000..67ad894
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy
@@ -0,0 +1,36 @@
+beans{
+ xmlns cxf: "http://camel.apache.org/schema/cxf"
+ xmlns jaxrs: "http://cxf.apache.org/jaxrs"
+ xmlns util: "http://www.springframework.org/schema/util"
+
+ RestProviders(org.openecomp.aai.rest.RestProviders)
+ LegacyMoxyConsumer(org.openecomp.aai.rest.LegacyMoxyConsumer)
+ URLFromVertexIdConsumer(org.openecomp.aai.rest.URLFromVertexIdConsumer)
+ VertexIdConsumer(org.openecomp.aai.rest.VertexIdConsumer)
+ BulkAddConsumer(org.openecomp.aai.rest.BulkAddConsumer)
+ ExampleConsumer(org.openecomp.aai.rest.ExampleConsumer)
+ SearchProvider(org.openecomp.aai.rest.search.SearchProvider)
+ ModelAndNamedQueryRestProvider(org.openecomp.aai.rest.search.ModelAndNamedQueryRestProvider)
+ ActionsProvider(org.openecomp.aai.rest.actions.ActionsProvider)
+
+ TransLogRestProvider(org.openecomp.aai.rest.translog.TransLogRestProvider)
+ EchoResponse(org.openecomp.aai.rest.util.EchoResponse)
+
+
+ util.list(id: 'jaxrsServices') {
+
+ //ref(bean:'RestProviders')
+ ref(bean:'ExampleConsumer')
+ ref(bean:'LegacyMoxyConsumer')
+ ref(bean:'VertexIdConsumer')
+ ref(bean:'URLFromVertexIdConsumer')
+ ref(bean:'BulkAddConsumer')
+ ref(bean:'SearchProvider')
+ ref(bean:'ModelAndNamedQueryRestProvider')
+ ref(bean:'ActionsProvider')
+
+
+ ref(bean:'TransLogRestProvider')
+ ref(bean:'EchoResponse')
+ }
+} \ No newline at end of file
diff --git a/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml
new file mode 100644
index 0000000..6ce0d42
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:cxf="http://cxf.apache.org/core"
+ xmlns:jms="http://www.springframework.org/schema/jms"
+ xmlns:task="http://www.springframework.org/schema/task"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
+ http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
+ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
+
+ <!-- Your bean definitions goes here -->
+ <!-- <bean id="performanceLog" name="performanceLog" class="com.att.ajsc.csi.logging.PerformanceTracking"
+ /> -->
+ <!-- <bean id="processRestletHeaders" name="processRestletHeaders" class="ajsc.restlet.ProcessRestletHeaders"
+ /> -->
+ <bean id="servicePropsBean" name="servicePropsBean"
+ class="org.openecomp.aai.ajsc_aai.util.ServicePropertiesMapBean" />
+ <bean id="jsonProvider" class="org.openecomp.aai.rest.CustomJacksonJaxBJsonProvider" />
+
+ <bean id="inInterceptor" class="org.openecomp.aai.interceptors.AAILogJAXRSInInterceptor" />
+ <bean id="outInterceptor" class="org.openecomp.aai.interceptors.AAILogJAXRSOutInterceptor" />
+ <cxf:bus bus="cxfBus">
+ <cxf:inInterceptors>
+ <ref bean="inInterceptor" />
+ </cxf:inInterceptors>
+ <cxf:outInterceptors>
+ <ref bean="outInterceptor" />
+ </cxf:outInterceptors>
+ </cxf:bus>
+ <context:component-scan base-package="org.openecomp.aai.tasks" />
+
+ <task:scheduler id="taskScheduler" pool-size="10" />
+ <task:executor id="taskExecutor" pool-size="10"
+ queue-capacity="5" />
+ <task:annotation-driven executor="taskExecutor"
+ scheduler="taskScheduler" />
+
+<!-- <bean id="jmsProperties" -->
+<!-- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" -->
+<!-- name="jmsProperties"> -->
+<!-- <property name="order" value="99999" /> -->
+<!-- <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> -->
+<!-- <property name="ignoreUnresolvablePlaceholders" value="true" /> -->
+<!-- <property name="properties"> -->
+<!-- <value> -->
+
+<!-- JMS -->
+<!-- JMS.BROKER.URL=tcp://localhost:61616 -->
+<!-- JMS.QUEUE.NAME=IN_QUEUE -->
+
+<!-- </value> -->
+<!-- </property> -->
+<!-- </bean> -->
+
+ <!-- ActiveMQ connection factory -->
+<!-- <bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> -->
+<!-- <constructor-arg index="0" value="${JMS.BROKER.URL}" /> -->
+<!-- </bean> -->
+
+ <!-- ConnectionFactory Definition -->
+<!-- <bean id="connectionFactory" -->
+<!-- class="org.springframework.jms.connection.CachingConnectionFactory"> -->
+<!-- <constructor-arg ref="amqConnectionFactory" /> -->
+<!-- </bean> -->
+
+ <!-- Destination Queue -->
+<!-- <bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue"> -->
+<!-- <constructor-arg index="0" value="${JMS.QUEUE.NAME}" /> -->
+<!-- </bean> -->
+
+ <!-- JmsTemplate Definition -->
+<!-- <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> -->
+<!-- <property name="connectionFactory" ref="connectionFactory" /> -->
+<!-- <property name="defaultDestination" ref="destinationQueue" /> -->
+<!-- </bean> -->
+
+ <!-- Message Producer -->
+<!-- <bean id="messageProducer" class="org.openecomp.aai.dmaap.AAIDmaapEventJMSProducer" /> -->
+
+ <!-- Message Consumer from Default Destination -->
+<!-- <bean id="messageDefaultConsumer" class="org.openecomp.aai.dmaap.AAIDmaapEventJMSConsumer" /> -->
+
+ <!-- Message Consumer Container for Default Destination -->
+<!-- <bean -->
+<!-- class="org.springframework.jms.listener.DefaultMessageListenerContainer"> -->
+<!-- <property name="connectionFactory" ref="connectionFactory" /> -->
+<!-- <property name="destinationName" value="${JMS.QUEUE.NAME}" /> -->
+<!-- <property name="messageListener" ref="messageDefaultConsumer" /> -->
+<!-- </bean> -->
+
+
+</beans> \ No newline at end of file
diff --git a/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt
new file mode 100644
index 0000000..3707179
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/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/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt
new file mode 100644
index 0000000..639e21b
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/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/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props
new file mode 100644
index 0000000..17ebc08
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props
@@ -0,0 +1 @@
+EXAMPLE.PROPERTY=EXAMLE_VALUE \ No newline at end of file
diff --git a/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route
new file mode 100644
index 0000000..6a86246
--- /dev/null
+++ b/ajsc-aai/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route
@@ -0,0 +1,4 @@
+<route xmlns="http://camel.apache.org/schema/spring" trace="true">
+ <from uri="att-dme2-servlet:///aai?matchOnUriPrefix=true" />
+ <to uri="cxfbean:jaxrsServices?providers=#jsonProvider&amp;bus=#cxfBus" />
+</route> \ No newline at end of file
diff --git a/ajsc-aai/src/main/assemble/ajsc_module_assembly.xml b/ajsc-aai/src/main/assemble/ajsc_module_assembly.xml
new file mode 100644
index 0000000..4ec4e28
--- /dev/null
+++ b/ajsc-aai/src/main/assemble/ajsc_module_assembly.xml
@@ -0,0 +1,66 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>${version}</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/routes/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/routes/</outputDirectory>
+ <includes>
+ <include>*.route</include>
+ </includes>
+
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/docs/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/docs/</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ <!-- <include>*.vm</include> -->
+ </includes>
+
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/lib/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/extJars/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/extJars/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+
+ <!-- also try to grab outputs from the "jar" plugin's package phase -->
+ <fileSet>
+ <directory>${project.basedir}/target/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/</outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/conf/</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/conf/</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ </includes>
+
+ </fileSet>
+ </fileSets>
+
+</assembly>
+
diff --git a/ajsc-aai/src/main/assemble/ajsc_props_assembly.xml b/ajsc-aai/src/main/assemble/ajsc_props_assembly.xml
new file mode 100644
index 0000000..5b8a6fa
--- /dev/null
+++ b/ajsc-aai/src/main/assemble/ajsc_props_assembly.xml
@@ -0,0 +1,23 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>${version}_properties</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-ajsc/props</directory>
+ <outputDirectory>${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/props/</outputDirectory>
+ <includes>
+ <include>*.props</include>
+ </includes>
+
+ </fileSet>
+
+ </fileSets>
+
+</assembly>
+
diff --git a/ajsc-aai/src/main/assemble/ajsc_runtime_assembly.xml b/ajsc-aai/src/main/assemble/ajsc_runtime_assembly.xml
new file mode 100644
index 0000000..e37d366
--- /dev/null
+++ b/ajsc-aai/src/main/assemble/ajsc_runtime_assembly.xml
@@ -0,0 +1,44 @@
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>runtimeEnvironment</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/context/</directory>
+ <outputDirectory>runtime/context/</outputDirectory>
+ <includes>
+ <include>*.context</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/serviceProperties/</directory>
+ <outputDirectory>runtime/serviceProperties/</outputDirectory>
+ <includes>
+ <include>*.props</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroRole</directory>
+ <outputDirectory>runtime/shiroRole/</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroUser</directory>
+ <outputDirectory>runtime/shiroUser/</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet><fileSet>
+ <directory>${project.basedir}/target/versioned-runtime/shiroUserRole</directory>
+ <outputDirectory>runtime/shiroUserRole</outputDirectory>
+ <includes>
+ <include>*.json</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly> \ No newline at end of file
diff --git a/ajsc-aai/src/main/config/ajsc-jetty.xml b/ajsc-aai/src/main/config/ajsc-jetty.xml
new file mode 100644
index 0000000..104c644
--- /dev/null
+++ b/ajsc-aai/src/main/config/ajsc-jetty.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure id="ajsc-server" class="org.eclipse.jetty.server.Server">
+ <!-- DO NOT REMOVE!!!! This is setting up the AJSC Context -->
+ <New id="ajscContext" class="org.eclipse.jetty.webapp.WebAppContext">
+ <Set name="contextPath"><SystemProperty name="AJSC_CONTEXT_PATH" /></Set>
+ <Set name="extractWAR">true</Set>
+ <Set name="tempDirectory"><SystemProperty name="AJSC_TEMP_DIR" /></Set>
+ <Set name="war"><SystemProperty name="AJSC_WAR_PATH" /></Set>
+ <Set name="descriptor"><SystemProperty name="AJSC_HOME" />/etc/runner-web.xml</Set>
+ <Set name="overrideDescriptor"><SystemProperty name="AJSC_HOME" />/etc/ajsc-override-web.xml</Set>
+ <Set name="throwUnavailableOnStartupException">true</Set>
+ <Set name="servletHandler">
+ <New class="org.eclipse.jetty.servlet.ServletHandler">
+ <Set name="startWithUnavailable">false</Set>
+ </New>
+ </Set>
+ <Set name="extraClasspath">
+ <SystemProperty name="AJSC_HOME" />/extJars/aai.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/logback-core-1.1.7.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/logback-access-1.1.7.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/eelf-core-0.0.1.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/slf4j-api-1.7.21.jar
+ </Set>
+ </New>
+
+ <Set name="handler">
+ <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
+ <Set name="handlers">
+ <Array type="org.eclipse.jetty.server.Handler">
+ <Item>
+ <New id="Contexts"
+ class="org.eclipse.jetty.server.handler.ContextHandlerCollection">
+ <Set name="Handlers">
+ <Array type="org.eclipse.jetty.webapp.WebAppContext">
+ <Item>
+ <Ref refid="ajscContext" />
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Item>
+ <!-- add a RequestLogHandler -->
+ <Item>
+ <New id="RequestLogHandler" class="org.eclipse.jetty.server.handler.RequestLogHandler"/>
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Set>
+
+ <Ref id="RequestLogHandler">
+ <Set name="requestLog">
+ <New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl">
+ <Set name="fileName"><SystemProperty name="AJSC_HOME" />/bundleconfig/etc/localhost-access-logback.xml</Set>
+ </New>
+ </Set>
+ </Ref>
+
+ <Call name="addBean">
+ <Arg>
+ <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+ <Set name="contexts">
+ <Ref refid="Contexts" />
+ </Set>
+ <Call id="extAppHotDeployProvider" name="addAppProvider">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
+ <Set name="monitoredDirName"><SystemProperty name="AJSC_HOME" />/extApps</Set>
+ <Set name="scanInterval">10</Set>
+ <Set name="extractWars">true</Set>
+ </New>
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </Call>
+
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="ajsc-server" />
+ </Arg>
+ <Set name="port"><SystemProperty name="AJSC_HTTP_PORT" default="8080" /></Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
+ <Set name="KeyStorePath">file:<SystemProperty name="AJSC_HOME" />/bundleconfig/etc/auth/aai_keystore</Set>
+ <Set name="KeyStorePassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_STORE_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="KeyManagerPassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_MANAGER_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="needClientAuth">false</Set>
+ <Set name="ExcludeProtocols">
+ <Array type="java.lang.String">
+ <Item>SSL</Item>
+ <Item>SSLv2</Item>
+ <Item>SSLv2Hello</Item>
+ <Item>SSLv3</Item>
+ </Array>
+ </Set>
+ </New>
+
+
+ <Call id="sslConnector" name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="ajsc-server" />
+ </Arg>
+ <Arg name="factories">
+ <Array type="org.eclipse.jetty.server.ConnectionFactory">
+ <Item>
+ <New class="org.eclipse.jetty.server.SslConnectionFactory">
+ <Arg name="next">http/1.1</Arg>
+ <Arg name="sslContextFactory">
+ <Ref refid="sslContextFactory" />
+ </Arg>
+ </New>
+ </Item>
+ <Item>
+ <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+ <Arg name="config">
+ <New class="org.eclipse.jetty.server.HttpConfiguration">
+ <Call name="addCustomizer">
+ <Arg>
+ <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </New>
+ </Item>
+ </Array>
+ </Arg>
+ <Set name="port"><SystemProperty name="AJSC_HTTPS_PORT" default="8443" /></Set>
+ <Set name="idleTimeout">30000</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <Get name="ThreadPool">
+ <Set name="minThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MIN" /></Set>
+ <Set name="maxThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MAX" /></Set>
+ <Set name="idleTimeout"><SystemProperty name="AJSC_JETTY_IDLETIME_MAX" /></Set>
+ <Set name="detailedDump">false</Set>
+ </Get>
+
+ <Call name="addBean">
+ <Arg>
+ <New class="org.eclipse.jetty.security.HashLoginService">
+ <Set name="name">Test Realm</Set>
+ <Set name="config"><SystemProperty name="AJSC_HOME" default="."/>/etc/realm.properties</Set>
+ <Set name="refreshInterval">5</Set>
+ <Call name="start"></Call>
+ </New>
+ </Arg>
+ </Call>
+</Configure>
diff --git a/ajsc-aai/src/main/config/ajsc-jolokia-override-web.xml b/ajsc-aai/src/main/config/ajsc-jolokia-override-web.xml
new file mode 100644
index 0000000..b242129
--- /dev/null
+++ b/ajsc-aai/src/main/config/ajsc-jolokia-override-web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/services/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/rest/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ManagementServlet</servlet-name>
+ <url-pattern>/mgmt</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>RestletServlet</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>CamelServlet</servlet-name>
+ <url-pattern>/services/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>jolokia-agent</servlet-name>
+ <servlet-class>org.jolokia.http.AgentServlet</servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>jolokia-agent</servlet-name>
+ <url-pattern>/jolokia/*</url-pattern>
+ </servlet-mapping>
+
+</web-app> \ No newline at end of file
diff --git a/ajsc-aai/src/main/config/ajsc-override-web.xml b/ajsc-aai/src/main/config/ajsc-override-web.xml
new file mode 100644
index 0000000..61e2836
--- /dev/null
+++ b/ajsc-aai/src/main/config/ajsc-override-web.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <filter-mapping>
+ <filter-name>WriteableRequestFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>InterceptorFilter</filter-name>
+ <url-pattern>/rest/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <servlet-mapping>
+ <servlet-name>ManagementServlet</servlet-name>
+ <url-pattern>/mgmt</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>RestletServlet</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>CamelServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+
+
+</web-app> \ No newline at end of file
diff --git a/ajsc-aai/src/main/config/ajsc-request.xml b/ajsc-aai/src/main/config/ajsc-request.xml
new file mode 100644
index 0000000..5d09b7a
--- /dev/null
+++ b/ajsc-aai/src/main/config/ajsc-request.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ns1:ErrorTranslationRequest
+ xsi:schemaLocation="http://csi.cingular.com/CSI/Namespaces/Types/Private/ErrorTranslationRequest.xsd ErrorTranslationRequest.xsd"
+ xmlns:ns1="http://csi.cingular.com/CSI/Namespaces/Types/Private/ErrorTranslationRequest.xsd"
+ xmlns:th="http://csi.cingular.com/CSI/Namespaces/Types/Private/Implementation/TransactionHeader.xsd"
+ xmlns:err="http://csi.cingular.com/CSI/Namespaces/Types/Public/ErrorResponse.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <ns1:TransactionHeader>
+ <th:applicationId></th:applicationId>
+ <th:MessageQualifier>
+ <th:messageQualifier></th:messageQualifier>
+ </th:MessageQualifier>
+ <th:activityCode></th:activityCode>
+ <th:sequenceNumber></th:sequenceNumber>
+ <th:extendedSequenceNumber></th:extendedSequenceNumber>
+ <th:creationDate></th:creationDate>
+ <th:transactionDate></th:transactionDate>
+ <th:timeToLive></th:timeToLive>
+ <th:reasonCode></th:reasonCode>
+ <th:systemId></th:systemId>
+ <th:operatorId></th:operatorId>
+ <th:reference></th:reference>
+ <th:replyToAddress></th:replyToAddress>
+ <th:originatorId></th:originatorId>
+ <th:atlasMessageId></th:atlasMessageId>
+ </ns1:TransactionHeader>
+ <ns1:operation></ns1:operation>
+ <ns1:ServiceEntityFault>
+ <err:reportingServiceEntity></err:reportingServiceEntity>
+ <err:faultDate></err:faultDate>
+ <err:faultSequenceNumber></err:faultSequenceNumber>
+ <err:faultLevel></err:faultLevel>
+ <err:faultCode></err:faultCode>
+ <err:faultDescription></err:faultDescription>
+ <err:ServiceProviderRawError>
+ <err:code></err:code>
+ <err:description></err:description>
+ <err:BISError>
+ <err:code></err:code>
+ <err:description></err:description>
+ <err:origination></err:origination>
+ <err:severity></err:severity>
+ </err:BISError>
+ </err:ServiceProviderRawError>
+ </ns1:ServiceEntityFault>
+ <ns1:conversationID></ns1:conversationID>
+ <ns1:partnerName></ns1:partnerName>
+ <ns1:isRESTService></ns1:isRESTService>
+</ns1:ErrorTranslationRequest> \ No newline at end of file
diff --git a/ajsc-aai/src/main/config/caet.properties b/ajsc-aai/src/main/config/caet.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ajsc-aai/src/main/config/caet.properties
diff --git a/ajsc-aai/src/main/config/hazelcast-client.properties b/ajsc-aai/src/main/config/hazelcast-client.properties
new file mode 100644
index 0000000..2624d3f
--- /dev/null
+++ b/ajsc-aai/src/main/config/hazelcast-client.properties
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+hazelcast.client.group.name = ajsc
+hazelcast.client.group.pass = ajscpass
+hazelcast.client.connection.timeout = 30000
+hazelcast.client.connection.attempts.limit = 3
+hazelcast.client.reconnection.timeout = 5000
+hazelcast.client.reconnection.attempts.limit= 5
+hazelcast.client.shuffle.addresses = false
+hazelcast.client.update.automatic = true
+hazelcast.client.addresses = localhost, 127.0.0.1 \ No newline at end of file
diff --git a/ajsc-aai/src/main/config/jul-redirect.properties b/ajsc-aai/src/main/config/jul-redirect.properties
new file mode 100644
index 0000000..8b6624d
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/config/realm.properties b/ajsc-aai/src/main/config/realm.properties
new file mode 100644
index 0000000..62b82a5
--- /dev/null
+++ b/ajsc-aai/src/main/config/realm.properties
@@ -0,0 +1,11 @@
+# format : username: password[,rolename ...]
+# default username/password: AAI/AAI, MSO/MSO, ModelLoader/ModelLoader...
+AAI:OBF:1gfr1ev31gg7,admin
+MSO:OBF:1jzx1lz31k01,admin
+SDNC:OBF:1itr1i0l1i151isv,admin
+DCAE:OBF:1g8u1f9d1f991g8w,admin
+POLICY:OBF:1mk61i171ima1im41i0j1mko,admin
+ASDC:OBF:1f991j0u1j001f9d,admin
+VID:OBF:1jm91i0v1jl9,admin
+APPC:OBF:1f991ksf1ksf1f9d,admin
+ModelLoader:OBF:1qvu1v2h1sov1sar1wfw1j7j1wg21saj1sov1v1x1qxw,admin \ No newline at end of file
diff --git a/ajsc-aai/src/main/config/runner-web.xml b/ajsc-aai/src/main/config/runner-web.xml
new file mode 100644
index 0000000..146e3bf
--- /dev/null
+++ b/ajsc-aai/src/main/config/runner-web.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false" version="3.0">
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/spring-servlet.xml,
+ classpath:applicationContext.xml
+ </param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>spring.profiles.default</param-name>
+ <param-value>nooauth</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>ManagementServlet</servlet-name>
+ <servlet-class>ajsc.ManagementServlet</servlet-class>
+ </servlet>
+
+ <filter>
+ <filter-name>WriteableRequestFilter</filter-name>
+ <filter-class>com.att.ajsc.csi.writeablerequestfilter.WriteableRequestFilter</filter-class>
+ </filter>
+
+ <filter>
+ <filter-name>InterceptorFilter</filter-name>
+ <filter-class>ajsc.filters.InterceptorFilter</filter-class>
+ <init-param>
+ <param-name>preProcessor_interceptor_config_file</param-name>
+ <param-value>/etc/PreProcessorInterceptors.properties</param-value>
+ </init-param>
+ <init-param>
+ <param-name>postProcessor_interceptor_config_file</param-name>
+ <param-value>/etc/PostProcessorInterceptors.properties</param-value>
+ </init-param>
+
+ </filter>
+
+ <servlet>
+ <servlet-name>RestletServlet</servlet-name>
+ <servlet-class>ajsc.restlet.RestletSpringServlet</servlet-class>
+ <init-param>
+ <param-name>org.restlet.component</param-name>
+ <param-value>restletComponent</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>CamelServlet</servlet-name>
+ <servlet-class>ajsc.servlet.AjscCamelServlet</servlet-class>
+ </servlet>
+
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+
+ <servlet>
+ <servlet-name>spring</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+
+
+ <servlet-mapping>
+ <servlet-name>spring</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>
+
+ <listener>
+ <listener-class>
+ org.openecomp.aai.util.AAIAppServletContextListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.openecomp.aai.ingestModel.IngestModelListener
+ </listener-class>
+ </listener>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Open Source</web-resource-name>
+ <url-pattern>/aai/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>admin</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>Test Realm</realm-name>
+ </login-config>
+
+ <security-role>
+ <role-name>admin</role-name>
+ </security-role>
+</web-app>
diff --git a/ajsc-aai/src/main/config/template.ajsc-jetty.xml b/ajsc-aai/src/main/config/template.ajsc-jetty.xml
new file mode 100644
index 0000000..3ae27c3
--- /dev/null
+++ b/ajsc-aai/src/main/config/template.ajsc-jetty.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure id="ajsc-server" class="org.eclipse.jetty.server.Server">
+ <!-- DO NOT REMOVE!!!! This is setting up the AJSC Context -->
+ <New id="ajscContext" class="org.eclipse.jetty.webapp.WebAppContext">
+ <Set name="contextPath"><SystemProperty name="AJSC_CONTEXT_PATH" /></Set>
+ <Set name="extractWAR">true</Set>
+ <Set name="tempDirectory"><SystemProperty name="AJSC_TEMP_DIR" /></Set>
+ <Set name="war"><SystemProperty name="AJSC_WAR_PATH" /></Set>
+ <Set name="descriptor"><SystemProperty name="AJSC_HOME" />/etc/runner-web.xml</Set>
+ <Set name="overrideDescriptor"><SystemProperty name="AJSC_HOME" />/etc/ajsc-override-web.xml</Set>
+ <Set name="throwUnavailableOnStartupException">true</Set>
+ <Set name="servletHandler">
+ <New class="org.eclipse.jetty.servlet.ServletHandler">
+ <Set name="startWithUnavailable">false</Set>
+ </New>
+ </Set>
+ <Set name="extraClasspath">
+ <SystemProperty name="AJSC_HOME" />/extJars/aai.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/logback-core-1.1.7.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/logback-access-1.1.7.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/eelf-core-0.0.5.jar,
+ <SystemProperty name="AJSC_HOME" />/extJars/slf4j-api-1.7.21.jar
+ </Set>
+
+ </New>
+
+ <Set name="handler">
+ <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
+ <Set name="handlers">
+ <Array type="org.eclipse.jetty.server.Handler">
+ <Item>
+ <New id="Contexts"
+ class="org.eclipse.jetty.server.handler.ContextHandlerCollection">
+ <Set name="Handlers">
+ <Array type="org.eclipse.jetty.webapp.WebAppContext">
+ <Item>
+ <Ref refid="ajscContext" />
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Item>
+ <!-- add a RequestLogHandler -->
+ <Item>
+ <New id="RequestLogHandler" class="org.eclipse.jetty.server.handler.RequestLogHandler"/>
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Set>
+
+ <Ref id="RequestLogHandler">
+ <Set name="requestLog">
+ <New id="requestLogImpl" class="ch.qos.logback.access.jetty.RequestLogImpl">
+ <Set name="fileName"><SystemProperty name="AJSC_HOME" />/bundleconfig/etc/localhost-access-logback.xml</Set>
+ </New>
+ </Set>
+ </Ref>
+
+ <Call name="addBean">
+ <Arg>
+ <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+ <Set name="contexts">
+ <Ref refid="Contexts" />
+ </Set>
+ <Call id="extAppHotDeployProvider" name="addAppProvider">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
+ <Set name="monitoredDirName"><SystemProperty name="AJSC_HOME" />/extApps</Set>
+ <Set name="scanInterval">10</Set>
+ <Set name="extractWars">true</Set>
+ </New>
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </Call>
+
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="ajsc-server" />
+ </Arg>
+ <Set name="port"><SystemProperty name="AJSC_HTTP_PORT" default="__AJSC_SVC_PORT__" /></Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
+ <Set name="KeyStorePath">file:<SystemProperty name="AJSC_HOME" />/bundleconfig/etc/auth/aai_keystore</Set>
+ <Set name="KeyStorePassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_STORE_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="KeyManagerPassword">
+ <Call class="org.eclipse.jetty.util.security.Password" name="deobfuscate">
+ <Arg><SystemProperty name="KEY_MANAGER_PASSWORD" /></Arg>
+ </Call>
+ </Set>
+ <Set name="needClientAuth">false</Set>
+ <Set name="ExcludeProtocols">
+ <Array type="java.lang.String">
+ <Item>SSL</Item>
+ <Item>SSLv2</Item>
+ <Item>SSLv2Hello</Item>
+ <Item>SSLv3</Item>
+ </Array>
+ </Set>
+ </New>
+
+ <Call id="sslConnector" name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="ajsc-server" />
+ </Arg>
+ <Arg name="factories">
+ <Array type="org.eclipse.jetty.server.ConnectionFactory">
+ <Item>
+ <New class="org.eclipse.jetty.server.SslConnectionFactory">
+ <Arg name="next">http/1.1</Arg>
+ <Arg name="sslContextFactory">
+ <Ref refid="sslContextFactory" />
+ </Arg>
+ </New>
+ </Item>
+ <Item>
+ <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+ <Arg name="config">
+ <New class="org.eclipse.jetty.server.HttpConfiguration">
+ <Call name="addCustomizer">
+ <Arg>
+ <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
+ </Arg>
+ </Call>
+ </New>
+ </Arg>
+ </New>
+ </Item>
+ </Array>
+ </Arg>
+ <Set name="port"><SystemProperty name="AJSC_HTTPS_PORT" default="__AJSC_SSL_PORT__"/></Set>
+ <Set name="idleTimeout">30000</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <Get name="ThreadPool">
+ <Set name="minThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MIN" /></Set>
+ <Set name="maxThreads"><SystemProperty name="AJSC_JETTY_ThreadCount_MAX" /></Set>
+ <Set name="idleTimeout"><SystemProperty name="AJSC_JETTY_IDLETIME_MAX" /></Set>
+ <Set name="detailedDump">false</Set>
+ </Get>
+
+ <Call name="addBean">
+ <Arg>
+ <New class="org.eclipse.jetty.security.HashLoginService">
+ <Set name="name">Test Realm</Set>
+ <Set name="config"><SystemProperty name="AJSC_HOME" default="."/>/etc/realm.properties</Set>
+ <Set name="refreshInterval">5</Set>
+ <Call name="start"></Call>
+ </New>
+ </Arg>
+ </Call>
+
+</Configure> \ No newline at end of file
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java b/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java
new file mode 100644
index 0000000..39c78f6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ajsc_aai;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import java.util.Map;
+import java.util.HashMap;
+
+@Path("/user")
+public class JaxrsUserService {
+
+ private static final Map<String,String> userIdToNameMap;
+ static {
+ userIdToNameMap = new HashMap<String,String>();
+ userIdToNameMap.put("userID1","Name1");
+ userIdToNameMap.put("userID2","Name2");
+ }
+
+ /**
+ * Lookup user.
+ *
+ * @param userId the user id
+ * @return the string
+ */
+ @GET
+ @Path("/{userId}")
+ @Produces("text/plain")
+ public String lookupUser(@PathParam("userId") String userId) {
+ String name = userIdToNameMap.get(userId);
+ return name != null ? name : "unknown id";
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java b/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java
new file mode 100644
index 0000000..0ecdf22
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ajsc_aai.filemonitor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ServicePropertiesMap
+{
+ private static HashMap<String, HashMap<String, String>> mapOfMaps = new HashMap<String, HashMap<String, String>>();
+ static final Logger logger = LoggerFactory.getLogger(ServicePropertiesMap.class);
+
+ /**
+ * Refresh.
+ *
+ * @param file the file
+ * @throws Exception the exception
+ */
+ public static void refresh(File file) throws Exception
+ {
+ try
+ {
+ logger.info("Loading properties - " + (file != null?file.getName():""));
+
+ //Store .json & .properties files into map of maps
+ String filePath = file.getPath();
+
+ if(filePath.lastIndexOf(".json")>0){
+
+ ObjectMapper om = new ObjectMapper();
+ TypeReference<HashMap<String, String>> typeRef = new TypeReference<HashMap<String, String>>() {};
+ HashMap<String, String> propMap = om.readValue(file, typeRef);
+ HashMap<String, String> lcasePropMap = new HashMap<String, String>();
+ for (String key : propMap.keySet() )
+ {
+ String lcaseKey = ifNullThenEmpty(key);
+ lcasePropMap.put(lcaseKey, propMap.get(key));
+ }
+
+ mapOfMaps.put(file.getName(), lcasePropMap);
+
+
+ }else if(filePath.lastIndexOf(".properties")>0){
+ Properties prop = new Properties();
+ FileInputStream fis = new FileInputStream(file);
+ prop.load(fis);
+
+ @SuppressWarnings("unchecked")
+ HashMap<String, String> propMap = new HashMap<String, String>((Map)prop);
+
+ mapOfMaps.put(file.getName(), propMap);
+ }
+
+ logger.info("File - " + file.getName() + " is loaded into the map and the corresponding system properties have been refreshed");
+ }
+ catch (Exception e)
+ {
+ logger.error("File " + (file != null?file.getName():"") + " cannot be loaded into the map ", e);
+ throw new Exception("Error reading map file " + (file != null?file.getName():""), e);
+ }
+ }
+
+ /**
+ * Gets the property.
+ *
+ * @param fileName the file name
+ * @param propertyKey the property key
+ * @return the property
+ */
+ public static String getProperty(String fileName, String propertyKey)
+ {
+ HashMap<String, String> propMap = mapOfMaps.get(fileName);
+ return propMap!=null?propMap.get(ifNullThenEmpty(propertyKey)):"";
+ }
+
+ /**
+ * Gets the properties.
+ *
+ * @param fileName the file name
+ * @return the properties
+ */
+ public static HashMap<String, String> getProperties(String fileName){
+ return mapOfMaps.get(fileName);
+ }
+
+ /**
+ * If null then empty.
+ *
+ * @param key the key
+ * @return the string
+ */
+ private static String ifNullThenEmpty(String key) {
+ if (key == null) {
+ return "";
+ } else {
+ return key;
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java b/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java
new file mode 100644
index 0000000..7577de7
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ajsc_aai.util;
+
+import org.openecomp.aai.ajsc_aai.filemonitor.ServicePropertiesMap;
+
+public class ServicePropertiesMapBean {
+
+ /**
+ * Gets the property.
+ *
+ * @param propFileName the prop file name
+ * @param propertyKey the property key
+ * @return the property
+ */
+ public static String getProperty(String propFileName, String propertyKey) {
+ return ServicePropertiesMap.getProperty(propFileName, propertyKey);
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/audit/ListEndpoints.java b/ajsc-aai/src/main/java/org/openecomp/aai/audit/ListEndpoints.java
new file mode 100644
index 0000000..e354973
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/audit/ListEndpoints.java
@@ -0,0 +1,249 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.audit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+import com.google.common.base.CaseFormat;
+
+/**
+ * The Class ListEndpoints.
+ */
+public class ListEndpoints {
+
+
+ private DynamicJAXBContext context = null;
+
+ private final String start = "inventory";
+
+ private final String[] blacklist = { "search", "aai-internal", "models", "named-queries" };
+
+ private List<String> endpoints = new ArrayList<>();
+
+ private Map<String, String> endpointToLogicalName = new HashMap<String, String>();
+
+ private final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new list endpoints.
+ *
+ * @param version the version
+ */
+ public ListEndpoints(Version version) {
+
+ Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, version, llBuilder);
+ Introspector start = loader.introspectorFromName(this.start);
+
+ beginAudit(start, "/aai/" + version);
+
+ }
+
+ /**
+ * Begin audit.
+ *
+ * @param obj the obj
+ * @param uri the uri
+ */
+ private void beginAudit(Introspector obj, String uri) {
+ String currentUri = "";
+
+ if (!obj.getDbName().equals("inventory")) {
+ currentUri = uri + obj.getGenericURI();
+ } else {
+ currentUri = uri;
+ }
+ if (obj.getName().equals("relationship-data") || obj.getName().equals("related-to-property")) {
+ return;
+ }
+ if (!obj.isContainer()) {
+ endpoints.add(currentUri);
+ }
+
+ populateLogicalName(obj, uri, currentUri);
+
+ outer: for (String propName : obj.getProperties()) {
+ for (String item : blacklist) {
+ if (propName.equals(item)) {
+ continue outer;
+ }
+ }
+ if (obj.isListType(propName)) {
+ if (obj.isComplexGenericType(propName)) {
+ beginAudit(
+ IntrospectorFactory.newInstance(ModelType.MOXY, obj.newInstanceOfNestedProperty(propName), llBuilder),
+ currentUri);
+ }
+ } else if (obj.isComplexType(propName)) {
+ beginAudit(IntrospectorFactory.newInstance(ModelType.MOXY, obj.newInstanceOfProperty(propName), llBuilder),
+ currentUri);
+ }
+ }
+
+ }
+
+ /**
+ * Populate logical name.
+ *
+ * @param obj the obj
+ * @param uri the uri
+ * @param currentUri the current uri
+ */
+ private void populateLogicalName(Introspector obj, String uri, String currentUri) {
+
+ if (obj.getDbName().equals("inventory") || currentUri.split("/").length <= 4 || currentUri.endsWith("relationship-list")) {
+ return;
+ }
+
+ if (uri.endsWith("/relationship-list")) {
+ uri = uri.substring(0, uri.lastIndexOf("/"));
+ }
+
+ String logicalName = "";
+ String keys = "";
+
+
+ if (!obj.getAllKeys().isEmpty()) {
+
+ Pattern p = Pattern.compile("/\\{[\\w\\d\\-]+\\}/\\{[\\w\\d\\-]+\\}+$");
+ Matcher m = p.matcher(currentUri);
+
+ if (m.find()) {
+ keys = StringUtils.join(obj.getAllKeys(), "-and-");
+ } else {
+ keys = StringUtils.join(obj.getAllKeys(), "-or-");
+ }
+ keys = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, keys);
+ if (!keys.isEmpty()) {
+ keys = "With" + keys;
+ }
+ }
+
+ logicalName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, obj.getDbName()) + keys;
+
+ if (endpointToLogicalName.containsKey(uri) && uri.endsWith("}")) {
+ logicalName = logicalName + "From" + endpointToLogicalName.get(uri);
+ } else if (endpointToLogicalName.containsKey(uri.substring(0, uri.lastIndexOf("/")))) {
+ logicalName = logicalName + "From" + endpointToLogicalName.get(uri.substring(0, uri.lastIndexOf("/")));
+ }
+
+ endpointToLogicalName.put(currentUri, logicalName);
+
+ }
+
+ /**
+ * Gets the logical names.
+ *
+ * @return the logical names
+ */
+ public Map<String, String> getLogicalNames() {
+
+ return endpointToLogicalName;
+
+ }
+
+ /**
+ * Gets the endpoints.
+ *
+ * @return the endpoints
+ */
+ public List<String> getEndpoints() {
+
+ return this.getEndpoints("");
+
+ }
+
+ /**
+ * Gets the endpoints.
+ *
+ * @param filterOut the filter out
+ * @return the endpoints
+ */
+ public List<String> getEndpoints(String filterOut) {
+ List<String> result = new ArrayList<>();
+ Pattern p = null;
+ Matcher m = null;
+ if (!filterOut.equals("")) {
+ p = Pattern.compile(filterOut);
+ m = null;
+ }
+ for (String s : endpoints) {
+ if (p != null) {
+ m = p.matcher(s);
+ if (m.find()) {
+ continue;
+ }
+ }
+
+ result.add(s);
+ }
+
+ return result;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (String s : endpoints) {
+ sb.append(s + "\n");
+ }
+ return sb.toString();
+
+ }
+
+ /**
+ * To string.
+ *
+ * @param filterOut the filter out
+ * @return the string
+ */
+ public String toString(String filterOut) {
+ StringBuilder sb = new StringBuilder();
+ Pattern p = Pattern.compile(filterOut);
+ Matcher m = null;
+ for (String s : endpoints) {
+ m = p.matcher(s);
+ if (!m.find()) {
+ sb.append(s + "\n");
+ }
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/auth/AAIAuth.java b/ajsc-aai/src/main/java/org/openecomp/aai/auth/AAIAuth.java
new file mode 100644
index 0000000..c62411f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/auth/AAIAuth.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.auth;
+
+import javax.ws.rs.core.HttpHeaders;
+
+import org.openecomp.aai.exceptions.AAIException;
+
+/**
+ * The Class AAIAuth.
+ */
+/*
+ * this appears to be simply a wrapper class for AAIAuthCore
+ * it just handled cookie stuff
+ * and can return an error code
+ * and forwards everything to AAIAuthCore to do the real work
+ * since cookies appear not to be used, not sure if this class
+ * is still needed, depending on other architectural needs
+ */
+public class AAIAuth {
+
+ /**
+ * Instantiates a new AAI auth.
+ */
+ public AAIAuth() {}
+
+ /**
+ * Auth user.
+ *
+ * @param headers the headers
+ * @param authUser the auth user
+ * @param auth_function the auth function
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ /*public String auth_user(HttpHeaders headers, String authUser, String auth_function) throws AAIException {
+ if (AAIAuthCore.getInstance().authorize(authUser, auth_function)) {
+ return "OK"; // this seems kinda brittle, since one could easily forget the caps & need to look it up in the caller
+ } else {
+ return "AAI_9101";
+ }
+ }*/
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/AAIProperties.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/AAIProperties.java
new file mode 100644
index 0000000..c1346e4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/AAIProperties.java
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db;
+
+import org.openecomp.aai.introspection.Version;
+
+public class AAIProperties {
+ public static final String NODE_TYPE = "aai-node-type";
+ public static final String LAST_MOD_SOURCE_OF_TRUTH = "last-mod-source-of-truth";
+ public static final String SOURCE_OF_TRUTH = "source-of-truth";
+ public static final String LAST_MOD_TS = "aai-last-mod-ts";
+ public static final String UNIQUE_KEY = "aai-unique-key";
+ public static final String CREATED_TS = "aai-created-ts";
+ public static final String RESOURCE_VERSION = "resource-version";
+ public static final Version LATEST = Version.v8;
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditDoc.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditDoc.java
new file mode 100644
index 0000000..58d3dc0
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditDoc.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+public class AuditDoc {
+
+ private List<DBProperty> properties;
+ private List<DBIndex> indexes;
+ private List<EdgeProperty> edgeLabels;
+
+ /**
+ * Gets the properties.
+ *
+ * @return the properties
+ */
+ public List<DBProperty> getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets the properties.
+ *
+ * @param properties the new properties
+ */
+ public void setProperties(List<DBProperty> properties) {
+ this.properties = properties;
+ }
+
+ /**
+ * Gets the indexes.
+ *
+ * @return the indexes
+ */
+ public List<DBIndex> getIndexes() {
+ return indexes;
+ }
+
+ /**
+ * Sets the indexes.
+ *
+ * @param indexes the new indexes
+ */
+ public void setIndexes(List<DBIndex> indexes) {
+ this.indexes = indexes;
+ }
+
+ /**
+ * Gets the edge labels.
+ *
+ * @return the edge labels
+ */
+ @JsonProperty("edge-labels")
+ public List<EdgeProperty> getEdgeLabels() {
+ return edgeLabels;
+ }
+
+ /**
+ * Sets the edge labels.
+ *
+ * @param edgeLabels the new edge labels
+ */
+ public void setEdgeLabels(List<EdgeProperty> edgeLabels) {
+ this.edgeLabels = edgeLabels;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditOXM.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditOXM.java
new file mode 100644
index 0000000..bbdd7c6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditOXM.java
@@ -0,0 +1,241 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.util.AAIConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.Multimap;
+import com.thinkaurelius.titan.core.Cardinality;
+import com.thinkaurelius.titan.core.Multiplicity;
+import com.thinkaurelius.titan.core.schema.SchemaStatus;
+
+public class AuditOXM extends Auditor {
+
+
+ private Set<Introspector> allObjects;
+ private final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new audit OXM.
+ *
+ * @param version the version
+ */
+ public AuditOXM(Version version) {
+ Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, version, llBuilder);
+ Set<String> objectNames = getAllObjects(version);
+ allObjects = new HashSet<>();
+ for (String key : objectNames) {
+ Introspector temp = loader.introspectorFromName(key);
+ allObjects.add(temp);
+ this.createDBProperties(temp);
+ }
+ for (Introspector temp : allObjects) {
+ this.createDBIndexes(temp);
+ }
+ createEdgeLabels();
+
+ }
+
+ /**
+ * Gets the all objects.
+ *
+ * @param version the version
+ * @return the all objects
+ */
+ private Set<String> getAllObjects(Version version) {
+ String fileName = AAIConstants.AAI_HOME_ETC_OXM + "aai_oxm_" + version.toString() + ".xml";
+ Set<String> result = new HashSet<>();
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ try {
+ docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+ Document doc = docBuilder.parse(fileName);
+ NodeList list = doc.getElementsByTagName("java-type");
+ for (int i = 0; i < list.getLength(); i++) {
+ result.add(list.item(i).getAttributes().getNamedItem("name").getNodeValue());
+ }
+ } catch (ParserConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (SAXException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ result.remove("EdgePropNames");
+ return result;
+
+ }
+
+ /**
+ * Creates the DB properties.
+ *
+ * @param temp the temp
+ */
+ private void createDBProperties(Introspector temp) {
+ List<String> objectProperties = temp.getProperties();
+
+ for (String prop : objectProperties) {
+ if (!properties.containsKey(prop)) {
+ DBProperty dbProperty = new DBProperty();
+ dbProperty.setName(prop);
+ if (temp.isListType(prop)) {
+ dbProperty.setCardinality(Cardinality.SET);
+ if (temp.isSimpleGenericType(prop)) {
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(temp.getGenericType(prop));
+ } catch (ClassNotFoundException e) {
+ clazz = Object.class;
+ }
+ dbProperty.setTypeClass(clazz);
+ properties.put(prop, dbProperty);
+ }
+ } else {
+ dbProperty.setCardinality(Cardinality.SINGLE);
+ if (temp.isSimpleType(prop)) {
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(temp.getType(prop));
+ } catch (ClassNotFoundException e) {
+ clazz = Object.class;
+ }
+ dbProperty.setTypeClass(clazz);
+ properties.put(prop, dbProperty);
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Creates the DB indexes.
+ *
+ * @param temp the temp
+ */
+ private void createDBIndexes(Introspector temp) {
+ String uniqueProps = temp.getMetadata("uniqueProps");
+ String namespace = temp.getMetadata("namespace");
+ if (uniqueProps == null) {
+ uniqueProps = "";
+ }
+ if (namespace == null) {
+ namespace = "";
+ }
+ boolean isTopLevel = namespace != "";
+ List<String> unique = Arrays.asList(uniqueProps.split(","));
+ List<String> indexed = temp.getIndexedProperties();
+ List<String> keys = temp.getKeys();
+
+ for (String prop : indexed) {
+ DBIndex dbIndex = new DBIndex();
+ LinkedHashSet<DBProperty> properties = new LinkedHashSet<>();
+ if (!this.indexes.containsKey(prop)) {
+ dbIndex.setName(prop);
+ dbIndex.setUnique(unique.contains(prop));
+ properties.add(this.properties.get(prop));
+ dbIndex.setProperties(properties);
+ dbIndex.setStatus(SchemaStatus.ENABLED);
+ this.indexes.put(prop, dbIndex);
+ }
+ }
+ if (keys.size() > 1 || isTopLevel) {
+ DBIndex dbIndex = new DBIndex();
+ LinkedHashSet<DBProperty> properties = new LinkedHashSet<>();
+ dbIndex.setName("key-for-" + temp.getDbName());
+ if (!this.indexes.containsKey(dbIndex.getName())) {
+ boolean isUnique = false;
+ if (isTopLevel) {
+ properties.add(this.properties.get(AAIProperties.NODE_TYPE));
+ }
+ for (String key : keys) {
+ properties.add(this.properties.get(key));
+
+ if (unique.contains(key) && !isUnique) {
+ isUnique = true;
+ }
+ }
+ dbIndex.setUnique(isUnique);
+ dbIndex.setProperties(properties);
+ dbIndex.setStatus(SchemaStatus.ENABLED);
+ this.indexes.put(dbIndex.getName(), dbIndex);
+ }
+ }
+
+ }
+
+ /**
+ * Creates the edge labels.
+ */
+ private void createEdgeLabels() {
+ Multimap<String, String> edgeRules = DbEdgeRules.EdgeRules;
+ for (String key : edgeRules.keySet()) {
+ Collection<String> collection = edgeRules.get(key);
+ EdgeProperty prop = new EdgeProperty();
+ //there is only ever one, they used the wrong type for EdgeRules
+ String label = "";
+ for (String item : collection) {
+ label = item.split(",")[0];
+ }
+ prop.setName(label);
+ prop.setMultiplicity(Multiplicity.MULTI);
+ this.edgeLabels.put(label, prop);
+ }
+ }
+
+ /**
+ * Gets the all introspectors.
+ *
+ * @return the all introspectors
+ */
+ public Set<Introspector> getAllIntrospectors() {
+ return this.allObjects;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditTitan.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditTitan.java
new file mode 100644
index 0000000..814afd6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditTitan.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import com.thinkaurelius.titan.core.EdgeLabel;
+import com.thinkaurelius.titan.core.PropertyKey;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.schema.TitanGraphIndex;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+
+public class AuditTitan extends Auditor {
+
+ private final TitanGraph graph;
+
+ /**
+ * Instantiates a new audit titan.
+ *
+ * @param g the g
+ */
+ public AuditTitan (TitanGraph g) {
+ this.graph = g;
+ buildSchema();
+ }
+
+ /**
+ * Builds the schema.
+ */
+ private void buildSchema() {
+ populateProperties();
+ populateIndexes();
+ populateEdgeLabels();
+ }
+
+ /**
+ * Populate properties.
+ */
+ private void populateProperties() {
+ TitanManagement mgmt = graph.openManagement();
+ Iterable<PropertyKey> iterable = mgmt.getRelationTypes(PropertyKey.class);
+ Iterator<PropertyKey> titanProperties = iterable.iterator();
+ PropertyKey propKey = null;
+ while (titanProperties.hasNext()) {
+ propKey = titanProperties.next();
+ DBProperty prop = new DBProperty();
+
+ prop.setName(propKey.name());
+ prop.setCardinality(propKey.cardinality());
+ prop.setTypeClass(propKey.dataType());
+
+ this.properties.put(prop.getName(), prop);
+ }
+ }
+
+ /**
+ * Populate indexes.
+ */
+ private void populateIndexes() {
+ TitanManagement mgmt = graph.openManagement();
+ Iterable<TitanGraphIndex> iterable = mgmt.getGraphIndexes(Vertex.class);
+ Iterator<TitanGraphIndex> titanIndexes = iterable.iterator();
+ TitanGraphIndex titanIndex = null;
+ while (titanIndexes.hasNext()) {
+ titanIndex = titanIndexes.next();
+ if (titanIndex.isCompositeIndex()) {
+ DBIndex index = new DBIndex();
+ LinkedHashSet<DBProperty> dbProperties = new LinkedHashSet<>();
+ index.setName(titanIndex.name());
+ index.setUnique(titanIndex.isUnique());
+ PropertyKey[] keys = titanIndex.getFieldKeys();
+ for (PropertyKey key : keys) {
+ dbProperties.add(this.properties.get(key.name()));
+ }
+ index.setProperties(dbProperties);
+ index.setStatus(titanIndex.getIndexStatus(keys[0]));
+ this.indexes.put(index.getName(), index);
+ }
+ }
+ }
+
+ /**
+ * Populate edge labels.
+ */
+ private void populateEdgeLabels() {
+ TitanManagement mgmt = graph.openManagement();
+ Iterable<EdgeLabel> iterable = mgmt.getRelationTypes(EdgeLabel.class);
+ Iterator<EdgeLabel> titanEdgeLabels = iterable.iterator();
+ EdgeLabel edgeLabel = null;
+ while (titanEdgeLabels.hasNext()) {
+ edgeLabel = titanEdgeLabels.next();
+ EdgeProperty edgeProperty = new EdgeProperty();
+
+ edgeProperty.setName(edgeLabel.name());
+ edgeProperty.setMultiplicity(edgeLabel.multiplicity());
+
+ this.edgeLabels.put(edgeProperty.getName(), edgeProperty);
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Auditor.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Auditor.java
new file mode 100644
index 0000000..67cf841
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Auditor.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class Auditor {
+
+ protected Map<String, DBProperty> properties = new HashMap<>();
+ protected Map<String, DBIndex> indexes = new HashMap<>();
+ protected Map<String, EdgeProperty> edgeLabels = new HashMap<>();
+
+ /**
+ * Gets the audit doc.
+ *
+ * @return the audit doc
+ */
+ public AuditDoc getAuditDoc() {
+ AuditDoc doc = new AuditDoc();
+ List<DBProperty> propertyList = new ArrayList<>();
+ List<DBIndex> indexList = new ArrayList<>();
+ List<EdgeProperty> edgeLabelList = new ArrayList<>();
+ propertyList.addAll(this.properties.values());
+ indexList.addAll(this.indexes.values());
+ edgeLabelList.addAll(this.edgeLabels.values());
+ Collections.sort(propertyList, new CompareByName());
+ Collections.sort(indexList, new CompareByName());
+ Collections.sort(edgeLabelList, new CompareByName());
+
+ doc.setProperties(propertyList);
+ doc.setIndexes(indexList);
+ doc.setEdgeLabels(edgeLabelList);
+
+ return doc;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditorFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditorFactory.java
new file mode 100644
index 0000000..bcc9d32
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditorFactory.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import org.openecomp.aai.introspection.Version;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+
+public class AuditorFactory {
+
+ /**
+ * Gets the OXM auditor.
+ *
+ * @param v the v
+ * @return the OXM auditor
+ */
+ public static Auditor getOXMAuditor (Version v) {
+ return new AuditOXM(v);
+ }
+
+ /**
+ * Gets the graph auditor.
+ *
+ * @param g the g
+ * @return the graph auditor
+ */
+ public static Auditor getGraphAuditor (TitanGraph g) {
+ return new AuditTitan(g);
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/CompareByName.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/CompareByName.java
new file mode 100644
index 0000000..ea45fd7
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/CompareByName.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.util.Comparator;
+
+public class CompareByName implements Comparator<Named>{
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compare(Named o1, Named o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBIndex.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBIndex.java
new file mode 100644
index 0000000..9e157a9
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBIndex.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.thinkaurelius.titan.core.schema.SchemaStatus;
+
+public class DBIndex implements Named {
+
+ private String name = null;
+ private boolean unique = false;
+ private LinkedHashSet<DBProperty> properties = new LinkedHashSet<>();
+ private SchemaStatus status = null;
+
+ /**
+ * Gets the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name.
+ *
+ * @param name the new name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Checks if is unique.
+ *
+ * @return true, if is unique
+ */
+ public boolean isUnique() {
+ return unique;
+ }
+
+ /**
+ * Sets the unique.
+ *
+ * @param unique the new unique
+ */
+ public void setUnique(boolean unique) {
+ this.unique = unique;
+ }
+
+ /**
+ * Gets the properties.
+ *
+ * @return the properties
+ */
+ public Set<DBProperty> getProperties() {
+ return properties;
+ }
+
+ /**
+ * Sets the properties.
+ *
+ * @param properties the new properties
+ */
+ public void setProperties(LinkedHashSet<DBProperty> properties) {
+ this.properties = properties;
+ }
+
+ /**
+ * Gets the status.
+ *
+ * @return the status
+ */
+ public SchemaStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the status.
+ *
+ * @param status the new status
+ */
+ public void setStatus(SchemaStatus status) {
+ this.status = status;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBProperty.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBProperty.java
new file mode 100644
index 0000000..f3000db
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBProperty.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import org.openecomp.aai.introspection.Introspector;
+
+import com.thinkaurelius.titan.core.Cardinality;
+
+public class DBProperty implements Named {
+
+
+ private String name = null;
+ private Cardinality cardinality = null;
+ private Class<?> typeClass = null;
+
+ /**
+ * Gets the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name.
+ *
+ * @param name the new name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Gets the cardinality.
+ *
+ * @return the cardinality
+ */
+ public Cardinality getCardinality() {
+ return cardinality;
+ }
+
+ /**
+ * Sets the cardinality.
+ *
+ * @param cardinality the new cardinality
+ */
+ public void setCardinality(Cardinality cardinality) {
+ this.cardinality = cardinality;
+ }
+
+ /**
+ * Gets the type class.
+ *
+ * @return the type class
+ */
+ public Class<?> getTypeClass() {
+ return typeClass;
+ }
+
+ /**
+ * Sets the type class.
+ *
+ * @param type the new type class
+ */
+ public void setTypeClass(Class<?> type) {
+ this.typeClass = type;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/EdgeProperty.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/EdgeProperty.java
new file mode 100644
index 0000000..d6c8e42
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/EdgeProperty.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonPropertyOrder;
+
+import com.thinkaurelius.titan.core.Multiplicity;
+
+@JsonPropertyOrder({ "label", "multiplicity" })
+public class EdgeProperty implements Named {
+
+ private String name = null;
+ private Multiplicity multiplicity = null;
+
+ /**
+ * Gets the name
+ */
+ @JsonProperty("label")
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name.
+ *
+ * @param name the new name
+ */
+ @JsonProperty("label")
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Gets the multiplicity.
+ *
+ * @return the multiplicity
+ */
+ public Multiplicity getMultiplicity() {
+ return multiplicity;
+ }
+
+ /**
+ * Sets the multiplicity.
+ *
+ * @param multiplicity the new multiplicity
+ */
+ public void setMultiplicity(Multiplicity multiplicity) {
+ this.multiplicity = multiplicity;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ManageTitanSchema.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ManageTitanSchema.java
new file mode 100644
index 0000000..0824f61
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ManageTitanSchema.java
@@ -0,0 +1,329 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.introspection.Version;
+
+import com.thinkaurelius.titan.core.PropertyKey;
+import com.thinkaurelius.titan.core.TitanGraph;
+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.core.schema.TitanManagement.IndexBuilder;
+
+public class ManageTitanSchema {
+
+
+ private TitanManagement graphMgmt;
+ private TitanGraph graph;
+ private List<DBProperty> aaiProperties;
+ private List<DBIndex> aaiIndexes;
+ private List<EdgeProperty> aaiEdgeProperties;
+ private Auditor oxmInfo = null;
+ private Auditor graphInfo = null;
+
+ /**
+ * Instantiates a new manage titan schema.
+ *
+ * @param graph the graph
+ */
+ public ManageTitanSchema(final TitanGraph graph) {
+ this.graph = graph;
+ oxmInfo = AuditorFactory.getOXMAuditor(Version.v8);
+ graphInfo = AuditorFactory.getGraphAuditor(graph);
+ }
+
+
+ /**
+ * Builds the schema.
+ */
+ public void buildSchema() {
+
+ this.graphMgmt = graph.openManagement();
+ aaiProperties = new ArrayList<>();
+ aaiEdgeProperties = new ArrayList<>();
+ aaiIndexes = new ArrayList<>();
+ aaiProperties.addAll(oxmInfo.getAuditDoc().getProperties());
+ aaiIndexes.addAll(oxmInfo.getAuditDoc().getIndexes());
+ aaiEdgeProperties.addAll(oxmInfo.getAuditDoc().getEdgeLabels());
+ try {
+ createPropertyKeys();
+ createIndexes();
+ createEdgeLabels();
+ } catch (Exception e) {
+ e.printStackTrace();
+ graphMgmt.rollback();
+ }
+ graphMgmt.commit();
+ }
+
+ /**
+ * Creates the property keys.
+ */
+ private void createPropertyKeys() {
+
+
+ for (DBProperty prop : aaiProperties) {
+
+ if (graphMgmt.containsPropertyKey(prop.getName())) {
+ PropertyKey key = graphMgmt.getPropertyKey(prop.getName());
+ boolean isChanged = false;
+ if (!prop.getCardinality().equals(key.cardinality())) {
+ isChanged = true;
+ }
+ if (!prop.getTypeClass().equals(key.dataType())) {
+ isChanged = true;
+ }
+ if (isChanged) {
+ //must modify!
+ this.replaceProperty(prop);
+ }
+ } else {
+ //create a new property key
+ System.out.println("Key: " + prop.getName() + " not found - adding");
+ graphMgmt.makePropertyKey(prop.getName()).dataType(prop.getTypeClass()).cardinality(prop.getCardinality()).make();
+ }
+ }
+
+ }
+
+ /**
+ * Creates the indexes.
+ */
+ private void createIndexes() {
+
+ for (DBIndex index : aaiIndexes) {
+ Set<DBProperty> props = index.getProperties();
+ boolean isChanged = false;
+ boolean isNew = false;
+ List<PropertyKey> keyList = new ArrayList<>();
+ for (DBProperty prop : props) {
+ keyList.add(graphMgmt.getPropertyKey(prop.getName()));
+ }
+ if (graphMgmt.containsGraphIndex(index.getName())) {
+ TitanGraphIndex titanIndex = graphMgmt.getGraphIndex(index.getName());
+ PropertyKey[] dbKeys = titanIndex.getFieldKeys();
+ if (dbKeys.length != keyList.size()) {
+ isChanged = true;
+ } else {
+ int i = 0;
+ for (PropertyKey key : keyList) {
+ if (!dbKeys[i].equals(key)) {
+ isChanged = true;
+ break;
+ }
+ i++;
+ }
+ }
+ } else {
+ isNew = true;
+ }
+ if (keyList.size() > 0) {
+ this.createIndex(graphMgmt, index.getName(), keyList, index.isUnique(), isNew, isChanged);
+ }
+ }
+ }
+
+ // Use EdgeRules to make sure edgeLabels are defined in the db. NOTE: the multiplicty used here is
+ // always "MULTI". This is not the same as our internal "Many2Many", "One2One", "One2Many" or "Many2One"
+ // We use the same edge-label for edges between many different types of nodes and our internal
+ // multiplicty definitions depends on which two types of nodes are being connected.
+ /**
+ * Creates the edge labels.
+ */
+ private void createEdgeLabels() {
+
+
+ for (EdgeProperty prop : aaiEdgeProperties) {
+
+ if (graphMgmt.containsEdgeLabel(prop.getName())) {
+ // see what changed
+ } else {
+ graphMgmt.makeEdgeLabel(prop.getName()).multiplicity(prop.getMultiplicity()).make();
+ }
+
+ }
+
+
+ }
+
+ /**
+ * Creates the property.
+ *
+ * @param mgmt the mgmt
+ * @param prop the prop
+ */
+ private void createProperty(TitanManagement mgmt, DBProperty prop) {
+ if (mgmt.containsPropertyKey(prop.getName())) {
+ PropertyKey key = mgmt.getPropertyKey(prop.getName());
+ boolean isChanged = false;
+ if (!prop.getCardinality().equals(key.cardinality())) {
+ isChanged = true;
+ }
+ if (!prop.getTypeClass().equals(key.dataType())) {
+ isChanged = true;
+ }
+ if (isChanged) {
+ //must modify!
+ this.replaceProperty(prop);
+ }
+ } else {
+ //create a new property key
+ System.out.println("Key: " + prop.getName() + " not found - adding");
+ mgmt.makePropertyKey(prop.getName()).dataType(prop.getTypeClass()).cardinality(prop.getCardinality()).make();
+ }
+ }
+
+ /**
+ * Creates the index.
+ *
+ * @param mgmt the mgmt
+ * @param indexName the index name
+ * @param keys the keys
+ * @param isUnique the is unique
+ * @param isNew the is new
+ * @param isChanged the is changed
+ */
+ private void createIndex(TitanManagement mgmt, String indexName, List<PropertyKey> keys, boolean isUnique, boolean isNew, boolean isChanged) {
+
+ /*if (isChanged) {
+ System.out.println("Changing index: " + indexName);
+ TitanGraphIndex oldIndex = mgmt.getGraphIndex(indexName);
+ mgmt.updateIndex(oldIndex, SchemaAction.DISABLE_INDEX);
+ mgmt.commit();
+ //cannot remove indexes
+ //graphMgmt.updateIndex(oldIndex, SchemaAction.REMOVE_INDEX);
+ }*/
+ if (isNew || isChanged) {
+
+ if (isNew) {
+ IndexBuilder builder = mgmt.buildIndex(indexName,Vertex.class);
+ for (PropertyKey k : keys) {
+ builder.addKey(k);
+ }
+ if (isUnique) {
+ builder.unique();
+ }
+ builder.buildCompositeIndex();
+ System.out.println("Built index for " + indexName + " with keys: " + keys);
+
+ //mgmt.commit();
+ }
+
+ //mgmt = graph.getManagementSystem();
+ //mgmt.updateIndex(mgmt.getGraphIndex(indexName), SchemaAction.REGISTER_INDEX);
+ //mgmt.commit();
+
+ try {
+ //waitForCompletion(indexName);
+ //TitanIndexRepair.hbaseRepair(AAIConstants.AAI_CONFIG_FILENAME, indexName, "");
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ graph.tx().rollback();
+ graph.close();
+ e.printStackTrace();
+ }
+
+ //mgmt = graph.getManagementSystem();
+ //mgmt.updateIndex(mgmt.getGraphIndex(indexName), SchemaAction.REINDEX);
+
+ //mgmt.updateIndex(mgmt.getGraphIndex(indexName), SchemaAction.ENABLE_INDEX);
+
+ //mgmt.commit();
+
+ }
+ }
+
+ /**
+ * Wait for completion.
+ *
+ * @param name the name
+ * @throws InterruptedException the interrupted exception
+ */
+ private void waitForCompletion(String name) throws InterruptedException {
+
+ boolean registered = false;
+ long before = System.currentTimeMillis();
+ while (!registered) {
+ Thread.sleep(500L);
+ TitanManagement mgmt = graph.openManagement();
+ TitanGraphIndex idx = mgmt.getGraphIndex(name);
+ registered = true;
+ for (PropertyKey k : idx.getFieldKeys()) {
+ SchemaStatus s = idx.getIndexStatus(k);
+ registered &= s.equals(SchemaStatus.REGISTERED);
+ }
+ mgmt.rollback();
+ }
+ System.out.println("Index REGISTERED in " + (System.currentTimeMillis() - before) + " ms");
+ }
+
+ /**
+ * Replace property.
+ *
+ * @param key the key
+ */
+ private void replaceProperty(DBProperty key) {
+
+
+
+
+ }
+
+ /**
+ * Update index.
+ *
+ * @param index the index
+ */
+ public void updateIndex(DBIndex index) {
+
+ TitanManagement mgmt = graph.openManagement();
+ List<PropertyKey> keys = new ArrayList<>();
+ boolean isNew = false;
+ boolean isChanged = false;
+ for (DBProperty prop : index.getProperties()) {
+ createProperty(mgmt, prop);
+ keys.add(mgmt.getPropertyKey(prop.getName()));
+ }
+ if (mgmt.containsGraphIndex(index.getName())) {
+ System.out.println("index already exists");
+ isNew = false;
+ isChanged = true;
+ } else {
+ isNew = true;
+ isChanged = false;
+ }
+ this.createIndex(mgmt, index.getName(), keys, index.isUnique(), isNew, isChanged);
+
+ mgmt.commit();
+
+ }
+
+
+
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Named.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Named.java
new file mode 100644
index 0000000..850af57
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Named.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+public interface Named {
+
+ /**
+ * Gets the name.
+ *
+ * @return the name
+ */
+ public String getName();
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java
new file mode 100644
index 0000000..a2449e6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.db.schema;
+
+import java.io.IOException;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.util.AAIConfig;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+public class ScriptDriver {
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws AAIException the AAI exception
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public static void main (String[] args) throws AAIException, JsonGenerationException, JsonMappingException, IOException {
+ CommandLineArgs cArgs = new CommandLineArgs();
+
+ new JCommander(cArgs, args);
+
+ if (cArgs.help) {
+ System.out.println("-c [path to graph configuration] -type [what you want to audit - oxm or graph]");
+ }
+ String config = cArgs.config;
+ AAIConfig.init();
+ TitanGraph graph = TitanFactory.open(config);
+ if (!(cArgs.type.equals("oxm") || cArgs.type.equals("graph"))) {
+ System.out.println("type: " + cArgs.type + " not recognized.");
+ System.exit(1);
+ }
+
+ Auditor a = null;
+ if (cArgs.type.equals("oxm")) {
+ a = AuditorFactory.getOXMAuditor(Version.v8);
+ } else if (cArgs.type.equals("graph")) {
+ a = AuditorFactory.getGraphAuditor(graph);
+ }
+
+ AuditDoc doc = a.getAuditDoc();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(doc);
+ System.out.println(json);
+
+ }
+
+}
+
+class CommandLineArgs {
+
+ @Parameter(names = "--help", description = "Help")
+ public boolean help = false;
+
+ @Parameter(names = "-c", description = "Configuration", required=true)
+ public String config;
+
+ @Parameter(names = "-type", description = "Type", required=true)
+ public String type = "graph";
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java
new file mode 100644
index 0000000..732393d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+
+import java.util.Iterator;
+import java.util.Properties;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanVertex;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+
+public class AddResourceVersionProp {
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ // NOTE -- This is a one-time migration for adding the new property "resource-version" to ALL of our nodes.
+ // Also -- since it's a one-time thing, we just re-use AAI_SCHEMA_MOD_LOG4J_PROPS
+
+ TitanGraph graph = null;
+
+ System.out.println(">>> WARNING: this script affects all nodes in the database. <<<< " );
+ System.out.println(">>> Processing will begin in 5 seconds (unless interrupted). <<<");
+ try {
+ // Give them a chance to back out of this
+ Thread.sleep(5000);
+ } catch ( java.lang.InterruptedException ie) {
+ System.out.println( " AddResourceVersionProp script has been aborted. ");
+ System.exit(1);
+ }
+
+ try {
+ AAIConfig.init();
+ ErrorLogHelper.loadProperties();
+
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+ if( graph == null ){
+ String emsg = "Not able to get a graph object in AddResourceVersionProp.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+
+ // For each node in the db -- update the "resource-version" and the last mod timestamp.
+ Iterable<TitanVertex> verts = null;
+ verts= graph.query().vertices();
+ Iterator<TitanVertex> it = verts.iterator();
+ int vtxCount = 0;
+ long unixTimeNow = System.currentTimeMillis() / 1000L;
+ String timeNowInSec = "" + unixTimeNow;
+
+ while( it.hasNext() ){
+ vtxCount++;
+ TitanVertex tmpVtx = (TitanVertex)it.next();
+ tmpVtx.property( "aai-last-mod-ts", timeNowInSec );
+ tmpVtx.property( "resource-version", timeNowInSec );
+ }
+
+ System.out.println("Updated data for " + vtxCount + " vertexes. Now call graph.tx().commit(). ");
+ graph.tx().commit();
+
+ }
+ catch (AAIException e) {
+ System.out.print("Threw a AAIException: \n");
+ System.out.println(e.getErrorObject().toString());
+ }
+ catch (Exception ex) {
+ System.out.print("Threw a regular Exception:\n");
+ System.out.println(ex.getMessage());
+ }
+ finally {
+ if( graph != null ){
+ // Any changes that worked correctly should have already done their commits.
+ graph.tx().rollback();
+ graph.close();
+ }
+
+ }
+
+
+ System.exit(0);
+
+ }// End of main()
+
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java
new file mode 100644
index 0000000..a9d6bb0
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java
@@ -0,0 +1,307 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TimeZone;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.Cardinality;
+import com.thinkaurelius.titan.core.PropertyKey;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanVertex;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+
+public class ChangePropertyCardinality {
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ //public static void ChangePropertyCardinality( String[] args ) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ // NOTE -- We're just working with properties that are used for NODES
+ String propName = "";
+ String targetDataType = "String";
+ String targetCardinality = "SET";
+ String preserveDataFlag = "false";
+ boolean preserveData = false;
+
+
+ String usageString = "Usage: ChangePropertyCardinality propertyName targetDataType targetCardinality preserveDataFlag \n";
+ if( args.length != 4 ){
+ String emsg = "Four Parameters are required. \n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else {
+ propName = args[0];
+ targetDataType = args[1];
+ targetCardinality = args[2];
+ preserveDataFlag = args[3];
+ }
+
+ if( propName.equals("") ){
+ String emsg = "Bad parameter - propertyName cannot be empty. \n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if( !targetDataType.equals("String") ){
+ // && !targetDataType.equals("Integer")
+ // && !targetDataType.equals("Long")
+ // && !targetDataType.equals("Boolean") ){
+ // String emsg = "Unsupported targetDataType. We only support String, Integer, Long or Boolean for now.\n" + usageString;
+ String emsg = "Unsupported targetDataType. We only support String for now.\n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if( !targetCardinality.equals("SET") ){
+ // && !targetCardinality.equals("LIST")
+ // && !targetCardinality.equals("SINGLE") ){
+ String emsg = "Unsupported targetCardinality. We only support SET for now.\n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else {
+ if( preserveDataFlag.equals("true") ){
+ preserveData = true;
+ String emsg = "Unsupported preserveDataFlag. For now, we only support: 'false'.\n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if (preserveDataFlag.equals("false") ){
+ preserveData = false;
+ }
+ else {
+ String emsg = "Unsupported preserveDataFlag. We only support: 'true' or 'false'.\n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ }
+
+ String targetDataTypeStr = "";
+ if( targetCardinality.equals("SINGLE") ){
+ targetDataTypeStr = targetDataType;
+ }
+ else if( targetCardinality.equals("SET") ){
+ targetDataTypeStr = "Set<" + targetDataType + ">";
+ }
+ else if( targetCardinality.equals("LIST") ){
+ targetDataTypeStr = "List<" + targetDataType + ">";
+ }
+
+ Class dType = null;
+ if(targetDataType.equals("String")){ dType = String.class; }
+ else if(targetDataType.equals("Integer")){ dType = Integer.class; }
+ else if(targetDataType.equals("Boolean")){ dType = Boolean.class; }
+ else if(targetDataType.equals("Character")){ dType = Character.class; }
+ else if(targetDataType.equals("Long")){ dType = Long.class; }
+ else if(targetDataType.equals("Float")){ dType = Float.class; }
+ else if(targetDataType.equals("Double")){ dType = Double.class; }
+
+ System.out.println("\n>> WARNING/NOTE - If the passed cardinality is not in synch with what is in the oxm file, ");
+ System.out.println("\n>> then this will cause problems when new environments are created.");
+
+ // Give a big warning if the DbMaps.PropertyDataTypeMap value does not agree with what we're doing
+ DbMaps dbMaps = null;
+ try {
+ dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ }
+ catch( AAIException ae ){
+ String emsg = "Could not instantiate a copy of dbMaps. ";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ String warningMsg = "";
+ if( !dbMaps.PropertyDataTypeMap.containsKey(propName) ){
+ String emsg = "Property Name = [" + propName + "] not found in PropertyDataTypeMap. ";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else {
+ String currentDataType = dbMaps.PropertyDataTypeMap.get(propName);
+ if( !currentDataType.equals(targetDataTypeStr) ){
+ warningMsg = "TargetDataType [" + targetDataTypeStr + "] does not match what is in DbMaps (" + currentDataType + ").";
+ }
+ }
+
+ if( !warningMsg.equals("") ){
+ System.out.println("\n>>> WARNING <<<< " );
+ System.out.println(">>> " + warningMsg + " <<<");
+ System.out.println(">>> !!! WARNING -- this change may be overwritten in some environments if <<<");
+ System.out.println(">>> !!! entries are out of synch with what is done with this script. <<<");
+ System.out.println(">>> WARNING <<<< " );
+ }
+
+ System.out.println(">>> Processing will begin in 5 seconds (unless interrupted). <<<");
+ try {
+ // Give them a chance to back out of this
+ Thread.sleep(5000);
+ } catch ( java.lang.InterruptedException ie) {
+ System.out.println( " DB Schema Update has been aborted. ");
+ System.exit(1);
+ }
+
+ TitanManagement graphMgt = null;
+ TitanGraph graph = null;
+ try {
+ AAIConfig.init();
+ ErrorLogHelper.loadProperties();
+
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+ if( graph == null ){
+ String emsg = "Not able to get a graph object in ChangePropertyCardinality.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ // Make sure this property is in the DB.
+ graphMgt = graph.openManagement();
+ if( graphMgt == null ){
+ String emsg = "Not able to get a graph Management object in ChangePropertyCardinality.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ PropertyKey origPropKey = graphMgt.getPropertyKey(propName);
+ if( origPropKey == null ){
+ // The old one wasn't there, so there's nothing to do
+ String emsg = "The propName = [" + propName + "] is not defined in our graph. ";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ if( origPropKey.cardinality().equals(Cardinality.valueOf(targetCardinality)) ){
+ // The existing one already has cardinality of what they're asking for.
+ String emsg = "The propName = [" + propName + "] already has Cardinality of [" + targetCardinality + "]. ";
+ System.out.println( emsg );
+ System.exit(0);
+ }
+
+ // Rename this property to a backup name (old name with "retired_" appended plus a dateStr)
+ SimpleDateFormat d = new SimpleDateFormat("MMddHHmm");
+ d.setTimeZone(TimeZone.getTimeZone("GMT"));
+ String dteStr = d.format(new Date()).toString();
+ String retiredName = propName + "-" + dteStr + "-RETIRED";
+ graphMgt.changeName( origPropKey, retiredName );
+
+ // Create a new property using the original property name and the targetDataType
+ PropertyKey freshPropKey = graphMgt.makePropertyKey(propName).dataType(dType).cardinality(Cardinality.valueOf(targetCardinality)).make();
+
+ System.out.println("Committing schema changes with graphMgt.tx().commit()");
+ graphMgt.commit();
+ graph.tx().commit();
+ graph.close();
+
+
+ // Get A new graph object
+ System.out.println(" ---- NOTE --- about to open a second graph object (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+ if( graph == null ){
+ String emsg = "Not able to get a graph object in SchemaMod.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ // For each node that has this property, update the new from the old and then remove the
+ // old property from that node
+ // ---- NOTE ---- We're not preserving data at this point
+ Iterable <Vertex> verts = null;
+ verts= graph.query().has(retiredName).vertices();
+ Iterator <Vertex> it = verts.iterator();
+ int vtxCount = 0;
+ while( it.hasNext() ){
+ vtxCount++;
+ TitanVertex tmpVtx = (TitanVertex)it.next();
+ String tmpVid = tmpVtx.id().toString();
+
+ Object origVal = tmpVtx.property(retiredName).orElse(null);
+ if( preserveData ){
+ tmpVtx.property(propName,origVal);
+ System.out.println("INFO -- just did the add of the freshPropertyKey and updated it with the orig value (" +
+ origVal.toString() + ")");
+ }
+ else {
+ // existing nodes just won't have this property anymore
+ //
+ }
+ tmpVtx.property(retiredName).remove();
+ System.out.println("INFO -- just did the remove of the " + retiredName + " from this vertex. (vid=" + tmpVid + ")");
+ }
+
+ System.out.println("Updated data for " + vtxCount + " vertexes. Now call graph.tx().commit(). ");
+ graph.tx().commit();
+
+ }
+ catch (AAIException e) {
+ System.out.print("Threw a AAIException: \n");
+ System.out.println(e.getErrorObject().toString());
+ }
+ catch (Exception ex) {
+ System.out.print("Threw a regular Exception:\n");
+ System.out.println(ex.getMessage());
+ }
+ finally {
+ if( graphMgt != null && graphMgt.isOpen() ){
+ // Any changes that worked correctly should have already done their commits.
+ graphMgt.rollback();
+ }
+ if( graph != null ){
+ // Any changes that worked correctly should have already done their commits.
+ graph.tx().rollback();
+ graph.close();
+ }
+
+ }
+
+ System.exit(0);
+
+ }// End of main()
+
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java
new file mode 100644
index 0000000..0e9e023
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java
@@ -0,0 +1,2184 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.AAIPrimaryHost;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+public class DataGrooming {
+
+ private static final String FROMAPPID = "AAI-DB";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static int dupeGrpsDeleted = 0;
+
+ private static AAILogger aaiLogger;
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_DATA_GROOMING_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ aaiLogger = new AAILogger(DataGrooming.class.getName());
+
+ String ver = "version"; // Placeholder
+ Boolean doAutoFix = false;
+ Boolean edgesOnlyFlag = false;
+ Boolean dontFixOrphansFlag = false;
+ Boolean skipHostCheck = false;
+ Boolean singleCommits = false;
+ Boolean dupeCheckOff = false;
+ Boolean dupeFixOn = false;
+ Boolean ghost2CheckOff = false;
+ Boolean ghost2FixOn = false;
+
+ int maxRecordsToFix = AAIConstants.AAI_GROOMING_DEFAULT_MAX_FIX;
+ int sleepMinutes = AAIConstants.AAI_GROOMING_DEFAULT_SLEEP_MINUTES;
+ try {
+ String maxFixStr = AAIConfig.get("aai.grooming.default.max.fix");
+ if( maxFixStr != null && !maxFixStr.equals("") ){
+ maxRecordsToFix = Integer.parseInt(maxFixStr);
+ }
+ String sleepStr = AAIConfig.get("aai.grooming.default.sleep.minutes");
+ if( sleepStr != null && !sleepStr.equals("") ){
+ sleepMinutes = Integer.parseInt(sleepStr);
+ }
+ }
+ catch ( Exception e ){
+ // Don't worry, we'll just use the defaults that we got from AAIConstants
+ System.out.println("WARNING - could not pick up aai.grooming values from aaiconfig.properties file. ");
+ }
+
+ String prevFileName = "";
+ dupeGrpsDeleted = 0;
+ SimpleDateFormat d = new SimpleDateFormat("yyyyMMddHHmm");
+ d.setTimeZone(TimeZone.getTimeZone("GMT"));
+ String dteStr = d.format(new Date()).toString();
+ String groomOutFileName = "dataGrooming." + dteStr + ".out";
+
+ if (args.length > 0) {
+ // They passed some arguments in that will affect processing
+ for (int i = 0; i < args.length; i++) {
+ String thisArg = args[i];
+ if (thisArg.equals("-edgesOnly")) {
+ edgesOnlyFlag = true;
+ } else if (thisArg.equals("-autoFix")) {
+ doAutoFix = true;
+ } else if (thisArg.equals("-skipHostCheck")) {
+ skipHostCheck = true;
+ } else if (thisArg.equals("-dontFixOrphans")) {
+ dontFixOrphansFlag = true;
+ } else if (thisArg.equals("-singleCommits")) {
+ singleCommits = true;
+ } else if (thisArg.equals("-dupeCheckOff")) {
+ dupeCheckOff = true;
+ } else if (thisArg.equals("-dupeFixOn")) {
+ dupeFixOn = true;
+ } else if (thisArg.equals("-ghost2CheckOff")) {
+ ghost2CheckOff = true;
+ } else if (thisArg.equals("-ghost2FixOn")) {
+ ghost2FixOn = true;
+ } else if (thisArg.equals("-maxFix")) {
+ i++;
+ if (i >= args.length) {
+ System.out
+ .println(" No value passed with -maxFix option. ");
+ System.exit(0);
+ }
+ String nextArg = args[i];
+ try {
+ maxRecordsToFix = Integer.parseInt(nextArg);
+ } catch (Exception e) {
+ System.out
+ .println("Bad value passed with -maxFix option: ["
+ + nextArg + "]");
+ System.exit(0);
+ }
+ } else if (thisArg.equals("-sleepMinutes")) {
+ i++;
+ if (i >= args.length) {
+ System.out
+ .println("No value passed with -sleepMinutes option.");
+ System.exit(0);
+ }
+ String nextArg = args[i];
+ try {
+ sleepMinutes = Integer.parseInt(nextArg);
+ } catch (Exception e) {
+ System.out
+ .println("Bad value passed with -sleepMinutes option: ["
+ + nextArg + "]");
+ System.exit(0);
+ }
+ } else if (thisArg.equals("-f")) {
+ i++;
+ if (i >= args.length) {
+ System.out.println(" No value passed with -f option. ");
+ System.exit(0);
+ }
+ prevFileName = args[i];
+ } else {
+ System.out
+ .println(" Unrecognized argument passed to DataGrooming: ["
+ + thisArg + "]. ");
+ System.out
+ .println(" Valid values are: -f -autoFix -maxFix -edgesOnly -dupeFixOn -donFixOrphans -sleepMinutes");
+ System.exit(0);
+ }
+ }
+ }
+
+
+ IngestModelMoxyOxm moxyMod = new IngestModelMoxyOxm();
+ try {
+ ArrayList <String> defaultVerLst = new ArrayList <String> ();
+ defaultVerLst.add( AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP) );
+ moxyMod.init( defaultVerLst, false);
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not do the moxyMod.init(). ";
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + ex.getMessage() + "]");
+ System.exit(1);
+ }
+
+ if (skipHostCheck) {
+ System.out.println(" We will skip the HostCheck as requested. ");
+ } else {
+ // Make sure we are on the "primary" host -- so the cron won't have
+ // us running on all the servers...
+ try {
+ AAIPrimaryHost primaryHost = new AAIPrimaryHost(TRANSID, FROMAPPID);
+ if( ! primaryHost.amIPrimary()) {
+ System.out.println(" This is not the Primary Host, so DataGrooming will not be run. "
+ + " (Note: -skipHostCheck option can override this check)");
+ System.exit(0);
+ }
+ }
+ catch ( Exception e) {
+ System.out.println(" Error trying to determine if this is the Primary Host. "
+ + " (Note: -skipHostCheck option can override this host-check)" );
+ System.exit(0);
+ }
+ }
+
+ try {
+ if (!prevFileName.equals("")) {
+ // They are trying to fix some data based on a data in a
+ // previous file.
+ System.out
+ .println(" Call doTheGrooming() with a previous fileName ["
+ + prevFileName + "] for cleanup. ");
+ Boolean finalShutdownFlag = true;
+ doTheGrooming(prevFileName, edgesOnlyFlag, dontFixOrphansFlag,
+ maxRecordsToFix, groomOutFileName, ver, singleCommits,
+ dupeCheckOff, dupeFixOn, ghost2CheckOff, ghost2FixOn, finalShutdownFlag);
+ } else if (doAutoFix) {
+ // They want us to run the processing twice -- first to look for
+ // delete candidates, then after
+ // napping for a while, run it again and delete any candidates
+ // that were found by the first run.
+ // Note: we will produce a seperate output file for each of the
+ // two runs.
+ System.out.println(" Doing an auto-fix call to Grooming. ");
+ System.out
+ .println(" First, Call doTheGrooming() to look at what's out there. ");
+ Boolean finalShutdownFlag = false;
+ int fixCandCount = doTheGrooming("", edgesOnlyFlag,
+ dontFixOrphansFlag, maxRecordsToFix, groomOutFileName,
+ ver, singleCommits, dupeCheckOff, dupeFixOn, ghost2CheckOff, ghost2FixOn, finalShutdownFlag);
+ if (fixCandCount == 0) {
+ System.out
+ .println(" No fix-Candidates were found by the first pass, so no second/fix-pass is needed. ");
+ } else {
+ // We'll sleep a little and then run a fix-pass based on the
+ // first-run's output file.
+ try {
+ System.out.println("About to sleep for " + sleepMinutes
+ + " minutes.");
+ int sleepMsec = sleepMinutes * 60 * 1000;
+ Thread.sleep(sleepMsec);
+ } catch (InterruptedException ie) {
+ System.out
+ .println("\n >>> Sleep Thread has been Interrupted <<< ");
+ System.exit(0);
+ }
+
+ d = new SimpleDateFormat("yyyyMMddHHmm");
+ d.setTimeZone(TimeZone.getTimeZone("GMT"));
+ dteStr = d.format(new Date()).toString();
+ String secondGroomOutFileName = "dataGrooming." + dteStr
+ + ".out";
+ System.out
+ .println(" Now, call doTheGrooming() a second time and pass in the name of the file "
+ + "generated by the first pass for fixing: ["
+ + groomOutFileName + "]");
+ finalShutdownFlag = true;
+ doTheGrooming(groomOutFileName, edgesOnlyFlag,
+ dontFixOrphansFlag, maxRecordsToFix,
+ secondGroomOutFileName, ver, singleCommits,
+ dupeCheckOff, dupeFixOn, ghost2CheckOff, ghost2FixOn, finalShutdownFlag);
+ }
+ } else {
+ // Do the grooming - plain vanilla (no fix-it-file, no
+ // auto-fixing)
+ Boolean finalShutdownFlag = true;
+ System.out.println(" Call doTheGrooming() ");
+ doTheGrooming("", edgesOnlyFlag, dontFixOrphansFlag,
+ maxRecordsToFix, groomOutFileName, ver, singleCommits,
+ dupeCheckOff, dupeFixOn, ghost2CheckOff, ghost2FixOn, finalShutdownFlag );
+ }
+ } catch (Exception ex) {
+ System.out.print("Threw a regular Exception:\n");
+ System.out.println(ex.getMessage());
+ }
+
+ System.out.println(" Done! ");
+ System.exit(0);
+
+ }// End of main()
+
+ /**
+ * Do the grooming.
+ *
+ * @param fileNameForFixing the file name for fixing
+ * @param edgesOnlyFlag the edges only flag
+ * @param dontFixOrphansFlag the dont fix orphans flag
+ * @param maxRecordsToFix the max records to fix
+ * @param groomOutFileName the groom out file name
+ * @param version the version
+ * @param singleCommits the single commits
+ * @param dupeCheckOff the dupe check off
+ * @param dupeFixOn the dupe fix on
+ * @param ghost2CheckOff the ghost 2 check off
+ * @param ghost2FixOn the ghost 2 fix on
+ * @param finalShutdownFlag the final shutdown flag
+ * @return the int
+ */
+ private static int doTheGrooming(String fileNameForFixing,
+ Boolean edgesOnlyFlag, Boolean dontFixOrphansFlag,
+ int maxRecordsToFix, String groomOutFileName, String version,
+ Boolean singleCommits,
+ Boolean dupeCheckOff, Boolean dupeFixOn,
+ Boolean ghost2CheckOff, Boolean ghost2FixOn, Boolean finalShutdownFlag) {
+
+ System.out.println(" Entering doTheGrooming \n");
+
+ int cleanupCandidateCount = 0;
+ BufferedWriter bw = null;
+ TitanGraph graph = null;
+ TitanGraph graph2 = null;
+ int deleteCount = 0;
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", TRANSID, FROMAPPID, "doTheGrooming");
+
+ ArrayList<String> deleteCandidateList = new ArrayList<String>();
+ TitanTransaction g = null;
+ TitanTransaction g2 = null;
+ try {
+ AAIConfig.init(TRANSID, FROMAPPID);
+ String targetDir = AAIConstants.AAI_HOME + AAIConstants.AAI_FILESEP
+ + "logs" + AAIConstants.AAI_FILESEP + "data"
+ + AAIConstants.AAI_FILESEP + "dataGrooming";
+
+ // Make sure the target directory exists
+ new File(targetDir).mkdirs();
+
+ if (!fileNameForFixing.equals("")) {
+ deleteCandidateList = getDeleteList(targetDir,
+ fileNameForFixing, edgesOnlyFlag, dontFixOrphansFlag,
+ dupeFixOn);
+ }
+
+ if (deleteCandidateList.size() > maxRecordsToFix) {
+ String infoMsg = " >> WARNING >> Delete candidate list size ("
+ + deleteCandidateList.size()
+ + ") is too big. The maxFix we are using is: "
+ + maxRecordsToFix
+ + ". No candidates will be deleted. ";
+ aaiLogger.debug(logline, infoMsg);
+ System.out.println(infoMsg);
+ // Clear out the list so it won't be processed below.
+ deleteCandidateList = new ArrayList<String>();
+ }
+
+ SimpleDateFormat d = new SimpleDateFormat("yyyyMMddHHmm");
+ d.setTimeZone(TimeZone.getTimeZone("GMT"));
+ String dteStr = d.format(new Date()).toString();
+
+ String fullOutputFileName = targetDir + AAIConstants.AAI_FILESEP
+ + groomOutFileName;
+ File groomOutFile = new File(fullOutputFileName);
+ try {
+ groomOutFile.createNewFile();
+ } catch (IOException e) {
+ String emsg = " Problem creating output file ["
+ + fullOutputFileName + "], exception=" + e.getMessage();
+ throw new AAIException("AAI_6124", emsg);
+ }
+
+ logline.add("OutputFileName", fullOutputFileName);
+ System.out.println(" Will write to " + fullOutputFileName );
+ FileWriter fw = new FileWriter(groomOutFile.getAbsoluteFile());
+ bw = new BufferedWriter(fw);
+ ErrorLogHelper.loadProperties();
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n");
+
+
+ graph = AAIGraph.getInstance().getGraph();
+ if (graph == null) {
+ String emsg = "null graph object in DataGrooming\n";
+ throw new AAIException("AAI_6101", emsg);
+ }
+ System.out.println(" Got the graph object. ");
+
+ g = graph.newTransaction();
+ if (g == null) {
+ String emsg = "null graphTransaction object in DataGrooming\n";
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+
+ ArrayList<String> errArr = new ArrayList<String>();
+ int totalNodeCount = 0;
+ HashMap<String, String> misMatchedHash = new HashMap<String, String>();
+ HashMap<String, TitanVertex> orphanNodeHash = new HashMap<String, TitanVertex>();
+ HashMap<String, TitanVertex> missingDepNodeHash = new HashMap<String, TitanVertex>();
+ HashMap<String, Edge> oneArmedEdgeHash = new HashMap<String, Edge>();
+ HashMap<String, String> emptyVertexHash = new HashMap<String, String>();
+ HashMap<String, TitanVertex> ghostNodeHash = new HashMap<String, TitanVertex>();
+ ArrayList<String> dupeGroups = new ArrayList<String>();
+
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Iterator<String> nodeMapKPropsIterator = dbMaps.NodeKeyProps.keySet().iterator();
+ String ntList = "";
+
+ System.out.println(" Starting DataGrooming Processing ");
+
+ if (edgesOnlyFlag) {
+ System.out.println(" NOTE >> Skipping Node processing as requested. Will only process Edges. << ");
+ }
+ else {
+ while (nodeMapKPropsIterator.hasNext()) {
+ String nType = nodeMapKPropsIterator.next();
+ int thisNtCount = 0;
+ int thisNtDeleteCount = 0;
+ String infoMsg = " > Look at : [" + nType + "] ...";
+ aaiLogger.debug(logline, infoMsg);
+ System.out.println(infoMsg);
+ ntList = ntList + "," + nType;
+
+ // Get a collection of the names of the key properties for this nodeType to use later
+ Collection<String> keyProps = DbMeth.getNodeKeyPropNames(TRANSID, FROMAPPID, nType, version);
+ // Get the types of nodes that this nodetype depends on for uniqueness (if any)
+ ArrayList <String> depNodeTypes = DbMeth.getDepNodeTypes(TRANSID, FROMAPPID, nType, version);
+
+ // Loop through all the nodes of this Node type
+ int lastShownForNt = 0;
+ ArrayList <TitanVertex> tmpList = new ArrayList <TitanVertex> ();
+ Iterable <?> verts = g.query().has("aai-node-type",nType).vertices();
+ Iterator<?> iterv = verts.iterator();
+ while (iterv.hasNext()) {
+ // We put the nodes into an ArrayList because the graph.query iterator can time out
+ tmpList.add((TitanVertex)iterv.next());
+ }
+
+ Iterator <?> iter = tmpList.iterator();
+ while (iter.hasNext()) {
+ try {
+ thisNtCount++;
+ if( thisNtCount == lastShownForNt + 250 ){
+ lastShownForNt = thisNtCount;
+ System.out.println("count for " + nType + " so far = " + thisNtCount );
+ }
+ totalNodeCount++;
+ TitanVertex thisVtx = (TitanVertex) iter.next();
+ String thisVid = thisVtx.id().toString();
+ ArrayList <TitanVertex> secondGetList = new ArrayList <TitanVertex> ();
+ // -----------------------------------------------------------------------
+ // For each vertex of this nodeType, we want to:
+ // a) make sure that it can be retrieved using it's AAI defined key
+ // b) make sure that it is not a duplicate
+ // -----------------------------------------------------------------------
+
+ // For this instance of this nodeType, get the key properties
+ HashMap<String, Object> propHashWithKeys = new HashMap<String, Object>();
+ Iterator<String> keyPropI = keyProps.iterator();
+ while (keyPropI.hasNext()) {
+ String propName = keyPropI.next();
+ String propVal = "";
+ Object obj = thisVtx.<Object>property(propName).orElse(null);
+ if (obj != null) {
+ propVal = obj.toString();
+ }
+ propHashWithKeys.put(propName, propVal);
+ }
+ try {
+ // If this node is dependent on another for uniqueness, then do the query from that parent node
+ // Note - all of our nodes that are dependent on others for uniqueness are
+ // "children" of that node.
+ boolean depNodeOk = true;
+ if( depNodeTypes.isEmpty() ){
+ // This kind of node is not dependent on any other.
+ // Make sure we can get it back using it's key properties and that we only get one.
+ secondGetList = getNodeJustUsingKeyParams( TRANSID, FROMAPPID, g, nType,
+ propHashWithKeys, version );
+ }
+ else {
+ // This kind of node is dependent on another for uniqueness.
+ // Start at it's parent (the dependent vertex) and make sure we can get it
+ // back using it's key properties and that we only get one.
+ Iterable <?> verts2 = thisVtx.query().direction(Direction.IN).has("isParent",true).vertices();
+ Iterator <?> vertI2 = verts2.iterator();
+ TitanVertex parentVtx = null;
+ int pCount = 0;
+ while( vertI2 != null && vertI2.hasNext() ){
+ parentVtx = (TitanVertex) vertI2.next();
+ pCount++;
+ }
+ if( pCount <= 0 ){
+ // It's Missing it's dependent/parent node
+ depNodeOk = false;
+ boolean zeroEdges = false;
+ try {
+ Iterator<Edge> tmpEdgeIter = thisVtx.edges(Direction.BOTH);
+ int edgeCount = 0;
+ while( tmpEdgeIter.hasNext() ){
+ edgeCount++;
+ tmpEdgeIter.next();
+ }
+ if( edgeCount == 0 ){
+ zeroEdges = true;
+ }
+ } catch (Exception ex) {
+ String msg = "WARNING from inside the for-each-vid-loop orphan-edges-check ";
+ logline.add(msg, ex.getMessage());
+ System.out.println(msg + ex.getMessage() + ex.toString());
+ }
+
+ if (deleteCandidateList.contains(thisVid)) {
+ boolean okFlag = true;
+ try {
+ thisVtx.remove();
+ deleteCount++;
+ thisNtDeleteCount++;
+ } catch (Exception e) {
+ okFlag = false;
+ String msg = "ERROR trying to delete missing-dep-node VID = " + thisVid;
+ logline.add(msg, e.getMessage());
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ logline.add( "DELETED missing-dep-node VID:", thisVid);
+ System.out.println(" DELETED missing-dep-node VID = " + thisVid);
+ }
+ } else {
+ // We count nodes missing their depNodes two ways - the first if it has
+ // at least some edges, and the second if it has zero edges. Either
+ // way, they are effectively orphaned.
+ // NOTE - Only nodes that have dependent nodes are ever considered "orphaned".
+ if( zeroEdges ){
+ missingDepNodeHash.put(thisVid, thisVtx);
+ }
+ else {
+ orphanNodeHash.put(thisVid, thisVtx);
+ }
+ }
+ }
+ else if ( pCount > 1 ){
+ // Not sure how this could happen? Should we do something here?
+ depNodeOk = false;
+ }
+ else {
+ // We found the parent - so use it to do the second-look.
+ // NOTE --- We're just going to do the same check from the other direction - because
+ // there could be duplicates or the pointer going the other way could be broken
+ ArrayList <TitanVertex> tmpListSec = new ArrayList <TitanVertex> ();
+ tmpListSec = DbMeth.getConnectedChildren(TRANSID, FROMAPPID, g, parentVtx, nType ) ;
+ Iterator<TitanVertex> vIter = tmpListSec.iterator();
+ while (vIter.hasNext()) {
+ TitanVertex tmpV = vIter.next();
+ if( vertexHasTheseKeys(tmpV, propHashWithKeys) ){
+ secondGetList.add(tmpV);
+ }
+ }
+ }
+ }
+
+ if( depNodeOk && (secondGetList == null || secondGetList.size() == 0) ){
+ // We could not get the node back using it's own key info.
+ // So, it's a PHANTOM
+ if (deleteCandidateList.contains(thisVid)) {
+ boolean okFlag = true;
+ try {
+ thisVtx.remove();
+ deleteCount++;
+ thisNtDeleteCount++;
+ } catch (Exception e) {
+ okFlag = false;
+ String msg = "ERROR trying to delete phantom VID = " + thisVid;
+ logline.add(msg, e.getMessage());
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ logline.add("DELETED VID:", thisVid);
+ System.out.println(" DELETED VID = " + thisVid);
+ }
+ } else {
+ ghostNodeHash.put(thisVid, thisVtx);
+ }
+ }
+ else if( (secondGetList.size() > 1) && depNodeOk && !dupeCheckOff ){
+ // Found some DUPLICATES - need to process them
+ System.out.print(" - now check Dupes for this guy - ");
+ ArrayList<String> tmpDupeGroups = checkAndProcessDupes(
+ TRANSID, FROMAPPID, g, version,
+ nType, secondGetList, dupeFixOn,
+ deleteCandidateList, singleCommits, dupeGroups, dbMaps);
+ Iterator<String> dIter = tmpDupeGroups.iterator();
+ while (dIter.hasNext()) {
+ // Add in any newly found dupes to our running list
+ String tmpGrp = dIter.next();
+ System.out.println("Found set of dupes: [" + tmpGrp + "]");
+ dupeGroups.add(tmpGrp);
+ }
+ }
+ }
+ catch (AAIException e1) {
+ String msg = " For nodeType = " + nType + " Caught this exception: "
+ + e1.getErrorObject().toString();
+ System.out.println(msg);
+ errArr.add(msg);
+ }
+ catch (Exception e2) {
+ String msg = " For nodeType = " + nType
+ + " Caught this exception: "
+ + e2.toString();
+ System.out.println(msg);
+ errArr.add(msg);
+ }
+ }// try block to enclose looping of a single vertex
+ catch (Exception exx) {
+ String msg = "WARNING from inside the while-verts-loop ";
+ logline.add(msg, exx.getMessage());
+ System.out.println(msg + exx.getMessage()
+ + exx.toString());
+ }
+
+ } // while loop for each record of a nodeType
+
+ if ( (thisNtDeleteCount > 0) && singleCommits ) {
+ g.commit();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ }
+ thisNtDeleteCount = 0;
+ System.out.println( " Processed " + thisNtCount + " records for [" + nType + "], " + totalNodeCount + " total overall. " );
+
+ }// While-loop for each node type
+ }// end of check to make sure we weren't only supposed to do edges
+
+
+ // --------------------------------------------------------------------------------------
+ // Now, we're going to look for one-armed-edges. Ie. an edge that
+ // should have
+ // been deleted (because a vertex on one side was deleted) but
+ // somehow was not deleted.
+ // So the one end of it points to a vertexId -- but that vertex is
+ // empty.
+ // --------------------------------------------------------------------------------------
+
+ // To do some strange checking - we need a second graph object
+ System.out.println(" ---- DEBUG --- about to open a SECOND graph (takes a little while)--------\n");
+ graph2 = TitanFactory.open(AAIConstants.AAI_CONFIG_FILENAME);
+
+ if (graph2 == null) {
+ String emsg = "null graph2 object in DataGrooming\n";
+ throw new AAIException("AAI_6101", emsg);
+ } else {
+ System.out.println("Got the graph2 object... \n");
+ }
+ g2 = graph2.newTransaction();
+ if (g2 == null) {
+ String emsg = "null graphTransaction2 object in DataGrooming\n";
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ ArrayList<Vertex> vertList = new ArrayList<Vertex>();
+ Iterable vIt3 = g.query().vertices();
+ Iterator<Vertex> vItor3 = vIt3.iterator();
+ // Gotta hold these in a List - or else HBase times out as you cycle
+ // through these
+ while (vItor3.hasNext()) {
+ Vertex v = vItor3.next();
+ vertList.add(v);
+ }
+ int counter = 0;
+ int lastShown = 0;
+ Iterator<Vertex> vItor2 = vertList.iterator();
+ System.out.println(" Checking for bad edges --- ");
+
+ while (vItor2.hasNext()) {
+ Vertex v = null;
+ try {
+ try {
+ v = vItor2.next();
+ } catch (Exception vex) {
+ String msg = ">>> WARNING trying to get next vertex on the vItor2 ";
+ logline.add(msg, vex.getMessage());
+ System.out.println(msg + vex.getMessage());
+ continue;
+ }
+
+ counter++;
+ String thisVertId = "";
+ try {
+ thisVertId = v.id().toString();
+ } catch (Exception ev) {
+ String msg = "WARNING when doing getId() on a vertex from our vertex list. ";
+ logline.add(msg, ev.getMessage());
+ System.out.println(msg);
+ continue;
+ }
+ if (ghostNodeHash.containsKey(thisVertId)) {
+ // This is a phantom node, so don't try to use it
+ System.out
+ .println(" >> Skipping edge check for edges from vertexId = "
+ + thisVertId
+ + ", since that guy is a Phantom Node");
+ continue;
+ }
+ if (counter == lastShown + 250) {
+ lastShown = counter;
+ System.out.println("... Checking edges for vertex # "
+ + counter);
+ }
+ Iterator<Edge> eItor = v.edges(Direction.BOTH);
+ while (eItor.hasNext()) {
+ Edge e = null;
+ Vertex vIn = null;
+ Vertex vOut = null;
+ try {
+ e = eItor.next();
+ } catch (Exception iex) {
+ String msg = ">>> WARNING trying to get next edge on the eItor ";
+ logline.add(msg, iex.getMessage());
+ System.out.println(msg + iex.getMessage());
+ continue;
+ }
+
+ try {
+ vIn = e.inVertex();
+ } catch (Exception err) {
+ String msg = ">>> WARNING trying to get edge's In-vertex ";
+ logline.add(msg, err.getMessage());
+ System.out.println(msg + err.getMessage());
+ }
+ String vNtI = "";
+ String vIdI = "";
+ TitanVertex ghost2 = null;
+
+ Boolean keysMissing = true;
+ Boolean cantGetUsingVid = false;
+ if (vIn != null) {
+ try {
+ Object ob = vIn.<Object>property("aai-node-type").orElse(null);
+ if (ob != null) {
+ vNtI = ob.toString();
+ keysMissing = anyKeyFieldsMissing(vNtI, vIn);
+ }
+ ob = vIn.id();
+ long vIdLong = 0L;
+ if (ob != null) {
+ vIdI = ob.toString();
+ vIdLong = Long.parseLong(vIdI);
+ }
+
+ if( ! ghost2CheckOff ){
+ TitanVertex connectedVert = g2.getVertex(vIdLong);
+ if( connectedVert == null ) {
+ System.out.println( "GHOST2 -- got NULL when doing getVertex for vid = " + vIdLong);
+ cantGetUsingVid = true;
+
+ // If we can NOT get this ghost with the SECOND graph-object,
+ // it is still a ghost since even though we can get data about it using the FIRST graph
+ // object.
+ try {
+ ghost2 = g.getVertex(vIdLong);
+ }
+ catch( Exception ex){
+ System.out.println( "GHOST2 -- Could not get the ghost info for a bad edge for vtxId = " + vIdLong);
+ }
+ if( ghost2 != null ){
+ ghostNodeHash.put(vIdI, ghost2);
+ }
+ }
+ }// end of the ghost2 checking
+ }
+ catch (Exception err) {
+ String msg = ">>> WARNING trying to get edge's In-vertex props ";
+ logline.add(msg, err.getMessage());
+ System.out.println(msg + err.getMessage());
+ }
+ }
+ if (keysMissing || vIn == null || vNtI.equals("")
+ || cantGetUsingVid) {
+ // this is a bad edge because it points to a vertex
+ // that isn't there anymore or is corrupted
+ String thisEid = e.id().toString();
+ if (deleteCandidateList.contains(thisEid) || deleteCandidateList.contains(vIdI)) {
+ boolean okFlag = true;
+ if (!vIdI.equals("")) {
+ // try to get rid of the corrupted vertex
+ try {
+ if( (ghost2 != null) && ghost2FixOn ){
+ ghost2.remove();
+ }
+ else {
+ vIn.remove();
+ }
+ if (singleCommits) {
+ g.commit();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ }
+ deleteCount++;
+ } catch (Exception e1) {
+ okFlag = false;
+ String msg = "WARNING when trying to delete bad-edge-connected VERTEX VID = "
+ + vIdI;
+ logline.add(msg, e1.getMessage());
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ logline.add(
+ "DELETED vertex on a bad edge = ",
+ vIdI);
+ System.out
+ .println(" DELETED vertex from bad edge = "
+ + vIdI);
+ }
+ } else {
+ // remove the edge if we couldn't get the
+ // vertex
+ try {
+ e.remove();
+ if (singleCommits) {
+ g.commit();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ }
+ deleteCount++;
+ } catch (Exception ex) {
+ // NOTE - often, the exception is just
+ // that this edge has already been
+ // removed
+ okFlag = false;
+ String msg = "WARNING when trying to delete edge = "
+ + thisEid;
+ logline.add(msg, ex.getMessage());
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ logline.add("DELETED edge = ", thisEid);
+ System.out.println(" DELETED edge = "
+ + thisEid);
+ }
+ }
+ } else {
+ oneArmedEdgeHash.put(thisEid, e);
+ if ((vIn != null) && (vIn.id() != null)) {
+ emptyVertexHash.put(thisEid, vIn.id()
+ .toString());
+ }
+ }
+ }
+
+ try {
+ vOut = e.outVertex();
+ } catch (Exception err) {
+ String msg = ">>> WARNING trying to get edge's Out-vertex ";
+ logline.add(msg, err.getMessage());
+ System.out.println(msg + err.getMessage());
+ }
+ String vNtO = "";
+ String vIdO = "";
+ ghost2 = null;
+ keysMissing = true;
+ cantGetUsingVid = false;
+ if (vOut != null) {
+ try {
+ Object ob = vOut.<Object>property("aai-node-type").orElse(null);
+ if (ob != null) {
+ vNtO = ob.toString();
+ keysMissing = anyKeyFieldsMissing(vNtO,
+ vOut);
+ }
+ ob = vOut.id();
+ long vIdLong = 0L;
+ if (ob != null) {
+ vIdO = ob.toString();
+ vIdLong = Long.parseLong(vIdO);
+ }
+
+ if( ! ghost2CheckOff ){
+ TitanVertex connectedVert = g2.getVertex(vIdLong);
+ if( connectedVert == null ) {
+ cantGetUsingVid = true;
+ System.out.println( "GHOST2 -- got NULL when doing getVertex for vid = " + vIdLong);
+ // If we can get this ghost with the other graph-object, then get it -- it's still a ghost
+ try {
+ ghost2 = g.getVertex(vIdLong);
+ }
+ catch( Exception ex){
+ System.out.println( "GHOST2 -- Could not get the ghost info for a bad edge for vtxId = " + vIdLong);
+ }
+ if( ghost2 != null ){
+ ghostNodeHash.put(vIdO, ghost2);
+ }
+ }
+ }
+ } catch (Exception err) {
+ String msg = ">>> WARNING trying to get edge's Out-vertex props ";
+ logline.add(msg, err.getMessage());
+ System.out.println(msg + err.getMessage());
+ }
+ }
+ if (keysMissing || vOut == null || vNtO.equals("")
+ || cantGetUsingVid) {
+ // this is a bad edge because it points to a vertex
+ // that isn't there anymore
+ String thisEid = e.id().toString();
+ if (deleteCandidateList.contains(thisEid) || deleteCandidateList.contains(vIdO)) {
+ boolean okFlag = true;
+ if (!vIdO.equals("")) {
+ // try to get rid of the corrupted vertex
+ try {
+ if( (ghost2 != null) && ghost2FixOn ){
+ ghost2.remove();
+ }
+ else {
+ vOut.remove();
+ }
+ if (singleCommits) {
+ g.commit();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ }
+ deleteCount++;
+ } catch (Exception e1) {
+ okFlag = false;
+ String msg = "WARNING when trying to delete bad-edge-connected VID = "
+ + vIdO;
+ logline.add(msg, e1.getMessage());
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ logline.add(
+ "DELETED vertex on a bad edge = ",
+ vIdO);
+ System.out
+ .println(" DELETED vertex from bad edge = "
+ + vIdO);
+ }
+ } else {
+ // remove the edge if we couldn't get the
+ // vertex
+ try {
+ e.remove();
+ if (singleCommits) {
+ g.commit();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ }
+ deleteCount++;
+ } catch (Exception ex) {
+ // NOTE - often, the exception is just
+ // that this edge has already been
+ // removed
+ okFlag = false;
+ String msg = "WARNING when trying to delete edge = "
+ + thisEid;
+ logline.add(msg, ex.getMessage());
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ logline.add("DELETED edge = ", thisEid);
+ System.out.println(" DELETED edge = "
+ + thisEid);
+ }
+ }
+ } else {
+ oneArmedEdgeHash.put(thisEid, e);
+ if ((vOut != null) && (vOut.id() != null)) {
+ emptyVertexHash.put(thisEid, vOut.id()
+ .toString());
+ }
+ }
+ }
+ }// End of while-edges-loop
+ } catch (Exception exx) {
+ String msg = "WARNING from in the while-verts-loop ";
+ logline.add(msg, exx.getMessage());
+ System.out.println(msg);
+ }
+ }// End of while-vertices-loop
+
+ deleteCount = deleteCount + dupeGrpsDeleted;
+ if (!singleCommits && deleteCount > 0) {
+ try {
+ System.out.println("About to do the commit for "
+ + deleteCount + " removes. ");
+ g.commit();
+ System.out.println("Commit was successful ");
+ } catch (Exception excom) {
+ String msg = " >>>> ERROR <<<< Could not commit changes. ";
+ logline.add(msg, excom.getMessage());
+ System.out.println(msg);
+ deleteCount = 0;
+ }
+ }
+
+ int ghostNodeCount = ghostNodeHash.size();
+ int orphanNodeCount = orphanNodeHash.size();
+ int missingDepNodeCount = missingDepNodeHash.size();
+ int oneArmedEdgeCount = oneArmedEdgeHash.size();
+ int dupeCount = dupeGroups.size();
+
+ deleteCount = deleteCount + dupeGrpsDeleted;
+
+ bw.write("\n\n ============ Summary ==============\n");
+ bw.write("Ran these nodeTypes: " + ntList + "\n\n");
+ bw.write("There were this many delete candidates from previous run = "
+ + deleteCandidateList.size() + "\n");
+ if (dontFixOrphansFlag) {
+ bw.write(" Note - we are not counting orphan nodes since the -dontFixOrphans parameter was used. \n");
+ }
+ bw.write("Deleted this many delete candidates = " + deleteCount
+ + "\n");
+ bw.write("Total number of nodes looked at = " + totalNodeCount
+ + "\n");
+ bw.write("Ghost Nodes identified = " + ghostNodeCount + "\n");
+ bw.write("Orphan Nodes identified = " + orphanNodeCount + "\n");
+ bw.write("Bad Edges identified = " + oneArmedEdgeCount + "\n");
+ bw.write("Missing Dependent Edge (but not orphaned) node count = "
+ + missingDepNodeCount + "\n");
+ bw.write("Duplicate Groups count = " + dupeCount + "\n");
+ bw.write("MisMatching Label/aai-node-type count = "
+ + misMatchedHash.size() + "\n");
+
+ bw.write("\n ------------- Delete Candidates ---------\n");
+ for (Map.Entry<String, TitanVertex> entry : ghostNodeHash
+ .entrySet()) {
+ String vid = entry.getKey();
+ bw.write("DeleteCandidate: Phantom Vid = [" + vid + "]\n");
+ cleanupCandidateCount++;
+ }
+ for (Map.Entry<String, TitanVertex> entry : orphanNodeHash
+ .entrySet()) {
+ String vid = entry.getKey();
+ bw.write("DeleteCandidate: OrphanDepNode Vid = [" + vid + "]\n");
+ if (!dontFixOrphansFlag) {
+ cleanupCandidateCount++;
+ }
+ }
+ for (Map.Entry<String, Edge> entry : oneArmedEdgeHash.entrySet()) {
+ String eid = entry.getKey();
+ bw.write("DeleteCandidate: Bad EDGE Edge-id = [" + eid + "]\n");
+ cleanupCandidateCount++;
+ }
+ for (Map.Entry<String, TitanVertex> entry : missingDepNodeHash
+ .entrySet()) {
+ String vid = entry.getKey();
+ bw.write("DeleteCandidate: (maybe) missingDepNode Vid = ["
+ + vid + "]\n");
+ cleanupCandidateCount++;
+ }
+ bw.write("\n-- NOTE - To see DeleteCandidates for Duplicates, you need to look in the Duplicates Detail section below.\n");
+
+ bw.write("\n ------------- GHOST NODES - detail ");
+ for (Map.Entry<String, TitanVertex> entry : ghostNodeHash
+ .entrySet()) {
+ try {
+ String vid = entry.getKey();
+ bw.write("\n ==> Phantom Vid = " + vid + "\n");
+ ArrayList<String> retArr = DbMeth.showPropertiesForNode(
+ TRANSID, FROMAPPID, entry.getValue());
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+
+ retArr = DbMeth.showAllEdgesForNode(TRANSID, FROMAPPID,
+ entry.getValue());
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+ } catch (Exception dex) {
+ String msg = "error trying to print detail info for a ghost-node: ";
+ logline.add(msg, dex.getMessage());
+ System.out.println(msg);
+ }
+ }
+
+ bw.write("\n ------------- Missing Dependent Edge ORPHAN NODES - detail: ");
+ for (Map.Entry<String, TitanVertex> entry : orphanNodeHash
+ .entrySet()) {
+ try {
+ String vid = entry.getKey();
+ bw.write("\n> Orphan Node Vid = " + vid + "\n");
+ ArrayList<String> retArr = DbMeth.showPropertiesForNode(
+ TRANSID, FROMAPPID, entry.getValue());
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+
+ retArr = DbMeth.showAllEdgesForNode(TRANSID, FROMAPPID,
+ entry.getValue());
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+ } catch (Exception dex) {
+ String msg = "error trying to print detail info for a Orphan Node /missing dependent edge: ";
+ logline.add(msg, dex.getMessage());
+ System.out.println(msg);
+ }
+ }
+
+ bw.write("\n ------------- Missing Dependent Edge (but not orphan) NODES: ");
+ for (Map.Entry<String, TitanVertex> entry : missingDepNodeHash
+ .entrySet()) {
+ try {
+ String vid = entry.getKey();
+ bw.write("\n> Missing edge to Dependent Node (but has edges) Vid = "
+ + vid + "\n");
+ ArrayList<String> retArr = DbMeth.showPropertiesForNode(
+ TRANSID, FROMAPPID, entry.getValue());
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+
+ retArr = DbMeth.showAllEdgesForNode(TRANSID, FROMAPPID,
+ entry.getValue());
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+ } catch (Exception dex) {
+ String msg = "error trying to print detail info for a node missing its dependent edge but not an orphan: ";
+ logline.add(msg, dex.getMessage());
+ System.out.println(msg);
+ }
+ }
+
+ bw.write("\n ------------- EDGES pointing to empty/bad vertices: ");
+ for (Map.Entry<String, Edge> entry : oneArmedEdgeHash.entrySet()) {
+ try {
+ String eid = entry.getKey();
+ Edge thisE = entry.getValue();
+ String badVid = emptyVertexHash.get(eid);
+ bw.write("\n> Edge pointing to bad vertex (Vid = "
+ + badVid + ") EdgeId = " + eid + "\n");
+ bw.write("Label: [" + thisE.label() + "]\n");
+ Iterator<Property<Object>> pI = thisE.properties();
+ while (pI.hasNext()) {
+ Property<Object> propKey = pI.next();
+ bw.write("Prop: [" + propKey + "], val = ["
+ + propKey.value() + "]\n");
+ }
+ } catch (Exception pex) {
+ String msg = "error trying to print empty/bad vertex data: ";
+ logline.add(msg, pex.getMessage());
+ System.out.println(msg);
+ }
+ }
+
+ bw.write("\n ------------- Duplicates: ");
+ Iterator<String> dupeIter = dupeGroups.iterator();
+ int dupeSetCounter = 0;
+ while (dupeIter.hasNext()) {
+ dupeSetCounter++;
+ String dset = (String) dupeIter.next();
+
+ bw.write("\n --- Duplicate Group # " + dupeSetCounter
+ + " Detail -----------\n");
+ try {
+ // We expect each line to have at least two vid's, followed
+ // by the preferred one to KEEP
+ String[] dupeArr = dset.split("\\|");
+ ArrayList<String> idArr = new ArrayList<String>();
+ int lastIndex = dupeArr.length - 1;
+ for (int i = 0; i <= lastIndex; i++) {
+ if (i < lastIndex) {
+ // This is not the last entry, it is one of the
+ // dupes, so we want to show all its info
+ bw.write(" >> Duplicate Group # "
+ + dupeSetCounter + " Node # " + i
+ + " ----\n");
+ String vidString = dupeArr[i];
+ idArr.add(vidString);
+ long longVertId = Long.parseLong(vidString);
+ Iterator<Vertex> vtxIterator = graph.vertices(longVertId);
+ TitanVertex vtx = null;
+ if (vtxIterator.hasNext()) {
+ vtx = (TitanVertex)vtxIterator.next();
+ }
+ ArrayList<String> retArr = DbMeth
+ .showPropertiesForNode(TRANSID, FROMAPPID,
+ vtx);
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+
+ retArr = DbMeth.showAllEdgesForNode(TRANSID,
+ FROMAPPID, vtx);
+ for (String info : retArr) {
+ bw.write(info + "\n");
+ }
+ } else {
+ // This is the last entry which should tell us if we
+ // have a preferred keeper
+ String prefString = dupeArr[i];
+ if (prefString.equals("KeepVid=UNDETERMINED")) {
+ bw.write("\n For this group of duplicates, could not tell which one to keep.\n");
+ bw.write(" >>> This group needs to be taken care of with a manual/forced-delete.\n");
+ } else {
+ // If we know which to keep, then the prefString
+ // should look like, "KeepVid=12345"
+ String[] prefArr = prefString.split("=");
+ if (prefArr.length != 2
+ || (!prefArr[0].equals("KeepVid"))) {
+ String msg = "Bad format. Expecting KeepVid=999999";
+ System.out.println(msg);
+ throw new Exception(msg);
+ } else {
+ String keepVidStr = prefArr[1];
+ if (idArr.contains(keepVidStr)) {
+ bw.write("\n The vertex we want to KEEP has vertexId = "
+ + keepVidStr);
+ bw.write("\n The others become delete candidates: \n");
+ idArr.remove(keepVidStr);
+ for (int x = 0; x < idArr.size(); x++) {
+ cleanupCandidateCount++;
+ bw.write("DeleteCandidate: Duplicate Vid = ["
+ + idArr.get(x) + "]\n");
+ }
+ } else {
+ String msg = "ERROR - Vertex Id to keep not found in list of dupes. dset = ["
+ + dset + "]";
+ System.out.println(msg);
+ throw new Exception(msg);
+ }
+ }
+ }// else we know which one to keep
+ }// else last entry
+ }// for each vertex in a group
+ } catch (Exception dex) {
+ String msg = "error trying to print duplicate vertex data: ";
+ logline.add(msg, dex.getMessage());
+ System.out.println(msg);
+ }
+
+ }// while - work on each group of dupes
+
+ bw.write("\n ------------- Mis-matched Label/aai-node-type Nodes: \n ");
+ for (Map.Entry<String, String> entry : misMatchedHash.entrySet()) {
+ String msg = entry.getValue();
+ bw.write("MixedMsg = " + msg + "\n");
+ }
+
+ bw.write("\n ------------- Got these errors while processing: \n");
+ Iterator<String> errIter = errArr.iterator();
+ while (errIter.hasNext()) {
+ String line = (String) errIter.next();
+ bw.write(line + "\n");
+ }
+
+ bw.close();
+
+ System.out
+ .println("\n ------------- Done doing all the checks ------------ ");
+ System.out.println("Output will be written to "
+ + fullOutputFileName);
+
+ if (cleanupCandidateCount > 0) {
+ // Technically, this is not an error -- but we're throwing this
+ // error so that hopefully a
+ // monitoring system will pick it up and do something with it.
+ String emsg = "See file: [" + fullOutputFileName
+ + "] and investigate delete candidates. ";
+ throw new AAIException("AAI_6123", emsg);
+ }
+
+ aaiLogger.info(logline, true, "0");
+ } catch (AAIException e) {
+ System.out.print("Threw a AAIException: \n");
+ System.out.println(e.getErrorObject().toString());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ } catch (Exception ex) {
+ System.out.print("Threw a regular Exception:\n");
+ System.out.println(ex.getMessage());
+ aaiLogger.error(
+ ErrorLogHelper.getErrorObject("AAI_6128", ex.getMessage()
+ + ", resolve and rerun dataGrooming"), logline, ex);
+ aaiLogger.info(logline, false, "AAI_6128");
+ } finally {
+ if (g != null) {
+ // Any changes that worked correctly should have already done
+ // their commits.
+ g.rollback();
+ graph.close();
+ }
+
+ if (bw != null) {
+ try {
+ bw.close();
+ } catch (IOException iox) {
+ String emsg = "Got an IOException trying to close bufferedWriter() \n";
+ logline.add("emsg", emsg);
+ }
+ }
+
+ if (g != null) {
+ // Any changes that worked correctly should have already done
+ // their commits.
+ try {
+ g.rollback();
+ } catch (Exception ex) {
+ // Don't throw anything because Titan sometimes is just saying that the graph is already closed
+ System.out.println("WARNING from final graphTransaction.rollback(): " + ex.getMessage() );
+ }
+ }
+
+ if (g2 != null) {
+ // Any changes that worked correctly should have already done
+ // their commits.
+ try {
+ g2.rollback();
+ } catch (Exception ex) {
+ // Don't throw anything because Titan sometimes is just saying that the graph is already closed
+ System.out.println("WARNING from final graphTransaction2.rollback(): " + ex.getMessage() );
+ }
+ }
+
+ if( finalShutdownFlag ){
+ try {
+ if( graph != null && graph.isOpen() ){
+ graph.tx().close();
+ graph.close();
+ }
+ } catch (Exception ex) {
+ // Don't throw anything because Titan sometimes is just saying that the graph is already closed{
+ System.out.println("WARNING from final graph.shutdown(): " + ex.getMessage() );
+ }
+
+ try {
+ if( graph2 != null && graph2.isOpen() ){
+ graph2.tx().close();
+ graph2.close();
+ }
+ } catch (Exception ex) {
+ // Don't throw anything because Titan sometimes is just saying that the graph is already closed{
+ System.out.println("WARNING from final graph2.shutdown(): " + ex.getMessage() );
+ }
+ }
+
+ }
+
+ return cleanupCandidateCount;
+
+ }// end of doTheGrooming()
+
+
+ /**
+ * Vertex has these keys.
+ *
+ * @param tmpV the tmp V
+ * @param propHashWithKeys the prop hash with keys
+ * @return the boolean
+ */
+ private static Boolean vertexHasTheseKeys( TitanVertex tmpV, HashMap <String, Object> propHashWithKeys) {
+ Iterator <?> it = propHashWithKeys.entrySet().iterator();
+ while( it.hasNext() ){
+ String propName = "";
+ String propVal = "";
+ Map.Entry <?,?>propEntry = (Map.Entry<?,?>)it.next();
+ Object propNameObj = propEntry.getKey();
+ if( propNameObj != null ){
+ propName = propNameObj.toString();
+ }
+ Object propValObj = propEntry.getValue();
+ if( propValObj != null ){
+ propVal = propValObj.toString();
+ }
+ Object checkValObj = tmpV.<Object>property(propName).orElse(null);
+ if( checkValObj == null ) {
+ return false;
+ }
+ else if( !propVal.equals(checkValObj.toString()) ){
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Any key fields missing.
+ *
+ * @param nType the n type
+ * @param v the v
+ * @return the boolean
+ */
+ private static Boolean anyKeyFieldsMissing(String nType, Vertex v) {
+
+ try {
+ Collection<String> keyProps = DbMeth.getNodeKeyPropNames(TRANSID,
+ FROMAPPID, nType, "junkversion");
+ Iterator<String> keyPropI = keyProps.iterator();
+ while (keyPropI.hasNext()) {
+ String propName = keyPropI.next();
+ Object ob = v.<Object>property(propName).orElse(null);
+ if (ob == null || ob.toString().equals("")) {
+ // It is missing a key property
+ return true;
+ }
+ }
+ } catch (AAIException e) {
+ // Something was wrong
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Gets the delete list.
+ *
+ * @param targetDir the target dir
+ * @param fileName the file name
+ * @param edgesOnlyFlag the edges only flag
+ * @param dontFixOrphans the dont fix orphans
+ * @param dupeFixOn the dupe fix on
+ * @return the delete list
+ * @throws AAIException the AAI exception
+ */
+ private static ArrayList<String> getDeleteList(String targetDir,
+ String fileName, Boolean edgesOnlyFlag, Boolean dontFixOrphans,
+ Boolean dupeFixOn) throws AAIException {
+
+ // Look in the file for lines formated like we expect - pull out any
+ // Vertex Id's to delete on this run
+ ArrayList<String> delList = new ArrayList<String>();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", TRANSID, FROMAPPID, "getDeleteList");
+
+ String fullFileName = targetDir + AAIConstants.AAI_FILESEP + fileName;
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new FileReader(fullFileName));
+ String line = br.readLine();
+ while (line != null) {
+ if (!line.equals("") && line.startsWith("DeleteCandidate")) {
+ if (edgesOnlyFlag && (!line.contains("Bad Edge"))) {
+ // We're not going to process edge guys
+ } else if (dontFixOrphans && line.contains("Orphan")) {
+ // We're not going to process orphans
+ } else if (!dupeFixOn && line.contains("Duplicate")) {
+ // We're not going to process Duplicates
+ } else {
+ int begIndex = line.indexOf("id = ");
+ int endIndex = line.indexOf("]");
+ String vidVal = line.substring(begIndex + 6, endIndex);
+ delList.add(vidVal);
+ }
+ }
+ line = br.readLine();
+ }
+ br.close();
+ } catch (IOException e) {
+ String emsg = "Could not open input-file [" + fullFileName
+ + "], exception= " + e.getMessage();
+ aaiLogger.info(logline, false, "AAI_6124");
+ throw new AAIException("AAI_6124", e, emsg);
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return delList;
+
+ }// end of getDeleteList
+
+ /**
+ * Gets the preferred dupe.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param g the g
+ * @param dupeVertexList the dupe vertex list
+ * @param ver the ver
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getPreferredDupe(String transId,
+ String fromAppId, TitanTransaction g,
+ ArrayList<TitanVertex> dupeVertexList, String ver)
+ throws AAIException {
+
+ // This method assumes that it is being passed a List of vertex objects
+ // which
+ // violate our uniqueness constraints.
+
+ TitanVertex nullVtx = null;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getPreferredDupe");
+
+ if (dupeVertexList == null) {
+ return nullVtx;
+ }
+ int listSize = dupeVertexList.size();
+ if (listSize == 0) {
+ return nullVtx;
+ }
+ if (listSize == 1) {
+ return ((TitanVertex) dupeVertexList.get(0));
+ }
+
+ TitanVertex vtxPreferred = null;
+ TitanVertex currentFaveVtx = (TitanVertex) dupeVertexList.get(0);
+ for (int i = 1; i < listSize; i++) {
+ TitanVertex vtxB = (TitanVertex) dupeVertexList.get(i);
+ vtxPreferred = pickOneOfTwoDupes(transId, fromAppId, g,
+ currentFaveVtx, vtxB, ver);
+ if (vtxPreferred == null) {
+ // We couldn't choose one
+ return nullVtx;
+ } else {
+ currentFaveVtx = vtxPreferred;
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return (currentFaveVtx);
+
+ } // end of getPreferredDupe()
+
+ /**
+ * Pick one of two dupes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param g the g
+ * @param vtxA the vtx A
+ * @param vtxB the vtx B
+ * @param ver the ver
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex pickOneOfTwoDupes(String transId,
+ String fromAppId, TitanTransaction g, TitanVertex vtxA,
+ TitanVertex vtxB, String ver) throws AAIException {
+
+ TitanVertex nullVtx = null;
+ TitanVertex preferredVtx = null;
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "pickOneOfTwoDupes");
+
+ Long vidA = new Long(vtxA.id().toString());
+ Long vidB = new Long(vtxB.id().toString());
+
+ // System.out.println( ">> choosing between vtxId = " + vidA +
+ // ", and vtxIdB = " + vidB );
+
+ String vtxANodeType = "";
+ String vtxBNodeType = "";
+ Object obj = vtxA.<Object>property("aai-node-type").orElse(null);
+ if (obj != null) {
+ vtxANodeType = obj.toString();
+ }
+ obj = vtxB.<Object>property("aai-node-type").orElse(null);
+ if (obj != null) {
+ vtxBNodeType = obj.toString();
+ }
+
+ if (vtxANodeType.equals("") || (!vtxANodeType.equals(vtxBNodeType))) {
+ // Either they're not really dupes or there's some bad data - so
+ // don't pick one
+ return nullVtx;
+ }
+
+ // Check that node A and B both have the same key values (or else they
+ // are not dupes)
+ // (We'll check dep-node later)
+ Collection<String> keyProps = DbMeth.getNodeKeyPropNames(transId,
+ fromAppId, vtxANodeType, ver);
+ Iterator<String> keyPropI = keyProps.iterator();
+ while (keyPropI.hasNext()) {
+ String propName = keyPropI.next();
+ String vtxAKeyPropVal = "";
+ obj = vtxA.<Object>property(propName).orElse(null);
+ if (obj != null) {
+ vtxAKeyPropVal = obj.toString();
+ }
+ String vtxBKeyPropVal = "";
+ obj = vtxB.<Object>property(propName).orElse(null);
+ if (obj != null) {
+ vtxBKeyPropVal = obj.toString();
+ }
+
+ if (vtxAKeyPropVal.equals("")
+ || (!vtxAKeyPropVal.equals(vtxBKeyPropVal))) {
+ // Either they're not really dupes or they are missing some key
+ // data - so don't pick one
+ return nullVtx;
+ }
+ }
+
+ // Collect the vid's and aai-node-types of the vertices that each vertex
+ // (A and B) is connected to.
+ HashMap emptyHash = new HashMap();
+ ArrayList<String> vtxIdsConn2A = new ArrayList<String>();
+ ArrayList<String> vtxIdsConn2B = new ArrayList<String>();
+ HashMap<String, String> nodeTypesConn2A = new HashMap<String, String>();
+ HashMap<String, String> nodeTypesConn2B = new HashMap<String, String>();
+
+ ArrayList<TitanVertex> vertListA = DbMeth.getConnectedNodes("transId",
+ "fromAppId", g, "", emptyHash, vtxA, ver, false);
+ if (vertListA != null) {
+ Iterator<TitanVertex> iter = vertListA.iterator();
+ while (iter.hasNext()) {
+ TitanVertex tvCon = iter.next();
+ String conVid = tvCon.id().toString();
+ String nt = "";
+ obj = tvCon.<Object>property("aai-node-type").orElse(null);
+ if (obj != null) {
+ nt = obj.toString();
+ }
+ nodeTypesConn2A.put(nt, conVid);
+ vtxIdsConn2A.add(conVid);
+ }
+ }
+
+ ArrayList<TitanVertex> vertListB = DbMeth.getConnectedNodes("transId",
+ "fromAppId", g, "", emptyHash, vtxB, ver, false);
+ if (vertListB != null) {
+ Iterator<TitanVertex> iter = vertListB.iterator();
+ while (iter.hasNext()) {
+ TitanVertex tvCon = iter.next();
+ String conVid = tvCon.id().toString();
+ String nt = "";
+ obj = tvCon.<Object>property("aai-node-type").orElse(null);
+ if (obj != null) {
+ nt = obj.toString();
+ }
+ nodeTypesConn2B.put(nt, conVid);
+ vtxIdsConn2B.add(conVid);
+ }
+ }
+
+ // 1 - If this kind of node needs a dependent node for uniqueness, then
+ // verify that they both nodes
+ // point to the same dependent node (otherwise they're not really
+ // duplicates)
+ // Note - there are sometimes more than one dependent node type since
+ // one nodeType can be used in
+ // different ways. But for a particular node, it will only have one
+ // dependent node that it's
+ // connected to.
+ ArrayList<String> depNodeTypes = DbMeth.getDepNodeTypes(transId,
+ fromAppId, vtxANodeType, ver);
+ if (depNodeTypes.isEmpty()) {
+ // This kind of node is not dependent on any other. That is ok.
+ } else {
+ String depNodeVtxId4A = "";
+ String depNodeVtxId4B = "";
+ Iterator<String> iter = depNodeTypes.iterator();
+ while (iter.hasNext()) {
+ String depNodeType = iter.next();
+ if (nodeTypesConn2A.containsKey(depNodeType)) {
+ // This is the dependent node type that vertex A is using
+ depNodeVtxId4A = nodeTypesConn2A.get(depNodeType);
+ }
+ if (nodeTypesConn2B.containsKey(depNodeType)) {
+ // This is the dependent node type that vertex B is using
+ depNodeVtxId4B = nodeTypesConn2B.get(depNodeType);
+ }
+ }
+ if (depNodeVtxId4A.equals("")
+ || (!depNodeVtxId4A.equals(depNodeVtxId4B))) {
+ // Either they're not really dupes or there's some bad data - so
+ // don't pick either one
+ return nullVtx;
+ }
+ }
+
+ if (vtxIdsConn2A.size() == vtxIdsConn2B.size()) {
+ // 2 - If they both have edges to all the same vertices, then return
+ // the one with the lower vertexId.
+ boolean allTheSame = true;
+ Iterator<String> iter = vtxIdsConn2A.iterator();
+ while (iter.hasNext()) {
+ String vtxIdConn2A = iter.next();
+ if (!vtxIdsConn2B.contains(vtxIdConn2A)) {
+ allTheSame = false;
+ break;
+ }
+ }
+
+ if (allTheSame) {
+ if (vidA < vidB) {
+ preferredVtx = vtxA;
+ } else {
+ preferredVtx = vtxB;
+ }
+ }
+ } else if (vtxIdsConn2A.size() > vtxIdsConn2B.size()) {
+ // 3 - VertexA is connected to more things than vtxB.
+ // We'll pick VtxA if its edges are a superset of vtxB's edges.
+ boolean missingOne = false;
+ Iterator<String> iter = vtxIdsConn2B.iterator();
+ while (iter.hasNext()) {
+ String vtxIdConn2B = iter.next();
+ if (!vtxIdsConn2A.contains(vtxIdConn2B)) {
+ missingOne = true;
+ break;
+ }
+ }
+ if (!missingOne) {
+ preferredVtx = vtxA;
+ }
+ } else if (vtxIdsConn2B.size() > vtxIdsConn2A.size()) {
+ // 4 - VertexB is connected to more things than vtxA.
+ // We'll pick VtxB if its edges are a superset of vtxA's edges.
+ boolean missingOne = false;
+ Iterator<String> iter = vtxIdsConn2A.iterator();
+ while (iter.hasNext()) {
+ String vtxIdConn2A = iter.next();
+ if (!vtxIdsConn2B.contains(vtxIdConn2A)) {
+ missingOne = true;
+ break;
+ }
+ }
+ if (!missingOne) {
+ preferredVtx = vtxB;
+ }
+ } else {
+ preferredVtx = nullVtx;
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return (preferredVtx);
+
+ } // end of pickOneOfTwoDupes()
+
+ /**
+ * Check and process dupes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param g the g
+ * @param version the version
+ * @param nType the n type
+ * @param passedVertList the passed vert list
+ * @param dupeFixOn the dupe fix on
+ * @param deleteCandidateList the delete candidate list
+ * @param singleCommits the single commits
+ * @param alreadyFoundDupeGroups the already found dupe groups
+ * @param dbMaps the db maps
+ * @return the array list
+ */
+ private static ArrayList<String> checkAndProcessDupes(String transId,
+ String fromAppId, TitanTransaction g, String version, String nType,
+ ArrayList<TitanVertex> passedVertList, Boolean dupeFixOn,
+ ArrayList<String> deleteCandidateList, Boolean singleCommits,
+ ArrayList<String> alreadyFoundDupeGroups, DbMaps dbMaps ) {
+
+ ArrayList<String> returnList = new ArrayList<String>();
+ ArrayList<TitanVertex> checkVertList = new ArrayList<TitanVertex>();
+ ArrayList<String> alreadyFoundDupeVidArr = new ArrayList<String>();
+ Boolean noFilterList = true;
+ Iterator<String> afItr = alreadyFoundDupeGroups.iterator();
+ while (afItr.hasNext()) {
+ String dupeGrpStr = afItr.next();
+ String[] dupeArr = dupeGrpStr.split("\\|");
+ int lastIndex = dupeArr.length - 1;
+ for (int i = 0; i < lastIndex; i++) {
+ // Note: we don't want the last one...
+ String vidString = dupeArr[i];
+ alreadyFoundDupeVidArr.add(vidString);
+ noFilterList = false;
+ }
+ }
+
+ // For a given set of Nodes that were found with a set of KEY
+ // Parameters, (nodeType + key data) we will
+ // see if we find any duplicate nodes that need to be cleaned up. Note -
+ // it's legit to have more than one
+ // node with the same key data if the nodes depend on a parent for
+ // uniqueness -- as long as the two nodes
+ // don't hang off the same Parent.
+ // If we find duplicates, and we can figure out which of each set of
+ // duplicates is the one that we
+ // think should be preserved, we will record that. Whether we can tell
+ // which one should be
+ // preserved or not, we will return info about any sets of duplicates
+ // found.
+ //
+ // Each element in the returned arrayList might look like this:
+ // "1234|5678|keepVid=UNDETERMINED" (if there were 2 dupes, and we
+ // couldn't figure out which one to keep)
+ // or, "100017|200027|30037|keepVid=30037" (if there were 3 dupes and we
+ // thought the third one was the one that should survive)
+
+ // Because of the way the calling code loops over stuff, we can get the
+ // same data multiple times - so we should
+ // not process any vertices that we've already seen.
+
+ try {
+ Iterator<TitanVertex> pItr = passedVertList.iterator();
+ while (pItr.hasNext()) {
+ TitanVertex tvx = (TitanVertex) pItr.next();
+ String passedId = tvx.id().toString();
+ if (noFilterList || !alreadyFoundDupeVidArr.contains(passedId)) {
+ // We haven't seen this one before - so we should check it.
+ checkVertList.add(tvx);
+ }
+ }
+
+ if (checkVertList.size() < 2) {
+ // Nothing new to check.
+ return returnList;
+ }
+
+ if (!dbMaps.NodeDependencies.containsKey(nType)) {
+ // If this was a node that does NOT depend on other nodes for
+ // uniqueness, and we
+ // found more than one node using its key -- record the found
+ // vertices as duplicates.
+ String dupesStr = "";
+ for (int i = 0; i < checkVertList.size(); i++) {
+ dupesStr = dupesStr
+ + ((TitanVertex) (checkVertList.get(i))).id()
+ .toString() + "|";
+ }
+ if (dupesStr != "") {
+ TitanVertex prefV = getPreferredDupe(transId, fromAppId,
+ g, checkVertList, version);
+ if (prefV == null) {
+ // We could not determine which duplicate to keep
+ dupesStr = dupesStr + "KeepVid=UNDETERMINED";
+ returnList.add(dupesStr);
+ } else {
+ dupesStr = dupesStr + "KeepVid=" + prefV.id();
+ Boolean didRemove = false;
+ if (dupeFixOn) {
+ didRemove = deleteNonKeepersIfAppropriate(g,
+ dupesStr, prefV.id().toString(),
+ deleteCandidateList, singleCommits);
+ }
+ if (didRemove) {
+ dupeGrpsDeleted++;
+ } else {
+ // keep them on our list
+ returnList.add(dupesStr);
+ }
+ }
+ }
+ } else {
+ // More than one node have the same key fields since they may
+ // depend on a parent node for
+ // uniqueness. Since we're finding more than one, we want to
+ // check to see if any of the
+ // vertices that have this set of keys are also pointing at the
+ // same 'parent' node.
+ // Note: for a given set of key data, it is possible that there
+ // could be more than one set of
+ // duplicates.
+ HashMap<String, ArrayList<TitanVertex>> vertsGroupedByParentHash = groupVertsByDepNodes(
+ transId, fromAppId, g, version, nType,
+ checkVertList, dbMaps);
+ for (Map.Entry<String, ArrayList<TitanVertex>> entry : vertsGroupedByParentHash
+ .entrySet()) {
+ ArrayList<TitanVertex> thisParentsVertList = entry
+ .getValue();
+ if (thisParentsVertList.size() > 1) {
+ // More than one vertex found with the same key info
+ // hanging off the same parent/dependent node
+ String dupesStr = "";
+ for (int i = 0; i < thisParentsVertList.size(); i++) {
+ dupesStr = dupesStr
+ + ((TitanVertex) (thisParentsVertList
+ .get(i))).id() + "|";
+ }
+ if (dupesStr != "") {
+ TitanVertex prefV = getPreferredDupe(transId,
+ fromAppId, g, thisParentsVertList,
+ version);
+
+ if (prefV == null) {
+ // We could not determine which duplicate to
+ // keep
+ dupesStr = dupesStr + "KeepVid=UNDETERMINED";
+ returnList.add(dupesStr);
+ } else {
+ Boolean didRemove = false;
+ dupesStr = dupesStr + "KeepVid="
+ + prefV.id().toString();
+ if (dupeFixOn) {
+ didRemove = deleteNonKeepersIfAppropriate(
+ g, dupesStr, prefV.id()
+ .toString(),
+ deleteCandidateList, singleCommits);
+ }
+ if (didRemove) {
+ dupeGrpsDeleted++;
+ } else {
+ // keep them on our list
+ returnList.add(dupesStr);
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ System.out
+ .println(" >>> Threw an error in checkAndProcessDupes - just absorb this error and move on. "
+ + e.getMessage());
+ }
+
+ return returnList;
+
+ }// End of checkAndProcessDupes()
+
+ /**
+ * Group verts by dep nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param g the g
+ * @param version the version
+ * @param nType the n type
+ * @param passedVertList the passed vert list
+ * @param dbMaps the db maps
+ * @return the hash map
+ * @throws AAIException the AAI exception
+ */
+ private static HashMap<String, ArrayList<TitanVertex>> groupVertsByDepNodes(
+ String transId, String fromAppId, TitanTransaction g, String version,
+ String nType, ArrayList<TitanVertex> passedVertList, DbMaps dbMaps)
+ throws AAIException {
+ // Given a list of Titan Vertices, group them together by dependent
+ // nodes. Ie. if given a list of
+ // ip address nodes (assumed to all have the same key info) they might
+ // sit under several different parent vertices.
+ // Under Normal conditions, there would only be one per parent -- but
+ // we're trying to find duplicates - so we
+ // allow for the case where more than one is under the same parent node.
+
+ HashMap<String, ArrayList<TitanVertex>> retHash = new HashMap<String, ArrayList<TitanVertex>>();
+ if (!dbMaps.NodeDependencies.containsKey(nType)) {
+ // This method really should not have been called if this is not the
+ // kind of node
+ // that depends on a parent for uniqueness, so just return the empty
+ // hash.
+ return retHash;
+ }
+
+ // Find out what types of nodes the passed in nodes can depend on
+ ArrayList<String> depNodeTypeL = new ArrayList<String>();
+ Collection<String> depNTColl = dbMaps.NodeDependencies.get(nType);
+ Iterator<String> ntItr = depNTColl.iterator();
+ while (ntItr.hasNext()) {
+ depNodeTypeL.add(ntItr.next());
+ }
+ // For each vertex, we want find its dependent vertex and add it to
+ // other vertexes that are dependent on that same guy.
+ if (passedVertList != null) {
+ HashMap<String, Object> emptyHash = new HashMap<String, Object>();
+ Iterator<TitanVertex> iter = passedVertList.iterator();
+ while (iter.hasNext()) {
+ TitanVertex thisVert = iter.next();
+ ArrayList<TitanVertex> connectedVList = DbMeth
+ .getConnectedNodes("transId", "fromAppId", g, "",
+ emptyHash, thisVert, "v3", false);
+ Iterator<TitanVertex> connIter = connectedVList.iterator();
+ while (connIter.hasNext()) {
+ TitanVertex tvCon = connIter.next();
+ String conNt = "";
+ Object obj = tvCon.<Object>property("aai-node-type").orElse(null);
+ if (obj != null) {
+ conNt = obj.toString();
+ }
+ if (depNTColl.contains(conNt)) {
+ // This must be the parent/dependent node
+ String parentVid = tvCon.id().toString();
+ if (retHash.containsKey(parentVid)) {
+ // add this vert to the list for this parent key
+ ((ArrayList) (retHash.get(parentVid)))
+ .add(thisVert);
+ } else {
+ // This is the first one we found on this parent
+ ArrayList<TitanVertex> vList = new ArrayList<TitanVertex>();
+ vList.add(thisVert);
+ retHash.put(parentVid, vList);
+ }
+ }
+ }
+ }
+ }
+
+ return retHash;
+
+ }// end of groupVertsByDepNodes()
+
+ /**
+ * Delete non keepers if appropriate.
+ *
+ * @param g the g
+ * @param dupeInfoString the dupe info string
+ * @param vidToKeep the vid to keep
+ * @param deleteCandidateList the delete candidate list
+ * @param singleCommits the single commits
+ * @return the boolean
+ */
+ private static Boolean deleteNonKeepersIfAppropriate(TitanTransaction g,
+ String dupeInfoString, String vidToKeep,
+ ArrayList<String> deleteCandidateList, Boolean singleCommits) {
+
+ Boolean deletedSomething = false;
+ // This assumes that the dupeInfoString is in the format of
+ // pipe-delimited vid's followed by
+ // ie. "3456|9880|keepVid=3456"
+ if (deleteCandidateList == null || deleteCandidateList.size() == 0) {
+ // No vid's on the candidate list -- so no deleting will happen on
+ // this run
+ return false;
+ }
+
+ String[] dupeArr = dupeInfoString.split("\\|");
+ ArrayList<String> idArr = new ArrayList<String>();
+ int lastIndex = dupeArr.length - 1;
+ for (int i = 0; i <= lastIndex; i++) {
+ if (i < lastIndex) {
+ // This is not the last entry, it is one of the dupes,
+ String vidString = dupeArr[i];
+ idArr.add(vidString);
+ } else {
+ // This is the last entry which should tell us if we have a
+ // preferred keeper
+ String prefString = dupeArr[i];
+ if (prefString.equals("KeepVid=UNDETERMINED")) {
+ // They sent us a bad string -- nothing should be deleted if
+ // no dupe could be tagged as preferred
+ return false;
+ } else {
+ // If we know which to keep, then the prefString should look
+ // like, "KeepVid=12345"
+ String[] prefArr = prefString.split("=");
+ if (prefArr.length != 2 || (!prefArr[0].equals("KeepVid"))) {
+ String msg = "Bad format. Expecting KeepVid=999999";
+ System.out.println(msg);
+ return false;
+ } else {
+ String keepVidStr = prefArr[1];
+ if (idArr.contains(keepVidStr)) {
+ idArr.remove(keepVidStr);
+
+ // So now, the idArr should just contain the vid's
+ // that we want to remove.
+ for (int x = 0; x < idArr.size(); x++) {
+ boolean okFlag = true;
+ String thisVid = idArr.get(x);
+ if (deleteCandidateList.contains(thisVid)) {
+ // This vid is a valid delete candidate from
+ // a prev. run, so we can remove it.
+ try {
+ long longVertId = Long
+ .parseLong(thisVid);
+ TitanVertex vtx = g
+ .getVertex(longVertId);
+ vtx.remove();
+ if (singleCommits) {
+ g.commit();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ }
+ } catch (Exception e) {
+ okFlag = false;
+ String msg = "ERROR trying to delete VID = "
+ + thisVid;
+ System.out.println(msg);
+ }
+ if (okFlag) {
+ System.out.println(" DELETED VID = "
+ + thisVid);
+ deletedSomething = true;
+ }
+ }
+ }
+ } else {
+ String msg = "ERROR - Vertex Id to keep not found in list of dupes. dupeInfoString = ["
+ + dupeInfoString + "]";
+ System.out.println(msg);
+ return false;
+ }
+ }
+ }// else we know which one to keep
+ }// else last entry
+ }// for each vertex in a group
+
+ return deletedSomething;
+
+ }// end of deleteNonKeepersIfAppropriate()
+
+
+ /**
+ * Gets the node just using key params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param keyPropsHash the key props hash
+ * @param apiVersion the api version
+ * @return the node just using key params
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <TitanVertex> getNodeJustUsingKeyParams( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> keyPropsHash, String apiVersion ) throws AAIException{
+
+ ArrayList <TitanVertex> retVertList = new ArrayList <TitanVertex> ();
+
+ // We assume that all NodeTypes have at least one key-property defined.
+ // Note - instead of key-properties (the primary key properties), a user could pass
+ // alternate-key values if they are defined for the nodeType.
+ ArrayList<String> kName = new ArrayList<String>();
+ ArrayList<Object> kVal = new ArrayList<Object>();
+ if( keyPropsHash == null || keyPropsHash.isEmpty() ){
+ String msg = " NO key properties passed for this getNodeJustUsingKeyParams() request. NodeType = [" + nodeType + "]. ";
+ System.out.println( msg );
+ throw new AAIException("AAI_6120", msg);
+ }
+
+ int i = -1;
+ for( Map.Entry<String, Object> entry : keyPropsHash.entrySet() ){
+ i++;
+ kName.add(i, entry.getKey());
+ kVal.add(i, entry.getValue());
+ }
+ int topPropIndex = i;
+ TitanVertex tiV = null;
+ String propsAndValuesForMsg = "";
+ Iterable <?> verts = null;
+
+ try {
+ if( topPropIndex == 0 ){
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ") ";
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType).vertices();
+ }
+ else if( topPropIndex == 1 ){
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ") ";
+ verts = graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has("aai-node-type",nodeType).vertices();
+ }
+ else if( topPropIndex == 2 ){
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ") ";
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has("aai-node-type",nodeType).vertices();
+ }
+ else if( topPropIndex == 3 ){
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ", "
+ + kName.get(3) + " = " + kVal.get(3) + ") ";
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).has("aai-node-type",nodeType).vertices();
+ }
+ else {
+ String emsg = " We only support 4 keys per nodeType for now \n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ }
+ catch( Exception ex ){
+ System.out.println( " ERROR trying to get node for: [" + propsAndValuesForMsg + "]");
+ }
+
+ if( verts != null ){
+ Iterator <?> vertI = verts.iterator();
+ while( vertI.hasNext() ){
+ tiV = (TitanVertex) vertI.next();
+ retVertList.add(tiV);
+ }
+ }
+
+ if( retVertList.size() == 0 ){
+ System.out.println("DEBUG No node found for nodeType = [" + nodeType +
+ "], propsAndVal = " + propsAndValuesForMsg );
+ }
+
+ return retVertList;
+
+ }// End of getNodeJustUsingKeyParams()
+
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java
new file mode 100644
index 0000000..f29acb4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java
@@ -0,0 +1,257 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import org.apache.tinkerpop.gremlin.structure.io.IoCore;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.util.TitanCleanup;
+
+
+
+
+public class DataSnapshot {
+
+ private static final String FROMAPPID = "AAI-DB";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static AAILogger aaiLogger;
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_DATA_SNAPSHOT_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ aaiLogger = new AAILogger(DataSnapshot.class.getName());
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", TRANSID, FROMAPPID, "DataSnapshot");
+
+ Boolean dbClearFlag = false;
+ TitanGraph graph = null;
+ String command = "JUST_TAKE_SNAPSHOT"; // This is the default
+ String oldSnapshotFileName = "";
+ if( args.length == 1 ){
+ command = args[0];
+ }
+ if( args.length == 2 ){
+ // If they pass in a RELOAD_ENTIRE_DB argument, then we will be reloading the database
+ // from the filename passed in -which will be expected to be found in our snapshot directory.
+ command = args[0];
+ oldSnapshotFileName = args[1];
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ AAIConfig.init();
+ ErrorLogHelper.loadProperties();
+ System.out.println("Command = " + command + ", oldSnapshotFileName = " + oldSnapshotFileName);
+ String targetDir = AAIConstants.AAI_HOME
+ + AAIConstants.AAI_FILESEP + "logs"
+ + AAIConstants.AAI_FILESEP + "data"
+ + AAIConstants.AAI_FILESEP + "dataSnapshots";
+
+ // Make sure the dataSnapshots directory is there
+ new File(targetDir).mkdirs();
+
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+
+ if( graph == null ){
+ String emsg = "Not able to get a graph object in DataSnapshot.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ if( command.equals("JUST_TAKE_SNAPSHOT") ){
+ // ------------------------------------------
+ // They just want to take a snapshot.
+ // ------------------------------------------
+ SimpleDateFormat d = new SimpleDateFormat("yyyyMMddHHmm");
+ d.setTimeZone(TimeZone.getTimeZone("GMT"));
+ String dteStr = d.format(new Date()).toString();
+ String newSnapshotOutFname = targetDir + AAIConstants.AAI_FILESEP + "dataSnapshot.out." + dteStr;
+
+ graph.io(IoCore.graphml()).writeGraph(newSnapshotOutFname);
+
+ System.out.println("Snapshot written to " + newSnapshotOutFname );
+ /**** Don't really want to do this every hour **************
+ int vCount = 0;
+ Iterator vIt = graph.query().vertices().iterator();
+ while( vIt.hasNext() ){
+ vCount++;
+ vIt.next();
+ }
+ System.out.println("A little after taking the snapshot, we see: " + vCount + " vertices in the db.");
+ ************/
+ }
+ else if( command.equals("CLEAR_ENTIRE_DATABASE") ){
+ // ------------------------------------------------------------------
+ // They are calling this to clear the db before re-loading it later
+ // ------------------------------------------------------------------
+
+ // First - make sure the backup file they will be using can be found and has data
+ if( oldSnapshotFileName.equals("") ){
+ String emsg = "No oldSnapshotFileName passed to DataSnapshot.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ String oldSnapshotFullFname = targetDir + AAIConstants.AAI_FILESEP + oldSnapshotFileName;
+ File f = new File(oldSnapshotFullFname);
+ if( ! f.exists() ){
+ String emsg = "oldSnapshotFile " + oldSnapshotFullFname + " could not be found.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if( ! f.canRead() ){
+ String emsg = "oldSnapshotFile " + oldSnapshotFullFname + " could not be read.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if( f.length() == 0 ){
+ String emsg = "oldSnapshotFile " + oldSnapshotFullFname + " had no data.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ System.out.println("\n>>> WARNING <<<< " );
+ System.out.println(">>> All data and schema in this database will be removed at this point. <<<");
+ System.out.println(">>> Processing will begin in 5 seconds. <<<");
+ System.out.println(">>> WARNING <<<< " );
+
+ try {
+ // Give them a chance to back out of this
+ Thread.sleep(5000);
+ } catch ( java.lang.InterruptedException ie) {
+ System.out.println( " DB Clearing has been aborted. ");
+ System.exit(1);
+ }
+
+ System.out.println( " Begin clearing out old data. ");
+ graph.close();
+ TitanCleanup.clear(graph);
+ System.out.println( " Done clearing data. " );
+ System.out.println( ">>> IMPORTANT - NOTE >>> you need to run the SchemaGenerator (use GenTester) before ");
+ System.out.println( " reloading data or the data will be put in without indexes. ");
+ dbClearFlag = true;
+ }
+ else if( command.equals("RELOAD_DATA") ){
+ // -------------------------------------------------------------------
+ // They want to restore the database from an old snapshot file
+ // -------------------------------------------------------------------
+ if( oldSnapshotFileName.equals("") ){
+ String emsg = "No oldSnapshotFileName passed to DataSnapshot when RELOAD_DATA used.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ String oldSnapshotFullFname = targetDir + AAIConstants.AAI_FILESEP + oldSnapshotFileName;
+ File f = new File(oldSnapshotFullFname);
+ if( ! f.exists() ){
+ String emsg = "oldSnapshotFile " + oldSnapshotFullFname + " could not be found.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if( ! f.canRead() ){
+ String emsg = "oldSnapshotFile " + oldSnapshotFullFname + " could not be read.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else if( f.length() == 0 ){
+ String emsg = "oldSnapshotFile " + oldSnapshotFullFname + " had no data.";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ System.out.println("We will load data IN from the file = " + oldSnapshotFullFname );
+ System.out.println( " Begin reloading data. ");
+ graph.io(IoCore.graphml()).readGraph(oldSnapshotFullFname);
+ System.out.println("Completed the inputGraph command, now try to commit()... ");
+ graph.tx().commit();
+ System.out.println("Completed reloading data.");
+
+ int vCount = 0;
+ Iterator vIt = graph.query().vertices().iterator();
+ while( vIt.hasNext() ){
+ vCount++;
+ vIt.next();
+ }
+ System.out.println("A little after repopulating from an old snapshot, we see: " + vCount + " vertices in the db.");
+ }
+ else {
+ String emsg = "Bad command passed to DataSnapshot: [" + command + "]";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ }
+ catch (AAIException e) {
+ System.out.print("Threw a AAIException: \n");
+ System.out.println(e.getErrorObject().toString());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_6128", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_6128");
+ }
+ catch (Exception ex) {
+ System.out.print("Threw a regular Exception:\n");
+ System.out.println(ex.getMessage());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_6128", ex.getMessage()), logline, ex);
+ aaiLogger.info(logline, false, "AAI_6128");
+ }
+ finally {
+ if( !dbClearFlag && graph != null ){
+ // Any changes that worked correctly should have already done thier commits.
+ graph.tx().rollback();
+ graph.close();
+ }
+ try { baos.close(); }
+ catch( IOException iox ){}
+ }
+
+
+ System.exit(0);
+
+ }// End of main()
+
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbEdgeGroup.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbEdgeGroup.java
new file mode 100644
index 0000000..15411f6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbEdgeGroup.java
@@ -0,0 +1,525 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.map.MultiValueMap;
+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.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.exceptions.AAIExceptionWithInfo;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class DbEdgeGroup {
+
+ private static AAILogger aaiLogger = new AAILogger(DbEdgeGroup.class.getName());
+
+ /**
+ * Replace edge group.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param scope the scope
+ * @param relatedNodesMultiMap the related nodes multi map
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ public static void replaceEdgeGroup( String transId,
+ String fromAppId,
+ TitanTransaction graph,
+ TitanVertex startVert,
+ String scope,
+ MultiValueMap relatedNodesMultiMap, // supports multiple entries for same nodetype
+ String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "replaceEdgeGroup");
+ logline.add("scope", scope);
+
+ // --------------------------------------------------------------------
+ // NOTE --- This routine is only used for "cousin" relationships.
+ // --------------------------------------------------------------------
+
+ /*
+ * scope can be one of these:
+ * a) "ALL_COUSIN_REL"
+ * b) "ONLY_PASSED_COUSINS_REL" (only look at the edge types that are
+ * represented in the passed list of relationships)
+ *
+ * Given a startNode and a list of relationshipInfo, we need to check the database and then,
+ * 1) Delete any in-scope db relationships which are not represented in the relationshipList.
+ * So, for ALL_COUSIN_REL, we would delete any db relationship that had an edge with
+ * parentOf = false if it was not represented in the passed Relationship List.
+ * For ONLY_PASSED_COUSINS_REL - we'd do the same as above, but only for edges that match the
+ * type in the passed relationshipList. We'd leave any others alone.
+ * 2) Then, Persist (add/update) all the remaining passed-in relationships.
+ */
+
+ if( !scope.equals("ALL_COUSIN_REL") && !scope.equals("ONLY_PASSED_COUSINS_REL") ){
+ String detail = "Illegal scope parameter passed: [" + scope + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ HashMap <String,String> vidToNodeTypeInDbHash = new HashMap <String,String>();
+ HashMap <String,String> nodeTypeInReqHash = new HashMap <String,String>();
+ HashMap <String,TitanEdge> vidToEdgeInDbHash = new HashMap <String,TitanEdge>();
+ HashMap <String,TitanVertex> vidToTargetVertexHash = new HashMap <String,TitanVertex>();
+
+ //------------------------------------------------------------------------------------------------------------
+ // 1) First -- look what is currently in the db --
+ // "cousins" => grab all nodes connected to startVertex that have edges with param: isParent = false.
+ //------------------------------------------------------------------------------------------------------------
+ GraphTraversalSource conPipeTraversal = startVert.graph().traversal();
+ GraphTraversal<Vertex, Edge> conPipe = conPipeTraversal.V(startVert).bothE().has("isParent",false);
+ // Note - it's ok if nothing is found
+ String msg1 = "Found connected cousin vid(s) in db: ";
+ if( conPipe != null ){
+ while( conPipe.hasNext() ){
+ TitanEdge ed = (TitanEdge) conPipe.next();
+ TitanVertex cousinV = ed.otherVertex(startVert);
+ String vid = cousinV.id().toString();
+ String noTy = cousinV.<String>property("aai-node-type").orElse(null);
+ vidToNodeTypeInDbHash.put(vid, noTy);
+ vidToEdgeInDbHash.put(vid, ed);
+
+ msg1 = msg1 + "[" + cousinV.id().toString() + "]";
+ }
+ }
+ logline.add("Note-1", msg1 );
+
+ //------------------------------------------------------------------------------------------------------------
+ //2) Get a List of the Titan nodes that the end-state list wants to be connected to
+ //------------------------------------------------------------------------------------------------------------
+ String msg2 = "They request edges to these vids:";
+ ArrayList <TitanVertex> targetConnectedToVertList = new ArrayList<TitanVertex>();
+ if( relatedNodesMultiMap != null ) {
+
+ Set entrySet = relatedNodesMultiMap.entrySet();
+ Iterator it = entrySet.iterator();
+ //System.out.println(" Object key Object value");
+ while (it.hasNext()) {
+ Map.Entry mapEntry = (Map.Entry) it.next();
+ String rel2Nt = (String) mapEntry.getKey();
+ int i = 0;
+ ArrayList <HashMap<String, Object>> propList = ((ArrayList<HashMap<String, Object>>)relatedNodesMultiMap.get(rel2Nt));
+ while (i < propList.size()) {
+ HashMap<String, Object> propFilterHash = (HashMap<String, Object>) propList.get(i++);
+
+ TitanVertex targetVert;
+
+ try {
+ targetVert = DbMeth.getUniqueNodeWithDepParams( transId,
+ fromAppId,
+ graph,
+ rel2Nt,
+ propFilterHash,
+ apiVersion );
+ } catch (AAIException e) {
+ if (e.getErrorObject().getErrorCode().equals("6114"))
+ throw new AAIExceptionWithInfo("AAI_6129",
+ e,
+ "Node of type " + rel2Nt + " not found for properties:" + propFilterHash.toString(),
+ propFilterHash,
+ rel2Nt);
+ else
+ throw e;
+ }
+
+ targetConnectedToVertList.add(targetVert);
+
+ String vid = targetVert.id().toString();
+ String noTy = targetVert.<String>property("aai-node-type").orElse(null);
+ nodeTypeInReqHash.put(noTy, "");
+ vidToTargetVertexHash.put(vid, targetVert);
+
+ msg2 = msg2 + "[" + targetVert.id().toString() + "]";
+ }
+ }
+ }
+ logline.add("Note-2", msg2 );
+
+ //-------------------------------------------------------------------------------------------------------------------
+ // 3) Compare what is in the DB with what they are requesting as an end-state.
+ // If any are found in the db-list but not the new-list, delete them from the db (conditionally - based on scope)
+ //-------------------------------------------------------------------------------------------------------------------
+ String startVtxNT = startVert.<String>property("aai-node-type").orElse(null);
+ String msg3 = "We will DELETE existing DB-edge to vids = ";
+ for( Map.Entry<String, TitanEdge> entry : vidToEdgeInDbHash.entrySet() ){
+ String vertId = entry.getKey();
+ TitanEdge dbEd = entry.getValue();
+ if( ! vidToTargetVertexHash.containsKey(vertId) ){
+ if( scope.equals("ALL_COUSIN_REL") ){
+ msg3 = msg3 + "[" + entry.getKey() + "]";
+ DbMeth.removeAaiEdge(transId, fromAppId, graph, dbEd);
+ }
+ else if( scope.equals("ONLY_PASSED_COUSINS_REL") ){
+ // If they use "ONLY_PASSED_COUSINS_REL" scope, they want us to delete an edge ONLY if:
+ // a) this edge is the same type that they passed in (but goes to a different endpoint)
+ // AND b) this additional edge would break the multiplicity edge rule.
+ String ntInDb = vidToNodeTypeInDbHash.get(vertId);
+ if( nodeTypeInReqHash.containsKey(ntInDb) && additionalEdgeWouldBreakMultEdgeRule(startVtxNT, ntInDb) ){
+ //System.out.println( "DEBUG -- Edge to vid = " + entry.getKey() + " will be deleted. ");
+ msg3 = msg3 + "[" + entry.getKey() + "]";
+ DbMeth.removeAaiEdge(transId, fromAppId, graph, dbEd);
+ }
+ }
+ }
+ else {
+ //System.out.println( "DEBUG -- Edge to vid = " + entry.getKey() + " is on request and in DB, so do not delete from the DB.");
+ }
+ }
+ logline.add("Note-3", msg3 );
+
+ //---------------------------------------------------------------
+ // 4) add/update (persist) all the relations on the new-list
+ //---------------------------------------------------------------
+ String msg4 = "Call persistAaiEdge on edge(s) going to vids = ";
+ for( Map.Entry<String, TitanVertex> entry : vidToTargetVertexHash.entrySet() ){
+ msg4 = msg4 + "[" + entry.getKey() + "]";
+ TitanVertex targV = entry.getValue();
+ DbMeth.persistAaiEdge(transId, fromAppId, graph, startVert, targV, apiVersion, "cousin");
+ }
+ logline.add("Note-4", msg4 );
+
+ aaiLogger.info(logline, true, "0");
+ return;
+
+}// End replaceEdgeGroup()
+
+
+/**
+ * Additional edge would break mult edge rule.
+ *
+ * @param startNodeType the start node type
+ * @param endNodeType the end node type
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+private static Boolean additionalEdgeWouldBreakMultEdgeRule( String startNodeType, String endNodeType )
+ throws AAIException {
+ // Return true if a second edge from the startNodeType to the endNodeType would
+ // break a multiplicity edge rule.
+ // Ie. Adding an edge to a second tenant (endNode) from a vserver (startNode) node would be flagged by this
+ // if we have our multiplicity rule set up for the "vserver-tenant" edge set up as "Many2One" or if
+ // it was set up the other way, "tenant-vserver" as "One2Many" or even if it was "One2One". In any of
+ // those scenarios, the addition of an edge from a particular vserver to an additional tenant node
+ // would break the rule.
+ String ruleKey = startNodeType + "|" + endNodeType;
+ boolean reverseRule = false;
+ if( DbEdgeRules.EdgeRules.containsKey(ruleKey) ){
+ // We can use the edge rule info in the order given
+ }
+ else {
+ ruleKey = endNodeType + "|" + startNodeType;
+ if( DbEdgeRules.EdgeRules.containsKey(ruleKey) ){
+ // we can use the rule, but need to reverse it to apply to the two nodeTypes we're looking at
+ reverseRule = true;
+ }
+ else {
+ // Couldn't find a rule for this edge
+ String detail = "No EdgeRule found for passed nodeTypes: " + startNodeType + ", " + endNodeType + ".";
+ throw new AAIException("AAI_6120", detail);
+ }
+ }
+
+ String edRule = "";
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ // For the current database, there can only be one type of edge between any two particular node-types.
+ edRule = ruleItr.next();
+ }
+ else {
+ // No edge rule found for this
+ String detail = "Could not find an EdgeRule for derived edgeRuleKey (nodeTypeA|nodeTypeB): " + ruleKey + ".";
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ int tagCount = DbEdgeRules.EdgeInfoMap.size();
+ String [] rules = edRule.split(",");
+ if( rules.length != tagCount ){
+ String detail = "Bad EdgeRule data (itemCount =" + rules.length + ") for key = [" + ruleKey + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ int multIndex = -1;
+ for( int i = 0; i < tagCount; i++ ){
+ Integer mapKey = new Integer(i);
+ String ruleName = DbEdgeRules.EdgeInfoMap.get(mapKey);
+ if( ruleName.equals("multiplicityRule") ){
+ multIndex = i;
+ break;
+ }
+ }
+
+ if( multIndex == -1 ){
+ String detail = "Bad EdgeRule data (multiplicityRule not found) for key = [" + ruleKey + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String multRule = rules[multIndex];
+ if( multRule.equals("Many2Many") ){
+ return false;
+ }
+ else if( multRule.equals("One2One") ){
+ return true;
+ }
+ else if( !multRule.equals("One2Many") && !multRule.equals("Many2One") ){
+ String detail = "Bad EdgeRule data - unrecognized rule [" + multRule + "] for key = [" + ruleKey + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ if( !reverseRule && multRule.equals("Many2One") ){
+ // We're looking at the rule in the "normal" direction as listed in EdgeRules
+ // Since there should only be one of the end-nodeType for this kind of source-nodeType and
+ // they want to add an additional edge from this source to a different node of this end-nodeType,
+ // we will return TRUE since that would violate the rule.
+ return true;
+ }
+ else if( reverseRule && multRule.equals("One2Many") ){
+ // We're looking at the rule in the reverse direction
+ return true;
+ }
+ else {
+ // Multiplicity rule would not be violated by adding an edge from this source to another end-nodeType node
+ return false;
+ }
+
+}// end of additionalEdgeWouldBreakMultEdgeRule()
+
+/**
+ * Delete edge group.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param relatedNodesMultiMap the related nodes multi map
+ * @param apiVersion the api version
+ * @return void
+ * @throws AAIException the AAI exception
+ */
+public static void deleteEdgeGroup( String transId,
+ String fromAppId,
+ TitanTransaction graph,
+ TitanVertex startVert,
+ MultiValueMap relatedNodesMultiMap,
+ String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deleteEdgeGroup");
+
+ // --------------------------------------------------------------------
+ // NOTE - This routine is only used for "cousin" relationships.
+ // ALSO - an edge deletion will fail if that edge was needed by
+ // the node on one of the sides for uniqueness. We're just
+ // being careful here - so far, I don't think a cousin-edge
+ // is ever used for this kind of dependency.
+ // --------------------------------------------------------------------
+
+ HashMap <String,TitanEdge> cousinVidToEdgeInDbHash = new HashMap <String,TitanEdge>();
+ String startVertNT = startVert.<String>property("aai-node-type").orElse(null);
+ String startVertVid = startVert.id().toString();
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(apiVersion);
+ Collection <String> startVertDepNTColl = dbMaps.NodeDependencies.get(startVertNT);
+
+ //-----------------------------------------------------------------------------------------------------
+ // Get a list of vertexes that are attached to the startVert as "cousins" and the connecting edges
+ //-----------------------------------------------------------------------------------------------------
+ GraphTraversalSource conPipeTraversal = startVert.graph().traversal();
+ GraphTraversal<Vertex, Edge> conPipe = conPipeTraversal.V(startVert).bothE().has("isParent",false);
+ if( conPipe != null ){
+ while( conPipe.hasNext() ){
+ TitanEdge ed = (TitanEdge) conPipe.next();
+ TitanVertex cousinV = ed.otherVertex(startVert);
+ String vid = cousinV.id().toString();
+ cousinVidToEdgeInDbHash.put(vid, ed);
+ }
+ }
+
+ //-------------------------------------------------------------
+ // Look through the Relationship info passed in.
+ // Delete edges as requested if they check-out as cousins.
+ //-------------------------------------------------------------
+ Boolean isFirst = true;
+ String msg = "Deleting edges from vid = " + startVertVid + "(" + startVertNT + "), to these: [";
+ if( relatedNodesMultiMap != null ) {
+ Set entrySet = relatedNodesMultiMap.entrySet();
+ Iterator it = entrySet.iterator();
+ //System.out.println(" Object key Object value");
+ while (it.hasNext()) {
+ Map.Entry mapEntry = (Map.Entry) it.next();
+ String rel2Nt = (String) mapEntry.getKey();
+ HashMap<String, Object> propFilterHash = (HashMap<String, Object>)((ArrayList) relatedNodesMultiMap.get(rel2Nt)).get(0);
+ TitanVertex otherEndVert = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph, rel2Nt, propFilterHash, apiVersion );
+ String otherNT = otherEndVert.<String>property("aai-node-type").orElse(null);
+ String reqDelConnectedVid = otherEndVert.id().toString();
+ if( !cousinVidToEdgeInDbHash.containsKey(reqDelConnectedVid) ){
+ String detail = "COUSIN Edge between " + startVertVid + " (" + startVertNT + ") and " + reqDelConnectedVid +
+ "(" + otherNT + ") not found. ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6127");
+ throw new AAIException("AAI_6127", detail);
+ }
+ else {
+ // This was a cousin edge. But before we delete it, we will check to make
+ // sure it doesn't have a unique-dependency issue (need to check in two directions)
+ Iterator <String> ntItr1 = startVertDepNTColl.iterator();
+ if( ntItr1.hasNext() ){
+ while( ntItr1.hasNext() ){
+ if( ntItr1.next().equals(otherNT) ){
+ String detail = "Edge between " + startVertVid + " and " + reqDelConnectedVid +
+ " cannot be deleted because of a uniqueness-dependancy between nodeTypes, " +
+ startVertNT + " and " + otherNT;
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6126");
+ throw new AAIException("AAI_6126", detail);
+ }
+ }
+ }
+
+ Collection <String> depNTColl = dbMaps.NodeDependencies.get(otherNT);
+ Iterator <String> ntItr2 = depNTColl.iterator();
+ if( ntItr2.hasNext() ){
+ while( ntItr2.hasNext() ){
+ if( ntItr2.next().equals(startVertNT) ){
+ String detail = "Edge between " + startVertVid + " and " + reqDelConnectedVid +
+ " cannot be deleted because of a uniqueness-dependancy between nodeTypes: " +
+ otherNT + " and " + startVertNT;
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6126");
+ throw new AAIException("AAI_6126", detail);
+ }
+ }
+ }
+
+ // It's OK to delete this edge as requested.
+ if( ! isFirst ){
+ msg = msg + ", ";
+ }
+ isFirst = false;
+ msg = msg + reqDelConnectedVid + "(" + otherNT + ")";
+ TitanEdge targetDelEdge = cousinVidToEdgeInDbHash.get(reqDelConnectedVid);
+ DbMeth.removeAaiEdge(transId, fromAppId, graph, targetDelEdge);
+ }
+ }
+ }
+
+ msg = msg + "]";
+ logline.add("Note ", msg );
+ aaiLogger.info(logline, true, "0");
+ return;
+
+}// End deleteEdgeGroup()
+
+
+/**
+ * Gets the edge group.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param vidToNodeTypeHash the vid to node type hash
+ * @param vidToVertexHash the vid to vertex hash
+ * @param scope the scope
+ * @param apiVersion the api version
+ * @return void
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+public static void getEdgeGroup( String transId,
+ String fromAppId,
+ TitanTransaction graph,
+ TitanVertex startVert,
+ HashMap <String,String> vidToNodeTypeHash,
+ HashMap <String,TitanVertex> vidToVertexHash,
+ String scope,
+ String apiVersion ) throws AAIException, UnsupportedEncodingException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getEdgeGroup");
+ logline.add("scope", scope);
+ logline.add("vid", startVert.id().toString());
+ logline.add("nodetype", startVert.property("aai-node-type").orElse(null).toString());
+
+ /*
+ * scope can be one of these:
+ * 1) "ONLY_COUSIN_REL" <-- This is the only one supported for now
+ * 2) "ALL_COUSIN_AND_CHILDREN_REL"
+ * 3) "ONLY_CHILDREN"
+ * 4) "USES_RESOURCE"
+ *
+ * Given a startNode and the scope, we need to return relationships that we find in the DB
+ */
+
+ if( !scope.equals("ONLY_COUSIN_REL") ){
+ String detail = "Illegal scope parameter passed: [" + scope + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ //------------------------------------------------------------------------------------------------------------
+ // Grab "first-layer" vertexes from the in the db --
+ // "cousins" => grab all nodes connected to startVertex that have edges with param: isParent = false.
+ // "children" => grab nodes via out-edge with isParent = true (NOT YET SUPPORTED)
+ //------------------------------------------------------------------------------------------------------------
+ Iterable<Vertex> qResult = startVert.query().has("isParent",false).vertices();
+ Iterator <Vertex> resultI = qResult.iterator();
+ String msg1 = "Found connected cousin vid(s) in db: ";
+ while( resultI.hasNext() ){
+ TitanVertex cousinV = (TitanVertex)resultI.next();
+ //showPropertiesForNode( transId, fromAppId, cousinV );
+
+ String vid = cousinV.id().toString();
+ String noTy = cousinV.<String>property("aai-node-type").orElse(null);
+ vidToNodeTypeHash.put(vid, noTy);
+ vidToVertexHash.put(vid, cousinV);
+
+ msg1 = msg1 + "[" + cousinV.id().toString() + "]";
+ }
+ logline.add("Note-1", msg1 );
+
+ aaiLogger.info(logline, true, "0");
+
+}// End getEdgeGroup()
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java
new file mode 100644
index 0000000..978cb57
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java
@@ -0,0 +1,3964 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.google.common.net.InetAddresses;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanProperty;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+/**
+ * General Database-level Utility class. These methods deal with the database one dataNode / Edge at a time.
+ * Transactions are managed at a higher level by the calling classes by passing in a TitanTransaction object.
+ */
+public class DbMeth{
+
+ private static AAILogger aaiLogger = new AAILogger(DbMeth.class.getName());
+
+ /**
+ * Patch aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex patchAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "patchAaiNode");
+
+ // If they're calling patchAaiNode, then we only want to add/update the properties that they
+ // pass us in the propHash. If there are others already in the DB, we leave them alone.
+
+ // Note: to be really official, we'd throw an error if the node wasn't already in the db.
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = true;
+ Boolean patchOnly = true;
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists);
+ aaiLogger.info(logline, true, "0");
+ return( tv );
+
+ } // end of patchAaiNode()
+
+ /**
+ * Patch aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex patchAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal) throws AAIException{
+ return patchAaiNode( transId, fromAppId, graph, nodeType,
+ propHash, depNodeVal, null );
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param patchOnly the patch only
+ * @param apiVersion the api version
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, Boolean patchOnly, String apiVersion) throws AAIException{
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = false;
+ return persistAaiNodeBASE( transId, fromAppId, graph, nodeType,
+ propHash, depNodeVal, patchOnly, apiVersion, objectExists);
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal, String apiVersion) throws AAIException{
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ Boolean patchOnly = false;
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = false;
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists);
+ return( tv );
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal) throws AAIException{
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ Boolean patchOnly = false;
+ boolean[] objectExists = new boolean[1];
+ objectExists[0] = false;
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, null, objectExists);
+ return( tv );
+ } // end of persistAaiNode()
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal, String apiVersion, boolean[] objectExists) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiNode");
+ Boolean patchOnly = false;
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists, null);
+ aaiLogger.info(logline, true, "0");
+ return( tv );
+ }
+
+ /**
+ * Persist aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @param thisNodeVertex the this node vertex
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNode(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, Boolean addIfNotFound, TitanVertex depNodeVal, String apiVersion, boolean[] objectExists, TitanVertex thisNodeVertex) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiNode");
+ Boolean patchOnly = false;
+ // If they're calling persistAaiNode, then we want to make the Db look like whatever they pass us. That is, if
+ // there is already a record in the DB, but they do not pass some of the existing properties, they should
+ // be cleared from the DB. Since we want to take care of all properties, we pass patchOnly = false
+ TitanVertex tv = persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists, thisNodeVertex);
+ aaiLogger.info(logline, true, "0");
+ return( tv );
+ }
+
+ /**
+ * Persist aai node BASE.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param patchOnly the patch only
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNodeBASE(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, Boolean patchOnly,
+ String apiVersion, boolean[] objectExists) throws AAIException{
+ return persistAaiNodeBASE(transId, fromAppId, graph, nodeType, propHash, depNodeVal, patchOnly, apiVersion, objectExists, null);
+ }
+
+ /**
+ * Persist aai node BASE.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propHash the prop hash
+ * @param depNodeVal the dep node val
+ * @param patchOnly the patch only
+ * @param apiVersion the api version
+ * @param objectExists the object exists
+ * @param thisNodeVertex the this node vertex
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex persistAaiNodeBASE(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap <String,Object> propHash, TitanVertex depNodeVal, Boolean patchOnly,
+ String apiVersion, boolean[] objectExists, TitanVertex thisNodeVertex) throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiNodeBASE");
+ logline.add("patchOnly", patchOnly);
+
+ if( graph == null ){
+ String emsg = "null graph object passed to persistAaiNodeBASE()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ boolean useDepNode = false;
+ String resourceVersion = null;
+ if( propHash.containsKey("resource-version") ){
+ resourceVersion = (String)(propHash.get("resource-version"));
+ }
+ String aaiUniqueKeyVal = null;
+ if( propHash.containsKey("aai-unique-key") ){
+ // Note -- we are assuming that nobody is monkeying with this. The 16-07 first-pass theory
+ // is that the REST layer is always gonna generate this or pass it through.
+ aaiUniqueKeyVal = (String)(propHash.get("aai-unique-key"));
+ propHash.remove("aai-unique-key");
+ }
+
+ if( needsADepNode4Uniqueness(transId, fromAppId, nodeType, apiVersion) ){
+ // This kind of node needs a dependent node (for uniqueness)
+ if( depNodeVal == null ){
+ // They should have passed in the node that this one depends on
+ String emsg = "null dependentNode object passed to persistAaiNodeBASE() but " + nodeType + " requires one.\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ else if( ! nodeTypeACanDependOnB(transId, fromAppId, nodeType, depNodeVal.<String>property("aai-node-type").orElse(null), apiVersion) ){
+ // They should have passed in the right type of node as the dependent node
+ String emsg = "dependentNode of type " + depNodeVal.<String>property("aai-node-type").orElse(null) + " passed to persistAaiNodeBASE() for nodeType" + nodeType + ".\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ useDepNode = true;
+ }
+ else {
+ depNodeVal = null;
+ }
+
+ // Note: as of 1607, we no longer validate property names since that's covered by the REST layer.
+ // Same goes for required fields (as of 1602)
+
+ // Special ip-address validation for ipAddr nodes only... This will go away when we go to YANG and
+ // do validations like this up at that layer.
+ if( nodeType.equals("ipaddress") ){
+ // Note - this will throw an exception if the ipAddress is using a bad format
+ ipAddressFormatOK( transId, fromAppId, (String)propHash.get("addr"), (String)propHash.get("version") );
+ }
+
+ // Use the key-fields/dependentNode to check if this is an add or an update
+ // We assume that all NodeTypes at least one key-property defined. A dependentNode is optional.
+ if( ! dbMaps.NodeKeyProps.containsKey(nodeType) ){
+ // Problem if no key Properties defined for this nodeType
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "No node-key-properties defined in dbMaps for nodeType = " + nodeType + " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ Boolean hasAltKey1 = false;
+ HashMap <String,Object>nodeAltKey1PropsHash = new HashMap<String,Object>();
+ Collection <String> altKey1Props = getNodeAltKey1PropNames(transId, fromAppId, nodeType, apiVersion);
+ if( altKey1Props != null ){
+ Iterator <String> altKey1PropI = altKey1Props.iterator();
+ while( altKey1PropI.hasNext() ){
+ String propName = altKey1PropI.next();
+ // NOTE: alt-keys are not always required fields. If it is null or blank, we won't
+ // do alt-key checks on it.
+ Object value = propHash.get(propName);
+ if( value != null && !value.toString().equals("") ){
+ hasAltKey1 = true;
+ nodeAltKey1PropsHash.put(propName, value);
+ }
+ }
+ }
+ HashMap <String,Object>nodeKeyPropsHash = new HashMap<String,Object>();
+ Collection <String> keyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+
+ Object value = propHash.get(propName);
+ nodeKeyPropsHash.put(propName, value);
+ }
+
+ // Check if this node is already in the database based on the Primary Key Info
+ TitanVertex existingVert = thisNodeVertex;
+ boolean foundTheNodeInDb = true;
+
+ if (existingVert == null) {
+ try {
+ existingVert = getUniqueNode( transId, fromAppId, graph, nodeType, nodeKeyPropsHash, depNodeVal, apiVersion );
+ }
+ catch (AAIException e) {
+ if (e.getErrorObject().getErrorCode().equals("6114")) {
+ foundTheNodeInDb = false;
+ }
+ else {
+ throw e;
+ }
+ }
+ }
+
+ // this is so the notification knows whether or not the operation was an UPDATE or a CREATe
+ objectExists[0] = foundTheNodeInDb;
+ if( foundTheNodeInDb ){
+ // A record was found in the DB using the PK.
+ if( needToDoResourceVerCheck(apiVersion, patchOnly) ){
+ // Need to check that they knew what they were updating
+ String existingResVer = existingVert.<String>property("resource-version").orElse(null);
+ if( resourceVersion == null || resourceVersion.equals("") ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6130");
+ String detail = "Resource-version not passed for update of = " + nodeType + ", " + nodeKeyPropsHash.toString();
+ throw new AAIException("AAI_6130", detail);
+ }
+ else if( (existingResVer != null) && !resourceVersion.equals(existingResVer) ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6131");
+ String detail = "Resource-version " + resourceVersion + " MISMATCH WITH EXISTING " + existingResVer + " for update of = " + nodeType + ", " + nodeKeyPropsHash.toString();
+ throw new AAIException("AAI_6131", detail);
+ }
+ }
+
+ // Need to ensure that the Alternate key isn't changing to a value that points to a different existing node.
+ // It is ok if it points to nothing -- that would just be an update for this node. It's also ok if
+ // it points to this (existing) node - that just means that it wasn't being updated.
+ if( hasAltKey1 ){
+ try {
+ TitanVertex chkVert = getUniqueNode( transId, fromAppId, graph, nodeType, nodeAltKey1PropsHash, depNodeVal, apiVersion );
+ if( ! chkVert.id().toString().equals(existingVert.id().toString()) ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6117");
+ String detail = "In-Use AlternateKey value passed for update of nodeType = " + nodeType;
+ throw new AAIException("AAI_6117", detail);
+ }
+ }
+ catch (AAIException e) {
+ if(! e.getErrorObject().getErrorCode().equals("6114") ){
+ throw e;
+ }
+ }
+ }
+ }
+ else {
+ // Note not in the DB -- This will be an ADD of a new node
+ // a) make sure they didn't say they were just doing "patchOnly" which cannot be an ADD.
+ // b) if there is an alternate key, we need to make sure the AK isn't already in use by somebody else.
+ if( patchOnly ){
+ String depMsg = "";
+ if( useDepNode ){
+ depMsg = " plus dependent node. ";
+ }
+ String msg = "Patch Request, but no Node of type " + nodeType + " found for properties: [" + propHash + "] " + depMsg;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ if( needToDoResourceVerCheck(apiVersion, patchOnly) && (resourceVersion != null) && !resourceVersion.equals("") ){
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6131");
+ String detail = "Resource-version was passed in, but this is an ADD of a " + nodeType + ", with these params: " + nodeKeyPropsHash.toString();
+ throw new AAIException("AAI_6131", detail);
+ }
+ if( hasAltKey1 ){
+ try {
+ getUniqueNode( transId, fromAppId, graph, nodeType, nodeAltKey1PropsHash, depNodeVal, apiVersion );
+ // Since the Primary Key for this nodeType wasn't found in the DB yet, the fact that
+ // we are able to find a record (no "6114" exception thrown) using the Alternate-Key is an error.
+ // We can't create a new node that uses an AK that's already in use.
+ logline.add("nodeType", nodeType);
+ aaiLogger.info(logline, false, "AAI_6117");
+ String detail = "Conflicting Key and Alternate-Key values passed for add of nodeType = " + nodeType;
+ throw new AAIException("AAI_6117", detail);
+ }
+ catch (AAIException e) {
+ if(! e.getErrorObject().getErrorCode().equals("6114") ){
+ throw e;
+ }
+ }
+ }
+ }
+
+ // ------------- Done with checking. Do the add or update to the dB -----------------------
+
+ if( foundTheNodeInDb ){
+ long unixTimeNow = System.currentTimeMillis() / 1000L;
+ // ----- This is an UPDATE ------
+
+
+ String existingSourceOfTruth = fromAppId; // default value if we can't get the old one
+ Object tmpOb = existingVert.<Object>property("source-of-truth").orElse(null);
+ if( tmpOb != null ){
+ existingSourceOfTruth = tmpOb.toString();
+ }
+ long existingCreateTs = unixTimeNow; // default value if we can't get the old one
+ tmpOb = existingVert.<Object>property("aai-created-ts").orElse(null);
+ if( tmpOb != null ){
+ existingCreateTs = (long) tmpOb;
+ }
+
+ String msg = "UPDATE vertex of type = [" + nodeType + "] ";
+ if( useDepNode ){
+ String depNType = depNodeVal.<String>property("aai-node-type").orElse(null);
+ HashMap <String, Object> depNodePropKeysHash = getNodeKeyPropHash(transId, fromAppId, graph, depNodeVal);
+ msg = "UPDATE existing node: type = " + nodeType + ", key(s) = [" + nodeKeyPropsHash +
+ "] which rides on dependent node: type = " + depNType + ", with key(s) = [" + depNodePropKeysHash + "].";
+ logline.add("msg", msg);
+ }
+ else {
+ msg = "UPDATE existing node: type = " + nodeType + ", key(s) = [" + nodeKeyPropsHash + "] (no dep. node).";
+ logline.add("msg", msg);
+ }
+ String removeList = "";
+ if( ! patchOnly ){
+ // They are updating an existing record, and they want us to "process all defined properties" (not just patch)
+ // So we will see if the node has any properties that were not passed-in. Those need to be removed.
+ Collection <String> propCol = dbMaps.NodeProps.get(nodeType);
+ Iterator <String> propIter = propCol.iterator();
+ while( propIter.hasNext() ){
+ String propName = propIter.next();
+ if( ! propHash.containsKey(propName) && !DbEdgeRules.ReservedPropNames.containsKey(propName)){
+ if( thisPropertyWasPutByNewerVersionOfCode(apiVersion, nodeType, propName) ){
+ // we must be using an older version of code here - but the property that
+ // has not been passed in this persist call is one that this older version of
+ // the database did not know about. So leave it alone.
+ }
+ else {
+ removeList = removeList + "," + propName;
+ existingVert.property(propName).remove();
+ }
+ }
+ }
+ }
+ if( !removeList.equals("") ){
+ String rmMsg = "Removed these props on update: [" + removeList + "]";
+ logline.add("removePropList", rmMsg);
+ }
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ // update the parameters that have been passed in (except the key-properties)
+ // taking away the key-property check. We will now allow this since
+ // the keys were used to identify this node, so they should be good and
+ // there are times when Titan resolves conflicts by only using the
+ // data set in an update - and was losing our key info...
+ // Similar to the change noted below.
+ //if( ! nodeKeyPropsHash.containsKey(entry.getKey()) ){
+ // existingVert.setProperty( entry.getKey(), entry.getValue() );
+ //}
+ if( ! entry.getKey().equals("resource-version") ){
+ boolean nonSingleCardinality = false;
+ boolean setSoNoDupes = false;
+ if( checkPropCardinality(entry.getKey(), "Set") ){
+ nonSingleCardinality = true;
+ setSoNoDupes = true;
+ }
+ else if( checkPropCardinality(entry.getKey(), "List") ){
+ nonSingleCardinality = true;
+ }
+
+ Iterator <Object> valIter = null;
+ if( nonSingleCardinality ){
+ String className = entry.getValue().getClass().getSimpleName();
+ if( className.equals("ArrayList") ){
+ valIter = ((ArrayList)(entry.getValue())).iterator();
+ }
+ else if( className.equals("List") ){
+ valIter = ((List)(entry.getValue())).iterator();
+ }
+ else if( className.equals("Set") ){
+ valIter = ((Set)(entry.getValue())).iterator();
+ }
+ }
+
+ if( nonSingleCardinality ){
+ // This property has Cardinality of List or Set - which need to be handled carefully
+ // Note -- for Lists or Sets, we assume they are of dataType String - that is all
+ // the Rest layer supports at the moment (16-02)
+ ArrayList <String> currentData = new ArrayList <String> ();
+ if( patchOnly ){
+ // When patching - gotta know what's already in the db
+ Iterator<VertexProperty<Object>> existingPropsIter = (existingVert.properties(entry.getKey()));
+ if( existingPropsIter != null ){
+ while( existingPropsIter.hasNext() ){
+ String existingVal = existingPropsIter.next().value().toString();
+ currentData.add( existingVal );
+ }
+ }
+ }
+ else {
+ // Since this is not a patch-update, we first have to clear out what is currently in the db.
+ existingVert.property(entry.getKey()).remove();
+ }
+
+ if( valIter != null ){
+ while( valIter.hasNext() ){
+ Object thisVal = valIter.next();
+ if( setSoNoDupes ){
+ // For Sets, we need to check that the data isn't already in the db or wasn't passed
+ // in to us twice in the propHash. Otherwise Titan throws an exception (instead of just ignoring it...)
+ if( !currentData.contains(thisVal) ){
+ // We don't have this data yet, so add it to the Set
+ existingVert.property( entry.getKey(), thisVal );
+ currentData.add( thisVal.toString() );
+ }
+ }
+ else {
+ // For List data types, it's ok to have duplicate values in the db (why would we want this?)
+ existingVert.property( entry.getKey(), thisVal );
+ }
+ }
+ }
+ }
+ else {
+ // This is a normal, "Cardinality = SINGLE" kind of property
+ // ResourceVersion is not populated based on passed-in data, it is set along with other internal properties below.
+ //Object cleanVal = convertTypeIfNeeded( entry.getKey(), entry.getValue() );
+ //existingVert.setProperty( entry.getKey(), cleanVal );
+ // ********************************
+ existingVert.property( entry.getKey(), entry.getValue() );
+ }
+ }
+ }
+
+ // DEBUG - trying to deal with the case where simultaneous PUTs
+ // cause our db to wind up with a vertex that does not have these three properties filled in.
+ existingVert.property( "aai-node-type", nodeType );
+ existingVert.property( "aai-created-ts", existingCreateTs );
+ existingVert.property( "source-of-truth", existingSourceOfTruth );
+
+ if( aaiUniqueKeyVal != null ){
+ existingVert.property( "aai-unique-key", aaiUniqueKeyVal );
+ }
+
+ existingVert.property( "aai-last-mod-ts", unixTimeNow );
+ String resVers = "" + unixTimeNow;
+ existingVert.property( "resource-version", resVers );
+ existingVert.property( "last-mod-source-of-truth", fromAppId );
+ msg = msg + ", [aai-last-mod-ts]/[" + unixTimeNow + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, true, "0");
+ return( existingVert );
+ }
+ else{
+ // ----- Not found in the DB, This must be an ADD ------
+ if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ aaiLogger.info(logline, false, "AAI_6120");
+ String detail = "nodeTypeCategory " + nodeType + " cannot be used to ADD a node. Need to pass a valid nodeType";
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ TitanVertex tiVnew = graph.addVertex( nodeType );
+
+ String msg = "ADD vertex of type = [" + nodeType + "] ";
+ if( depNodeVal != null ){
+ String depNType = depNodeVal.<String>property("aai-node-type").orElse(null);
+ HashMap <String, Object> depNodePropKeysHash = getNodeKeyPropHash(transId, fromAppId, graph, depNodeVal);
+ msg = msg + " onto dependent node: type = " + depNType + ", which has key(s) = [" + depNodePropKeysHash +
+ "]. New Node Prop/values = ";
+ }
+ else {
+ msg = msg + " Note: no dependent node. New Node Prop/values = ";
+ }
+ boolean first = true;
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ if( ! entry.getKey().equals("resource-version") ){
+ if( first ){
+ msg = msg + " [" + entry.getKey() + "]/[" + entry.getValue() + "]";
+ first = false;
+ }
+ else {
+ msg = msg + ", [" + entry.getKey() + "]/[" + entry.getValue() + "]";
+ }
+
+ boolean nonSingleCardinality = false;
+ boolean setSoNoDupes = false;
+ if( checkPropCardinality(entry.getKey(), "Set") ){
+ nonSingleCardinality = true;
+ setSoNoDupes = true;
+ }
+ else if( checkPropCardinality(entry.getKey(), "List") ){
+ nonSingleCardinality = true;
+ }
+
+ Iterator <Object> valIter = null;
+ if( nonSingleCardinality ){
+ String className = entry.getValue().getClass().getSimpleName();
+ if( className.equals("ArrayList") ){
+ valIter = ((ArrayList)(entry.getValue())).iterator();
+ }
+ else if( className.equals("List") ){
+ valIter = ((List)(entry.getValue())).iterator();
+ }
+ else if( className.equals("Set") ){
+ valIter = ((Set)(entry.getValue())).iterator();
+ }
+ }
+
+ if( nonSingleCardinality ){
+ // This property has Cardinality of List or Set - which need to be handled carefully
+ ArrayList <String> currentData = new ArrayList <String> ();
+ if( valIter != null ){
+ while( valIter.hasNext() ){
+ Object thisVal = valIter.next();
+ if( setSoNoDupes ){
+ // For Sets, we need to check that they're not passing us duplicate data in propHash.
+ // Otherwise Titan throws an exception (instead of just ignoring it...)
+ if( !currentData.contains(thisVal) ){
+ // We don't have this data yet, so add it to the Set
+ tiVnew.property( entry.getKey(), thisVal );
+ currentData.add( thisVal.toString() );
+ }
+ }
+ else {
+ // For List data types, it's ok to have duplicate values in the db (why would we want this?)
+ tiVnew.property( entry.getKey(), thisVal );
+ }
+ }
+ }
+ }
+ else {
+ // This is a normal, "Cardinality = SINGLE" kind of property
+ // ResourceVersion is not populated based on passed-in data, it is set along with other internal properties below.
+ tiVnew.property( entry.getKey(), entry.getValue() );
+ }
+ }
+ }
+
+ tiVnew.property( "aai-node-type", nodeType );
+ long unixTime = System.currentTimeMillis() / 1000L;
+ tiVnew.property( "aai-created-ts", unixTime );
+ tiVnew.property( "aai-last-mod-ts", unixTime );
+ String resVers = "" + unixTime;
+ tiVnew.property( "resource-version", resVers );
+ tiVnew.property( "source-of-truth", fromAppId );
+ tiVnew.property( "last-mod-source-of-truth", fromAppId );
+ if( aaiUniqueKeyVal != null ){
+ tiVnew.property( "aai-unique-key", aaiUniqueKeyVal );
+ }
+ msg = msg + ", [aai-created-ts]/[" + unixTime + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, true, "0");
+ return( tiVnew );
+ }
+
+ } // end of persistAaiNodeBASE()
+
+
+ /**
+ * Need to do resource ver check.
+ *
+ * @param apiVersion the api version
+ * @param patchOnlyFlag the patch only flag
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean needToDoResourceVerCheck(String apiVersion, Boolean patchOnlyFlag)
+ throws AAIException{
+
+ if( patchOnlyFlag ){
+ // we do not do resource checking for patch requests.
+ return false;
+ }
+
+ String resourceCheckOnFlag = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
+
+ int apiVerInt = cleanUpApiVersion(apiVersion);
+
+ if( (resourceCheckOnFlag != null) && resourceCheckOnFlag.equals("true") ){
+ // Only do the check if the resource enable flag is set to "true"
+ if( apiVerInt > 4 ){
+ // We're only doing the resource version checks for v5 and later
+ return true;
+ }
+ }
+
+ return false;
+ }// End needToDoResourceVerCheck()
+
+
+ /**
+ * Clean up api version.
+ *
+ * @param apiVersionString the api version string
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ private static int cleanUpApiVersion( String apiVersionString ) throws AAIException {
+ // Note: we expect an apiVersion to start with the letter "v", followed by an integer.
+
+ int versionInt = 0;
+ String verStr = apiVersionString;
+ if( (apiVersionString == null) || (apiVersionString.length() < 2) ){
+ // Passed in version doesn't look right
+ verStr = org.openecomp.aai.util.AAIApiVersion.get();
+ }
+ versionInt = getVerNumFromVerString( verStr );
+
+ return versionInt;
+ }
+
+ /**
+ * Gets the ver num from ver string.
+ *
+ * @param versionString the version string
+ * @return the ver num from ver string
+ * @throws AAIException the AAI exception
+ */
+ private static int getVerNumFromVerString( String versionString )throws AAIException {
+ int versionInt = 0;
+ if( versionString == null || versionString.length() < 2 ){
+ String detail = " Bad Version (format) passed to getVerNumFromVerString: [" + versionString + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ int strLen = versionString.length();
+ // We assume that a version looks like "v" followed by an integer
+ if( ! versionString.substring(0,1).equals("v") ){
+ String detail = " Bad Version (format) passed to getVerNumFromVerString: [" + versionString + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+ else {
+ String intPart = versionString.substring(1,strLen);
+ try {
+ versionInt = Integer.parseInt( intPart );
+ }
+ catch( Exception e ){
+ String detail = " Bad Version passed to getVerNumFromVerString: [" + versionString + "].";
+ throw new AAIException("AAI_6121", detail);
+ }
+ }
+ return versionInt;
+ }
+
+
+ /**
+ * Gets the node key prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return HashMap of keyProperties
+ * @throws AAIException the AAI exception
+ */
+ public static Collection <String> getNodeKeyPropNames( String transId, String fromAppId, String nodeType, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeKeyPropNames");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Collection <String> keyProps = new ArrayList <String>();
+ if( dbMaps.NodeKeyProps.containsKey(nodeType) ){
+ keyProps = dbMaps.NodeKeyProps.get(nodeType);
+ }
+ else if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The passed-in nodeType was really a nodeCategory, so we need to look up the key params
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ // For now, we only look for one.
+ catInfo = catItr.next();
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "Required Property name(s) not found for nodeType = " + nodeType+ " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String keyPropsString = flds[0];
+ String [] propNames = keyPropsString.split("\\|");
+ for( int i = 0; i < propNames.length; i++ ){
+ keyProps.add(propNames[i]);
+ }
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "Required Property name(s) not found for nodeType = " + nodeType+ " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+ // Don't log it when it's ok -- we have way too many of these...
+ //aaiLogger.debug(logline, " end ");
+ return keyProps;
+
+ }// end of getNodeKeyPropNames
+
+ /**
+ * Gets the node key prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the node key prop names
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static Collection <String> getNodeKeyPropNames( String transId, String fromAppId, String nodeType ) throws AAIException{
+ return getNodeKeyPropNames( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Gets the node alt key 1 prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return HashMap of keyProperties
+ * @throws AAIException the AAI exception
+ */
+ public static Collection <String> getNodeAltKey1PropNames( String transId, String fromAppId, String nodeType, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeAltKey1PropNames");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Collection <String> altKey1Props = new ArrayList <String>();
+ if( dbMaps.NodeAltKey1Props.containsKey(nodeType) ){
+ altKey1Props = dbMaps.NodeAltKey1Props.get(nodeType);
+ }
+ else if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The passed-in nodeType was really a nodeCategory, so we need to look up the key params
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ catInfo = catItr.next();
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String altKeyPropsString = flds[1];
+ String [] propNames = altKeyPropsString.split("\\|");
+ for( int i = 0; i < propNames.length; i++ ){
+ altKey1Props.add(propNames[i]);
+ }
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return altKey1Props;
+
+ }// end of getNodeAltKey1PropNames
+
+ /**
+ * Gets the node alt key 1 prop names.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the node alt key 1 prop names
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static Collection <String> getNodeAltKey1PropNames( String transId, String fromAppId, String nodeType ) throws AAIException{
+ return getNodeAltKey1PropNames( transId, fromAppId, nodeType, null);
+ }
+
+
+ /**
+ * Gets the unique node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param keyPropsHash the key props hash
+ * @param depNodeVal the dep node val
+ * @param apiVersion the api version
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getUniqueNode( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> keyPropsHash, TitanVertex depNodeVal, String apiVersion ) throws AAIException{
+
+ // NOTE - this is really for use by the PersistNode method -- it is looking to see if
+ // a node exists in the database given either Primary or Alternate Key data and dependent
+ // node data (if required for uniqueness).
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getUniqueNode");
+ logline.add("nodeType", nodeType);
+ if( keyPropsHash != null ){
+ logline.add("keyProps", keyPropsHash.toString());
+ }
+
+ // Note - the passed in nodeType could really be a nodeTypeCategory ---
+ Boolean nodeTypeIsCategory = DbEdgeRules.NodeTypeCategory.containsKey(nodeType);
+
+ Boolean useDepNode = false;
+ if( needsADepNode4Uniqueness(transId, fromAppId, nodeType, apiVersion) ){
+ // This kind of node depends on another node for uniqueness
+ if( depNodeVal == null ){
+ // They should have passed in the node that this one depends on
+ String emsg = "null dependentNode object passed to getUniqueNode() but " + nodeType + " requires one.\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ else if( ! nodeTypeACanDependOnB(transId, fromAppId, nodeType, depNodeVal.<String>property("aai-node-type").orElse(null), apiVersion) ){
+ // They should have passed in the right type of node as the dependent node
+ String emsg = "dependentNode of type " + depNodeVal.<String>property("aai-node-type").orElse(null) + " passed to getUniqueNode() for nodeType" + nodeType + ".\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ useDepNode = true;
+ }
+ else {
+ depNodeVal = null;
+ }
+
+ // We assume that all NodeTypes have at least one key-property defined. A dependentNode is optional.
+ // Note - instead of key-properties (the primary key properties), a user could pass
+ // alternate-key values if they are defined for the nodeType.
+ ArrayList<String> kName = new ArrayList<String>();
+ ArrayList<Object> kVal = new ArrayList<Object>();
+
+ Collection <String> keyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion);
+ Iterator <String> keyPropI = keyProps.iterator();
+ Boolean haveSomePrimKeyProps = false;
+ Boolean primaryKeyComplete = true;
+ while( keyPropI.hasNext() ){
+ haveSomePrimKeyProps = true;
+
+ String propName = keyPropI.next();
+ if( ! keyPropsHash.containsKey(propName) ){
+ primaryKeyComplete = false;
+ }
+ else {
+ Object valObj = keyPropsHash.get(propName);
+ if( valObj == null ){
+ primaryKeyComplete = false;
+ }
+ else {
+ String value = valObj.toString();
+ if( value == null || value.equals("") ){
+ // They passed the property name, but no value
+ primaryKeyComplete = false;
+ }
+ }
+ }
+ }
+
+ int i = -1;
+ if( haveSomePrimKeyProps && primaryKeyComplete ){
+ keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ String value = (keyPropsHash.get(propName)).toString();
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)value);
+ }
+ }
+ else {
+ // See if they're using the alternate key
+ Collection <String> altKey1Props = getNodeAltKey1PropNames(transId, fromAppId, nodeType, apiVersion);
+ Iterator <String> altKey1PropI = altKey1Props.iterator();
+ Boolean haveSomeAltKey1Props = false;
+ Boolean altKey1Complete = true;
+ while( altKey1PropI.hasNext() ){
+ haveSomeAltKey1Props = true;
+ String propName = altKey1PropI.next();
+ if( ! keyPropsHash.containsKey(propName) ){
+ altKey1Complete = false;
+ }
+ else {
+ Object valObj = keyPropsHash.get(propName);
+ if( valObj == null ){
+ altKey1Complete = false;
+ }
+ else {
+ String value = valObj.toString();
+ if( value == null || value.equals("") ){
+ // They passed the property name, but no value
+ altKey1Complete = false;
+ }
+ }
+ }
+ }
+ if( haveSomeAltKey1Props && altKey1Complete ){
+ altKey1PropI = altKey1Props.iterator();
+ while( altKey1PropI.hasNext() ){
+ String propName = altKey1PropI.next();
+ String value = (keyPropsHash.get(propName)).toString();
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)value);
+ }
+ }
+ }
+
+ int topPropIndex = i;
+ TitanVertex tiV = null;
+ String propsAndValuesForMsg = "";
+ if( !useDepNode ){
+ // There is no node that this type of node depends on, so we can look for it based
+ // solely on the Aai-defined key fields.
+ Iterable <?> verts = null;
+
+ logline.add("topPropIndex", topPropIndex);
+ if( topPropIndex == -1 ){
+ // Problem if no key Properties defined for this nodeType
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "Bad or Incomplete Key Property params: (" + keyPropsHash.toString() +
+ ") for nodeType: " + nodeType + " (ver=" + defVer + ")";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6105");
+ throw new AAIException("AAI_6105", detail);
+ }
+ else if( topPropIndex == 0 ){
+ if (nodeTypeIsCategory) // dont know real type
+ verts= graph.query().has(kName.get(0),kVal.get(0)).vertices();
+ else // need this to find dvs switch: dvs.switch-name and port-group.switch-name issue
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ") ";
+ }
+ else if( topPropIndex == 1 ){
+ verts = graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ") ";
+ }
+ else if( topPropIndex == 2 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ") ";
+ }
+ else if( topPropIndex == 3 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ", "
+ + kName.get(3) + " = " + kVal.get(3) + ") ";
+ }
+ else {
+ String emsg = " We only support 4 keys per nodeType for now \n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+
+ Iterator <?> vertI = verts.iterator();
+ if( vertI != null && vertI.hasNext()) {
+ // We found a vertex that meets the input criteria.
+ tiV = (TitanVertex) vertI.next();
+
+ if( vertI.hasNext() ){
+ // Since this routine is looking for a unique node for the given input values, if
+ // more than one is found - it's a problem.
+ logline.add("keyProps", propsAndValuesForMsg);
+ aaiLogger.info(logline, false, "AAI_6112");
+ String detail = "More than one Node found by getUniqueNode for params: " + propsAndValuesForMsg + "\n";
+ throw new AAIException("AAI_6112", detail);
+ }
+ }
+ else {
+ // No Vertex was found for this key - throw a not-found exception
+ String msg = "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ else {
+ // Need to use the dependent vertex to look for this one.
+ // filter this to the actual keys because
+ HashMap<String,Object> onlyKeysHash = new HashMap<String,Object>();
+
+ Collection <String> onlyKeyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion);
+
+ Iterator <String> onlyKeyPropsI = onlyKeyProps.iterator();
+
+ while( onlyKeyPropsI.hasNext() ){
+ String keyName = onlyKeyPropsI.next();
+ onlyKeysHash.put(keyName, keyPropsHash.get(keyName));
+ }
+
+ propsAndValuesForMsg = onlyKeysHash.toString() + " combined with a Dependent [" + depNodeVal.<String>property("aai-node-type").orElse(null) + "] node.";
+ ArrayList<TitanVertex> resultList = DbMeth.getConnectedNodes(transId, fromAppId, graph, nodeType, onlyKeysHash,
+ depNodeVal, apiVersion, false);
+ if( resultList.size() > 1 ){
+ // More than one vertex found when we thought there should only be one.
+ logline.add("keyProps", propsAndValuesForMsg);
+ aaiLogger.info(logline, false, "AAI_6112");
+ String detail = "More than one Node found by getUniqueNode for params: " + propsAndValuesForMsg + "\n";
+ throw new AAIException("AAI_6112", detail);
+ }
+ else if( resultList.size() == 1 ){
+ tiV = resultList.get(0);
+ }
+ }
+
+ if( tiV == null ){
+ // No Vertex was found for this key - throw a not-found exception
+ String msg = "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ if( !DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The nodeType passed in was a real one, not a nodeTypeCategory, so we will
+ // use it as part of the query to make sure we find the right type of node.
+ // This can be an issue if they're using nodeTypes covered by a nodeTypeCategory but
+ // pass in the wrong nodeType. We don't want them to ask for one thing and get the other.
+ String foundNodeType = tiV.<String>property("aai-node-type").orElse(null);
+ if( foundNodeType != null && !foundNodeType.equals(nodeType) ){
+ String msg = "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg + " (did find a " + foundNodeType + " though.)";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ aaiLogger.info(logline, true, "0");
+ return tiV;
+ }
+
+ }// End of getUniqueNode()
+
+ /**
+ * Gets the unique node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param keyPropsHash the key props hash
+ * @param depNodeVal the dep node val
+ * @return the unique node
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex getUniqueNode( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> keyPropsHash, TitanVertex depNodeVal) throws AAIException {
+ return getUniqueNode( transId, fromAppId, graph, nodeType,
+ keyPropsHash, depNodeVal, null );
+ }
+ // End getUniqueNode()
+
+
+ /**
+ * Gets the unique node with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param nodePropsHash the node props hash
+ * @param apiVersion the api version
+ * @return TitanVertex
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getUniqueNodeWithDepParams( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> nodePropsHash, String apiVersion )
+ throws AAIException{
+ /*
+ * This method uses the nodePropsHash to walk back over dependent nodes until it finds one that
+ * does not depend on any other for uniqueness. It uses the getUniqueNode() method as it finds
+ * dependent nodes. NOTE -- it is passed a hash of all the nodeProperties -- for itself and
+ * for any dependent nodes that it will need to find. There are some types of nodes that can
+ * depend on more than one node, we assume that there wouldn't be a case where BOTH types of
+ * dependent nodes are in the trail that we need to traverse. Ie. an ipaddress can depend on
+ * either a vserver or pserver. NOTE this case can now happen -- nodePropsHash
+ * should now be sent as a LinkedHashMap in this case so we can search in order.
+ */
+
+ // NOTE ALSO -- We're currently supporting 6 layers of dependency. We never thought there would be this
+ // many layers before hitting a node-type that would be uniquely identifiable on it's own. So the
+ // code is a little ugly with all these nested if-then-else's. Since we're supporting so many
+ // layers, it should be re-written so we can support "n" layers instead of having to go in hear
+ // and adding code... But as of 15-07, we really don't NEED more than 5.
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getUniqueNodeWithDepParams");
+ logline.add("nodeType", nodeType);
+ if( nodePropsHash != null ){
+ logline.add("nodeProps", nodePropsHash.toString());
+ }
+
+ // NOTE: The passed in nodeType could really be a nodeTypeCategory --
+ // The calls to figureDepNodeTypeForRequest() below will deal with it for the dep nodes, the
+ // call to getUniqueNode() takes care of it for the node itself.
+
+ TitanVertex nullVert = null;
+ String depNodeType = figureDepNodeTypeForRequest( transId, fromAppId, nodeType, nodePropsHash, apiVersion );
+ if( depNodeType.equals("")){
+ // This kind of node does not depend on another node for uniqueness, so
+ // we can just use the "getUniqueNode()" method to get it.
+ aaiLogger.info(logline, true, "0");
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, nullVert, apiVersion) );
+ }
+ else {
+ // Will need to find the second-layer dependent node
+ String secondLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, depNodeType, nodePropsHash, apiVersion );
+ if( secondLayerDepNodeType.equals("")){
+ // This second-layer kind of node does not depend on another node for uniqueness.
+ // So once we find the second-layer node, we can use it to get the top-layer guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the third-layer dependent node
+ /// String thirdLayerDepNodeType = dbMaps.NodeDependencies.get(secondLayerDepNodeType);
+ String thirdLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion );
+
+ if( thirdLayerDepNodeType.equals("")){
+ // This third-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the third-layer dependent node
+ String forthLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion );
+ if( forthLayerDepNodeType == null || forthLayerDepNodeType.equals("")){
+ // This forth-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the third, then second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex forthLayerDepVert = getUniqueNode(transId, fromAppId, graph, thirdLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, forthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the forth-layer dependent node
+ String fifthLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, forthLayerDepNodeType, nodePropsHash, apiVersion );
+ if( fifthLayerDepNodeType == null || fifthLayerDepNodeType.equals("")){
+ // This fifth-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the forth, third, then second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, forthLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex fifthLayerDepVert = getUniqueNode(transId, fromAppId, graph, forthLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex forthLayerDepVert = getUniqueNode(transId, fromAppId, graph, thirdLayerDepNodeType, thisNodeTypeParamHash, fifthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, forthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // Will need to find the fifth-layer dependent node
+ String sixthLayerDepNodeType = figureDepNodeTypeForRequest( transId, fromAppId, fifthLayerDepNodeType, nodePropsHash, apiVersion );
+ if( sixthLayerDepNodeType == null || sixthLayerDepNodeType.equals("")){
+ // This six-layer kind of node does not depend on another node for uniqueness.
+ // So we can find it, and then use it to find the fifth, forth, third, then second-layer and then use that to find the top guy.
+ HashMap <String,Object> thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, fifthLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex sixthLayerDepVert = getUniqueNode(transId, fromAppId, graph, fifthLayerDepNodeType, thisNodeTypeParamHash, nullVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, forthLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex fifthLayerDepVert = getUniqueNode(transId, fromAppId, graph, forthLayerDepNodeType, thisNodeTypeParamHash, sixthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, thirdLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex forthLayerDepVert = getUniqueNode(transId, fromAppId, graph, thirdLayerDepNodeType, thisNodeTypeParamHash, fifthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, secondLayerDepNodeType, nodePropsHash, apiVersion);
+ TitanVertex thirdLayerDepVert = getUniqueNode(transId, fromAppId, graph, secondLayerDepNodeType, thisNodeTypeParamHash, forthLayerDepVert, apiVersion);
+
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, depNodeType, nodePropsHash, apiVersion);
+ TitanVertex secLayerDepVert = getUniqueNode(transId, fromAppId, graph, depNodeType, thisNodeTypeParamHash, thirdLayerDepVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ thisNodeTypeParamHash = getThisNodeTypeParams(transId, fromAppId, nodeType, nodePropsHash, apiVersion);
+ return( getUniqueNode(transId, fromAppId, graph, nodeType, thisNodeTypeParamHash, secLayerDepVert, apiVersion) );
+ }
+ else {
+ // We don't currently support more layers. We can later if we need to.
+ // Hopefully, we'll never need to go this deep -- there should be unique keys in there somewhere!
+ String detail = "CODE-LIMITATION - Can't resolve dependant node layers for nodeType = " + nodeType;
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", detail);
+ }
+ }
+ }
+ }
+ }
+ }
+ } // End getUniqueNodeWithDepParams()
+
+ /**
+ * Gets the unique node with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param nodePropsHash the node props hash
+ * @return the unique node with dep params
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanVertex getUniqueNodeWithDepParams( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> nodePropsHash ) throws AAIException {
+ return getUniqueNodeWithDepParams(transId, fromAppId, graph, nodeType, nodePropsHash, null);
+ }
+
+
+ /**
+ * Gets the this node type params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param targetNodeType the target node type
+ * @param passedHash the passed hash
+ * @param apiVersion the api version
+ * @return the this node type params
+ * @throws AAIException the AAI exception
+ */
+ private static HashMap <String, Object> getThisNodeTypeParams(String transId, String fromAppId, String targetNodeType,
+ HashMap<String,Object> passedHash, String apiVersion )throws AAIException{
+ /*
+ * For the passed-in hash, each key is assumed to look like, "nodeType.paramName". We want to
+ * pick out the entries that match the targetNodeType and return those with the values they go with. The
+ * returned keys will have the "nodeType." stripped off.
+ *
+ * NOTE - the nodeType passed to this method could actually be a nodeTypeCategory. Just keepin it ugly.
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getThisNodeTypeParams");
+ logline.add("targetNodeType", targetNodeType);
+ if( passedHash == null ){
+ String detail = "Bad param: null passedHash ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ logline.add("passedHash", passedHash.toString());
+
+ String targetNodeTypeCat = "";
+ if( DbEdgeRules.NodeTypeCatMap.containsKey(targetNodeType) ){
+ targetNodeTypeCat = DbEdgeRules.NodeTypeCatMap.get(targetNodeType);
+ }
+
+ HashMap <String,Object> returnHash = new HashMap <String,Object> ();
+ Iterator <Map.Entry<String,Object>>it = passedHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <String,Object>pairs = (Map.Entry<String,Object>)it.next();
+ String k = (pairs.getKey()).toString();
+ int periodLoc = k.indexOf(".");
+ if( periodLoc <= 0 ){
+ String emsg = "Bad filter param key passed in: [" + k + "]. Expected format = [nodeName.paramName]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String nty = k.substring(0,periodLoc);
+ String paramName = k.substring(periodLoc + 1);
+ if( nty.equals(targetNodeType) || (!targetNodeTypeCat.equals("") && nty.equals(targetNodeTypeCat)) ){
+ String newK = paramName;
+ returnHash.put( newK,pairs.getValue() );
+ }
+ }
+ }
+
+ //aaiLogger.debug(logline, " - end ");
+ return returnHash;
+
+ }// End of getThisNodeTypeParams()
+
+ /**
+ * Gets the this node type params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param targetNodeType the target node type
+ * @param passedHash the passed hash
+ * @return the this node type params
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static HashMap <String, Object> getThisNodeTypeParams(String transId, String fromAppId, String targetNodeType,
+ HashMap<String,Object> passedHash )throws AAIException{
+ return getThisNodeTypeParams( transId, fromAppId, targetNodeType,
+ passedHash, null);
+
+ }
+
+ /**
+ * Gets the dep node types.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return the dep node types
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <String> getDepNodeTypes(String transId, String fromAppId, String nodeType, String apiVersion)throws AAIException{
+ /*
+ * This returns any nodeTypes that this nodeType can be dependent on. A particular instance of a node will only
+ * depend on one other node - we don't currently support dependence on multiple nodes.
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getDepNodeTypes");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ ArrayList <String> depNodeTypeL = new ArrayList <String> ();
+ if( !DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // This is a good-ole nodeType
+ Collection <String> depNTColl = dbMaps.NodeDependencies.get(nodeType);
+ Iterator <String> ntItr = depNTColl.iterator();
+ while( ntItr.hasNext() ){
+ depNodeTypeL.add(ntItr.next());
+ }
+ }
+ else {
+ // The passed-in nodeType must really be a nodeTypeCategory
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ // For now, we only look for one.
+ catInfo = catItr.next();
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6121");
+ String detail = "Error getting DbEdgeRules.NodeTypeCategory info for nodeTypeCat = " + nodeType;
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String nodeTypesString = flds[0];
+ String hasDepNodes = flds[3];
+ if( hasDepNodes.equals("true") ){
+ String [] ntNames = nodeTypesString.split("\\|");
+ for( int i = 0; i < ntNames.length; i++ ){
+ Collection <String> depNTColl = dbMaps.NodeDependencies.get(nodeType);
+ Iterator <String> ntItr = depNTColl.iterator();
+ while( ntItr.hasNext() ){
+ String depNode = ntItr.next();
+ if( !depNodeTypeL.contains(depNode) ){
+ depNodeTypeL.add(depNode);
+ }
+ }
+ }
+ }
+ }
+
+
+ //aaiLogger.debug(logline, " end ");
+ return depNodeTypeL;
+
+ }// End getDepNodeTypes()
+
+ /**
+ * Gets the dep node types.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the dep node types
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList <String> getDepNodeTypes(String transId, String fromAppId, String nodeType)throws AAIException{
+ return getDepNodeTypes( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Gets the default delete scope.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return the default delete scope
+ * @throws AAIException the AAI exception
+ */
+ private static String getDefaultDeleteScope(String transId, String fromAppId, String nodeType, String apiVersion)throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getDefaultDeleteScope");
+ logline.add("nodeType", nodeType);
+
+ // At some point we may have different delete rules for different services, so this is
+ // a list for now even thought there's only one scope per nodeType.
+ Collection <String> scopeList = DbEdgeRules.DefaultDeleteScope.get(nodeType);
+ if( scopeList.isEmpty() ){
+ String detail = "No default deleteScope found for nodeType = [" + nodeType + "] ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+ else {
+ aaiLogger.debug(logline, " end ");
+ Iterator <String> ito = scopeList.iterator();
+ return ito.next();
+ }
+
+ }// End getDefaultDeleteScope()
+
+ /**
+ * Gets the default delete scope.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the default delete scope
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static String getDefaultDeleteScope(String transId, String fromAppId, String nodeType)throws AAIException{
+ return getDefaultDeleteScope( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Needs A dep node 4 uniqueness.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean needsADepNode4Uniqueness(String transId, String fromAppId, String nodeType, String apiVersion)throws AAIException{
+ // Note: the passed in nodeType could really be a nodeTypeCategory. That is handled by getDepNodeTypes()
+
+ ArrayList <String> depList = getDepNodeTypes(transId, fromAppId, nodeType, apiVersion);
+ if( depList.isEmpty() ){
+ return false;
+ }
+ else {
+ return true;
+ }
+
+ }// End needsADepNode4Uniqueness()
+
+ /**
+ * Needs A dep node 4 uniqueness.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static Boolean needsADepNode4Uniqueness(String transId, String fromAppId, String nodeType)throws AAIException{
+ return needsADepNode4Uniqueness( transId, fromAppId, nodeType, null);
+ }
+
+ /**
+ * Node type A can depend on B.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeTypeA the node type A
+ * @param nodeTypeB the node type B
+ * @param apiVersion the api version
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean nodeTypeACanDependOnB(String transId, String fromAppId, String nodeTypeA, String nodeTypeB, String apiVersion)
+ throws AAIException{
+ // Note: the passed in nodeType could really be a nodeTypeCategory. That is handled by getDepNodeTypes()
+
+ ArrayList <String> depList = getDepNodeTypes(transId, fromAppId, nodeTypeA, apiVersion);
+ if( depList.isEmpty() ){
+ return false;
+ }
+ else if( depList.contains(nodeTypeB) ){
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ }// End nodeTypeACanDependOnB()
+
+ /**
+ * Node type A can depend on B.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeTypeA the node type A
+ * @param nodeTypeB the node type B
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static Boolean nodeTypeACanDependOnB(String transId, String fromAppId, String nodeTypeA, String nodeTypeB)
+ throws AAIException{
+ return nodeTypeACanDependOnB( transId, fromAppId, nodeTypeA, nodeTypeB, null);
+ }
+
+ /**
+ * Figure dep node type for request.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param requestParamHash the request param hash
+ * @param apiVersion the api version
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String figureDepNodeTypeForRequest(String transId, String fromAppId, String nodeType,
+ HashMap<String,Object> requestParamHash, String apiVersion )throws AAIException{
+ /*
+ * This is ugly. But if the passed-in nodeType is dependent on another nodeType for
+ * uniqueness, we need to return what that dependent node-type is. The ugly comes in
+ * because a node can be dependent on more than one type of node. So, to tell which one
+ * is going to apply, we root through the passed request parameters to see which of
+ * the possible dependent node types is being used.
+ * Note -- if there comes a day when there are so many dependencies that the request could
+ * have more than one that match -- Then we need to think up something new. But for now,
+ * we have to assume that if there are more than one legal dep-node-types, only one will
+ * be represented in the requestHash data. >>> NOTE >>> That day has come. For
+ * the upstreamers will send in a LinkedHashMap instead of just an unordered
+ * HashMap so we can look in order for the dependent node.
+ *
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "figureDepNodeTypeForRequest");
+ logline.add("nodeType", nodeType);
+ if( requestParamHash == null ){
+ String detail = "Bad param: null requestParamHash ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ logline.add("requestParamHash", requestParamHash.toString());
+
+ ArrayList <String> depNodeTypes = getDepNodeTypes(transId, fromAppId, nodeType, apiVersion);
+ if( depNodeTypes.isEmpty() ){
+ // This kind of node is not dependent on any other
+ //aaiLogger.debug(logline, " (not dependent) - end ");
+ return "";
+ }
+ else if( depNodeTypes.size() == 1 ){
+ // This kind of node can only depend on one other nodeType - so return that.
+ //aaiLogger.debug(logline, " (depends on " + depNodeTypes.get(0) + " - end ");
+ return depNodeTypes.get(0);
+ }
+ else {
+ // We need to look to find the first of the dep-node types that is represented in the passed-in
+ // request data. That will be the one we need to use.
+
+ // first find out what node-types are represented in the requestHash
+
+ Iterator <Map.Entry<String,Object>>it = requestParamHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <String,Object>pairs = (Map.Entry<String,Object>)it.next();
+ String k = (pairs.getKey()).toString();
+ int periodLoc = k.indexOf(".");
+ if( periodLoc <= 0 ){
+ String emsg = "Bad filter param key passed in: [" + k + "]. Expected format = [nodeName.paramName]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String nty = k.substring(0,periodLoc);
+ if( depNodeTypes.contains(nty) ){
+ // This is the first possible dep. node type we've found for the passed in data set
+ return nty;
+ }
+ }
+ }
+
+ }
+
+ // It's not an error if none is found - the caller needs to deal with cases where there
+ // should be a dep. node identified but isn't.
+ //aaiLogger.debug(logline, " no dep NT found - end ");
+ return "";
+
+ }// End of figureDepNodeTypeForRequest()
+
+ /**
+ * Figure dep node type for request.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param requestParamHash the request param hash
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static String figureDepNodeTypeForRequest(String transId, String fromAppId, String nodeType,
+ HashMap<String,Object> requestParamHash )throws AAIException{
+ return figureDepNodeTypeForRequest( transId, fromAppId, nodeType, requestParamHash, null);
+ }
+
+ /**
+ * Detach connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param autoDeleteOrphans the auto delete orphans
+ * @param apiVersion the api version
+ * @return deletedNodeCount
+ * @throws AAIException the AAI exception
+ */
+ public static int detachConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, boolean autoDeleteOrphans, String apiVersion ) throws AAIException{
+
+ /* Find nodes that are attached to this node which meet the nodeType/filterParams criteria.
+ * Remove the edges that go to those nodes.
+ * If that turns any of the nodes into an orphan, then delete it if the autoDeleteOrphans flag is set.
+ * Return a count of how many nodes were actually deleted (not just detached).
+ */
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "detachConnectedNodes");
+ logline.add("nodeType", nodeType);
+ if( propFilterHash != null ){
+ logline.add("propFilter", propFilterHash.toString());
+ }
+
+ int deletedCount = 0;
+
+ if( startNodeVal == null ){
+ // They should have passed in the node that this query starts from
+ String emsg = "null startNode object passed to detachConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+
+ // We want to loop through the connected Nodes that we found.
+ // For each connected Node, we'll get the all edges that start from that node and look for the one
+ // that connects back to our startNode.
+ // Only delete the edge that connects back to our startNode.
+ // then autoDeleteOrphans flag is set, then delete the connectedNode if it's now orphaned.
+ //
+
+ String startNodeVId = startNodeVal.id().toString();
+ ArrayList<TitanVertex> conNodeList = getConnectedNodes( transId, fromAppId, graph, nodeType, propFilterHash, startNodeVal, apiVersion, false );
+ Iterator<TitanVertex> conVIter = conNodeList.iterator();
+ while( conVIter.hasNext() ){
+ TitanVertex connectedVert = conVIter.next();
+ boolean isFirstOne = true;
+ Iterator<Edge> eI = connectedVert.edges(Direction.BOTH);
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(connectedVert);
+ String otherSideLookingBackVId = otherVtx.id().toString();
+ if( startNodeVId.equals(otherSideLookingBackVId) ){
+ // This is an edge from the connected node back to our starting node
+ if( isFirstOne && !eI.hasNext() && autoDeleteOrphans ){
+ // This was the one and only edge for this connectedNode, so
+ // delete the node and edge since flag was set
+ String resVers = connectedVert.<String>property("resource-version").orElse(null);
+ removeAaiNode( transId, fromAppId, graph, connectedVert, "USE_DEFAULT", apiVersion, resVers);
+ deletedCount = deletedCount + 1;
+ }
+ else {
+ removeAaiEdge( transId, fromAppId, graph, ed );
+ }
+ }
+ isFirstOne = false;
+ }
+ }
+ aaiLogger.info(logline, true, "0");
+ return deletedCount;
+
+ } // end of detachConnectedNodes()
+
+
+
+ /**
+ * Detach connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param autoDeleteOrphans the auto delete orphans
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static int detachConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, boolean autoDeleteOrphans ) throws AAIException{
+ return detachConnectedNodes( transId, fromAppId, graph, nodeType,
+ propFilterHash, startNodeVal, autoDeleteOrphans, null);
+ }
+
+ /**
+ * Gets the nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param noFilterOnPurpose the no filter on purpose
+ * @param apiVersion the api version
+ * @return ArrayList<TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, Boolean noFilterOnPurpose, String apiVersion ) throws AAIException{
+ boolean skipGroomingFlag = true;
+ // we will only do real-time grooming if a system variable is set, telling us not to skip it.
+ String skipGroomingStr = AAIConstants.AAI_SKIPREALTIME_GROOMING;
+ if( skipGroomingStr.equals("false") ){
+ skipGroomingFlag = false;
+ }
+ return( getNodes(transId, fromAppId, graph, nodeType, propFilterHash, noFilterOnPurpose, apiVersion, skipGroomingFlag) );
+ }
+
+ /**
+ * Gets the nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param noFilterOnPurpose the no filter on purpose
+ * @param apiVersion the api version
+ * @param skipGroomCheck the skip groom check
+ * @return ArrayList<TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, Boolean noFilterOnPurpose, String apiVersion, boolean skipGroomCheck )
+ throws AAIException{
+ // Note - the skipGroomCheck flag is set to true when the DataGrooming tool is using this method to collect
+ // node data. When the grooming tool is collecting data, we don't want any nodes skipped, because we
+ // want details about what nodes/edges are bad - more detail than the check in this method does
+ // as it checks if a node is ok to return to a caller.
+
+ /* Use the nodeType + filterParams to find nodes.
+ */
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ ArrayList<TitanVertex> returnVertList = new ArrayList<TitanVertex>();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodes");
+ logline.add("nodeType", nodeType);
+ if( propFilterHash != null ){
+ logline.add("propFilter", propFilterHash.toString());
+ }
+ if( nodeType == null || nodeType.equals("") ){
+ // They should have passed in a nodeType
+ String emsg = "Required field: nodeType not passed to getNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ if( !noFilterOnPurpose && (propFilterHash == null || propFilterHash.isEmpty()) ){
+ // They should have passed at least one property to filter on
+ String emsg = "Required field: propFilterHash not passed to getNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ ArrayList<String> kName = new ArrayList<String>();
+ ArrayList<Object> kVal = new ArrayList<Object>();
+ int i = -1;
+ Collection <String> indexedProps = dbMaps.NodeMapIndexedProps.get(nodeType);
+ // First loop through to pick up the indexed-properties if there are any being used
+
+ if( propFilterHash != null ){
+ Iterator <?> it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) it.next();
+ String propName = (propEntry.getKey()).toString();
+ // Don't allow search on properties that do not have SINGLE cardinality
+ if( !checkPropCardinality(propName, "Set") && !checkPropCardinality(propName, "List") ){
+ if( indexedProps.contains(propName) ){
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)propEntry.getValue());
+ }
+ }
+ }
+
+ // Now go through again and pick up the non-indexed properties
+ it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <?,?> propEntry = (Map.Entry<?,?>)it.next();
+ String propName = (propEntry.getKey()).toString();
+ // Don't allow search on properties that do not have SINGLE cardinality
+ if( !checkPropCardinality(propName, "Set") && !checkPropCardinality(propName, "List") ){
+ if( ! indexedProps.contains(propName) ){
+ i++;
+ kName.add(i, propName);
+ kVal.add(i, (Object)propEntry.getValue());
+ }
+ }
+ }
+ }
+
+ Iterable <?> verts = null;
+ String propsAndValuesForMsg = "";
+ int topPropIndex = i;
+ if( topPropIndex == -1 ){
+ // No Filtering -- just go get them all
+ verts= graph.query().has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " ( no filter props ) ";
+ }
+ else if( topPropIndex == 0 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ") ";
+ }
+ else if( topPropIndex == 1 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ") ";
+ }
+ else if( topPropIndex == 2 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ") ";
+ }
+ else if( topPropIndex == 3 ){
+ verts= graph.query().has(kName.get(0),kVal.get(0)).has(kName.get(1),kVal.get(1)).has(kName.get(2),kVal.get(2)).has(kName.get(3),kVal.get(3)).has("aai-node-type",nodeType).vertices();
+ propsAndValuesForMsg = " (" + kName.get(0) + " = " + kVal.get(0) + ", "
+ + kName.get(1) + " = " + kVal.get(1) + ", "
+ + kName.get(2) + " = " + kVal.get(2) + ", "
+ + kName.get(3) + " = " + kVal.get(3) + ") ";
+ }
+ else {
+ String emsg = " -- Sorry -- we only support 4 filter properties in getNodes() for now... \n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ if( verts != null ){
+ // We did find some matching vertices
+ Iterator <?> it = verts.iterator();
+ while( it.hasNext() ){
+ TitanVertex v = (TitanVertex)it.next();
+
+ if( skipGroomCheck ){
+ // Good or bad, just return everything we find
+ returnVertList.add( v );
+ }
+ else {
+ // Weed out any bad vertices we find
+ if( thisVertexNotReachable(transId, fromAppId, graph, v, apiVersion) ){
+ String msg = "IN-LINE GROOMING - Unreachable Node DETECTED > skipping it. ";
+ logline.add("msg", msg);
+ }
+ else if( thisVertexHasBadEdges(transId, fromAppId, graph, v, apiVersion) ){
+ String msg = "IN-LINE GROOMING - BAD EDGE DETECTED > skipping vtxId = [" + v.id() + "] ";
+ logline.add("msg", msg);
+ }
+ else if( thisVertexIsAPhantom(transId, fromAppId, graph, v, apiVersion) ){
+ String msg = "IN-LINE GROOMING - BAD NODE DETECTED > skipping vtxId = [" + v.id() + "] ";
+ logline.add("msg", msg);
+ }
+ else {
+ returnVertList.add( v );
+ }
+ }
+ }
+ }
+ logline.add("passedValues", propsAndValuesForMsg);
+ aaiLogger.info(logline, true, "0");
+ return returnVertList;
+
+ }
+
+ /**
+ * Gets the nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param noFilterOnPurpose the no filter on purpose
+ * @return the nodes
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList<TitanVertex> getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, Boolean noFilterOnPurpose ) throws AAIException{
+ return getNodes(transId, fromAppId, graph, nodeType,
+ propFilterHash, noFilterOnPurpose, null );
+ }
+ // End of getNodes()
+
+
+ /**
+ * Gets the connected children.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVtx the start vtx
+ * @param limitToThisNodeType the limit to this node type
+ * @return ArrayList <TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getConnectedChildren( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVtx, String limitToThisNodeType ) throws AAIException{
+
+ // Just get child nodes (ie. other end of an OUT edge that is tagged as a parent/Child edge)
+
+ ArrayList <TitanVertex> childList = new ArrayList <TitanVertex> ();
+ Boolean doNodeTypeCheck = false;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getConnectedChildren");
+ if( limitToThisNodeType != null && ! limitToThisNodeType.equals("") ){
+ doNodeTypeCheck = true;
+ }
+ Iterable <?> verts = startVtx.query().direction(Direction.OUT).has("isParent",true).vertices();
+ Iterator <?> vertI = verts.iterator();
+ TitanVertex tmpVtx = null;
+ while( vertI != null && vertI.hasNext() ){
+ tmpVtx = (TitanVertex) vertI.next();
+ if( ! doNodeTypeCheck ){
+ childList.add(tmpVtx);
+ }
+ else {
+ String tmpNT = tmpVtx.<String>property("aai-node-type").orElse(null);
+ if( tmpNT != null && tmpNT.equals(limitToThisNodeType) ){
+ childList.add(tmpVtx);
+ }
+ }
+ }
+
+ return childList;
+
+ }// End of getConnectedChildren()
+
+
+
+ /**
+ * Gets the connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param apiVersion the api version
+ * @param excludeRecurComingIn the exclude recur coming in
+ * @return ArrayList <TitanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList<TitanVertex> getConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, String apiVersion, Boolean excludeRecurComingIn ) throws AAIException{
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ /* Get (almost) all the nodes that are connected to this vertex.
+ * Narrow down what is returned using optional filter parameters nodeType and propFilterHash
+ * NOTE - the default behavior has changed slightly. For start-Nodes that
+ * can be recursivly connected, this method will only bring back the same kind of
+ * connected node by following an OUT edge. Ie. if the start node is an "model-element",
+ * then this method will only follow OUT edges to get to other "model-element" type nodes.
+ */
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getConnectedNodes");
+ logline.add("nodeType", nodeType);
+ if( propFilterHash != null ){
+ logline.add("propFilter", propFilterHash.toString());
+ }
+
+ String startNodeNT = "";
+ if( startNodeVal == null ){
+ // They should have passed in the node that this query starts from
+ String emsg = "null startNode object passed to getConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg);
+ }
+ else {
+ startNodeNT = startNodeVal.<String>property("aai-node-type").orElse(null);
+ }
+
+ boolean nodeTypeFilter = false;
+ if( nodeType != null && !nodeType.equals("") ){
+ // They want to filter using nodeType
+ if( ! dbMaps.NodeProps.containsKey(nodeType) ){
+ String emsg = " Unrecognized nodeType [" + nodeType + "] passed to getConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6115");
+ throw new AAIException("AAI_6115", emsg);
+ }
+ nodeTypeFilter = true;
+ }
+
+ ArrayList <String> excludeVidList = new <String> ArrayList ();
+ if( DbEdgeRules.CanBeRecursiveNT.containsKey(startNodeNT) && excludeRecurComingIn ){
+ // If we're starting on a nodeType that supports recursion, then find any connected
+ // nodes that are coming from IN edges so we can exclude them later.
+
+ Iterable <?> vertsR = startNodeVal.query().direction(Direction.IN).vertices();
+ Iterator <?> vertIR = vertsR.iterator();
+ while( vertIR != null && vertIR.hasNext() ){
+ TitanVertex tmpVertIN = (TitanVertex) vertIR.next();
+ String tmpNT = tmpVertIN.<String>property("aai-node-type").orElse(null);
+ if( tmpNT != null && tmpNT.equals(startNodeNT) ){
+ // We're on a nodetype that supports recursion (like model-element) and we've
+ // found an connected Node of this same type on an IN edge - put this
+ // on our excludeList.
+ excludeVidList.add( tmpVertIN.id().toString() );
+ }
+ }
+ }
+
+ boolean propertyFilter = false;
+ if( propFilterHash != null && !propFilterHash.isEmpty() ){
+ // They want to filter using some properties
+ Iterator <?> it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>)it.next();
+ String propName = (propEntry.getKey()).toString();
+ if( ! dbMaps.NodeProps.containsValue(propName) ){
+ String emsg = " Unrecognized property name [" + propName + "] passed to getConnectedNodes().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6116");
+ throw new AAIException("AAI_6116", emsg);
+ }
+ // Don't allow search on properties that do not have SINGLE cardinality
+ if( !checkPropCardinality(propName, "Set") && !checkPropCardinality(propName, "List") ){
+ propertyFilter = true;
+ }
+ }
+ }
+ // If filter-properties were passed in, then look for nodes that have those values.
+ ArrayList<TitanVertex> returnVertList = new ArrayList<TitanVertex>();
+ Iterable<TitanVertex> qResult = null;
+ Iterator<TitanVertex> resultI = null;
+ try {
+ qResult = startNodeVal.query().vertices();
+ resultI = qResult.iterator();
+ }
+ catch( NullPointerException npe ){
+ String emsg = "Titan null pointer exception trying to get nodes connected to vertexId = " +
+ startNodeVal.id() + ", aai-node-type = [" + startNodeVal.property("aai-node-type") + "].";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ while( resultI != null && resultI.hasNext() ){
+ boolean addThisOne = true;
+ TitanVertex tmpV = (TitanVertex)resultI.next();
+ if( tmpV == null ){
+ String emsg = "Titan gave a null vertex when looking for nodes connected to vertexId = " +
+ startNodeVal.id() + ", aai-node-type = [" + startNodeVal.property("aai-node-type") + "].";
+ logline.add("emsg", emsg);
+ // Note - we will skip this one, but try to return any others that we find.
+ addThisOne = false;
+ }
+
+ else {
+ String tmpVid = tmpV.id().toString();
+ if( nodeTypeFilter ){
+ Object nto = tmpV.<Object>property("aai-node-type").orElse(null);
+ if( nto == null || !nto.toString().equals(nodeType) ){
+ String emsg = "Found a connected vertex (vertexId = " +
+ tmpVid + "), but it had no aai-node-type property. ";
+ logline.add("emsg", emsg);
+ // Note - we will skip this one, but try to return any others that we find.
+ addThisOne = false;
+ }
+ }
+
+ if( excludeVidList.contains(tmpVid) ){
+ String emsg = "Found a connected vertex (vertexId = " +
+ tmpVid + "), but will exclude it since it is on an IN edge and this nodeType " +
+ startNodeNT + " can be recursively attached.";
+ logline.add("emsg", emsg);
+ // Note - we will skip this one, but try to return any others that we find.
+ addThisOne = false;
+ }
+
+ if( propertyFilter ){
+ Iterator <?> it = propFilterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry <?,?>propEntry = (Map.Entry<?,?>)it.next();
+ String propName = (propEntry.getKey()).toString();
+ if( checkPropCardinality(propName, "Set") || checkPropCardinality(propName, "List") ){
+ // Don't allow search on properties that do not have SINGLE cardinality
+ continue;
+ }
+ Object propVal = propEntry.getValue();
+ Object foundVal = tmpV.<Object>property(propName).orElse(null);
+ if( foundVal != null && propVal != null && !foundVal.toString().equals(propVal.toString()) ){
+ addThisOne = false;
+ break;
+ }
+ else if( (foundVal == null && propVal != null) || (foundVal != null && propVal == null) ){
+ addThisOne = false;
+ break;
+ }
+ }
+ }
+ }
+ if( addThisOne ){
+ // This node passed the tests -- put it on the return List
+ returnVertList.add( (TitanVertex)tmpV );
+ }
+ }
+ //aaiLogger.debug(logline, " end ");
+ return returnVertList;
+
+ }// End of getConnectedNodes()
+
+
+ /**
+ * Gets the connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @param apiVersion the api version
+ * @return the connected nodes
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList<TitanVertex> getConnectedNodes(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal, String apiVersion ) throws AAIException {
+ return getConnectedNodes( transId, fromAppId, graph, nodeType,
+ propFilterHash, startNodeVal, apiVersion, true );
+ }
+
+ /**
+ * Gets the connected nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param nodeType the node type
+ * @param propFilterHash the prop filter hash
+ * @param startNodeVal the start node val
+ * @return the connected nodes
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static ArrayList<TitanVertex> getConnectedNodes(String transId, String fromAppId, TitanTransaction graph, String nodeType,
+ HashMap<String,Object> propFilterHash, TitanVertex startNodeVal ) throws AAIException {
+ return getConnectedNodes( transId, fromAppId, graph, nodeType,
+ propFilterHash, startNodeVal, null, true );
+
+ }
+
+ /**
+ * Ip address format OK.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param addrVal the addr val
+ * @param addrVer the addr ver
+ * @param apiVersion the api version
+ * @return Boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean ipAddressFormatOK(String transId, String fromAppId, String addrVal, String addrVer, String apiVersion) throws AAIException{
+
+ /* NOTE -- the google methods we use do not allow leading zeros in ipV4 addresses.
+ * So it will reject, "22.33.44.001"
+ */
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "ipAddressFormatOK");
+ logline.add("addrVal", addrVal);
+ logline.add("addrVer", addrVer);
+
+ if( addrVal == null ){
+ String emsg = " Bad data (addrVal = null) passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else if( addrVer == null ){
+ String emsg = " Bad data (addrType = null) passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+
+ Boolean retVal = false;
+ Boolean lookingForV4 = false;
+ Boolean lookingForV6 = false;
+ InetAddress inetAddr = null;
+
+ if( addrVer.equalsIgnoreCase("v4") || addrVer.equals("ipv4") || addrVer.equals("4")){
+ lookingForV4 = true;
+ }
+ else if( addrVer.equalsIgnoreCase("v6") || addrVer.equals("ipv6") || addrVer.equals("6")){
+ lookingForV6 = true;
+ }
+ else {
+ String emsg = " Bad data for addressVersion [" + addrVer + "] passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+
+ try {
+ inetAddr = InetAddresses.forString(addrVal);
+ if( inetAddr instanceof Inet4Address ){
+ if( lookingForV4 ){
+ retVal = true;
+ }
+ else {
+ String emsg = " Bad data. Address is a V4, but addressType said it should be V6. ["
+ + addrVal + "], [" + addrVer + "] passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ else if( inetAddr instanceof Inet6Address ){
+ if( lookingForV6 ){
+ retVal = true;
+ }
+ else {
+ String emsg = " Bad data. Address is a V6, but addressType said it should be V4. ["
+ + addrVal + "], [" + addrVer + "] passed to ipAddressFormatOK().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ }
+ catch (IllegalArgumentException e) {
+ String emsg = " Badly formed ip-address: [" + addrVal + "] passed to ipAddressFormatOK()";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ aaiLogger.info(logline, true, "0");
+ return retVal;
+
+ }//end of ipAddressFormatOk()
+
+ /**
+ * Ip address format OK.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param addrVal the addr val
+ * @param addrVer the addr ver
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean ipAddressFormatOK(String transId, String fromAppId, String addrVal, String addrVer) throws AAIException{
+ return ipAddressFormatOK( transId, fromAppId, addrVal, addrVer, null);
+ }
+
+ /**
+ * Save aai edge to db.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeLabel the edge label
+ * @param outV the out V
+ * @param inV the in V
+ * @param propHash the prop hash
+ * @param apiVersion the api version
+ * @return TitanEdge
+ * @throws AAIException the AAI exception
+ */
+ private static TitanEdge saveAaiEdgeToDb(String transId, String fromAppId, TitanTransaction graph, String edgeLabel,
+ TitanVertex outV, TitanVertex inV, HashMap <String,Object> propHash, String apiVersion) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "saveAaiEdgeToDb");
+
+
+ // If this edge doesn't exist yet, then create it.
+
+ // NOTE - the Titan javaDoc says that there might not always be an id for a node.
+ // This is the internal-titan-unique-id, not any of our data.
+ // Not sure how to know when it might be there and when it might not?!
+ // So far, it has worked for all my testing, but this might warrant some
+ // further investigation.
+
+ TitanEdge existingEdge = null;
+ String inVId = inV.id().toString();
+ Iterator <Edge> eI = outV.edges(Direction.BOTH, edgeLabel);
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(outV);
+ if( (otherVtx.id().toString()).equals(inVId) ){
+ // NOTE -?- Not sure -- at some point we might want to check the edgeLabels also since we might
+ // want to allow two different-type edges between the same two vertexes? (or maybe not.)
+ existingEdge = ed;
+ break;
+ }
+ }
+
+ if( existingEdge != null ){
+ // This is just an UPDATE
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ String msg = "update edge property/val = [" + entry.getKey() + "]/[" + entry.getValue() + "]";
+ logline.add("msg", msg);
+ existingEdge.property( entry.getKey(), entry.getValue() );
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return( existingEdge );
+ }
+ else {
+ // This is an ADD
+
+ // Uniqueness double-check. This is just to catch the possibility that at the transaction layer,
+ // if data came in for two identical nodes that point to the same dependant node (for uniqueness),
+ // we would only be able to catch the problem at the time the edge to the second node is added.
+ // For example - if they had a VM and then got a request to add two ipAddress nodes, but some
+ // bad data was passed and those two ipAddress nodes were identical -- we'd want to catch it.
+ String outV_NType = outV.<String>property("aai-node-type").orElse(null);
+ String inV_NType = inV.<String>property("aai-node-type").orElse(null);
+ if( needsADepNode4Uniqueness(transId, fromAppId, outV_NType, apiVersion)
+ && nodeTypeACanDependOnB(transId, fromAppId, outV_NType, inV_NType, apiVersion) ){
+ // The out-Vertex has a uniqueness dependency on the in-vertex
+ // Make sure we haven't already added an node/edge like this in this transaction
+ HashMap <String, Object> nodeKeyPropsHash = getNodeKeyPropHash(transId, fromAppId, graph, outV);
+ ArrayList<TitanVertex> resultList = new ArrayList<TitanVertex>();
+ resultList = DbMeth.getConnectedNodes("transId", "fromAppId", graph, outV_NType, nodeKeyPropsHash, inV, apiVersion, false);
+ if( resultList.size() > 0 ){
+ aaiLogger.info(logline, false, "AAI_6117");
+ String propInfo = "";
+ if( nodeKeyPropsHash != null ){
+ propInfo = nodeKeyPropsHash.toString();
+ }
+ String detail = "Failed to add edge. This node (" + inV_NType + ") already has an edge to a " + outV_NType +
+ " node with kepProps [" + propInfo + "]\n";
+ throw new AAIException("AAI_6117", detail);
+ }
+ }
+ else if( needsADepNode4Uniqueness(transId, fromAppId, inV_NType, apiVersion)
+ && nodeTypeACanDependOnB(transId, fromAppId, inV_NType, outV_NType, apiVersion) ){
+ // The in-Vertex has a uniqueness dependency on the out-vertex
+ // Make sure we haven't already added an node/edge like this in this transaction
+ HashMap <String, Object> nodeKeyPropsHash = getNodeKeyPropHash(transId, fromAppId, graph, inV);
+ ArrayList<TitanVertex> resultList = new ArrayList<TitanVertex>();
+ resultList = DbMeth.getConnectedNodes("transId", "fromAppId", graph, inV_NType, nodeKeyPropsHash, outV, apiVersion, false);
+ if( resultList.size() > 0 ){
+ aaiLogger.info(logline, false, "AAI_6117");
+ String propInfo = "";
+ if( nodeKeyPropsHash != null ){
+ propInfo = nodeKeyPropsHash.toString();
+ }
+ String detail = "Failed to add edge. This node (" + outV_NType + ") already has an edge to a " + inV_NType +
+ " node with kepProps [" + propInfo + "]\n";
+ throw new AAIException("AAI_6117", detail);
+ }
+ }
+
+
+ // We're good to go to add this edge
+
+ TitanEdge tEdge = outV.addEdge( edgeLabel, inV );
+ // Add the properties to the new Edge
+ for( Map.Entry<String, Object> entry : propHash.entrySet() ){
+ tEdge.property( entry.getKey(), entry.getValue() );
+ }
+
+ // For (resource-id updates) we need to "touch" the vertices on each side of the edge so
+ // anybody working on one of those vertices will know that something (ADDing this edge) has happened.
+ touchVertex( transId, fromAppId, inV );
+ touchVertex( transId, fromAppId, outV );
+
+ aaiLogger.debug(logline, " end ");
+ return tEdge;
+ }
+
+ }// End saveAaiEdgeToDb()
+
+
+
+ /**
+ * Derive edge rule key for this edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param tEdge the t edge
+ * @return String - key to look up edgeRule (fromNodeType|toNodeType)
+ * @throws AAIException the AAI exception
+ */
+ public static String deriveEdgeRuleKeyForThisEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanEdge tEdge ) throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deriveEdgeRulesKeyForThisEdge");
+
+ TitanVertex fromVtx = tEdge.outVertex();
+ TitanVertex toVtx = tEdge.inVertex();
+ String startNodeType = fromVtx.<String>property("aai-node-type").orElse(null);
+ String targetNodeType = toVtx.<String>property("aai-node-type").orElse(null);
+ String key = startNodeType + "|" + targetNodeType;
+ if( DbEdgeRules.EdgeRules.containsKey(key) ){
+ // We can use the node info in the order they were given
+ return( key );
+ }
+ else {
+ key = targetNodeType + "|" + startNodeType;
+ if( DbEdgeRules.EdgeRules.containsKey(key) ){
+ return( key );
+ }
+ else {
+ // Couldn't find a rule for this edge
+ String detail = "No EdgeRule found for passed nodeTypes: " + startNodeType + ", "
+ + targetNodeType ;
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ }
+ }// end of deriveEdgeRuleKeyForThisEdge()
+
+
+
+ /**
+ * Save aai edge to db.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeLabel the edge label
+ * @param outV the out V
+ * @param inV the in V
+ * @param propHash the prop hash
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ private static TitanEdge saveAaiEdgeToDb(String transId, String fromAppId, TitanTransaction graph, String edgeLabel,
+ TitanVertex outV, TitanVertex inV, HashMap <String,Object> propHash) throws AAIException{
+ return saveAaiEdgeToDb( transId, fromAppId, graph, edgeLabel,
+ outV, inV, propHash, null);
+ }
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @param apiVersion the api version
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, TitanVertex targetVert, String apiVersion ) throws AAIException{
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion, "");
+ return returnEdge;
+ }
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @param apiVersion the api version
+ * @param edgeType the edge type
+ * @return TitanEdge
+ * @throws AAIException the AAI exception
+ */
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, TitanVertex targetVert, String apiVersion, String edgeType ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdge");
+
+ TitanVertex fromVtx = null;
+ TitanVertex toVtx = null;
+ String startNodeType = startVert.<String>property("aai-node-type").orElse(null);
+ String targetNodeType = targetVert.<String>property("aai-node-type").orElse(null);
+ String fwdRuleKey = startNodeType + "|" + targetNodeType;
+ int fwdRuleCount = 0;
+ String fwdRule = "";
+ String fwdLabel = "";
+ String revRuleKey = targetNodeType + "|" + startNodeType;
+ int revRuleCount = 0;
+ String revRule = "";
+ String revLabel = "";
+ String edRule = "";
+ String edLabel = "";
+
+ Boolean checkType = false;
+ if( (edgeType != null) && edgeType != "" ){
+ checkType = true;
+ }
+
+ // As of 16-07, it is possible to have more than one kind of edge defined between a given
+ // pair of nodeTypes. So we need to check to see if there is only one possibility, or if
+ // we need to look at the edgeType to determine which to use.
+ // NOTE -- we're only supporting having 2 edges between a given pair of nodeTypes and
+ // one and only one of them would have to be a parent-child edge.
+
+ if( DbEdgeRules.EdgeRules.containsKey(fwdRuleKey) ){
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(fwdRuleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ while( ruleItr.hasNext() ){
+ String tmpRule = ruleItr.next();
+ String [] rules = tmpRule.split(",");
+ String tmpLabel = rules[0];
+ String tmpParChild = rules[3];
+ if( !checkType
+ || (checkType && tmpParChild.equals("true") && edgeType.equals("parentChild"))
+ || (checkType && tmpParChild.equals("false") && edgeType.equals("cousin")) ){
+ // Either they didn't want us to check the edgeType or it is a match
+ fwdRuleCount++;
+ if( fwdRuleCount > 1 ){
+ // We found more than one with the given info
+ String detail = "Multiple EdgeRules found for nodeTypes: [" + startNodeType + "], ["
+ + targetNodeType + "], edgeType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ else {
+ fwdRule = tmpRule;
+ fwdLabel = tmpLabel;
+ }
+ }
+ }
+ }
+
+ // Try it the other way also (unless this is the case of a nodeType recursively pointing to itself
+ // Ie. the edge rule: "model-element|model-element"
+ if( !revRuleKey.equals(fwdRuleKey) && DbEdgeRules.EdgeRules.containsKey(revRuleKey) ){
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(revRuleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ while( ruleItr.hasNext() ){
+ String tmpRule = ruleItr.next();
+ String [] rules = tmpRule.split(",");
+ String tmpLabel = rules[0];
+ String tmpParChild = rules[3];
+ if( !checkType
+ || (checkType && tmpParChild.equals("true") && edgeType.equals("parentChild"))
+ || (checkType && tmpParChild.equals("false") && edgeType.equals("cousin")) ){
+ // Either they didn't want us to check the edgeType or it is a match
+ revRuleCount++;
+ if( revRuleCount > 1 ){
+ // We found more than one with the given info
+ String detail = "Multiple EdgeRules found for nodeTypes: [" + targetNodeType + "], ["
+ + startNodeType + "], edgeType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ else {
+ revRule = tmpRule;
+ revLabel = tmpLabel;
+ }
+ }
+ }
+ }
+
+ if( (fwdRuleCount == 1) && (revRuleCount == 0) ){
+ // We can use the node info in the order they were given
+ fromVtx = startVert;
+ toVtx = targetVert;
+ edRule = fwdRule;
+ edLabel = fwdLabel;
+ }
+ else if( (fwdRuleCount == 0) && (revRuleCount == 1) ){
+ // We need to switch the vertex order so the edge-direction is correct
+ toVtx = startVert;
+ fromVtx = targetVert;
+ edRule = revRule;
+ edLabel = revLabel;
+ }
+ else if( (fwdRuleCount == 0) && (revRuleCount == 0) ){
+ // No edge rule found for this
+ String detail = "No EdgeRule found for passed nodeTypes: " + startNodeType + ", " + targetNodeType
+ + "], checkLabelType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+ else if( (fwdRuleCount > 0) && (revRuleCount > 0) ){
+ // We found more than one with the given info
+ String detail = "Multiple EdgeRules (fwd and rev) found for nodeTypes: [" + startNodeType + "], ["
+ + targetNodeType + "], checkLabelType = [" + edgeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ // If we got to this point, we now have a single edge label and we know to and from Vtx.
+
+ HashMap <String,Object> edgeParamHash = getEdgeTagPropPutHash4Rule(transId, fromAppId, edRule);
+ // We do "source-of-truth" for all edges
+ edgeParamHash.put("source-of-truth", fromAppId );
+
+ TitanEdge returnEdge = saveAaiEdgeToDb(transId, fromAppId, graph, edLabel, fromVtx, toVtx, edgeParamHash, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, TitanVertex targetVert ) throws AAIException{
+ return persistAaiEdge( transId, fromAppId, graph,
+ startVert, targetVert, null);
+ }
+ // End persistAaiEdge()
+
+
+ /**
+ * Persist aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeLabel the edge label
+ * @param startVert the start vert
+ * @param targetVert the target vert
+ * @param propHash the prop hash
+ * @param addIfNotFound the add if not found
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanEdge persistAaiEdge( String transId, String fromAppId, TitanTransaction graph,
+ String edgeLabel, TitanVertex startVert, TitanVertex targetVert,
+ HashMap <String,Object> propHash, Boolean addIfNotFound ) throws AAIException{
+
+ /*----- This method is depricated ------
+ * We will ignore the parameters: edgeLabel, propHash and addIfNotFound
+ * We will use the remaining params to call the newer version of this method
+ */
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdge--Depricated--");
+
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, null);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }// End depricated version of persistAaiEdge()
+
+
+ /**
+ * Persist aai edge with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetNodeType the target node type
+ * @param targetNodeParamHash the target node param hash
+ * @param apiVersion the api version
+ * @return TitanEdge
+ * @throws AAIException the AAI exception
+ */
+ public static TitanEdge persistAaiEdgeWithDepParams( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, String targetNodeType, HashMap <String,Object> targetNodeParamHash, String apiVersion) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdgeWithDepParams");
+
+ TitanVertex targetVert = getUniqueNodeWithDepParams( transId, fromAppId, graph, targetNodeType, targetNodeParamHash, apiVersion );
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }// End persistAaiEdgeWithDepParams()
+
+ // Version that lets you pass in an edgeType ("parentChild" or "cousin" since it sometimes cannot be determined
+ /**
+ * Persist aai edge with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetNodeType the target node type
+ * @param targetNodeParamHash the target node param hash
+ * @param apiVersion the api version
+ * @param edgeType the edge type
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ // from the two nodeTypes anymore (16-07)
+ public static TitanEdge persistAaiEdgeWithDepParams( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, String targetNodeType, HashMap <String,Object> targetNodeParamHash,
+ String apiVersion, String edgeType) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "persistAaiEdgeWithDepParams");
+
+ TitanVertex targetVert = getUniqueNodeWithDepParams( transId, fromAppId, graph, targetNodeType, targetNodeParamHash, apiVersion );
+ TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion, edgeType);
+
+ aaiLogger.info(logline, true, "0");
+ return returnEdge;
+
+ }// End persistAaiEdgeWithDepParams()
+
+ /**
+ * Persist aai edge with dep params.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param startVert the start vert
+ * @param targetNodeType the target node type
+ * @param targetNodeParamHash the target node param hash
+ * @return the titan edge
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static TitanEdge persistAaiEdgeWithDepParams( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex startVert, String targetNodeType, HashMap <String,Object> targetNodeParamHash) throws AAIException{
+ return persistAaiEdgeWithDepParams( transId, fromAppId, graph,
+ startVert, targetNodeType, targetNodeParamHash, null);
+ }
+
+ /**
+ * Gets the node key prop hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param vtx the vtx
+ * @return nodeKeyPropHash
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, Object> getNodeKeyPropHash( String transId, String fromAppId, TitanTransaction graph, TitanVertex vtx) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeKeyPropHash");
+
+ if( vtx == null ){
+ String emsg = "null node object passed to getNodeKeyPropHash().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg );
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ if( ! dbMaps.NodeKeyProps.containsKey(nType) ){
+ // Problem if no key Properties defined for this nodeType
+ logline.add("nodeType", nType);
+ aaiLogger.info(logline, false, "AAI_6105");
+ String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String detail = "No node-key-properties defined in dbMaps for nodeType = " + nType + " (ver=" + defVer + ")";
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ HashMap <String,Object>nodeKeyPropsHash = new HashMap<String,Object>();
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(nType);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ Object value = (Object) vtx.<Object>property(propName).orElse(null);
+ nodeKeyPropsHash.put(propName, value);
+ }
+
+ //aaiLogger.debug(logline, " end ");
+ return nodeKeyPropsHash;
+
+ }// End of getNodeKeyPropHash()
+
+ /**
+ * Gets the node name prop hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param vtx the vtx
+ * @param apiVersion the api version
+ * @return nodeKeyPropHash
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, Object> getNodeNamePropHash( String transId, String fromAppId, TitanTransaction graph, TitanVertex vtx, String apiVersion) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeNamePropHash");
+
+ if( vtx == null ){
+ String emsg = "null node object passed to getNodeNamePropHash().\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6109");
+ throw new AAIException("AAI_6109", emsg );
+ }
+
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ HashMap <String,Object>nodeNamePropsHash = new HashMap<String,Object>();
+ Collection <String> keyProps = DbMeth.getNodeNameProps(transId, fromAppId, nType, apiVersion);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ Object value = (Object) vtx.<Object>property(propName).orElse(null);
+ nodeNamePropsHash.put(propName, value);
+ }
+
+ //aaiLogger.debug(logline, " end ");
+ return nodeNamePropsHash;
+
+ }// End of getNodeNamePropHash()
+
+
+ /**
+ * Removes the aai edge.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param tEdge the t edge
+ * @return void
+ */
+ public static void removeAaiEdge( String transId, String fromAppId, TitanTransaction graph, TitanEdge tEdge){
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "removeAaiEdge");
+
+ // Before removing the edge, touch the vertices on each side so their resource-versions will get updated
+ TitanVertex tmpVIn = tEdge.inVertex();
+ touchVertex( transId, fromAppId, tmpVIn );
+
+ TitanVertex tmpVOut = tEdge.outVertex();
+ touchVertex( transId, fromAppId, tmpVOut );
+
+ // Remove the passed in edge.
+ tEdge.remove();
+ aaiLogger.info(logline, true, "0");
+
+ }// end of removeAaiEdge()
+
+
+ /**
+ * Removes the aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @param apiVersion the api version
+ * @param resourceVersion the resource version
+ * @throws AAIException the AAI exception
+ */
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam,
+ String apiVersion, String resourceVersion ) throws AAIException{
+ // Note: the resource Version Override flag is only set to true when called by the Model Delete code which
+ // has no way to know the resource-versions of nodes at lower-levels of it's model topology.
+ Boolean resVersionOverrideFlag = false;
+ removeAaiNode( transId, fromAppId, graph, thisVtx, scopeParam, apiVersion, resourceVersion, resVersionOverrideFlag );
+ }
+
+
+ /**
+ * <pre>
+ * Possible values for deleteScope can be:
+ * USE_DEFAULT - Get the scope from ref data for this node
+ * THIS_NODE_ONLY (but should fail if it there are nodes that depend on it for uniqueness)
+ * CASCADE_TO_CHILDREN - will look for OUT-Edges that have parentOf/hasDelTarget = true and follow those down
+ * ERROR_4_IN_EDGES_OR_CASCADE - combo of error-if-any-IN-edges + CascadeToChildren
+ * ERROR_IF_ANY_IN_EDGES - Fail if this node has any existing IN edges
+ * ERROR_IF_ANY_EDGES - Fail if this node has any existing edges at all!
+ * </pre>.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @param apiVersion the api version
+ * @param resourceVersion the resource version
+ * @param resVerOverride the res ver override
+ * @return void
+ * @throws AAIException the AAI exception
+ */
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam,
+ String apiVersion, String resourceVersion, Boolean resVerOverride ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "removeAaiNode");
+ logline.add("scopeParam", scopeParam);
+
+ String nodeType2Del = thisVtx.<String>property("aai-node-type").orElse(null);
+ String deleteScope = scopeParam;
+ if( scopeParam.equals("USE_DEFAULT") ){
+ deleteScope = getDefaultDeleteScope(transId, fromAppId, nodeType2Del, apiVersion);
+ logline.add("deleteScope", deleteScope);
+ }
+
+ if( !resVerOverride && needToDoResourceVerCheck(apiVersion, false) ){
+ // Need to check that they knew what they were deleting
+ String existingResVer = thisVtx.<String>property("resource-version").orElse(null);
+ if( resourceVersion == null || resourceVersion.equals("") ){
+ aaiLogger.info(logline, false, "AAI_6130");
+ String detail = "Resource-version not passed for delete of = " + nodeType2Del;
+ throw new AAIException("AAI_6130", detail);
+ }
+ else if( (existingResVer != null) && !resourceVersion.equals(existingResVer) ){
+ aaiLogger.info(logline, false, "AAI_6131");
+ String detail = "Resource-version MISMATCH for delete of = " + nodeType2Del;
+ throw new AAIException("AAI_6131", detail);
+ }
+ }
+
+ if( !deleteScope.equals("THIS_NODE_ONLY")
+ && !deleteScope.equals("CASCADE_TO_CHILDREN")
+ && !deleteScope.equals("ERROR_4_IN_EDGES_OR_CASCADE")
+ && !deleteScope.equals("ERROR_IF_ANY_EDGES")
+ && !deleteScope.equals("ERROR_IF_ANY_IN_EDGES") ){
+ aaiLogger.info(logline, false, "AAI_6120");
+ String detail = " Unrecognized value in deleteScope: [" + deleteScope + "].";
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ if( deleteScope.equals("ERROR_IF_ANY_EDGES") ){
+ if ( thisVtx.edges(Direction.BOTH).hasNext() ) {
+ aaiLogger.info(logline, false, "AAI_6120");
+ String detail = " Node cannot be deleted because it still has Edges and the ERROR_IF_ANY_EDGES scope was used.\n";
+ throw new AAIException("AAI_6110", detail);
+ }
+ }
+ else if( deleteScope.equals("ERROR_IF_ANY_IN_EDGES") || deleteScope.equals("ERROR_4_IN_EDGES_OR_CASCADE") ){
+ Iterator <Edge> eI = thisVtx.edges(Direction.IN);
+ boolean onlyHasParent = false;
+ Edge temp = null;
+ if( eI != null && eI.hasNext() ){
+ temp = eI.next();
+ Boolean isParent = temp.<Boolean>property("isParent").orElse(null);
+ if (isParent != null && isParent && !eI.hasNext()) {
+ onlyHasParent = true;
+ }
+
+ if (!onlyHasParent) {
+ aaiLogger.info(logline, false, "AAI_6110");
+ String detail = " Node cannot be deleted because it still has Edges and the " + deleteScope + " scope was used.\n";
+ throw new AAIException("AAI_6110", detail);
+ }
+ }
+ }
+ else if( deleteScope.equals("THIS_NODE_ONLY")){
+ // Make sure nobody depends on this node.
+ Iterator<Edge> eI = thisVtx.edges(Direction.BOTH);
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(thisVtx);
+ String nodeTypeA = otherVtx.<String>property("aai-node-type").orElse(null);
+ if( nodeTypeACanDependOnB(transId, fromAppId, nodeTypeA, nodeType2Del, apiVersion)){
+ // We're only supposed to delete this node - but another node is dependant on it,
+ // so we shouldn't delete this one.
+ aaiLogger.info(logline, false, "AAI_6110");
+ String detail = " Node cannot be deleted using scope = " + deleteScope +
+ " another node (type = " + nodeTypeA + ") depends on it for uniqueness.";
+ throw new AAIException("AAI_6110", detail);
+ }
+ }
+ }
+
+ // We've passed our checks - so do some deleting of edges and maybe pass
+ // the delete request down to children or delete-targets.
+
+ // First we deal with the "IN"-Edges which can't have children/delete-targets which
+ // by definition (of "IN") on the other end
+ Iterator <Edge> eI_In = thisVtx.edges(Direction.IN);
+ while( eI_In.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI_In.next();
+
+ //- "touch" vertex on other side of this edge so it gets a fresh resource-version
+ TitanVertex tmpVOther = ed.otherVertex(thisVtx);
+ touchVertex( transId, fromAppId, tmpVOther );
+
+ ed.remove();
+ }
+
+ // Now look at the "OUT"-edges which might include children or delete-targets
+ String cascadeMsg = "This nt = " + nodeType2Del + ", Cascading del to: ";
+ Iterator <Edge> eI_Out = thisVtx.edges(Direction.OUT);
+ if( !eI_Out.hasNext() ){
+ cascadeMsg = cascadeMsg + "[no children for this node]";
+ }
+ while( eI_Out.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI_Out.next();
+
+ // "touch" vertex on other side of this edge so it gets a fresh resource-version
+ TitanVertex tmpVOther = ed.otherVertex(thisVtx);
+ touchVertex( transId, fromAppId, tmpVOther );
+
+ Boolean otherVtxAChild = ed.<Boolean>property("isParent").orElse(null);
+ if( otherVtxAChild == null ){
+ otherVtxAChild = false;
+ }
+
+ Boolean otherVtxADeleteTarget = ed.<Boolean>property("hasDelTarget").orElse(null);
+ if( otherVtxADeleteTarget == null ){
+ otherVtxADeleteTarget = false;
+ }
+
+ if( (otherVtxAChild || otherVtxADeleteTarget) &&
+ (deleteScope.equals("CASCADE_TO_CHILDREN") || deleteScope.equals("ERROR_4_IN_EDGES_OR_CASCADE")) ){
+ // Delete the edge to the child and Pass the delete down to it.
+ ed.remove();
+ TitanVertex otherVtx = (TitanVertex) ed.otherVertex(thisVtx);
+ String vid = otherVtx.id().toString();
+ String nty = otherVtx.<String>property("aai-node-type").orElse(null);
+ String resVers = otherVtx.<String>property("resource-version").orElse(null);
+ cascadeMsg = cascadeMsg + "[" + nty + ":" + vid + "]";
+ removeAaiNode(transId, fromAppId, graph, otherVtx, "CASCADE_TO_CHILDREN", apiVersion, resVers);
+ }
+ else {
+ // The other node is not a child or deleteTarget. Delete the edge to it if it is not
+ // dependent (Should never be dependent since it's not a child/delTarget... but
+ // someone could create a node that was dependent for Uniqueness without
+ // being a child/target.
+
+ // DEBUG -- eventually add the check for dependancy that isn't on a parent-type or delTarget-type edge
+ ed.remove();
+ }
+ }
+ logline.add("cascadeMsg",cascadeMsg);
+
+ Iterator<Edge> eI = thisVtx.edges(Direction.BOTH);
+ if( ! eI.hasNext() ){
+ // By this point, either there were no edges to deal with, or we have dealt with them.
+ thisVtx.remove();
+ }
+ else {
+ // Something went wrong and we couldn't delete all the edges for this guy.
+ aaiLogger.info(logline, false, "AAI_6110");
+ String detail = "Node could be deleted because it unexpectedly still has Edges.\n";
+ throw new AAIException("AAI_6110", detail);
+ }
+ aaiLogger.info(logline, true, "0");
+
+ }
+
+
+ /**
+ * Removes the aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @return void
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam) throws AAIException{
+ removeAaiNode(transId, fromAppId, graph, thisVtx, scopeParam, null, null);
+ }
+
+ /**
+ * Removes the aai node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisVtx the this vtx
+ * @param scopeParam the scope param
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ @Deprecated
+ public static void removeAaiNode( String transId, String fromAppId, TitanTransaction graph, TitanVertex thisVtx, String scopeParam,
+ String apiVersion ) throws AAIException{
+ removeAaiNode(transId, fromAppId, graph, thisVtx, scopeParam, apiVersion, null);
+ }
+ // end of removeAaiNode()
+
+
+ /**
+ * Delete all graph data.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @return void
+ */
+ public static void deleteAllGraphData( String transId, String fromAppId, TitanGraph graph ){
+ /** ======================================================================
+ * WARNING -- this removes ALL the data that is currently in the graph.
+ * ======================================================================
+ **/
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deleteAllGraphData");
+ Iterator<Edge> edges = graph.edges(Direction.BOTH);
+ graph.tx().commit();
+ Edge edge = null;
+ while (edges.hasNext()) {
+ edge = edges.next();
+ edges.remove();
+ }
+ graph.tx().commit();
+ Iterator<Vertex> vertices = graph.vertices();
+ graph.tx().commit();
+ Vertex vertex = null;
+ while (vertices.hasNext()) {
+ vertex = vertices.next();
+ vertex.remove();
+ }
+ graph.tx().commit();
+ aaiLogger.info(logline, true, "0");
+ }
+
+
+ /**
+ * Show all edges for node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @return the array list
+ */
+ public static ArrayList <String> showAllEdgesForNode( String transId, String fromAppId, TitanVertex tVert ){
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+ Iterator <Edge> eI = tVert.edges(Direction.BOTH);
+ if( ! eI.hasNext() ){
+ retArr.add("No edges were found for this vertex. ");
+ }
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ String lab = ed.label();
+ TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert);
+ if( vtx == null ){
+ retArr.add(" >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
+ }
+ else {
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ String vid = vtx.id().toString();
+ retArr.add("Found an edge (" + lab + ") from this vertex to a [" + nType + "] node with VtxId = " + vid );
+ //DEBUG ---
+ //showPropertiesForEdge( transId, fromAppId, ed );
+ }
+ }
+ return retArr;
+ }
+
+
+ /**
+ * Show properties for node.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @return the array list
+ */
+ public static ArrayList <String> showPropertiesForNode( String transId, String fromAppId, TitanVertex tVert ){
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+ if( tVert == null ){
+ retArr.add("null Node object passed to showPropertiesForNode()\n");
+ }
+ else {
+ String nodeType = "";
+ //String datType = "";
+ Object ob = tVert.<Object>property("aai-node-type").orElse(null);
+ if( ob == null ){
+ nodeType = "null";
+ }
+ else{
+ nodeType = ob.toString();
+ //datType = ob.getClass().getSimpleName();
+ }
+
+ retArr.add(" AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
+ retArr.add(" Property Detail: ");
+ Iterator<VertexProperty<Object>> pI = tVert.properties();
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ Object val = tp.value();
+ //retArr.add("Prop: [" + tp.getPropertyKey() + "], val = [" + val + "], dataType = " + val.getClass() );
+ retArr.add("Prop: [" + tp.key() + "], val = [" + val + "] ");
+ }
+ }
+ return retArr;
+ }
+
+
+ /**
+ * Gets the node name props.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param nodeType the node type
+ * @param apiVersion the api version
+ * @return HashMap of keyProperties
+ * @throws AAIException the AAI exception
+ */
+ public static Collection <String> getNodeNameProps( String transId, String fromAppId, String nodeType, String apiVersion ) throws AAIException{
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getNodeNameProps");
+ logline.add("nodeType", nodeType);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Collection <String> nameProps = new ArrayList <String>();
+ if( dbMaps.NodeNameProps.containsKey(nodeType) ){
+ nameProps = dbMaps.NodeNameProps.get(nodeType);
+ }
+ else if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){
+ // The passed-in nodeType was really a nodeCategory, theoretically, all the guys in the same
+ // category should have the same name property -- so if they just give us the category, we will
+ // just give the name info from the first nodeType we encounter of that category.
+ Collection <String> nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType);
+ Iterator <String> catItr = nTypeCatCol.iterator();
+ String catInfo = "";
+ if( catItr.hasNext() ){
+ // For now, we only look for one.
+ catInfo = catItr.next();
+ }
+ else {
+ aaiLogger.info(logline, false, "AAI_6105");
+ String detail = "Required Property name(s) not found for nodeType = " + nodeType;
+ throw new AAIException("AAI_6105", detail);
+ }
+
+ String [] flds = catInfo.split(",");
+ if( flds.length != 4 ){
+ String detail = "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ String nodeTypesString = flds[0];
+ String [] nodeTypeNames = nodeTypesString.split("\\|");
+ if( nodeTypeNames != null && nodeTypeNames.length > 0 ){
+ // We'll just use the first one
+ String nt = nodeTypeNames[0];
+ nameProps = dbMaps.NodeNameProps.get(nt);
+ }
+ }
+
+
+ // Note - it's ok if there was no defined name property for this nodeType.
+
+ return nameProps;
+
+ }// end of getNodeKeyPropNames
+
+
+ /**
+ * Gets the edge tag prop put hash 4 rule.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param edRule the ed rule
+ * @return the edge tag prop put hash 4 rule
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getEdgeTagPropPutHash4Rule( String transId, String fromAppId, String edRule )
+ throws AAIException{
+ // For a given edgeRule - already pulled out of DbEdgeRules.EdgeRules -- parse out the "tags" that
+ // need to be set for this kind of edge.
+ // These are the Boolean properties like, "isParent", "usesResource" etc.
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getEdgeTagPropPutHash4Rule");
+
+ HashMap <String,Object> retEdgePropPutMap = new HashMap <String,Object>();
+
+ if( (edRule == null) || edRule.equals("") ){
+ // No edge rule found for this
+ String detail = " blank edRule passed to getEdgeTagPropPutHash4Rule() ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ int tagCount = DbEdgeRules.EdgeInfoMap.size();
+ String [] rules = edRule.split(",");
+ if( rules.length != tagCount ){
+ String detail = "Bad EdgeRule data (itemCount =" + rules.length + ") for rule = [" + edRule + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ // In DbEdgeRules.EdgeRules -- What we have as "edRule" is a comma-delimited set of strings.
+ // The first item is the edgeLabel.
+ // The second in the list is always "direction" which is always OUT for the way we've implemented it.
+ // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to
+ // tags as defined in EdgeInfoMap.
+ // Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it
+ for( int i = DbEdgeRules.firstTagIndex; i < tagCount; i++ ){
+ String booleanStr = rules[i];
+ Integer mapKey = new Integer(i);
+ String propName = DbEdgeRules.EdgeInfoMap.get(mapKey);
+ String revPropName = propName + "-REV";
+
+ if( booleanStr.equals("true") ){
+ retEdgePropPutMap.put(propName, true);
+ retEdgePropPutMap.put(revPropName,false);
+ }
+ else if( booleanStr.equals("false") ){
+ retEdgePropPutMap.put(propName, false);
+ retEdgePropPutMap.put(revPropName,false);
+ }
+ else if( booleanStr.equals("reverse") ){
+ retEdgePropPutMap.put(propName, false);
+ retEdgePropPutMap.put(revPropName,true);
+ }
+ else {
+ String detail = "Bad EdgeRule data for rule = [" + edRule + "], val = [" + booleanStr + "].";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6121");
+ throw new AAIException("AAI_6121", detail);
+ }
+
+ }
+
+ return retEdgePropPutMap;
+
+ } // End of getEdgeTagPropPutHash()
+
+
+
+ /**
+ * Gets the edge tag prop put hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param edgeRuleKey the edge rule key
+ * @return the edge tag prop put hash
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getEdgeTagPropPutHash( String transId, String fromAppId, String edgeRuleKey )
+ throws AAIException{
+ // For a given edgeRuleKey (nodeTypeA|nodeTypeB), look up the rule that goes with it in
+ // DbEdgeRules.EdgeRules and parse out the "tags" that need to be set on each edge.
+ // These are the Boolean properties like, "isParent", "usesResource" etc.
+ // Note - this code is also used by the updateEdgeTags.java code
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getEdgeTagPropPutHash");
+
+ if( ! DbEdgeRules.EdgeRules.containsKey(edgeRuleKey) ){
+ String detail = "Could not find an DbEdgeRule entry for passed edgeRuleKey (nodeTypeA|nodeTypeB): " + edgeRuleKey + ".";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ String edRule = "";
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(edgeRuleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ // For the current database, there can only be one type of edge between any two particular node-types.
+ // DEBUG ------------------- TBD -------------
+ // WARNING --- THIS IS NOT TRUE ANYMORE (16-07) ---- WARNING
+
+ edRule = ruleItr.next();
+ }
+ else {
+ // No edge rule found for this
+ String detail = "Could not find an EdgeRule for passed edgeRuleKey (nodeTypeA|nodeTypeB): " + edgeRuleKey + ".";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", detail);
+ }
+
+ HashMap <String,Object> retEdgePropPutMap = getEdgeTagPropPutHash4Rule(transId, fromAppId, edRule);
+
+ return retEdgePropPutMap;
+
+ } // End of getEdgeTagPropPutHash()
+
+
+ /**
+ * This property was put by newer version of code.
+ *
+ * @param apiVersionStr the api version str
+ * @param nodeType the node type
+ * @param propName the prop name
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ private static boolean thisPropertyWasPutByNewerVersionOfCode( String apiVersionStr,
+ String nodeType, String propName) throws AAIException{
+ // We want to return True if the nodeType + property-name combo was introduced AFTER the apiVersion passed.
+
+ int apiVerInt = 0;
+ int propIntroVerInt = 0;
+
+ if( apiVersionStr == null || apiVersionStr.equals("") ){
+ apiVersionStr = org.openecomp.aai.util.AAIApiVersion.get();
+ }
+ apiVerInt = getVerNumFromVerString(apiVersionStr);
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ String propIntroKey = nodeType + "|" + propName;
+ if( propName.equals("prov-status") ){
+ // This is a special case -- The dbMaps from v2 has it in there, but it was introduced half way through. So
+ // it needs to be catogorized as v3.
+ propIntroVerInt = 3;
+ }
+ else if( ! dbMaps.PropertyVersionInfoMap.containsKey(propIntroKey) ){
+ String detail = propIntroKey + " [" + propIntroKey + "] not found in dbMaps.PropertyVersionInfoMap.";
+ throw new AAIException("AAI_6121", detail);
+ }
+ else {
+ String propIntroVerString = dbMaps.PropertyVersionInfoMap.get(propIntroKey);
+ propIntroVerInt = getVerNumFromVerString( propIntroVerString );
+ }
+
+ if( propIntroVerInt > apiVerInt ){
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ } // End of thisPropertyWasPutByNewerVersionOfCode()
+
+
+ /**
+ * Touch vertex.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param v the v
+ * @return void
+ */
+ public static void touchVertex( String transId, String fromAppId, TitanVertex v ){
+ // We want to "touch" the vertex -- Ie. update it's last-mod-date, last-mod- resource-version to the current date/time
+ if( v != null ){
+ long unixTimeNow = System.currentTimeMillis() / 1000L;
+ String timeNowInSec = "" + unixTimeNow;
+ v.property( "aai-last-mod-ts", timeNowInSec );
+ v.property( "resource-version", timeNowInSec );
+ v.property( "last-mod-source-of-truth", fromAppId );
+ }
+ } // End of touchVertex()
+
+
+ /**
+ * Check prop cardinality.
+ *
+ * @param propName the prop name
+ * @param cardinalityType the cardinality type
+ * @return boolean
+ * @throws AAIException the AAI exception
+ */
+ public static boolean checkPropCardinality( String propName, String cardinalityType ) throws AAIException {
+
+ // Return true if the named property is tagged in our dbMaps PropetyDataTypeMap as
+ // having the passed in cardinality type.
+ // NOTE: supported cardinality types in dbMaps = "Set" or "List"
+ // In Titan, those go in as "SET" and "LIST"
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ if( dbMaps.PropertyDataTypeMap.containsKey(propName) ){
+ String propDataType = dbMaps.PropertyDataTypeMap.get(propName);
+ if( propDataType != null && propDataType.startsWith(cardinalityType) ){
+ return true;
+ }
+ }
+ return false;
+
+ } // End of checkPropCardinality()
+
+ /**
+ * Convert type if needed.
+ *
+ * @param propName the prop name
+ * @param val the val
+ * @return convertedValue (if it was a String but needed to be a Boolean)
+ * @throws AAIException the AAI exception
+ */
+ public static Object convertTypeIfNeeded( String propName, Object val )
+ throws AAIException {
+ // Make sure the dataType of the passed-in Object matches what the DB expects
+
+ // NOTE: since this is a fix very late in our dev cycle, we'll just fix the scenarios that
+ // we're having trouble with which is Strings getting into the db which should be going in as
+ // Booleans or Integers.
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ if( dbMaps.PropertyDataTypeMap.containsKey(propName) ){
+ String dbExpectedDataType = dbMaps.PropertyDataTypeMap.get(propName);
+ if( dbExpectedDataType != null
+ && dbExpectedDataType.equals("Boolean")
+ && val != null
+ && !(val instanceof Boolean) ){
+ String valStr = val.toString().trim();
+ if( valStr.equals("true") || valStr.equals("True") || valStr.equals("TRUE") ){
+ return Boolean.valueOf("true");
+ }
+ else if( valStr.equals("false") || valStr.equals("False") || valStr.equals("FALSE") ){
+ return Boolean.valueOf("false");
+ }
+ else {
+ String emsg = "Error trying to convert value: [" + valStr + "] to a Boolean for property + " + propName + "\n";
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ else if( dbExpectedDataType != null
+ && dbExpectedDataType.equals("Integer")
+ && val != null
+ && !(val.toString().trim().equals(""))
+ && !(val instanceof Integer) ){
+ String valStr = val.toString().trim();
+ Integer newInt;
+ try {
+ newInt = Integer.valueOf(valStr);
+ return newInt;
+ }
+ catch( Exception e ){
+ String emsg = "Error trying to convert value: [" + valStr + "] to an Integer for property + " + propName + "\n";
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ }
+
+ // If it didn't need to be converted, just return it.
+ return val;
+
+ } // End of convertTypeIfNeeded()
+
+
+
+ /**
+ * This vertex not reachable.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param v the v
+ * @param version the version
+ * @return boolean
+ */
+ public static boolean thisVertexNotReachable( String transId, String fromAppId, TitanTransaction graph, TitanVertex v, String version){
+ if( v == null ){
+ return true;
+ }
+ else {
+ try {
+ v.id().toString();
+ }
+ catch( Exception ex ){
+ // Could not get this -- sometimes we're holding a vertex object that has gotten deleted, so
+ // when we try to get stuff from it, we get an "Element Has Been Removed" error from Titan
+ return true;
+ }
+ }
+
+ return false;
+
+ } // End of thisVertexNotReachable()
+
+ /**
+ * This vertex has bad edges.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param v the v
+ * @param version the version
+ * @return boolean
+ */
+ public static boolean thisVertexHasBadEdges( String transId, String fromAppId, TitanTransaction graph, TitanVertex v, String version){
+
+ Iterator <Edge> eItor = v.edges(Direction.BOTH);
+ while( eItor.hasNext() ){
+ Edge e = null;
+ e = eItor.next();
+ if( e == null ){
+ return true;
+ }
+ Vertex vIn = e.inVertex();
+ if( (vIn == null) || (vIn.<String>property("aai-node-type").orElse(null) == null) ){
+ // this is a bad edge because it points to a vertex that isn't there anymore
+ return true;
+ }
+
+ Vertex vOut = e.outVertex();
+ if( (vOut == null) || (vOut.<String>property("aai-node-type").orElse(null) == null) ){
+ // this is a bad edge because it points to a vertex that isn't there anymore
+ return true;
+ }
+ }
+
+ // If we made it to here, the vertex's edges must be ok.
+ return false;
+
+ } // End of thisVertexHasBadEdges()
+
+
+ /**
+ * This vertex is A phantom.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param v the v
+ * @param version the version
+ * @return boolean
+ * @throws AAIException the AAI exception
+ */
+ public static boolean thisVertexIsAPhantom( String transId, String fromAppId, TitanTransaction graph, TitanVertex v, String version )
+ throws AAIException {
+
+
+ // The kind of Phantom we're looking for is the kind that we sometimes get when we do a select without
+ // using key properties. They can be in the database as a vertex, but the indexes that should point to
+ // them are not working -- so they cannot be used by normal interfaces (like the REST API) which means
+ // that if we return it, it can mess up a caller who tries to use it.
+ if( v == null ){
+ return true;
+ }
+ String thisVid = v.id().toString();
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ Object propOb = v.<Object>property("aai-node-type").orElse(null);
+ if( propOb == null ){
+ // This vertex does not have an aai-node-type ---> it is messed up
+ return true;
+ }
+ String nType = propOb.toString();
+ if( ! dbMaps.NodeKeyProps.containsKey(nType) ){
+ // This node Type does not have keys defined
+ // This could just be bad reference data, so we will not flag this guy, but we
+ // can't really do our test...
+ return false;
+ }
+
+ HashMap <String,Object> propHashWithKeys = new HashMap<String, Object>();
+ Collection <String> keyProps = null;
+ try {
+ keyProps = getNodeKeyPropNames(transId, fromAppId, nType, version);
+ }
+ catch (AAIException ex) {
+ // something wrong with getting this guy's key property names - we'll abandon this test...
+ return false;
+ }
+
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String propName = keyPropI.next();
+ String propVal = "";
+ Object ob = v.<Object>property(propName).orElse(null);
+ if( ob != null ){
+ propVal = ob.toString();
+ }
+ propHashWithKeys.put(propName, propVal);
+ }
+ try {
+ // Note - We can get more than one back since some nodes need a dep. node for uniqueness.
+ // We don't care about that -- we just want to make sure we can get this vertex back when
+ // we're searching with it's indexed fields.
+ // NOTE - we're passing the skipGroomCheck to getNodes so we don't wind up in an infinite loop
+ ArrayList <TitanVertex> vertList2 = getNodes( transId, fromAppId, graph, nType, propHashWithKeys, false, version, true );
+ Iterator<TitanVertex> iter2 = vertList2.iterator();
+ while( iter2.hasNext() ){
+ TitanVertex tvx2 = iter2.next();
+ String foundId = tvx2.id().toString();
+ if( foundId.equals( thisVid ) ){
+ // We could get back the vertex by looking it up using key properties... That's good.
+ return false;
+ }
+ }
+ }
+ catch (Exception e2) {
+ //String msg = " Error encountered for this vertex id: [" + thisVid +
+ // "]. Caught this exception: " + e2.toString();
+ // Something messed up - but that doesn't prove that this is a phantom.
+ return false;
+ }
+
+ // If we dropped down to here, we have looked but could not pull the vertex out of the
+ // db using it's key fields, so it gets flagged as a Phantom.
+ return true;
+
+ } // End of thisVertexIsAPhantom()
+
+
+ /**
+ * Gets the node by unique key.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param aaiUniquekey the aai uniquekey
+ * @return the node by unique key
+ */
+ public TitanVertex getNodeByUniqueKey(String transId, String fromAppId, TitanTransaction graph, String aaiUniquekey) {
+
+ TitanVertex vert = null;
+
+ Iterator<?> vertI = graph.query().has("aai-unique-key", aaiUniquekey).vertices().iterator();
+
+ if( vertI != null && vertI.hasNext()) {
+ // We found a vertex that meets the input criteria.
+ vert = (TitanVertex) vertI.next();
+ }
+
+ return vert;
+ }
+
+
+
+}
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbSearchWithTags.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbSearchWithTags.java
new file mode 100644
index 0000000..5ab8134
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbSearchWithTags.java
@@ -0,0 +1,771 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+
+/**
+ * Database-level Search-Utility class that uses edge-tags to help it navigate the graph.
+ */
+public class DbSearchWithTags{
+
+ private static AAILogger aaiLogger = new AAILogger(DbSearchWithTags.class.getName());
+
+
+ /**
+ * Identify top node set.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeTag the edge tag
+ * @param topNodeType the top node type
+ * @param initialFilterHash the initial filter hash
+ * @param maxLevels the max levels
+ * @return List<titanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, TitanVertex> identifyTopNodeSet( String transId, String fromAppId, TitanTransaction graph,
+ String edgeTag, String topNodeType, HashMap <String,Object> initialFilterHash, int maxLevels )
+ throws AAIException {
+
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "identifyInitialNodeSet");
+
+ HashMap <String, TitanVertex> topVertHash = new HashMap <String, TitanVertex>();
+ if( graph == null ){
+ String emsg = "null graph object passed to identifyInitialNodeSet()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+
+ // Given the filter, we want to select all the nodes of the type the filter tells us that have the
+ // property they gave us.
+ // Then looping through those start points, we will look "up" and then "down" to find the set of target/top nodes.
+
+ if( initialFilterHash == null || initialFilterHash.isEmpty() ){
+ String emsg = " initialFilterHash is required for identifyInitialNodeSet() call. \n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ // NOTE: we're expecting the filter to have a format like this: "nodeType.parameterName:parameterValue"
+ Iterator <?> it = initialFilterHash.entrySet().iterator();
+ // -- DEBUG -- for now we only deal with ONE initial filter parameter
+ // it would be easy enough to deal with multiple parameters if they all
+ // applied to the same nodeType.
+ String propNodeTypeDotName = "";
+ String initNodeType = "";
+ String initPropName = "";
+ HashMap <String,Object> initFilterTweakedHash = new HashMap <String,Object>();
+
+ HashMap <String,Object> initFilterHashUpper = new HashMap <String,Object>();
+ HashMap <String,Object> initFilterHashLower = new HashMap <String,Object>();
+ Boolean isKludgeCase = false;
+ String extraChecks = "";
+
+ String propVal = "";
+ if( it.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) it.next();
+ propNodeTypeDotName = (propEntry.getKey()).toString();
+ propVal = (propEntry.getValue()).toString();
+ }
+
+ int periodLoc = propNodeTypeDotName.indexOf(".");
+ if( periodLoc <= 0 ){
+ String emsg = "Bad filter param key passed in: [" + propNodeTypeDotName + "]. Expected format = [nodeName.paramName]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ initNodeType = propNodeTypeDotName.substring(0,periodLoc);
+ initPropName = propNodeTypeDotName.substring(periodLoc + 1);
+ initFilterTweakedHash.put(initPropName, propVal);
+
+ if( (initNodeType.equals("generic-vnf") && initPropName.equals("vnf-name"))
+ || (initNodeType.equals("vserver") && initPropName.equals("vserver-name")) ){
+ isKludgeCase = true;
+ String propValUpper = propVal.toUpperCase();
+ initFilterHashUpper.put(initPropName, propValUpper);
+ String propValLower = propVal.toLowerCase();
+ initFilterHashLower.put(initPropName, propValLower);
+ extraChecks = ", " + initFilterHashUpper.toString() + ", " + initFilterHashLower.toString();
+ }
+ }
+
+ ArrayList <TitanVertex> startVList = DbMeth.getNodes( transId, fromAppId, graph, initNodeType, initFilterTweakedHash, true, "v?");
+ if( startVList.isEmpty() && isKludgeCase ){
+ // We couldn't find any start nodes, but for two kludged cases, we will look again with all upper case
+ // and then again with all Lower case if needed.
+ startVList = DbMeth.getNodes( transId, fromAppId, graph, initNodeType, initFilterHashUpper, true, "v?");
+ if( startVList.isEmpty() ){
+ // Still have no results, but since we're in the kludge case, we'll try again.
+ startVList = DbMeth.getNodes( transId, fromAppId, graph, initNodeType, initFilterHashLower, true, "v?");
+ }
+ }
+
+ // To make sure we don't have duplicates, create a hash of the resulting vertices using their vertexId as the key
+ HashMap<String, TitanVertex> startVertHash = new HashMap<String, TitanVertex>();
+ Iterator<TitanVertex> iter = startVList.iterator();
+ while( iter.hasNext() ){
+ TitanVertex tvx = iter.next();
+ String vid = tvx.id().toString();
+ startVertHash.put(vid,tvx);
+ }
+
+ if( startVertHash.isEmpty() ){
+ System.out.println("Probably want to log this -- but, No vertices found for inital search conditions: [ " +
+ initialFilterHash.toString() + "]" + extraChecks );
+ }
+ else {
+ for( Map.Entry<String, TitanVertex> entry : startVertHash.entrySet() ){
+ // For each starting point vertex found, we need to look for 'top-level' vertices that correspond to it
+ TitanVertex tv = entry.getValue();
+ HashMap <String,TitanVertex> targVHash = lookForTargetsUsingStartNodes( transId, fromAppId, graph,
+ edgeTag, topNodeType, tv, maxLevels );
+
+ Iterator <?> vit = targVHash.entrySet().iterator();
+ while( vit.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) vit.next();
+ String foundVid = (propEntry.getKey()).toString();
+ TitanVertex foundVtx = (TitanVertex) (propEntry.getValue());
+ topVertHash.put(foundVid, foundVtx);
+ }
+ }
+ }
+
+ if( topVertHash.isEmpty() ){
+ // No Vertex was found - throw a not-found exception
+ String msg = "No Node of type " + topNodeType + " found for properties: " + initialFilterHash.toString() + extraChecks;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ return topVertHash;
+ }
+
+ }// End identifyInitialNodeSet()
+
+
+ /**
+ * Look for targets using start nodes.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeTag the edge tag
+ * @param topNodeType the top node type
+ * @param startVtx the start vtx
+ * @param maxLevels the max levels
+ * @return HashMap<vtxId,titanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, TitanVertex> lookForTargetsUsingStartNodes( String transId, String fromAppId, TitanTransaction graph,
+ String edgeTag, String topNodeType, TitanVertex startVtx, int maxLevels )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "lookForTargetsUsingStartNodes");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to lookForTargetsUsingStartNodes()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ // Walk the graph using tagged "IN" edges to try to find topNodeType vertices
+ HashMap <String, TitanVertex> targetVertHash = lookForTargetsInOneDirection( transId, fromAppId, graph,
+ edgeTag, topNodeType, startVtx, Direction.IN, 0, maxLevels );
+
+ // Walk the graph using tagged "OUT" edges to find vertices of the topNodeType
+ HashMap <String, TitanVertex> foundOutVtxHash = lookForTargetsInOneDirection( transId, fromAppId, graph,
+ edgeTag, topNodeType, startVtx, Direction.OUT, 0, maxLevels );
+
+ // Add the targetVertHash that was found for IN edges with the foundOutVtxHash
+ if( !foundOutVtxHash.isEmpty() ){
+ Iterator <?> vit = foundOutVtxHash.entrySet().iterator();
+ while( vit.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) vit.next();
+ String foundVid = (propEntry.getKey()).toString();
+ TitanVertex foundVtx = (TitanVertex) (propEntry.getValue());
+ targetVertHash.put(foundVid, foundVtx);
+ }
+ }
+
+ return targetVertHash;
+
+ } // End of lookForTargetsUsingStartNodes()
+
+
+ /**
+ * Look for targets in one direction.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeTag the edge tag
+ * @param topNodeType the top node type
+ * @param startVtx the start vtx
+ * @param dir the dir
+ * @param levelCounter the level counter
+ * @param maxLevels the max levels
+ * @return HashMap<vtxId,titanVertex>
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, TitanVertex> lookForTargetsInOneDirection( String transId, String fromAppId, TitanTransaction graph,
+ String edgeTag, String topNodeType, TitanVertex startVtx, Direction dir, int levelCounter, int maxLevels )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "lookForTargetsInOneDirection");
+ levelCounter++;
+
+ //System.out.println(" DEBUG -- levelcount in lookForTargetsInOneDirection = " + levelCounter);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "lookForTargetsInOneDirection() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ HashMap <String, TitanVertex> targetVertHash = new HashMap <String, TitanVertex>();
+
+ if( startVtx.property("aai-node-type").orElse(null).equals(topNodeType) ){
+ // We're starting on the kind of node we were looking for - so just return it, don't keep looking
+ // NOTE - this assumes that we will not find layers of the target-type node --
+ String vid = startVtx.id().toString();
+ targetVertHash.put(vid, startVtx);
+ return targetVertHash;
+ }
+
+ //System.out.println("DEBUG -- about to run the actual edge query (dir = " + dir + ", tag = " + edgeTag + ", level = " + levelCounter );
+
+ // Look for target nodes using results we got looking at normal edges in the "normal" direction
+ Iterable <?> verts = startVtx.query().direction(dir).has(edgeTag,true).vertices();
+ Iterator <?> vertI = verts.iterator();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ String nType = tmpVert.<String>property("aai-node-type").orElse(null);
+ //System.out.println("DEBUG -- going " + dir + ", found a node [" + nType + "], id = " + vid + " -- ");
+ if( nType.equals(topNodeType) ){
+ // We found a vertex that meets the input criteria - put it on our output hash.
+ targetVertHash.put(vid, tmpVert);
+ }
+ else {
+ // keep looking in the same direction
+ //System.out.println("DEBUG1 -- do the actual recursive call staring from this node (vid = " + vid + "), direction = " + dir);
+ HashMap <String, TitanVertex> tmpHash = lookForTargetsInOneDirection( transId, fromAppId, graph,
+ edgeTag, topNodeType, tmpVert, dir, levelCounter, maxLevels );
+ if( !tmpHash.isEmpty() ){
+ // We found more vertexes to add to the return Hash
+ Iterator <?> vit = tmpHash.entrySet().iterator();
+ while( vit.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) vit.next();
+ String foundVid = (propEntry.getKey()).toString();
+ TitanVertex foundVtx = (TitanVertex) (propEntry.getValue());
+ targetVertHash.put(foundVid, foundVtx);
+ }
+ }
+ }
+ }
+
+ // Also walk the graph with "-REV" tags for edges that are opposite of the direction asked for
+ String revEdgeTag = edgeTag + "-REV";
+ Direction revDir = Direction.IN;
+ if( dir.equals(Direction.IN) ){
+ revDir = Direction.OUT;
+ }
+ //System.out.println("DEBUG -- about to run the REVERSE edge query (dir = " + revDir + ", tag = " + revEdgeTag + ", level = " + levelCounter );
+ Iterable <?> vertsRev = startVtx.query().direction(revDir).has(revEdgeTag,true).vertices();
+ Iterator <?> vertIRev = vertsRev.iterator();
+ while( vertIRev != null && vertIRev.hasNext() ){
+ TitanVertex tmpVertRev = (TitanVertex) vertIRev.next();
+ String vid = tmpVertRev.id().toString();
+ String nType = tmpVertRev.<String>property("aai-node-type").orElse(null);
+ //System.out.println("DEBUG -- going REV: " + revDir + ", found a node [" + nType + "], id = " + vid + ")");
+
+ if( nType.equals(topNodeType) ){
+ // We found a vertex that meets the input criteria - put it on our output hash.
+ targetVertHash.put(vid, tmpVertRev);
+ }
+ else {
+ // keep looking in the same direction -- Ie. the same direction that this method was called with
+ //System.out.println("DEBUG2 -- do the actual recursive call staring from this node (vid = " + vid + "), direction = " + dir + "----");
+ HashMap <String, TitanVertex> tmpHash = lookForTargetsInOneDirection( transId, fromAppId, graph,
+ edgeTag, topNodeType, tmpVertRev, dir, levelCounter, maxLevels );
+ if( !tmpHash.isEmpty() ){
+ // We found more vertexes to add to the return Hash
+ Iterator <?> vit = tmpHash.entrySet().iterator();
+ while( vit.hasNext() ){
+ Map.Entry<?,?> propEntry = (Map.Entry<?,?>) vit.next();
+ String foundVid = (propEntry.getKey()).toString();
+ TitanVertex foundVtx = (TitanVertex) (propEntry.getValue());
+ targetVertHash.put(foundVid, foundVtx);
+ }
+ }
+ }
+ }
+
+ return targetVertHash;
+ }// End lookForTargetsInOneDirection()
+
+
+ /**
+ * Collect result set.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeTag the edge tag
+ * @param thisLevelVertex the this level vertex
+ * @param secFilterHash the sec filter hash
+ * @param retNodeType the ret node type
+ * @param levelCounter the level counter
+ * @param maxLevels the max levels
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ResultSet collectResultSet( String transId, String fromAppId, TitanTransaction graph,
+ String edgeTag, TitanVertex thisLevelVertex, HashMap <String,Object> secFilterHash,
+ String retNodeType, int levelCounter, int maxLevels )
+ throws AAIException {
+
+ // Note: our return data set is everything on the OUT-edge side of the topVertex - or following
+ // an IN-edge but with a "-REV" tagged edge
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectResultSet");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to collectResultSet()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ //String thisVid = thisLevelVertex.id().toString();
+ //String thisNt = thisLevelVertex.<String>property("aai-node-type").orElse(null);
+ //System.out.println(" DEBUG -- level counter in collectResultSet = " + levelCounter + " thisNodeType = " + thisNt + " this vid = " + thisVid);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectResultSet() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ ResultSet rs = new ResultSet();
+ rs.vert = thisLevelVertex;
+
+ // Look at the tagged "OUT" edges for this node
+ //System.out.println("DEBUG -- about to run the collectResult query at level = " + levelCounter );
+ Iterable <?> verts = thisLevelVertex.query().direction(Direction.OUT).has(edgeTag,true).vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ ArrayList <TitanVertex> nodeList = new <TitanVertex> ArrayList ();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ nodeList.add(tmpVert);
+ }
+
+ // Look at the reverse-tagged "IN" edges for this node
+ String reverseEdgeTag = edgeTag + "-REV";
+ Iterable <?> vertsRev = thisLevelVertex.query().direction(Direction.IN).has(reverseEdgeTag,true).vertices();
+ Iterator <?> vertIRev = vertsRev.iterator();
+ while( vertIRev != null && vertIRev.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertIRev.next();
+ nodeList.add(tmpVert);
+ }
+
+ if( nodeList.isEmpty() ){
+ // There were no sub-vertices, so we can return this result set
+ //System.out.println("DEBUG -- no subVert found here - we will return the resultSet with no sub dudes. ");
+ }
+ else {
+ // For each sub-vertex found, need to get it's result set (recursively)
+ Iterator<?> nodeIter = nodeList.iterator();
+ while( nodeIter.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) nodeIter.next();
+ ResultSet tmpResSet = collectResultSet( transId, fromAppId, graph, edgeTag, tmpVert,
+ secFilterHash, retNodeType, levelCounter, maxLevels );
+ rs.subResultSet.add(tmpResSet);
+ //System.out.println("DEBUG -- found this guy at level " + levelCounter + ", nodeType = " + tmpVert.property("aai-node-type").orElse(null));
+ }
+ }
+
+ //System.out.println("DEBUG -- returning from a call to collectResultSet() ");
+ return rs;
+
+ } // End of collectResultSet()
+
+
+ /**
+ * Collect result set.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param edgeTag the edge tag
+ * @param thisLevelVertex the this level vertex
+ * @param secFilterHash the sec filter hash
+ * @param retNodeType the ret node type
+ * @param levelCounter the level counter
+ * @param fwdSearchDirection the fwd search direction
+ * @param revSearchDirection the rev search direction
+ * @param doPruning the do pruning
+ * @param pruneNodeType -- nodeType of nodes we want to stop collecting at
+ * @param pruneKeepId -- vertexId of a pruneType node that we DO want to keep
+ * @param trimList the trim list
+ * @param maxLevels the max levels
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ResultSet collectResultSet( String transId, String fromAppId, TitanTransaction graph,
+ String edgeTag,
+ TitanVertex thisLevelVertex,
+ HashMap <String,Object> secFilterHash,
+ String retNodeType,
+ int levelCounter,
+ Direction fwdSearchDirection,
+ Direction revSearchDirection,
+ Boolean doPruning,
+ String pruneNodeType,
+ String pruneKeepId,
+ ArrayList trimList,
+ int maxLevels )
+ throws AAIException {
+
+ // Note - our return data set is everything found starting at this vertex and found
+ // following edges that are either a) in the search-direction, or b) tagged the opposite of the
+ // search-Direction, but tagged to be followed in "-REV" direction.
+
+ // Note - when pruning, if we hit a node of type pruneNodeType that does Not have the ID matching
+ // pruneKeepId, then we do NOT add that vertex to our result set
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectResultSet");
+
+ boolean needToDoPruning = false;
+ if( doPruning && pruneKeepId != null && !pruneKeepId.equals("") && pruneNodeType != null && !pruneNodeType.equals("") ){
+ needToDoPruning = true;
+ }
+
+ if( graph == null ){
+ String emsg = "null graph object passed to collectResultSet()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ //String thisVid = thisLevelVertex.id().toString();
+ //String thisNt = thisLevelVertex.<String>property("aai-node-type").orElse(null);
+ //System.out.println(" DEBUG -- level counter in collectResultSet = " + levelCounter + " thisNodeType = " + thisNt + " this vid = " + thisVid);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectResultSet() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ ResultSet rs = new ResultSet();
+ rs.vert = thisLevelVertex;
+
+ // Look at the FWD edges for this node
+ //System.out.println("DEBUG -- about to run the collectResult query at level = " + levelCounter );
+ Iterable <?> verts = thisLevelVertex.query().direction(fwdSearchDirection).has(edgeTag,true).vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ //int levelNodeCount = 0;
+ ArrayList <TitanVertex> nodeList = new <TitanVertex> ArrayList ();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String nodeType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( needToDoPruning ){
+ if( nodeType.equals(pruneNodeType) &&
+ !tmpVert.id().toString().equals(pruneKeepId) ){
+ // This node is the type we're pruning and it is not the ONE that we want to keep - so
+ // do not put it into the resultSet
+ }
+ else {
+ // Don't need to prune this one
+ if( ! trimList.contains(nodeType) ){
+ // They're not trimming or pruning this kind of thing - so keep it.
+ nodeList.add(tmpVert);
+ }
+ }
+ }
+ else {
+ if( ! trimList.contains(nodeType) ){
+ // They're not trimming or pruning this kind of thing - so keep it.
+ nodeList.add(tmpVert);
+ }
+ }
+ }
+
+ // Look at the reverse-tagged edges that are in the rev-direction for this node
+ String reverseEdgeTag = edgeTag + "-REV";
+ Iterable <?> vertsRev = thisLevelVertex.query().direction(revSearchDirection).has(reverseEdgeTag,true).vertices();
+ Iterator <?> vertIRev = vertsRev.iterator();
+ while( vertIRev != null && vertIRev.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertIRev.next();
+ String nodeType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( needToDoPruning ){
+ if( nodeType.equals(pruneNodeType) &&
+ !tmpVert.id().toString().equals(pruneKeepId) ){
+ // This node is the type we're pruning and it is not the ONE that we want to keep - so
+ // do not put it into the resultSet
+ }
+ else {
+ if( ! trimList.contains(nodeType) ){
+ // They're not trimming or pruning this kind of thing - so keep it.
+ nodeList.add(tmpVert);
+ }
+ }
+ }
+ else {
+ if( ! trimList.contains(nodeType) ){
+ // They're not trimming or pruning this kind of thing - so keep it.
+ nodeList.add(tmpVert);
+ }
+ }
+ }
+
+ if( nodeList.isEmpty() ){
+ // There were no sub-vertices, so we can return this result set
+ //System.out.println("DEBUG -- no subVert found here - we will return the resultSet with no sub dudes. ");
+ }
+ else {
+ // For each sub-vertex found, need to get it's result set (recursively)
+ Iterator<?> nodeIter = nodeList.iterator();
+ while( nodeIter.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) nodeIter.next();
+ ResultSet tmpResSet = collectResultSet( transId, fromAppId, graph, edgeTag, tmpVert,
+ secFilterHash, retNodeType, levelCounter,
+ fwdSearchDirection, revSearchDirection, doPruning,
+ pruneNodeType, pruneKeepId, trimList, maxLevels );
+
+ rs.subResultSet.add(tmpResSet);
+ //System.out.println("DEBUG -- found this guy at level " + levelCounter + ", nodeType = " + tmpVert.property("aai-node-type").orElse(null));
+ }
+ }
+
+ //System.out.println("DEBUG -- returning from a call to collectResultSet() ");
+ return rs;
+
+ } // End of collectResultSet()
+
+
+
+
+
+
+ /**
+ * Prints the out result set.
+ *
+ * @param resSet the res set
+ * @param levelCount the level count
+ */
+ public static void printOutResultSet( ResultSet resSet, int levelCount ) {
+
+ levelCount++;
+ for( int i= 1; i <= levelCount; i++ ){
+ System.out.print("-");
+ }
+ String nt = resSet.vert.<String>property("aai-node-type").orElse(null);
+
+ Iterator<VertexProperty<Object>> pI = resSet.vert.properties();
+ String propsStr = "";
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ String pkTop = tp.key();
+ /***
+ if( ! pkTop.toString().startsWith("aai")
+ && ! pkTop.toString().equals("source-of-truth")
+ && ! pkTop.toString().equals("resource-version")
+ && ! pkTop.toString().startsWith("last-mod")
+ ){
+ ****/
+ // For my testing - just want to see these:
+ if( pkTop.equals("vserver-id")
+ || pkTop.toString().equals("vnf-name")
+ || pkTop.toString().equals("vnf-id")
+ || pkTop.toString().equals("vserver-name")
+ || pkTop.toString().equals("hostname")
+ ){
+ propsStr = propsStr + " [" + tp.key() + " = " + tp.value() + "]";
+ }
+ }
+
+ System.out.println( levelCount + " " + nt + ", " + propsStr );
+
+ if( !resSet.subResultSet.isEmpty() ){
+ ListIterator<ResultSet> listItr = resSet.subResultSet.listIterator();
+ while( listItr.hasNext() ){
+ printOutResultSet( listItr.next(), levelCount );
+ }
+ }
+
+ }// end of printOutResultSet()
+
+
+ /**
+ * Satisfies hash of filters.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param resSet the res set
+ * @param filterHash the filter hash
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ public static boolean satisfiesHashOfFilters( String transId, String fromAppId,
+ ResultSet resSet, HashMap <String,Object> filterHash ) throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "satisfiesHashOfFilters");
+
+ if( filterHash.isEmpty() ){
+ // Nothing to match - so we're OK
+ //System.out.println("DEBUG ----- nothing to match for sec. filters - so we're ok ");
+ return true;
+ }
+
+ Iterator <?> it = filterHash.entrySet().iterator();
+ while( it.hasNext() ){
+ Map.Entry<?,?> filtEntry = (Map.Entry<?,?>) it.next();
+ String propNodeTypeDotName = (filtEntry.getKey()).toString();
+ String fpv = (filtEntry.getValue()).toString();
+
+ int periodLoc = propNodeTypeDotName.indexOf(".");
+ if( periodLoc <= 0 ){
+ String emsg = "Bad filter param key passed in: [" + propNodeTypeDotName + "]. Expected format = [nodeName.paramName]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String fnt = propNodeTypeDotName.substring(0,periodLoc);
+ String fpn = propNodeTypeDotName.substring(periodLoc + 1);
+
+ if( !filterMetByThisSet( resSet, fnt, fpn, fpv ) ){
+ //System.out.println(" DEBUG -- FAILED to satisfy filter: [" + fnt + "|" + fpn + "|" + fpv + "].");
+ return false;
+ }
+ }
+ }
+
+ //System.out.println("DEBUG ----- Made it PAST all sec. filters - so we're ok ");
+ // Made it through all the filters -- must be good to go.
+ return true;
+
+ }// end of satisfiesHashOfFilters()
+
+
+ /**
+ * Filter met by this set.
+ *
+ * @param resSet the res set
+ * @param filtNodeType the filt node type
+ * @param filtPropName the filt prop name
+ * @param filtPropVal the filt prop val
+ * @return true, if successful
+ */
+ public static boolean filterMetByThisSet( ResultSet resSet, String filtNodeType, String filtPropName, String filtPropVal ) {
+ // Note - we are just looking for a positive match for one filter for this resultSet
+ // NOTE: we're expecting the filter to have a format like this: "nodeType.parameterName:parameterValue"
+
+ TitanVertex vert = resSet.vert;
+ if( vert == null ){
+ return false;
+ }
+ else {
+ String nt = resSet.vert.<String>property("aai-node-type").orElse(null);
+ if( nt.equals( filtNodeType ) ){
+ if( filtPropName.equals("vertex-id") ){
+ // vertex-id can't be gotten the same way as other properties
+ String thisVtxId = vert.id().toString();
+ if( thisVtxId.equals(filtPropVal) ){
+ //System.out.println(" DEBUG -- filter [" + filtNodeType + "|" + filtPropName + "|" + filtPropVal + "] has been met.");
+ return true;
+ }
+ }
+ else {
+ Object thisValObj = vert.property(filtPropName).orElse(null);
+ if( thisValObj != null ){
+ String thisVal = thisValObj.toString();
+ if( thisVal.equals(filtPropVal) ){
+ //System.out.println(" DEBUG -- filter [" + filtNodeType + "|" + filtPropName + "|" + filtPropVal + "] has been met.");
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ // Didn't find a match at the this level, so check the sets below it meet the criteria
+ if( !resSet.subResultSet.isEmpty() ){
+ ListIterator<ResultSet> listItr = resSet.subResultSet.listIterator();
+ while( listItr.hasNext() ){
+ if( filterMetByThisSet(listItr.next(), filtNodeType, filtPropName, filtPropVal) ){
+ return true;
+ }
+ }
+ }
+
+ return false;
+
+ }// end of filterMetByThisSet()
+
+
+}
+
+
+
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java
new file mode 100644
index 0000000..3ad93cf
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanGraphQuery;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+
+public class ForceDeleteTool {
+
+
+ private static final String FROMAPPID = "AAI-DB";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ //SWGK 01/21/2016 - To suppress the warning message when the tool is run from the Terminal.
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_DATA_GROOMING_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ if( args == null || args.length != 2 ){
+ String msg = "usage: ForceDeleteTool action data (action = COLLECT_DATA or DELETE_NODE or DELETE_EDGE) \n";
+ System.out.println(msg);
+ System.exit(1);
+ }
+ String actionVal = args[0];
+ String dataString = args[1];
+
+ //DEBUG -- public static void forceDeleteTool( String actionVal, String dataString ){
+
+ TitanGraph graph = null;
+
+ if( !actionVal.equals("COLLECT_DATA") && !actionVal.equals("DELETE_NODE") && !actionVal.equals("DELETE_EDGE")){
+ String emsg = "Bad action parameter [" + actionVal + "] passed to ForceDeleteTool(). Valid values = COLLECT_DATA or DELETE_NODE or DELETE_EDGE\n";
+ System.out.println(emsg);
+ System.exit(0);
+ }
+ try {
+ AAIConfig.init(TRANSID, FROMAPPID);
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n");
+ graph = TitanFactory.open(AAIConstants.AAI_CONFIG_FILENAME);
+
+ //graph = AAIGraph.getInstance().getGraph();
+
+ if( graph == null ){
+ String emsg = "could not get graph object in ForceDeleteTool() \n";
+ System.out.println(emsg);
+ System.exit(0);
+ }
+ }
+ catch (AAIException e1) {
+ String msg = e1.getErrorObject().toString();
+ System.out.println(msg);
+ System.exit(0);
+ }
+ catch (Exception e2) {
+ String msg = e2.toString();
+ System.out.println(msg);
+ System.exit(0);
+ }
+
+ if( actionVal.equals("COLLECT_DATA") ){
+ // When doing COLLECT_DATA, we expect the dataString string to look like this:
+ // "propName1|propVal1,propName2|propVal2" etc. We will look for a node or nodes
+ // that have properties that ALL match what was passed in.
+
+ int resCount = 0;
+ int firstPipeLoc = dataString.indexOf("|");
+ if( firstPipeLoc <= 0 ){
+ String msg = "Bad dataString passed for collecting data: [" + dataString + "]. \n Expecting a format like, 'propName1|propVal1,propName2|propVal2'";
+ System.out.println(msg);
+ System.exit(0);
+ }
+ TitanGraphQuery tgQ = graph.query();
+ String qStringForMsg = " graph.query()";
+ // Note - if they're only passing on parameter, there won't be any commas
+ String [] paramArr = dataString.split(",");
+ for( int i = 0; i < paramArr.length; i++ ){
+ int pipeLoc = paramArr[i].indexOf("|");
+ if( pipeLoc <= 0 ){
+ String msg = "Bad dataString passed for collecting data: [" + dataString + "]. \n Expecting a format like, 'propName1|propVal1,propName2|propVal2'";
+ System.out.println(msg);
+ System.exit(0);
+ }
+ else {
+ String propName = paramArr[i].substring(0,pipeLoc);
+ String propVal = paramArr[i].substring(pipeLoc + 1);
+ tgQ = tgQ.has(propName,propVal);
+ qStringForMsg = qStringForMsg + ".has(" + propName + "," + propVal + ")";
+ }
+ }
+ if( (tgQ != null) && (tgQ instanceof TitanGraphQuery) ){
+ Iterable <TitanVertex> verts = (Iterable<TitanVertex>) tgQ.vertices();
+ Iterator <TitanVertex> vertItor = verts.iterator();
+ while( vertItor.hasNext() ){
+ resCount++;
+ TitanVertex v = (TitanVertex)vertItor.next();
+ Iterator<VertexProperty<Object>> pI = v.properties();
+ System.out.println("\n\n>>> Found Vertex with VertexId = " + v.id() + ", properties: ");
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ System.out.println(" [" + tp.key() + "|" + tp.value() + "] ");
+ }
+
+ try {
+ ArrayList <String> retArr = DbMeth.showAllEdgesForNode(TRANSID, FROMAPPID, v);
+ for( String info : retArr ){ System.out.println( info ); }
+ }
+ catch (Exception e){
+ System.out.println("Error trying to display edge info. " + e.getMessage() );
+ }
+ }
+ }
+ else {
+ String msg = "Bad TitanGraphQuery object. ";
+ System.out.println(msg);
+ System.exit(0);
+ }
+
+ System.out.println("\n\n Found: " + resCount + " nodes for this query: [" + qStringForMsg + "]" );
+ System.out.println(" ");
+ }
+ else if( actionVal.equals("DELETE_NODE") ){
+ long longVertId = Long.parseLong(dataString);
+ Vertex vtx = graph.vertices( longVertId ).next();
+ if (vtx != null)
+ {
+ vtx.remove();
+ graph.tx().commit();
+ System.out.println(">>>>>>>>>> Removed vertex with vertexId = " + dataString );
+ }
+ else
+ {
+ System.out.println(">>>>>>>>>> Vertex with vertexId = " + dataString + " not found.");
+
+ }
+ }
+ else if( actionVal.equals("DELETE_EDGE") ){
+ String edgeId = dataString;
+ TitanEdge edge = (TitanEdge) graph.edges( edgeId ).next();
+ if (edge != null)
+ {
+ edge.remove();
+ graph.tx().commit();
+ System.out.println(">>>>>>>>>> Removed edge with edgeId = " + edgeId );
+ }
+ else
+ {
+ System.out.println(">>>>>>>>>> Edge with edgeId = " + edgeId + " not found.");
+
+ }
+ System.exit(0);
+ }
+ else {
+ String emsg = "Unknown action parameter [" + actionVal + "] passed to ForceDeleteTool(). Valid values = COLLECT_DATA, DELETE_NODE or DELETE_EDGE \n";
+ System.out.println(emsg);
+ System.exit(0);
+ }
+
+ System.exit(0);
+
+ }// end of main()
+
+
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/GenTester.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/GenTester.java
new file mode 100644
index 0000000..1a6f806
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/GenTester.java
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.util.Properties;
+import java.util.UUID;
+
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+//import com.thinkaurelius.titan.core.util.TitanCleanup;
+
+
+
+
+public class GenTester {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ TitanGraph graph = null;
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_CREATE_DB_SCHEMA_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(GenTester.class.getName());
+ LogLine logline = new LogLine();
+ String component = "AAI-DB";
+ String fromAppId = "GenTester";
+ String transId = UUID.randomUUID().toString();
+ logline.init(component, transId, fromAppId, "main");
+
+ boolean genDbWithNoSchema = false;
+ boolean addDefaultCR = true;
+ boolean createHBaseLogTableIfNeeded = false;
+
+ try {
+ if (args != null && args.length > 0 ){
+ for( int i = 0; i < args.length; i++ ){
+ // First - look to see if they passed a NO SCHEMA parameter - if they did, then we will
+ // ignore other parameters
+ if ( "GEN_DB_WITH_NO_SCHEMA".equals(args[i]) ){
+ genDbWithNoSchema = true;
+ }
+ else if ("GEN_DB_WITH_NO_DEFAULT_CR".equals(args[i])) {
+ addDefaultCR = false;
+ }
+ else if ("CREATE_HBASE_LOG_TBL".equals(args[i])) {
+ createHBaseLogTableIfNeeded = true;
+ }
+ else {
+ AAIException e = new AAIException("AAI_3000", "Unrecognized argument passed to GenTester.java: [" + args[i] + "]. ");
+ ErrorObject eo = ErrorLogHelper.getErrorObject("AAI_3000", "Unrecognized argument passed to GenTester.java: [" + args[0] + "]. ");
+ logline.add("error:", "Unrecognized argument passed to GenTester.java: [" + args[i] + "]. ");
+ logline.add("error help:", "Either pass no argument for normal processing, or use 'GEN_DB_WITH_NO_SCHEMA'.");
+ aaiLogger.error(eo, logline, e);
+ aaiLogger.audit(logline);
+ String msg = "Unrecognized argument passed to GenTester.java: [" + args[i] + "]. ";
+ System.out.println(msg);
+ System.exit(1);
+ }
+ }
+ }
+
+ if( createHBaseLogTableIfNeeded ){
+ // Note - this is separate from the Titan stuff
+ SchemaGenerator.createHBaseLogTableIfNeeded();
+ }
+
+ if( genDbWithNoSchema ){
+ // Note this is done to create an empty DB with no Schema so that
+ // an HBase copyTable can be used to set up a copy of the db.
+ logline.add("", " ---- NOTE --- about to load a graph without doing any schema processing (takes a little while) -------- ");
+ graph = AAIGraph.getInstance().getGraph();
+
+ if( graph == null ){
+ AAIException e = new AAIException("AAI_5102");
+ ErrorObject eo = ErrorLogHelper.getErrorObject("AAI_5102", "Error creating Titan graph.");
+ aaiLogger.error(eo, logline, e);
+ aaiLogger.audit(logline);
+ String msg = "Error creating Titan graph.";
+ System.out.println(msg);
+ System.exit(1);
+ }
+ else {
+ logline.add("", "Successfully loaded a Titan graph without doing any schema work. ");
+ aaiLogger.audit(logline);
+ System.exit(0);
+ }
+ }
+ else {
+ AAIConfig.init();
+ ErrorLogHelper.loadProperties();
+ logline.add("", " ---- NOTE --- about to open graph (takes a little while)--------;");
+ graph = AAIGraph.getInstance().getGraph();
+
+ if( graph == null ){
+ AAIException e = new AAIException("AAI_5102");
+ ErrorObject eo = ErrorLogHelper.getErrorObject("AAI_5102", "Error creating Titan graph. ");
+ aaiLogger.error(eo, logline, e);
+ aaiLogger.audit(logline);
+ String msg = "Error creating Titan graph.";
+ System.out.println(msg);
+ System.exit(1);
+ }
+
+ // Load the propertyKeys, indexes and edge-Labels into the DB
+ TitanManagement graphMgt = graph.openManagement();
+
+ logline.add("", "-- Loading new schema elements into Titan --");
+ SchemaGenerator.loadSchemaIntoTitan( graph, graphMgt );
+ }
+
+ }
+ catch( Exception ex ){
+ logline.add("ERROR:", "caught this exception: " + ex);
+ ErrorObject eo = ErrorLogHelper.getErrorObject("AAI_4000", ex.getMessage());
+ aaiLogger.error(eo, logline, ex);
+ aaiLogger.audit(logline);
+ String msg = "caught this exception: " + ex;
+ System.out.println(msg);
+ System.exit(1);
+ }
+
+
+ if( graph != null ){
+ logline.add("", "-- graph commit");
+ graph.tx().commit();
+ }
+
+ if( graph != null ){
+ logline.add("", "-- graph shutdown ");
+ graph.close();
+ }
+ logline.add("", "-- all done, if program does not exit, please kill.");
+ aaiLogger.audit(logline);
+ System.exit(0);
+ }
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java
new file mode 100644
index 0000000..7b9f031
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java
@@ -0,0 +1,3490 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.SimpleTimeLimiter;
+import com.google.common.util.concurrent.TimeLimiter;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+/**
+ * Utility class that uses Model/Named-Query definitions to navigate the graph.
+ */
+public class ModelBasedProcessing{
+
+ private static AAILogger aaiLogger = new AAILogger(ModelBasedProcessing.class.getName());
+ private static int maxLevels = 50; // max depth allowed for our model - to protect against infinite loop problems
+
+
+
+ /**
+ * Gets the start nodes and models.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param passedModelNameVersionId the passed model name version id -- optional (unique id for a model)
+ * @param passedModelId the passed model id -- optional
+ * @param passedModelName the passed model name
+ * @param passedTopNodeType the passed top node type -- optional (needed if neither model-id nor model-name-version-id is passed)
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data)
+ * @param apiVer the api ver
+ * @return List of TitanVertex's
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,String> getStartNodesAndModels( String transId, String fromAppId, TitanTransaction graph,
+ String passedModelNameVersionId,
+ String passedModelId,
+ String passedModelName,
+ String passedTopNodeType,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "getStartNodesAndModels");
+
+
+ // ----------------------------------------------------------------------------------------------------
+ // Get a hash for all start-nodes (key = vtxId, val = modelNameVersionId that applies)
+ // If no start-node-key info is passed, then use either the passed modelNameVersionId or
+ // the passed model-id or model-name to collect them.
+ // If start-node-key info is given, use it instead to look for start-nodes.
+ // Note: if ONLY start-node-key info is given, then it would have to map to nodes which
+ // have persona data. Otherwise we'd have no way to know what model to collect data with.
+ // ----------------------------------------------------------------------------------------------------
+
+ Iterable <?> startVerts = null;
+ HashMap <String, String> startVertInfo = new HashMap <String,String> ();
+ if( startNodeFilterArrayOfHashes.isEmpty() ){
+ // Since they did not give any data to find start instances, we will have to find them
+ // using whatever model-info they provided so we can use it to map to persona-data in the db.
+ if( (passedModelNameVersionId == null || passedModelNameVersionId.equals(""))
+ && (passedModelId == null || passedModelId.equals(""))
+ && (passedModelName == null || passedModelName.equals(""))){
+ String emsg = "ModelId or ModelName or ModelNameVersionId required if no startNodeFilter data passed. \n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+ else {
+ // Use whatever model info they pass to find start-node instances
+ // Get the first/top named-query-element used by this query
+ if( passedModelNameVersionId != null && !passedModelNameVersionId.equals("") ){
+ // Need to look up the model-id and model-version to check against persona data
+ TitanVertex modVtx = getModelUsingUUID( transId, fromAppId, graph, passedModelNameVersionId );
+ String calcModId = modVtx.<String>property("model-id").orElse(null);
+ String calcModVer = modVtx.<String>property("model-version").orElse(null);
+ // Now we can look up instances that match this model's info
+ startVerts = graph.query().has("persona-model-id",calcModId).has("persona-model-version",calcModVer).vertices();
+ }
+ else if( passedModelId != null && !passedModelId.equals("") ){
+ // They gave us the model-id
+ startVerts = graph.query().has("persona-model-id",passedModelId).vertices();
+ }
+ else if( passedModelName != null && !passedModelName.equals("") ){
+ ArrayList <TitanVertex> modelVtxList = getModelsUsingName(transId, fromAppId, graph, passedModelName);
+ ArrayList <TitanVertex> startVtxList = new ArrayList <TitanVertex> ();
+ // Need to look up the model-ids and model-versions to check against persona data
+ if( !modelVtxList.isEmpty() ){
+ for( int i = 0; i < modelVtxList.size(); i++ ){
+ String calcModId = (modelVtxList.get(i)).<String>property("model-id").orElse(null);
+ String calcModVer = (modelVtxList.get(i)).<String>property("model-version").orElse(null);
+ // Now we can look up instances that match this model's info
+ Iterable <?> tmpStartVerts = graph.query().has("persona-model-id",calcModId).has("persona-model-version",calcModVer).vertices();
+ Iterator <?> tmpStartIter = tmpStartVerts.iterator();
+ while( tmpStartIter.hasNext() ){
+ TitanVertex tmpStartVert = (TitanVertex) tmpStartIter.next();
+ startVtxList.add(tmpStartVert);
+ }
+ }
+ }
+ if( !startVtxList.isEmpty() ){
+ startVerts = startVtxList;
+ }
+ }
+ }
+
+ if( startVerts != null ){
+ Iterator <?> startVertsIter = startVerts.iterator();
+ while( startVertsIter.hasNext() ){
+ TitanVertex tmpStartVert = (TitanVertex) startVertsIter.next();
+ String vid = tmpStartVert.id().toString();
+ String tmpModId = tmpStartVert.<String>property("persona-model-id").orElse(null);
+ String tmpModVers = tmpStartVert.<String>property("persona-model-version").orElse(null);
+ String calcModNameVersId = getModNameVerId( transId, fromAppId, graph, tmpModId, tmpModVers );
+ startVertInfo.put(vid, calcModNameVersId);
+ }
+ }
+ if( startVertInfo.isEmpty() ){
+ String emsg = "Start Node(s) could not be found for model data passed. " +
+ "(modelNameVersionId = [" + passedModelNameVersionId +
+ "], modelId = [" + passedModelId +
+ "], modelName = [" + passedModelName +
+ "])\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", emsg);
+ }
+ }
+ else {
+ // Use start-node filter info to find start-node(s) - Note - there could also be model info passed that we'll need
+ // to use to trim down the set of start-nodes that we find based on the startNodeFilter data.
+ String modTopNodeType ="";
+ String modInfoStr = "";
+ if( passedModelNameVersionId != null && !passedModelNameVersionId.equals("") ){
+ modTopNodeType = getModelTopWidgetType( transId, fromAppId, graph, passedModelNameVersionId, "", "" );
+ modInfoStr = "modelNameVersionId = (" + passedModelNameVersionId + ")";
+ }
+ else if( passedModelId != null && !passedModelId.equals("") ){
+ modTopNodeType = getModelTopWidgetType( transId, fromAppId, graph,"", passedModelId, "" );
+ modInfoStr = "modelId = (" + passedModelId + ")";
+ }
+ else if( passedModelName != null && !passedModelName.equals("") ){
+ modTopNodeType = getModelTopWidgetType( transId, fromAppId, graph,"", "", passedModelName );
+ modInfoStr = "modelName = (" + passedModelName + ")";
+ }
+
+ if( modTopNodeType.equals("") ){
+ if( (passedTopNodeType == null) || passedTopNodeType.equals("") ){
+ String msg = "Could not determine the top-node nodeType for this request. modelInfo: [" + modInfoStr + "]";
+ throw new AAIException("AAI_6118", msg);
+ }
+ else {
+ // We couldn't find a top-model-type based on passed in model info, but they
+ // gave us a type to use -- so use it.
+ modTopNodeType = passedTopNodeType;
+ }
+ }
+ else {
+ // we did get a topNode type based on model info - make sure it doesn't contradict
+ // the passsed-in one (if there is one)
+ if( passedTopNodeType != null && !passedTopNodeType.equals("")
+ && !passedTopNodeType.equals(modTopNodeType) ){
+ String emsg = "topNodeType passed in [" + passedTopNodeType
+ + "] does not match nodeType derived for model info passed in: ["
+ + modTopNodeType + "]\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+
+ ArrayList <String> modelNameVersionIds2Check = new ArrayList <String> ();
+ if( (passedModelName != null && !passedModelName.equals("")) ){
+ // They passed a modelName, so find all the model UUIDs (model-name-version-id's) that map to this
+ modelNameVersionIds2Check = getModelUuidsUsingName(transId, fromAppId, graph, passedModelName);
+ }
+ if( (passedModelNameVersionId != null && !passedModelNameVersionId.equals("")) ){
+ // They passed in a modelNameVersionId
+ if( modelNameVersionIds2Check.isEmpty() ){
+ // There was no modelName passed, so we can use the passed modelNameVersionId
+ modelNameVersionIds2Check.add(passedModelNameVersionId);
+ }
+ else if( modelNameVersionIds2Check.contains(passedModelNameVersionId) ){
+ // The passed in uuid does not conflict with what we got using the passed-in modelName.
+ // We'll just use the passed in uuid in this case.
+ // Hopefully they would not be passing strange combinations like this, but we'll try to deal with it.
+ modelNameVersionIds2Check = new ArrayList <String> (); // Clear out what we had
+ modelNameVersionIds2Check.add(passedModelNameVersionId);
+ }
+ }
+
+ // We should now be OK with our topNodeType for this request, so we can look for the actual startNodes
+ for( int i=0; i < startNodeFilterArrayOfHashes.size(); i++ ){
+ // Locate the starting node which will be used to look which corresponds to this set of filter data
+ TitanVertex startVtx = null;
+ try {
+ startVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ modTopNodeType, startNodeFilterArrayOfHashes.get(i), apiVer );
+ }
+ catch( AAIException e ){
+ String msg = "Could not find startNode of type = [" + modTopNodeType + "], given these params: "
+ + startNodeFilterArrayOfHashes.get(i) + ". msg # from getUniqueNode() = " + e.getMessage();
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String vid = startVtx.id().toString();
+ String personaModVersion = startVtx.<String>property("persona-model-version").orElse(null);
+ String personaModId = startVtx.<String>property("persona-model-id").orElse(null);
+
+ // Either this start-node has persona info (which should not contradict any passed-in model info)
+ // or they should have passed in the model to use - so we'd just use that.
+ if( personaModVersion != null && !personaModVersion.equals("") ){
+ // There is persona data in this start-node. So make sure it doesn't contradict any "passed" stuff
+ // Find out what modelNameVersionId that maps to
+ String personaModelNameVerId = getModNameVerId(transId, fromAppId, graph, personaModId, personaModVersion);
+
+ if( modelNameVersionIds2Check.isEmpty()
+ && (passedModelId == null || passedModelId.equals("")) ){
+ // They didn't pass any model info, so use the persona one.
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ else if( modelNameVersionIds2Check.isEmpty()
+ && (passedModelId != null && !passedModelId.equals("")) ){
+ // They passed in just the modelId - so check it
+ if( passedModelId.equals(personaModId) ){
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ }
+ else if( !modelNameVersionIds2Check.isEmpty()
+ && (passedModelId == null || passedModelId.equals("")) ){
+ // They passed in modelNameVersionId - so check
+ if( modelNameVersionIds2Check.contains(personaModelNameVerId) ){
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ }
+ else if( !modelNameVersionIds2Check.isEmpty()
+ && (passedModelId != null && !passedModelId.equals("")) ){
+ // We have BOTH a modelNameVersionIds and a modelId to check
+ if( passedModelId.equals(personaModId)
+ && modelNameVersionIds2Check.contains(personaModelNameVerId) ){
+ startVertInfo.put(vid, personaModelNameVerId);
+ }
+ }
+ }
+ else {
+ // This start node did not have persona info -- so we will use the passed in model info if they passed one
+ if( passedModelNameVersionId.equals("") ){
+ String emsg = "Found startNode but no model info passed in and no persona model info in the start node.";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6120");
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ startVertInfo.put(vid, passedModelNameVersionId);
+ }
+ }
+ }
+ }
+
+ return startVertInfo;
+
+ }//end of getStartNodesAndModels()
+
+
+ /**
+ * Query by model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id -- optional - (unique id for a model)
+ * @param modelId the model id -- optional
+ * @param modelName the model name
+ * @param topNodeType - optional (needed if neither model-id nor model-name-version-id is passed)
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes -- optional (used to locate the first node(s) of instance data)
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByModel( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId,
+ String modelId,
+ String modelName,
+ String topNodeType,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ final String transId_f = transId;
+ final String fromAppId_f = fromAppId;
+ final TitanTransaction graph_f = graph;
+ final String modelNameVersionId_f = modelNameVersionId;
+ final String modelId_f = modelId;
+ final String modelName_f = modelName;
+ final String topNodeType_f = topNodeType;
+ final ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes;
+ final String apiVer_f = apiVer;
+
+ // Find out what our time-limit should be
+ int timeLimitSec = 0;
+ String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec");
+ if( timeLimitString != null && !timeLimitString.equals("") ){
+ try {
+ timeLimitSec = Integer.parseInt(timeLimitString);
+ }
+ catch ( Exception nfe ){
+ // Don't worry, we will leave the limit as zero - which tells us not to use it.
+ }
+ }
+
+ if( timeLimitSec <= 0 ){
+ // We will NOT be using a timer
+ return queryByModel_Timed( transId, fromAppId, graph,
+ modelNameVersionId,
+ modelId,
+ modelName,
+ topNodeType,
+ startNodeFilterArrayOfHashes,
+ apiVer );
+ }
+
+ ArrayList <ResultSet> resultList = new ArrayList <ResultSet> ();
+ TimeLimiter limiter = new SimpleTimeLimiter();
+ try {
+ resultList = limiter.callWithTimeout(new Callable <ArrayList <ResultSet>>() {
+ public ArrayList <ResultSet> call() throws AAIException {
+ return queryByModel_Timed( transId_f, fromAppId_f, graph_f,
+ modelNameVersionId_f,
+ modelId_f,
+ modelName_f,
+ topNodeType_f,
+ startNodeFilterArrayOfHashes_f,
+ apiVer_f );
+ }
+ }, timeLimitSec, TimeUnit.SECONDS, true);
+ }
+ catch (AAIException ae) {
+ // Re-throw AAIException so we get can tell what happened internally
+ throw ae;
+ }
+ catch (UncheckedTimeoutException ute) {
+ throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)");
+ }
+ catch (Exception e) {
+ throw new AAIException("AAI_6128", "Unexpected exception in queryByModel(): " + e.getMessage() );
+ }
+
+
+ return resultList;
+ }
+
+
+ /**
+ * Query by model timed.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @param modelId the model id
+ * @param modelName the model name
+ * @param topNodeType the top node type
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes
+ * @param apiVer the api ver
+ * @return the array list
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByModel_Timed( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId,
+ String modelId,
+ String modelName,
+ String topNodeType,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+
+
+ ArrayList <ResultSet> resultArray = new ArrayList <ResultSet> ();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "queryByModel");
+
+ // NOTE: this method can be used for different styles of queries:
+ // a) They could pass neither a modelNameVersionId or a modelId but just a set of data defining start-nodes.
+ // Note - with no model info, we need them to pass the startNodeType for us to be able to use the
+ // start-node-filter data. We would look at each start node and ensure that each has persona-model info.
+ // Use whatever model corresponds to each instance to pull that instance's data.
+ // b) They could pass a modelId, but no modelNameVersionId and no startNode info. In this case, we
+ // Would look in the database for all nodes that have a persona-model-id that matches what was
+ // passed, and then for each of those instances, pull the data based on the corresponding model.
+ // c) They could pass a model-name-version-id, but no startNode info. We'd make sure that if a
+ // model-id was also passed, that it does not conflict - but it really should be null if they
+ // are passing a full model-name-version-id. Like case -b-, we'd do a query for all nodes
+ // that have persona info that corresponds to the model-name-veersion-id passed and then
+ // collect data for each one.
+ // d) They could pass either modelNameVersionId or modelId AND startNodeFilter info. In this case we
+ // would look at the model info to figure out what the top-node-type is, then look at the
+ // top-node instances based on the startNodeFilter. We'd only collect data for each instance if
+ // it's persona model info matches what was passed in.
+
+
+ // ----------------------------------------------------------------------------------------------------------
+ // Get a Hash of all the start-nodes (top node for a model where we will start collecting data)
+ // for startNode2ModelHash: key = vertex-id for the startNode, value = modelNameVersionType for model
+ // ----------------------------------------------------------------------------------------------------------
+ HashMap <String, String> startNode2ModelHash = getStartNodesAndModels( transId, fromAppId, graph,
+ modelNameVersionId, modelId, modelName, topNodeType,
+ startNodeFilterArrayOfHashes, apiVer );
+
+ //System.out.println("\nDEBUG -- Here's a dump of the startnodes/models: " + startNode2ModelHash.toString());
+
+
+ // --------------------------------------------------------------------------------------------------------
+ // Figure out what-all models we're gonna be dealing with
+ // Note - Instances must all use the same type of start-node, but do not have to all use the same model.
+ // --------------------------------------------------------------------------------------------------------
+ HashMap <String, TitanVertex> distinctModelsHash = new HashMap <String,TitanVertex> ();
+ // For distinctModelsHash: key = modelTypeVersionId, val= modelVertex
+ String startNodeType = "";
+ if( topNodeType != null && !topNodeType.equals("") ){
+ startNodeType = topNodeType;
+ }
+
+ Set <String> snKeySet = startNode2ModelHash.keySet();
+ Iterator<String> startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String vtxKey = (String) startNodeIterator.next();
+ String modKey = startNode2ModelHash.get(vtxKey);
+ if( !distinctModelsHash.containsKey(modKey) ){
+ // First time seeing this model
+ TitanVertex modVtx = getModelUsingUUID(transId, fromAppId, graph, modKey);
+ String tmpNodeType = getModelWidgetType( modVtx, "" );
+ if( startNodeType.equals("") ){
+ startNodeType = tmpNodeType;
+ }
+ else if( !startNodeType.equals(tmpNodeType) ){
+ String msg = "Conflict between startNode types for models involved: [" + startNodeType
+ + "], [" + tmpNodeType + "]";
+ throw new AAIException("AAI_6125", msg);
+ }
+ distinctModelsHash.put(modKey, modVtx);
+ }
+ }
+
+ //System.out.println("\nDEBUG -- Here's a dump of the DISTINCT models hash: " + distinctModelsHash.toString() );
+
+ // ---------------------------------------------------------------------------------------------------------------
+ // Get the "valid-next-step" hash for each distinct model
+ // While we're at it, get a mapping of model-id|model-version to model-name-version-id for the models being used
+ // ---------------------------------------------------------------------------------------------------------------
+ HashMap <String, Multimap<String, String>> validNextStepHash = new HashMap <String, Multimap<String, String>>();
+ // validNextStepHash: key = modelNameVerId, value = nextStepMap
+ Set <String> keySet = distinctModelsHash.keySet();
+ Iterator<String> modelIterator = keySet.iterator();
+ while( modelIterator.hasNext() ){
+ String modKey = (String) modelIterator.next();
+ TitanVertex modelVtx = (TitanVertex)distinctModelsHash.get(modKey);
+ Multimap<String, String> tmpTopoMap = genTopoMap4Model( transId, fromAppId, graph,
+ modelVtx, modKey, dbMaps );
+ validNextStepHash.put(modKey, tmpTopoMap);
+ }
+
+ //System.out.println("\n\nDEBUG -- Here's a dump of the validNextStepHash "+ validNextStepHash.toString() );
+
+ // -------------------------------------------------------------------------------------------------
+ // Figure out what the "start-node" for each instance will be (plus the info we will use to
+ // represent that in our topology)
+ // -------------------------------------------------------------------------------------------------
+ ArrayList <String> failedPersonaCheckVids = new ArrayList <String> ();
+ HashMap <String, String> firstStepInfoHash = new HashMap <String,String> ();
+ // For firstStepInfoHash: key = startNodeVtxId, val=topNodeType plus personaData if applicable
+ // ie. the value is what we'd use as the "first-step" for this model.
+ if( !nodeTypeSupportsPersona( startNodeType, dbMaps) ){
+ // This node type doesn't have persona info, so we just use startNodeType for the first-step-info
+ snKeySet = startNode2ModelHash.keySet();
+ startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String vtxKey = (String) startNodeIterator.next();
+ firstStepInfoHash.put(vtxKey,startNodeType);
+ }
+ }
+ else {
+ // Need to check that this node's persona data is good and if it is - use it for the first step info
+ snKeySet = startNode2ModelHash.keySet();
+ startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String vtxKey = (String) startNodeIterator.next();
+ Iterator<Vertex> vtxIterator = graph.vertices(vtxKey);
+ TitanVertex tmpVtx = (TitanVertex)vtxIterator.next();
+ String thisVtxModelUUID = startNode2ModelHash.get(vtxKey);
+ TitanVertex modelVtx = (TitanVertex)distinctModelsHash.get(thisVtxModelUUID);
+ String modId = modelVtx.<String>property("model-id").orElse(null);
+ String modVersion = modelVtx.<String>property("model-version").orElse(null);
+ String personaModId = tmpVtx.<String>property("persona-model-id").orElse(null);
+ String personaModVersion = tmpVtx.<String>property("persona-model-version").orElse(null);
+
+ if( modId.equals(personaModId) && modVersion.equals(personaModVersion) ){
+ String tmpPersonaInfoStr = startNodeType + "," + personaModId + "," + personaModVersion;
+ firstStepInfoHash.put(vtxKey, tmpPersonaInfoStr );
+ }
+ else {
+ // we won't use this start node below when we collect data because it should have
+ // had persona data that matched it's model - but it did not.
+ failedPersonaCheckVids.add(vtxKey);
+ }
+ }
+ }
+
+ //System.out.println("\nDEBUG -- Here's a dump of the firstStepInfoHash hash: " + firstStepInfoHash.toString() );
+
+ // ------------------------------------------------------------------------------------------------
+ // Loop through each start-node, collect it's data using collectInstanceData() and put the
+ // resultSet onto the resultArray.
+ // ------------------------------------------------------------------------------------------------
+
+ // Make sure they're not bringing back too much data
+ String maxString = AAIConfig.get("aai.model.query.resultset.maxcount");
+ if( maxString != null && !maxString.equals("") ){
+ int maxSets = 0;
+ try {
+ maxSets = Integer.parseInt(maxString);
+ }
+ catch ( Exception nfe ){
+ // Don't worry, we will leave the max as zero - which tells us not to use it.
+ }
+
+ if( maxSets > 0 && (startNode2ModelHash.size() > maxSets) ){
+ String msg = " Query returns " + startNode2ModelHash.size() + " resultSets. Max allowed is: " + maxSets;
+ throw new AAIException("AAI_6141", msg);
+ }
+ }
+
+ snKeySet = startNode2ModelHash.keySet();
+ startNodeIterator = snKeySet.iterator();
+ while( startNodeIterator.hasNext() ){
+ String topNodeVtxId = (String) startNodeIterator.next();
+ if( failedPersonaCheckVids.contains(topNodeVtxId) ){
+ // Skip this vertex because it failed it's persona-data check above
+ continue;
+ }
+
+ Iterator<Vertex> vtxIterator = graph.vertices(topNodeVtxId);
+ TitanVertex tmpStartVtx = (TitanVertex)vtxIterator.next();
+ String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId);
+ String modelTypeNameVerId = startNode2ModelHash.get(topNodeVtxId);
+ Multimap<String, String> validNextStepMap = validNextStepHash.get(modelTypeNameVerId);
+
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+ HashMap <String,String> emptyDelKeyHash = new HashMap <String,String> ();
+ HashMap <String,String> emptyNQElementHash = new HashMap <String,String> (); // Only applies to Named Queries
+ ResultSet tmpResSet = collectInstanceData( transId, fromAppId, graph,
+ tmpStartVtx, elementLocationTrail,
+ validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, emptyNQElementHash, apiVer );
+
+ resultArray.add(tmpResSet);
+ }
+
+ return resultArray;
+
+ }// queryByModel()
+
+
+
+ /**
+ * Run delete by model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id -- unique id for a model
+ * @param topNodeTypeVal the top node type val -- required if no model-name-version-id is passed
+ * @param startNodeFilterHash the start node filter hash -- used to locate the first node of instance data
+ * @param apiVer the api ver
+ * @param resVersion the res version -- resourceVersion of the top/first widget in the model instance
+ * @return HashMap (keys = vertexIds that were deleted)
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,String> runDeleteByModel( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId, String topNodeTypeVal, HashMap <String,Object> startNodeFilterHash, String apiVer, String resVersion )
+ throws AAIException{
+
+ HashMap <String,String> retHash = new HashMap <String,String> ();
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "runDeleteByModel");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to runDeleteByModel()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ // Locate the Model to be used
+ TitanVertex modelVtx = null;
+
+ if( modelNameVersionId != null && !modelNameVersionId.equals("") ){
+ HashMap <String,Object> propHash0 = new HashMap<String, Object>();
+ propHash0.put("model-name-version-id", modelNameVersionId);
+ modelVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "model", propHash0, null, apiVer );
+ if( modelVtx == null ){
+ String msg = "No model found for model-name-version-id = [" + modelNameVersionId + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ else {
+ // if they didn't pass the modelNameVersionId, then we need to use the startNode to figure it out
+ // Locate the starting node based on the start node params
+ if( topNodeTypeVal == null || topNodeTypeVal.equals("") ){
+ String msg = "If no model info is passed, then topNodeType is required. ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6118");
+ throw new AAIException("AAI_6118", msg);
+ }
+ TitanVertex startVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNodeTypeVal, startNodeFilterHash, apiVer );
+ String startVertPersonaModId = startVtx.<String>property("persona-model-id").orElse(null);
+ String startVertPersonaModVersion = startVtx.<String>property("persona-model-version").orElse(null);
+ modelVtx = getModelUsingPersonaInfo( transId, fromAppId, graph,
+ startVertPersonaModId, startVertPersonaModVersion );
+ }
+
+ if( modelVtx == null ){
+ String msg = "Could not determine the model for the given input parameters. ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String topNType = "unknown";
+ String modelType = getModelType( modelVtx, "" );
+ if( modelType.equals("widget") ){
+ // If they want to delete using a widget-level model.. That is just a delete of the one
+ // instance of one of our nodes.
+ String widgModNodeType = modelVtx.<String>property("model-name").orElse(null);
+ if( (widgModNodeType == null) || widgModNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model [" + modelNameVersionId + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+ TitanVertex widgetVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, widgModNodeType, startNodeFilterHash, null, apiVer );
+ String widgId = widgetVtx.id().toString();
+ DbMeth.removeAaiNode( transId, fromAppId, graph, widgetVtx, "USE_DEFAULT", "v7", resVersion);
+ retHash.put(widgId, widgModNodeType);
+ return( retHash );
+ }
+
+ // ----------------------------------------------------------------------------
+ // If we got to here, this must be either a service or resource model.
+ // So, we'll need to get a Hash of which parts of the model to delete.
+ // ----------------------------------------------------------------------------
+ String chkFirstNodePersonaModelId = "";
+ String chkFirstNodePersonaModelVersion = "";
+ String personaData = "";
+ TitanVertex firstModElementVertex = getTopElementForSvcOrResModel( modelVtx );
+ topNType = getElementWidgetType( firstModElementVertex, "" );
+ if( (topNType == null) || topNType.equals("") ){
+ String msg = "Could not determine the top-node nodeType for model: [" + modelNameVersionId + "]";
+ throw new AAIException("AAI_6132", msg);
+ }
+ if( nodeTypeSupportsPersona(topNType, dbMaps) ){
+ chkFirstNodePersonaModelId = modelVtx.<String>property("model-id").orElse(null);
+ chkFirstNodePersonaModelVersion = modelVtx.<String>property("model-version").orElse(null);
+ personaData = "," + chkFirstNodePersonaModelId + "," + chkFirstNodePersonaModelVersion;
+ }
+
+ // Get the deleteKeyHash for this model
+ String incomingTrail = "";
+ HashMap <String, String> currentHash = new HashMap <String,String> ();
+ HashMap <String, TitanVertex> modConHash = new HashMap <String,TitanVertex> ();
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+ HashMap <String, String> delKeyHash = collectDeleteKeyHash( transId, fromAppId, graph,
+ firstModElementVertex, incomingTrail, currentHash, vidsTraversed,
+ 0, dbMaps, modConHash,
+ chkFirstNodePersonaModelId, chkFirstNodePersonaModelVersion );
+
+
+ //System.out.println("\n ----DEBUG -----: Delete Hash for model: [" + modelNameVersionId + "] looks like: ");
+ //for( Map.Entry<String, String> entry : delKeyHash.entrySet() ){
+ // System.out.println("key = [" + entry.getKey() + "], val = [" + entry.getValue() + "]");
+ //}
+ //System.out.println("\n -----");
+
+
+ // Locate the starting node that we'll use to start looking for instance data
+ TitanVertex startVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNType, startNodeFilterHash, apiVer );
+
+ if( !chkFirstNodePersonaModelId.equals("") ){
+ // NOTE: For Service or Resource models, if this is a nodeType that supports persona's, then
+ // we need to make sure that the start node matches the persona values.
+ String startVertPersonaModId = startVtx.<String>property("persona-model-id").orElse(null);
+ String startVertPersonaModVersion = startVtx.<String>property("persona-model-version").orElse(null);
+ if( !chkFirstNodePersonaModelId.equals(startVertPersonaModId)
+ || !chkFirstNodePersonaModelVersion.equals(startVertPersonaModVersion) ){
+ String msg = "Persona-Model data mismatch for start node (" + topNType + "), " +
+ startNodeFilterHash ;
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ String topVid = startVtx.id().toString();
+
+ // Read the model into a Map for processing
+ Multimap <String, String> validNextStepMap = genTopoMap4Model(transId, fromAppId, graph,
+ modelVtx, modelNameVersionId, dbMaps );
+
+ logline.add("TopoMap", validNextStepMap.toString() );
+
+ // Collect the data
+ String elementLocationTrail = topNType + personaData;
+ vidsTraversed = new ArrayList <String> ();
+ HashMap <String,String> emptyHash = new HashMap <String,String> ();
+
+ // Pass emptyHash for the NQElement hash since that parameter only applies to Named Queries
+ ResultSet retResSet = collectInstanceData( transId, fromAppId, graph,
+ startVtx, elementLocationTrail,
+ validNextStepMap, vidsTraversed, 0, delKeyHash, emptyHash, apiVer );
+
+ // Note: the new ResultSet will have each element tagged with the del flag so we'll know if it
+ // should be deleted or not - so loop through the results in a try-block since some things
+ // will get auto-deleted by parents before we get to them --- and try to remove each one.
+ String vidToResCheck = topVid;
+ retHash = deleteAsNeededFromResultSet( transId, fromAppId, graph, retResSet,
+ vidToResCheck, apiVer, resVersion, emptyHash );
+ String msgStr = "processed deletes for these vids: (\n"+ retHash.keySet().toString() + ").";
+
+ logline.add("DeleteReturnVal", msgStr);
+ return retHash;
+
+ }// End of runDeleteByModel()
+
+
+ /**
+ * Delete as needed from result set.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param resSet the res set
+ * @param vidToResCheck -- this vertex will need to have its resource-version checked
+ * @param apiVer the api ver
+ * @param resVersion the res version
+ * @param hashSoFar the hash so far -- hash of what's been deleted so far
+ * @return String
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,String> deleteAsNeededFromResultSet( String transId, String fromAppId, TitanTransaction graph,
+ ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, HashMap <String,String> hashSoFar )
+ throws AAIException
+ {
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "deleteAsNeededFromResultSet");
+ HashMap <String,String> retHash = new HashMap <String,String> ();
+ retHash.putAll( hashSoFar );
+ Boolean deleteIt = false;
+
+ if( graph == null ){
+ String emsg = "null graph object passed to deleteAsNeededFromResultSet()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ if( resSet.vert == null ){
+ return retHash;
+ }
+
+ TitanVertex thisVtx = resSet.vert;
+ String thisGuyId = "";
+ String thisNT = "";
+ String thisGuyStr = "";
+
+ try {
+ thisGuyId = thisVtx.id().toString();
+ thisNT = thisVtx.<String>property("aai-node-type").orElse(null);
+ thisGuyStr = thisGuyId + "[" + thisNT + " found at:" + resSet.locationInModelSubGraph + "]";
+ }
+ catch (Exception ex) {
+ // Sometimes things have already been deleted by the time we get to them - just log it.
+ String warnMsg = "WARNING Exception when deleting " + thisGuyStr + ". msg = " + ex.getMessage();
+ logline.add("warnMsg", warnMsg);
+ }
+
+ if( thisGuyId.equals("") ){
+ // The vertex must have already been removed. Just return.
+ return retHash;
+ }
+ else {
+ if( resSet.getNewDataDelFlag() != null && resSet.getNewDataDelFlag().equals("T") ){
+ String infoMsg = ">> will try to delete this one >> " + thisGuyStr ;
+ logline.add("infoMsg", infoMsg);
+
+ try {
+ Boolean resVerOverRide = true;
+ if( thisGuyId.equals(vidToResCheck) ){
+ // This is the one vertex that we want to check the resourceId before deleting
+ resVerOverRide = false;
+ }
+ DbMeth.removeAaiNode( transId, fromAppId, graph, thisVtx, "USE_DEFAULT", apiVer, resVersion, resVerOverRide );
+ }
+ catch (AAIException ae) {
+ String errorCode = ae.getErrorObject().getErrorCode();
+ if ( errorCode.equals("6130") || errorCode.equals("6131") ) {
+ // They didn't pass the correct resource-version for the top node.
+ throw ae;
+ }
+ else {
+ String errText = ae.getErrorObject().getErrorText();
+ String errDetail = ae.getErrorObject().getDetails();
+ String warnMsg = "WARNING Exception when deleting " + thisGuyStr + ". ErrorCode = " + errorCode +
+ ", errorText = " + errText + ", details = " + errDetail;
+ logline.add("warnMsg", warnMsg);
+ }
+ }
+ catch( Exception e ){
+ // We'd expect to get a "node not found" here sometimes depending on the order that
+ // the model has us finding / deleting nodes.
+ // Ignore the exception - but log it so we can see what happened.
+ String warnMsg = "WARNING Exception when deleting " + thisGuyStr + e.getMessage();
+ //System.out.println(" \nDEBUG --- " + warnMsg );
+ logline.add("warnMsg", warnMsg);
+ }
+
+ // We can't depend on a thrown exception to tell us if a node was deleted since it may
+ // have been auto=deleted before this removeAaiNode() call.
+ // --- Not sure if we would want to check anything here -- because the graph.commit() is done outside of this call.
+
+ deleteIt = true;
+ }
+ else {
+ // --- DEBUG ----
+ //System.out.println(">>>>>>> NOT DELETING THIS ONE >>>> " + thisGuyStr );
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode(transId, fromAppId, thisVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+ // --- DEBUG ----
+ }
+ }
+
+ // Now call this routine for the sub-resultSets
+ List <ResultSet> subResultSetList = resSet.getSubResultSet();
+ Iterator <ResultSet> subResSetIter = subResultSetList.iterator();
+ while( subResSetIter.hasNext() ){
+ ResultSet tmpSubResSet = subResSetIter.next();
+ retHash = deleteAsNeededFromResultSet( transId, fromAppId, graph, tmpSubResSet,
+ vidToResCheck, apiVer, resVersion, retHash );
+ }
+
+ if( deleteIt ){
+ retHash.put(thisGuyId, thisGuyStr);
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return retHash;
+
+ }// deleteAsNeededFromResultSet()
+
+
+ /**
+ * Query by named query.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryUuid the named query uuid
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByNamedQuery( String transId, String fromAppId, TitanTransaction graph,
+ String namedQueryUuid,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ final String transId_f = transId;
+ final String fromAppId_f = fromAppId;
+ final TitanTransaction graph_f = graph;
+ final String namedQueryUuid_f = namedQueryUuid;
+ final ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes;
+ final String apiVer_f = apiVer;
+
+ // Find out what our time-limit should be
+ int timeLimitSec = 0;
+ String timeLimitString = AAIConfig.get("aai.model.query.timeout.sec");
+ if( timeLimitString != null && !timeLimitString.equals("") ){
+ try {
+ timeLimitSec = Integer.parseInt(timeLimitString);
+ }
+ catch ( Exception nfe ){
+ // Don't worry, we will leave the limit as zero - which tells us not to use it.
+ }
+ }
+
+ if( timeLimitSec <= 0 ){
+ // We will NOT be using a timer
+ return queryByNamedQuery_Timed( transId, fromAppId, graph,
+ namedQueryUuid,
+ startNodeFilterArrayOfHashes,
+ apiVer );
+ }
+
+ ArrayList <ResultSet> resultList = new ArrayList <ResultSet> ();
+ TimeLimiter limiter = new SimpleTimeLimiter();
+ try {
+ resultList = limiter.callWithTimeout(new Callable <ArrayList <ResultSet>>() {
+ public ArrayList <ResultSet> call() throws AAIException {
+ return queryByNamedQuery_Timed( transId_f, fromAppId_f, graph_f,
+ namedQueryUuid_f,
+ startNodeFilterArrayOfHashes_f,
+ apiVer_f );
+ }
+ }, timeLimitSec, TimeUnit.SECONDS, true);
+
+ }
+ catch (AAIException ae) {
+ // Re-throw AAIException so we get can tell what happened internally
+ throw ae;
+ }
+ catch (UncheckedTimeoutException ute) {
+ throw new AAIException("AAI_6140", "Query Processing Limit exceeded. (limit = " + timeLimitSec + " seconds)");
+ }
+ catch (Exception e) {
+ throw new AAIException("AAI_6128", "Unexpected exception in queryByNamedQuery(): " + e.getMessage() );
+ }
+
+ return resultList;
+ }
+
+
+ /**
+ * Query by named query timed.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryUuid the named query uuid
+ * @param startNodeFilterArrayOfHashes the start node filter array of hashes --used to locate the first nodes of instance data
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> queryByNamedQuery_Timed( String transId, String fromAppId, TitanTransaction graph,
+ String namedQueryUuid,
+ ArrayList <HashMap <String,Object>> startNodeFilterArrayOfHashes,
+ String apiVer )
+ throws AAIException{
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "queryByNamedQuery");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to queryByNamedQuery()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ // Locate the Query to be used
+ HashMap <String,Object> propHash0 = new HashMap<String, Object>();
+ propHash0.put("named-query-uuid", namedQueryUuid);
+ TitanVertex queryVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "named-query", propHash0, null, apiVer );
+ if( queryVtx == null ){
+ String msg = "No named-query found for named-query-uuid = " + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+
+ //System.out.println("\n DEBUG --- Found query vertex: " );
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode("junkId", "junkApp", queryVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+
+
+ // Get the first/top named-query-element used by this query
+ Iterable <?> verts = queryVtx.query().direction(Direction.OUT).labels("startsWith").vertices();
+ Iterator <?> vertI = verts.iterator();
+ TitanVertex firstNqElementVert = null;
+ int count = 0;
+ String topNType = "";
+ while( vertI != null && vertI.hasNext() ){
+ firstNqElementVert = (TitanVertex) vertI.next();
+ count++;
+ topNType = getElementWidgetType( firstNqElementVert, "" );
+ }
+
+ if( count < 1 ){
+ // A named query must start with a single top element
+ String msg = "No top-node defined for named-query-uuid = [" + namedQueryUuid + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+ else if( count > 1 ){
+ // A named query should start with a single top element
+ String msg = "More than one top-node defined for named-query-uuid = [" + namedQueryUuid + "]";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+ if( (topNType == null) || topNType.equals("") ){
+ String msg = "Could not determine the top-node nodeType for Named Query: [" + namedQueryUuid + "]";
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ // Read the topology into a hash for processing
+ Multimap <String, String> validNextStepMap = genTopoMap4NamedQ(transId, fromAppId, graph, queryVtx, namedQueryUuid);
+
+ ArrayList <TitanVertex> startVertList = new ArrayList <TitanVertex>();
+ if( startNodeFilterArrayOfHashes.size() == 1 ){
+ // If there is only one set of startFilter info given, then allow it to possibly not be
+ // defining just one start node.
+ try {
+ TitanVertex tmpVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNType, startNodeFilterArrayOfHashes.get(0), apiVer );
+ // Only found one, so just use it.
+ startVertList.add(tmpVtx);
+ }
+ catch( AAIException ate ){
+ // Either there is more than one node found using these parameters or these
+ // were not the key params. Either way, see if they can lead us to some start-nodes.
+
+ // NOTE: for now, getNodes() is only taking parameters for the nodeType passed, so if
+ // any of the parameters have the nodeType appended, it should be stripped off.
+ // Ie. "customer.global-cust-id" should be passed just as, "global-cust-id"
+ HashMap <String, Object> cleanHash = new HashMap <String,Object>();
+ HashMap <String, Object> tmpHash = startNodeFilterArrayOfHashes.get(0);
+ Set <String> propKeySet = tmpHash.keySet();
+ Iterator<String> propIter = propKeySet.iterator();
+ while( propIter.hasNext() ){
+ String oldVtxKey = (String) propIter.next();
+ String newKey = oldVtxKey;
+ String [] parts = oldVtxKey.split("\\.");
+ if( parts.length == 2 ){
+ newKey = parts[1];
+ }
+ Object obVal = tmpHash.get(oldVtxKey);
+ cleanHash.put(newKey,obVal);
+ }
+
+ startVertList = DbMeth.getNodes( transId, fromAppId, graph, topNType,
+ cleanHash, false, apiVer, true );
+
+ if( startVertList.isEmpty() ){
+ String msg = "No Node of type [" + topNType + "] found for properties: " + cleanHash.toString();
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+ }
+ }
+ else {
+ // Since they give an array of startNodeFilterHash info, we expect each one
+ // to just point to one node.
+ for( int i = 0; i < startNodeFilterArrayOfHashes.size(); i++ ){
+ // Locate the starting node for each set of data
+ TitanVertex tmpVtx = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph,
+ topNType, startNodeFilterArrayOfHashes.get(i), apiVer );
+ startVertList.add(tmpVtx);
+ }
+ }
+
+ // Make sure they're not bringing back too much data
+ String maxString = AAIConfig.get("aai.model.query.resultset.maxcount");
+ if( maxString != null && !maxString.equals("") ){
+ int maxSets = Integer.parseInt(maxString);
+ if( startVertList.size() > maxSets ){
+ String msg = " Query returns " + startVertList.size() + " resultSets. Max allowed is: " + maxSets;
+ throw new AAIException("AAI_6141", msg);
+ }
+ }
+
+ // Loop through each start node and get its data
+ ArrayList <ResultSet> resSetList = new ArrayList <ResultSet> ();
+ for( int i = 0; i < startVertList.size(); i++ ){
+ TitanVertex startVtx = startVertList.get(i);
+ // Collect the data
+ String elementLocationTrail = topNType;
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+ HashMap <String,String> emptyDelKeyHash = new HashMap <String,String> (); // Does not apply to Named Queries
+
+ // Get the mapping of namedQuery elements to our widget topology for this namedQuery
+ String incomingTrail = "";
+ HashMap <String, String> currentHash = new HashMap <String,String> ();
+
+ HashMap <String,String> namedQueryElementHash = collectNQElementHash( transId, fromAppId, graph,
+ firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0 );
+
+ vidsTraversed = new ArrayList <String> ();
+ ResultSet tmpResSet = collectInstanceData( transId, fromAppId, graph,
+ startVtx, elementLocationTrail,
+ validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, namedQueryElementHash, apiVer );
+ resSetList.add(tmpResSet);
+ }
+
+ // Since a NamedQuery can mark some nodes as "do-not-display", we need to collapse our resultSet so
+ // does not display those nodes.
+ ArrayList <ResultSet> collapsedResSetList = new ArrayList <ResultSet> ();
+ if( resSetList != null && !resSetList.isEmpty() ){
+ for( int i = 0; i < resSetList.size(); i++ ){
+ // Note - a single resultSet could be collapsed into many smaller ones if they
+ // marked all the "top" node-elements as do-not-output. Ie. the query may
+ // have had a top-node of "generic-vnf" which joins down to different l-interfaces.
+ // If they only want to see the l-interfaces, then a single result set
+ // would be "collapsed" into many separate resultSets - each of which is
+ // just a single l-interface.
+ ArrayList <ResultSet> tmpResSetList = collapseForDoNotOutput(resSetList.get(i));
+ if( tmpResSetList != null && !tmpResSetList.isEmpty() ){
+ for( int x = 0; x < tmpResSetList.size(); x++ ){
+ collapsedResSetList.add(tmpResSetList.get(x));
+ }
+ }
+ }
+ }
+
+ return collapsedResSetList;
+
+
+ }// End of queryByNamedQuery()
+
+
+ /**
+ * Collapse for do not output.
+ *
+ * @param resSetVal the res set val
+ * @return the array list
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <ResultSet> collapseForDoNotOutput( ResultSet resSetVal )
+ throws AAIException {
+
+ // Given a ResultSet -- if it is tagged to NOT be output, then replace it with
+ // it's sub-ResultSets if it has any.
+ ArrayList <ResultSet> colResultSet = new ArrayList <ResultSet> ();
+
+ if( resSetVal.getDoNotOutputFlag().equals("true") ){
+ // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets
+ ArrayList <ResultSet> subResList = (ArrayList<ResultSet>) resSetVal.getSubResultSet();
+ for( int k = 0; k < subResList.size(); k++ ){
+ ArrayList <ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(k));
+ colResultSet.addAll(newSubResList);
+ }
+ }
+ else {
+ // This set will be displayed
+ colResultSet.add(resSetVal);
+ }
+
+ // For each result set now at this level, call this same routine to collapse their sub-resultSets
+ for( int i = 0; i < colResultSet.size(); i++ ){
+ ArrayList <ResultSet> newSubSet = new ArrayList <ResultSet> ();
+ ArrayList <ResultSet> subResList = (ArrayList<ResultSet>) colResultSet.get(i).getSubResultSet();
+ for( int n = 0; n < subResList.size(); n++ ){
+ ArrayList <ResultSet> newSubResList = collapseForDoNotOutput(subResList.get(n));
+ newSubSet.addAll(newSubResList);
+ }
+ // Replace the old subResultSet with the collapsed set
+ colResultSet.get(i).subResultSet = newSubSet;
+ }
+
+ return colResultSet;
+
+ }// End collapseForDoNotOutput()
+
+
+
+ /**
+ * Collect instance data.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param thisVertsTrail the this verts trail
+ * @param elementLocationTrail -- trail of nodeTypes that got us here (this vertex) from the top
+ * @param validNextStepMap the valid next step map -- hash of valid next steps (node types) for this model
+ * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @param delKeyHash -- hashMap of which spots on our topology should be deleted during a modelDelete
+ * @param namedQueryElementHash - hashMap which maps each spot in our widget topology to the NamedQueryElemment that it maps to
+ * @param apiVer the api ver
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static ResultSet collectInstanceData( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex,
+ String thisVertsTrail,
+ Multimap <String,String> validNextStepMap,
+ ArrayList <String> vidsTraversed,
+ int levelCounter,
+ HashMap <String,String> delKeyHash, // only applies when collecting data using the default model for delete
+ HashMap <String,String> namedQueryElementHash, // only applies to named-query data collecting
+ String apiVer
+ ) throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectInstanceData");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to collectInstanceData()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ String thisVid = thisLevelVertex.id().toString();
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectInstanceData() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+
+ ResultSet rs = new ResultSet();
+ if( namedQueryElementHash.containsKey(thisVertsTrail) ){
+ // We're collecting data for a named-query, so need to see if we need to do anything special
+ String nqElUuid = namedQueryElementHash.get(thisVertsTrail);
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+ propHash.put( "named-query-element-uuid", nqElUuid );
+ TitanVertex nqElementVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "named-query-element", propHash, null, apiVer);
+ if( nqElementVtx == null ){
+ String msg = " Could not find named-query-element with named-query-element-uuid = [" + nqElUuid + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String tmpDoNotShow = nqElementVtx.<String>property("do-not-output").orElse(null);
+ if( tmpDoNotShow != null && tmpDoNotShow.equals("true") ){
+ rs.doNotOutputFlag = "true";
+ }
+
+ if( namedQueryConstraintSaysStop(transId, fromAppId, graph, nqElementVtx, thisLevelVertex, apiVer) ){
+ // There was a property constraint which says they do not want to collect this vertex or whatever
+ // might be below it. Just return the empty rs here.
+ return rs;
+ }
+
+ String propLimDesc = nqElementVtx.<String>property("property-limit-desc").orElse(null);
+ if( (propLimDesc != null) && !propLimDesc.equals("") ){
+ rs.propertyLimitDesc = propLimDesc;
+ }
+
+ // Look to see if we need to use an Override of the normal properties
+ HashMap <String,Object> tmpPropertyOverRideHash = getNamedQueryPropOverRide(transId, fromAppId, graph, nqElementVtx, thisLevelVertex, apiVer);
+ //System.out.println(" DEBUG --- USING this propertyOverride data set on ResSet [" + tmpPropertyOverRideHash.toString() + "]");
+ rs.propertyOverRideHash = tmpPropertyOverRideHash;
+
+ // See if we need to look up any "unconnected" data that needs to be associated with this result set
+ HashMap <String,Object> tmpExtraPropHash = getNamedQueryExtraDataLookup(transId, fromAppId, graph, nqElementVtx, thisLevelVertex, apiVer);
+ //System.out.println(" DEBUG --- ADDING this EXTRA Lookup data to the ResSet [" + tmpExtraPropHash.toString() + "]");
+ rs.extraPropertyHash = tmpExtraPropHash;
+ }
+
+ rs.vert = thisLevelVertex;
+ rs.locationInModelSubGraph = thisVertsTrail;
+ if( delKeyHash.containsKey(thisVertsTrail) && delKeyHash.get(thisVertsTrail).equals("T") ){
+ rs.newDataDelFlag = "T";
+ }
+ else {
+ rs.newDataDelFlag = "F";
+ }
+
+ // Use Gremlin-pipeline to just look for edges that go to a valid "next-steps"
+ Collection <String> validNextStepColl = validNextStepMap.get(thisVertsTrail);
+
+ // Because of how we process linkage-points, we may have duplicate node-types in our next-stepMap (for one step)
+ // So, to keep from looking (and bringing back) the same data twice, we need to make sure our next-steps are unique
+ HashSet <String> validNextStepHashSet = new HashSet <String> ();
+ Iterator <String> ntcItr = validNextStepColl.iterator();
+ while( ntcItr.hasNext() ){
+ String targetStepStr = ntcItr.next();
+ validNextStepHashSet.add(targetStepStr);
+ }
+
+ ArrayList <String> tmpVidsTraversedList = new ArrayList <String> ();
+ tmpVidsTraversedList.addAll(vidsTraversed);
+ tmpVidsTraversedList.add(thisVid);
+
+ Iterator <String> ntItr = validNextStepHashSet.iterator();
+ while( ntItr.hasNext() ){
+ String targetStep = ntItr.next();
+ // NOTE: NextSteps can either be just a nodeType, or can be a nodeType plus
+ // persona-model-id and persona-model-version if those need to be checked also.
+ // When the persona stuff is part of the step, it is a comma separated string.
+ // Ie. "nodeType,personaModelId,personaModeVersion"
+ String targetNodeType = "";
+ String pmid = "";
+ String pmv = "";
+ Boolean stepIsJustNT = true;
+ if( targetStep.contains(",") ){
+ stepIsJustNT = false;
+ String[] pieces = targetStep.split(",");
+ if( pieces.length != 3 ){
+ String msg = "Unexpected format for nextStep in model processing = ["
+ + targetStep + "]. ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6128");
+ throw new AAIException("AAI_6128", msg);
+ }
+ else {
+ targetNodeType = pieces[0];
+ pmid = pieces[1];
+ pmv = pieces[2];
+ }
+ }
+ else {
+ // It's just the nodeType with no other info
+ targetNodeType = targetStep;
+ }
+
+ GraphTraversal<Vertex, Vertex> modPipe = null;
+ if( stepIsJustNT ){
+ modPipe = graph.traversal().V(thisLevelVertex).both().has("aai-node-type", targetNodeType);
+ }
+ else {
+ modPipe = graph.traversal().V(thisLevelVertex).both().has("aai-node-type", targetNodeType).has("persona-model-id",pmid).has("persona-model-version",pmv);
+ }
+
+ if( modPipe == null || !modPipe.hasNext() ){
+ //System.out.println("DEBUG - didn't find any [" + targetStep + "] connected to this guy (which is ok)");
+ }
+ else {
+ while( modPipe.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) modPipe.next();
+ String tmpVid = tmpVert.id().toString();
+ String tmpTrail = thisVertsTrail + "|" + targetStep;
+ if( !vidsTraversed.contains(tmpVid) ){
+ // This is one we would like to use - so we'll include the result set we get for it
+ ResultSet tmpResSet = collectInstanceData( transId, fromAppId, graph,
+ tmpVert, tmpTrail,
+ validNextStepMap, tmpVidsTraversedList,
+ levelCounter, delKeyHash, namedQueryElementHash, apiVer );
+
+ rs.subResultSet.add(tmpResSet);
+ }
+ }
+ }
+ }
+
+ return rs;
+
+ } // End of collectInstanceData()
+
+
+ /**
+ * Gen topo map 4 model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelVertex the model vertex
+ * @param modelUuid the model uuid
+ * @param dbMaps the db maps
+ * @return MultiMap of valid next steps for each potential model-element
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> genTopoMap4Model( String transId, String fromAppId,
+ TitanTransaction graph, TitanVertex modelVertex, String modelUuid, DbMaps dbMaps )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "genTopoMap4Model");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to genTopoMap4Model()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ if( modelVertex == null ){
+ String msg = " null modelVertex passed to genTopoMap4Model() ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6114");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ Multimap <String, String> initialEmptyMap = ArrayListMultimap.create();
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+
+ String modelType = getModelType( modelVertex, "" );
+ if( modelType.equals("widget") ){
+ // A widget model by itself does not have a topoplogy. That is - it has no "model-elements" which
+ // define how it is connected to other things. All it has is a name which ties it to
+ // an aai-node-type
+ Iterable <?> verts = modelVertex.query().direction(Direction.OUT).labels("startsWith").vertices();
+ Iterator <?> vertI = verts.iterator();
+ if( vertI != null && vertI.hasNext() ){
+ String msg = "Bad Model Definition: Widget Model with a startsWith edge to a model-element. "
+ + " Model UUID = " + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+ else {
+ return initialEmptyMap;
+ }
+ }
+
+ String firstModelId = modelVertex.<String>property("model-id").orElse(null);
+ String firstModelVersion = modelVertex.<String>property("model-version").orElse(null);
+ if( firstModelId == null || firstModelId.equals("") || firstModelVersion == null || firstModelVersion.equals("") ){
+ String msg = "Bad Model Definition: Bad model-id or model-version. Model UUID = "
+ + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ TitanVertex firstElementVertex = getTopElementForSvcOrResModel( modelVertex );
+ TitanVertex firstEleModVtx = getModelThatElementRepresents( firstElementVertex, "" );
+ String firstElemModelType = getModelType( firstEleModVtx, "" );
+ if( ! firstElemModelType.equals("widget") ){
+ String msg = "Bad Model Definition: First element must correspond to a widget type model. Model UUID = "
+ + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ Multimap <String, String> collectedMap = collectTopology4Model( transId, fromAppId, graph,
+ firstElementVertex, "",
+ initialEmptyMap, vidsTraversed, 0, dbMaps, null, firstModelId, firstModelVersion );
+
+ //DEBUG -----------------
+ //System.out.println("DEBUG -- go this topo map for this model: ");
+ //Set keySet = collectedMap.keySet();
+ //Iterator keyIterator = keySet.iterator();
+ //while (keyIterator.hasNext() ) {
+ // String key = (String) keyIterator.next();
+ // System.out.println( "DEBUG -- for this key: [" + key + "], got these values: ");
+ // Collection <String> values = collectedMap.get(key) ;
+ // Iterator valIter = values.iterator();
+ // while( valIter.hasNext() ){
+ // System.out.println(" >>> [" + valIter.next() + "]");
+ // }
+ //}
+ //DEBUG -------------------------
+
+ return collectedMap;
+
+ } // End of genTopoMap4Model()
+
+
+
+ /**
+ * Gets the mod constraint hash.
+ *
+ * @param modelElementVtx the model element vtx
+ * @param currentHash -- the current ModelConstraint's that this routine will add to if it finds any.
+ * @return HashMap of model-constraints that will be looked at for this model-element and what's "below" it.
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, TitanVertex> getModConstraintHash( TitanVertex modelElementVtx, HashMap <String, TitanVertex> currentHash )
+ throws AAIException {
+
+ // For a given model-element vertex, look to see if there are any "model-constraint" elements that is has
+ // an OUT "uses" edge to. If it does, then get any "constrained-element-set" nodes that are pointed to
+ // by the "model-constraint". That will be the replacement "constrained-element-set". The UUID of the
+ // "constrained-element-set" that it is supposed to replace is found in the property:
+ // model-constraint.constrained-element-set-uuid-to-replace
+ //
+ // For now, that is the only type of model-constraint allowed, so that is all we will look for.
+ // Pass back any of these "constrained-element-set" nodes along with any that were passed in by
+ // the "currentHash" parameter.
+
+ if( modelElementVtx == null ){
+ String msg = " null modelElementVtx passed to getModConstraintHash() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String modelType = modelElementVtx.<String>property("aai-node-type").orElse(null);
+ if( modelType == null || (!modelType.equals("model-element")) ){
+ String msg = " getModConstraintHash() called with wrong type model: [" + modelType + "]. ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ HashMap <String, TitanVertex> thisHash = new HashMap <String, TitanVertex> ();
+ if( currentHash != null ){
+ thisHash.putAll(currentHash);
+ }
+
+ int count = 0;
+ ArrayList <TitanVertex> modelConstraintArray = new ArrayList <TitanVertex> ();
+ Iterable <?> verts = modelElementVtx.query().direction(Direction.OUT).labels("uses").vertices();
+ Iterator <?> vertI = verts.iterator();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( (connectToType != null) && connectToType.equals("model-constraint") ){
+ // We need to find the constrained element set pointed to by this and add it to the Hash to return
+ modelConstraintArray.add(tmpVert);
+ count++;
+ }
+ }
+
+ if( count > 0 ) {
+ for( int i = 0; i < count; i++ ){
+ TitanVertex vtxOfModelConstraint = modelConstraintArray.get(i);
+ String uuidOfTheOneToBeReplaced = vtxOfModelConstraint.<String>property("constrained-element-set-uuid-2-replace").orElse(null);
+ // We have the UUID of the constrained-element-set that will be superseded, now find the
+ // constrained-element-set to use in its place
+ Iterable <?> mverts = vtxOfModelConstraint.query().direction(Direction.OUT).labels("uses").vertices();
+ Iterator <?> mvertI = mverts.iterator();
+ while( mvertI != null && mvertI.hasNext() ){
+ // There better only be one...
+ TitanVertex tmpVert = (TitanVertex) mvertI.next();
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
+ // This is the "constrained-element-set" that we want to use as the Replacement
+ thisHash.put(uuidOfTheOneToBeReplaced, tmpVert );
+ }
+ }
+ }
+ return thisHash;
+ }
+ else {
+ // Didn't find anything to add, so just return what they passed in.
+ return currentHash;
+ }
+
+ } // End of getModConstraintHash()
+
+
+ /**
+ * Gets the top element for svc or res model.
+ *
+ * @param modelVertex the model vertex
+ * @return first element pointed to by this model
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getTopElementForSvcOrResModel( TitanVertex modelVertex )
+ throws AAIException {
+
+ // For a "resource" or "service" type model, return the "top" element in that model
+ if( modelVertex == null ){
+ String msg = " null modelVertex passed to getTopoElementForSvcOrResModel() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String modelType = modelVertex.<String>property("model-type").orElse(null);
+ if( modelType == null || (!modelType.equals("service")) && (!modelType.equals("resource")) ){
+ String msg = " getTopElementForSvcOrResModel() called with wrong type model: [" + modelType + "]. ";
+ throw new AAIException("AAI_6114", msg);
+ }
+ String modelUuid = modelVertex.<String>property("model-name-version-id").orElse(null);
+
+ TitanVertex firstElementVertex = null;
+ Iterable <?> verts = modelVertex.query().direction(Direction.OUT).labels("startsWith").vertices();
+
+ Iterator <?> vertI = verts.iterator();
+ int elCount = 0;
+ while( vertI != null && vertI.hasNext() ){
+ elCount++;
+ firstElementVertex = (TitanVertex) vertI.next();
+ }
+
+ if( elCount > 1 ){
+ String msg = "Illegal model defined: More than one first element defined for = " + modelUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ if( firstElementVertex == null ){
+ String msg = "Could not find first model element = " + modelUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return firstElementVertex;
+
+ } // End of getTopElementForSvcOrResModel()
+
+
+
+ /**
+ * Gets the named query prop over ride.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryElementVertex the named query element vertex
+ * @param instanceVertex the instance vertex
+ * @param apiVer the api ver
+ * @return HashMap of alternate properties to return for this element
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getNamedQueryPropOverRide( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex namedQueryElementVertex, TitanVertex instanceVertex, String apiVer )
+ throws AAIException {
+
+ // If this model-element says that they want an alternative set of properties returned, then pull that
+ // data out of the instance vertex.
+
+ HashMap <String,Object> altPropHash = new HashMap <String,Object> ();
+
+ if( namedQueryElementVertex == null ){
+ String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ ArrayList <String> propCollectList = new ArrayList <String> ();
+ Iterator <VertexProperty<Object>> vpI = namedQueryElementVertex.properties("property-collect-list");
+ while( vpI.hasNext() ){
+ VertexProperty <Object> vpOb = vpI.next();
+ // Some property-collect-lists are winding up in the database as toString() versions of
+ // an arrayList instead of as ArrayLists or as multiple properties with the same name.
+ // Whichever it is, we need to handle it.
+ ArrayList <String> propCollList = makeSureItsAnArrayList( vpOb );
+ if( propCollList != null ){
+ for( int i = 0; i < propCollList.size(); i++ ){
+ String thisPropName = propCollList.get(i);
+ Object instanceVal = instanceVertex.<Object>property(thisPropName).orElse(null);
+ altPropHash.put(thisPropName, instanceVal);
+ }
+ }
+ }
+
+ return altPropHash;
+
+ } // End of getNamedQueryPropOverRide()
+
+
+ /**
+ * Named query constraint says stop.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryElementVertex the named query element vertex
+ * @param instanceVertex the instance vertex
+ * @param apiVer the api ver
+ * @return true - if a constraint was defined that has not been met by the passed instanceVertex
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean namedQueryConstraintSaysStop( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex namedQueryElementVertex, TitanVertex instanceVertex, String apiVer )
+ throws AAIException {
+
+ // For each (if any) property-constraint defined for this named-query-element, we will evaluate if
+ // the constraint is met or not-met. if there are constraints and any are not-met, then
+ // we return "true".
+
+ if( namedQueryElementVertex == null ){
+ String msg = " null namedQueryElementVertex passed to namedQueryConstraintSaysStop() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+ if( instanceVertex == null ){
+ String msg = " null instanceVertex passed to namedQueryConstraintSaysStop() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ GraphTraversal<Vertex, Vertex> constrPipe = graph.traversal()
+ .V(namedQueryElementVertex).out("uses").has("aai-node-type","property-constraint");
+
+ if( constrPipe == null || !constrPipe.hasNext() ){
+ // There's no "property-constraint" defined for this named-query-element. No problem.
+ return false;
+ }
+
+ while( constrPipe.hasNext() ){
+ TitanVertex constrVtx = (TitanVertex) constrPipe.next();
+ // We found a property constraint that we will need to check
+ String conType = constrVtx.<String>property("constraint-type").orElse(null);
+ if( (conType == null) || conType.equals("")){
+ String msg = " Bad property-constraint (constraint-type) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String propName = constrVtx.<String>property("property-name").orElse(null);
+ if( (propName == null) || propName.equals("")){
+ String msg = " Bad property-constraint (property-name) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String propVal = constrVtx.<String>property("property-value").orElse(null);
+ if( (propVal == null) || propVal.equals("")){
+ String msg = " Bad property-constraint (propVal) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ // See if that constraint is met or not
+ String val = instanceVertex.<String>property(propName).orElse(null);
+ if( val == null ){
+ val = "";
+ }
+
+ if( conType.equals("EQUALS") ){
+ if( !val.equals(propVal) ){
+ // This constraint was not met
+ return true;
+ }
+ }
+ else if( conType.equals("NOT-EQUALS") ){
+ if( val.equals(propVal) ){
+ // This constraint was not met
+ return true;
+ }
+ }
+ else {
+ String msg = " Bad property-constraint (constraint-type) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ }
+
+ return false;
+
+ } // End of namedQueryConstraintSaysStop()
+
+
+ /**
+ * Gets the named query extra data lookup.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryElementVertex the named query element vertex
+ * @param instanceVertex the instance vertex
+ * @param apiVer the api ver
+ * @return HashMap of alternate properties to return for this element
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getNamedQueryExtraDataLookup( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex namedQueryElementVertex, TitanVertex instanceVertex, String apiVer )
+ throws AAIException {
+
+ // For each (if any) related-lookup defined for this named-query-element, we will go and
+ // and try to find it. All the related-lookup data will get put in a hash and returned.
+
+ if( namedQueryElementVertex == null ){
+ String msg = " null namedQueryElementVertex passed to getNamedQueryExtraDataLookup() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+ if( instanceVertex == null ){
+ String msg = " null instanceVertex passed to getNamedQueryExtraDataLookup() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ HashMap <String,Object> retHash = new HashMap <String,Object> ();
+
+ GraphTraversal<Vertex, Vertex> lookPipe = graph.traversal()
+ .V(namedQueryElementVertex).out("uses").has("aai-node-type","related-lookup");
+
+ if( lookPipe == null || !lookPipe.hasNext() ){
+ // There's no "related-lookup" defined for this named-query-element. No problem.
+ return retHash;
+ }
+
+ while( lookPipe.hasNext() ){
+ TitanVertex relLookupVtx = (TitanVertex) lookPipe.next();
+
+ //System.out.println("DEBUG --- found a related-lookup record -- ");
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode("junkId", "junkApp", relLookupVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+
+ // We found a related-lookup record to try and use
+ String srcProp = relLookupVtx.<String>property("source-node-property").orElse(null);
+ if( (srcProp == null) || srcProp.equals("")){
+ String msg = " Bad related-lookup (source-node-property) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String targetNodeType = relLookupVtx.<String>property("target-node-type").orElse(null);
+ if( (targetNodeType == null) || targetNodeType.equals("")){
+ String msg = " Bad related-lookup (targetNodeType) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+ String targetProp = relLookupVtx.<String>property("target-node-property").orElse(null);
+ if( (targetProp == null) || targetProp.equals("")){
+ String msg = " Bad related-lookup (target-node-property) found in Named Query definition. ";
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ /***
+ ArrayList <String> propCollectList = new ArrayList <String>();
+ Iterator <VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list");
+ while( vpI.hasNext() ){
+ VertexProperty <Object> vpOb = vpI.next();
+ // Some property-collect-lists are winding up in the database as toString() versions of
+ // an arrayList instead of as ArrayLists or as multiple properties with the same name.
+ // Whichever it is, we need to handle it.
+ ArrayList <String> propCList = makeSureItsAnArrayList( vpOb );
+ if( propCList != null ){
+ for( int i = 0; i < propCList.size(); i++ ){
+ String thisPropName = propCList.get(i);
+ propCollectList.add(thisPropName);
+ }
+ }
+ }
+ ***/
+
+ ArrayList <String> propCollectList = new ArrayList <String> ();
+ Iterator <VertexProperty<Object>> vpI = relLookupVtx.properties("property-collect-list");
+ while( vpI.hasNext() ){
+ propCollectList.add((String)vpI.next().value());
+ }
+
+
+
+
+ // Use the value from the source to see if we can find ONE target record using the value from the source
+ String valFromInstance = instanceVertex.<String>property(srcProp).orElse(null);
+ if( valFromInstance == null ){
+ valFromInstance = "";
+ }
+
+ HashMap <String,Object> propHash = new HashMap <String,Object>();
+ propHash.put(targetProp, valFromInstance);
+ ArrayList <TitanVertex> vertList = DbMeth.getNodes(transId, fromAppId, graph, targetNodeType, propHash, true, apiVer, true);
+ int foundCount = vertList.size();
+
+ if( foundCount == 0 ){
+ //System.out.println("\n\n---------- FOUND NOTHING on the related lookup for: [" + targetNodeType
+ // + "], using propHash = [" + propHash + "]\n");
+ }
+ else if( foundCount > 1 ){
+ //System.out.println("DEBUG -- can't use this because there are too many records found using targetNodeType = ["
+ // + targetNodeType + "], with property Hash = [" + propHash + "]\n");
+ }
+ else {
+ TitanVertex tmpVtx = vertList.get(0);
+ //System.out.println("\nDEBUG -- Found a related vertex using our lookup ");
+ // Pick up the properties from the target vertex that they wanted us to get
+ for( int j = 0; j < propCollectList.size(); j++ ){
+ String tmpPropName = propCollectList.get(j);
+ Object valObj = tmpVtx.<Object>property(tmpPropName).orElse(null);
+ String lookupKey = targetNodeType + "." + tmpPropName;
+ retHash.put(lookupKey, valObj);
+ }
+ }
+ }
+
+ return retHash;
+
+ } // End of getNamedQueryExtraDataLookup()
+
+
+ /**
+ * Collect NQ element hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this nq-element vertex) from the top
+ * @param currentHash the current hash
+ * @param Map that got us to this point (that we will use as the base of the map we will return)
+ * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @return HashMap of all widget-points on a namedQuery topology with the value being the "named-query-element-uuid" for that spot.
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, String> collectNQElementHash( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ HashMap <String,String> currentHash, ArrayList <String> vidsTraversed,
+ int levelCounter ) throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectNQElementHash");
+
+ HashMap <String, String> thisHash = new HashMap <String,String> ();
+ thisHash.putAll(currentHash);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectNQElementHash() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+ String thisVid = thisLevelVertex.id().toString();
+
+ // Find out what widget-model (and thereby what aai-node-type) this element represents.
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType;
+ }
+ vidsTraversed.add(thisVid);
+
+ String nqElementUuid = thisLevelVertex.<String>property("named-query-element-uuid").orElse(null);
+ if( nqElementUuid == null || nqElementUuid.equals("") ){
+ String msg = " named-query element UUID not found at trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6133", msg);
+ }
+ thisHash.put(thisGuysTrail, nqElementUuid );
+
+ // Now go "down" and look at the sub-elements pointed to so we can get their data.
+ Iterable <?> verts = thisLevelVertex.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ HashMap <String,Object> elementHash = new HashMap<String, Object>();
+
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( connectToType != null && connectToType.equals("named-query-element") ){
+ // This is what we would expect
+ elementHash.put(vid, tmpVert);
+ }
+ else {
+ String msg = " named query element has [connectedTo] edge to improper nodeType= ["
+ + connectToType + "] trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6133", msg);
+ }
+ for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
+ TitanVertex elVert = (TitanVertex)(entry.getValue());
+ String tmpElVid = elVert.id().toString();
+ if( !vidsTraversed.contains(tmpElVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ HashMap <String, String> tmpHash = collectNQElementHash( transId, fromAppId, graph,
+ elVert, thisGuysTrail, currentHash, vidsTraversed, levelCounter);
+ thisHash.putAll(tmpHash);
+ }
+ }
+ }
+ return thisHash;
+
+ } // End of collectNQElementHash()
+
+
+ /**
+ * Collect delete key hash.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param incomingTrail the incoming trail -- trail of nodeTypes that got us here (this vertex) from the top
+ * @param currentHash the current hash
+ * @param Map that got us to this point (that we will use as the base of the map we will return)
+ * @param vidsTraversed the vids traversed ---- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @param dbMaps the db maps
+ * @param modConstraintHash the mod constraint hash
+ * @param overRideModelId the over ride model id
+ * @param overRideModelVersion the over ride model version
+ * @return HashMap of all widget-points on a model topology with the value being the "newDataDelFlag" for that spot.
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String, String> collectDeleteKeyHash( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ HashMap <String,String> currentHash, ArrayList <String> vidsTraversed,
+ int levelCounter, DbMaps dbMaps, HashMap <String, TitanVertex> modConstraintHash,
+ String overRideModelId, String overRideModelVersion )
+ throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectDeleteKeyHash");
+
+ HashMap <String, String> thisHash = new HashMap <String,String> ();
+ thisHash.putAll(currentHash);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectDeleteKeyHash() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+ String thisVid = thisLevelVertex.id().toString();
+ HashMap <String, TitanVertex> modConstraintHash2Use = null;
+
+ // If this element represents a resource or service model, then we will replace this element with
+ // the "top" element of that resource or service model. That model-element already points to its
+ // topology, so it will graft in that model's topology.
+ // EXCEPT - if this element has "linkage-points" defined, then we need to do some extra
+ // processing for how we join to that model and will not try to go any "deeper".
+
+ //ArrayList <String> linkagePtList = thisLevelVertex.<ArrayList>property("linkage-points").orElse(null);
+ Object objVal = thisLevelVertex.property("linkage-points").orElse(null);
+ ArrayList <String> linkagePtList = makeSureItsAnArrayList( objVal );
+
+ if( linkagePtList != null && !linkagePtList.isEmpty() ){
+ // Whatever this element is - we are connecting to it via a linkage-point
+ // We will figure out what to do and then return without going any deeper
+ String elemFlag = thisLevelVertex.<String>property("new-data-del-flag").orElse(null);
+
+ HashSet <String> linkageConnectNodeTypes = getLinkageConnectNodeTypes( linkagePtList );
+ Iterator <?> linkNtIter = linkageConnectNodeTypes.iterator();
+ String incTrail = "";
+ if( !incomingTrail.equals("") ){
+ incTrail = incomingTrail + "|";
+ }
+
+ while( linkNtIter.hasNext() ){
+ // The 'trail' (or trails) for this element should just be the to the first-contact on the linkage point
+ String linkTrail = incTrail + linkNtIter.next();
+ Boolean alreadyTaggedFalse = false;
+ if( thisHash.containsKey(linkTrail) && thisHash.get(linkTrail).equals("F") ){
+ // some other path with a matching trail has the deleteFlag set to "F", so we do not want
+ // to override that since our model code only uses nodeTypes to know where it is - and we
+ // would rather do less deleting than needed instead of too much deleting.
+ alreadyTaggedFalse = true;
+ }
+ if( elemFlag != null && elemFlag.equals("T") && !alreadyTaggedFalse ){
+ // This trail should be marked with an "T"
+ thisHash.put(linkTrail, "T");
+ }
+ else {
+ thisHash.put(linkTrail, "F");
+ }
+ }
+ return thisHash;
+ }
+
+
+
+ // ---------------------------------------------------------------
+ // If we got to here, then this was not an element that used a linkage-point
+ // ---------------------------------------------------------------
+
+ // Find out what widget-model (and thereby what aai-node-type) this element represents.
+ // Even if this element is pointing to a service or resource model, it must have a
+ // first element which is a single widget-type model.
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+ String firstElementModelInfo = "";
+
+ vidsTraversed.add(thisVid);
+ TitanVertex elementVtxForThisLevel = null;
+ TitanVertex thisElementsModelVtx = getModelThatElementRepresents( thisLevelVertex, incomingTrail );
+ String modType = getModelType( thisElementsModelVtx, incomingTrail );
+
+ String subModelFirstModId = thisElementsModelVtx.<String>property("model-id").orElse(null);
+ String subModelFirstVersion = thisElementsModelVtx.<String>property("model-version").orElse(null);
+ if( modType.equals("widget") ){
+ if( overRideModelId != null && !overRideModelId.equals("") ){
+ // Note - this is just to catch the correct model for the TOP node in a model since
+ // it will have an element which will always be a widget even though the model
+ // could be a resource or service model.
+ firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersion;
+ }
+ }
+ else if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) ){
+ firstElementModelInfo = "," + subModelFirstModId + "," + subModelFirstVersion;
+ }
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType + firstElementModelInfo;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType + firstElementModelInfo;
+ }
+
+ String tmpFlag = "F";
+ Boolean stoppedByASvcOrResourceModelElement = false;
+ if( modType.equals("widget") ){
+ elementVtxForThisLevel = thisLevelVertex;
+ // For the element-model for the widget at this level, record it's delete flag
+ tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null);
+ }
+ else {
+ // For an element that is referring to a resource or service model, we replace this
+ // this element with the "top" element for that resource/service model so that the
+ // topology of that resource/service model gets included in this topology.
+ String modelUuid = thisElementsModelVtx.<String>property("model-name-version-id").orElse(null);
+ if( subModelFirstModId == null || subModelFirstModId.equals("")
+ || subModelFirstVersion == null || subModelFirstVersion.equals("") ){
+ String msg = "Bad Model Definition: Bad model-id or model-version. Model UUID = " + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ // BUT -- if the model-element HERE at the resource/service level does NOT have
+ // it's new-data-del-flag set to "T", then we do not need to go down into the
+ // sub-model looking for delete-able things.
+
+ tmpFlag = thisLevelVertex.<String>property("new-data-del-flag").orElse(null);
+ elementVtxForThisLevel = getTopElementForSvcOrResModel(thisElementsModelVtx);
+ if( tmpFlag != null && tmpFlag.equals("T") ){
+ modConstraintHash2Use = getModConstraintHash( thisLevelVertex, modConstraintHash );
+ }
+ else {
+ stoppedByASvcOrResourceModelElement = true;
+ }
+ // For the element-model for the widget at this level, record it's delete flag
+ tmpFlag = elementVtxForThisLevel.<String>property("new-data-del-flag").orElse(null);
+ }
+
+ String flag2Use = "F"; // by default we'll use "F" for the delete flag
+ if( ! stoppedByASvcOrResourceModelElement ){
+ // Since we haven't been stopped by a resource/service level "F", we can look at the lower level flag
+ if( thisHash.containsKey(thisGuysTrail) ){
+ // We've seen this spot in the topology before - do not override the delete flag if the older one is "F"
+ // We will only over-ride it if the old one was "T" and the new one is "F" (anything but "T")
+ String oldFlag = thisHash.get(thisGuysTrail);
+ if( oldFlag.equals("T") && (tmpFlag != null) && tmpFlag.equals("T") ){
+ // The old flag was "T" and the new flag is also "T"
+ flag2Use = "T";
+ }
+ else {
+ // the old flag was not "F" - so don't override it
+ flag2Use = "F";
+ }
+ }
+ else if( (tmpFlag != null) && tmpFlag.equals("T") ){
+ // We have not seen this one, so we can set it to "T" if that's what it is.
+ flag2Use = "T";
+ }
+ }
+
+ thisHash.put(thisGuysTrail, flag2Use);
+ if( ! stoppedByASvcOrResourceModelElement ){
+ // Since we haven't been stopped by a resource/service level "F", we will continue to
+ // go "down" and look at the elements pointed to so we can get their data.
+ Iterable <?> verts = elementVtxForThisLevel.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ HashMap <String,Object> elementHash = new HashMap<String, Object>();
+
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( connectToType != null && connectToType.equals("model-element") ){
+ // A nice, regular old model-element
+ elementHash.put(vid, tmpVert);
+ }
+ else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
+ // translate the constrained-element-set into a hash of model-element TitanVertex's
+ String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null);
+ if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){
+ // This constrained-element-set is being superseded by a different one
+ TitanVertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid);
+ elementHash = getNextStepElementsFromSet( replacementConstraintVert );
+ // Now that we've found and used the replacement constraint, we don't need to carry it along any farther
+ modConstraintHash.remove(constrainedElementSetUuid);
+ }
+ else {
+ elementHash = getNextStepElementsFromSet( tmpVert );
+ }
+ }
+ else {
+ String msg = " model element has [connectedTo] edge to improper nodeType= ["
+ + connectToType + "] trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
+ TitanVertex elVert = (TitanVertex)(entry.getValue());
+ String tmpElVid = elVert.id().toString();
+ String tmpElNT = getElementWidgetType( elVert, thisGuysTrail );
+ check4EdgeRule(tmpElNT, thisElementNodeType, dbMaps);
+ if( !vidsTraversed.contains(tmpElVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ HashMap <String, String> tmpHash = collectDeleteKeyHash( transId, fromAppId, graph,
+ elVert, thisGuysTrail,
+ currentHash, vidsTraversed, levelCounter, dbMaps, modConstraintHash2Use,
+ "", "" );
+ thisHash.putAll(tmpHash);
+ }
+ }
+ }
+ }
+ return thisHash;
+
+ } // End of collectDeleteKeyHash()
+
+
+ /**
+ * Gets the linkage connect node types.
+ *
+ * @param linkagePtList the linkage pt list
+ * @return the linkage connect node types
+ * @throws AAIException the AAI exception
+ */
+ public static HashSet <String> getLinkageConnectNodeTypes( ArrayList <String> linkagePtList )
+ throws AAIException {
+ // linkage points are a path from the top of a model to where we link in.
+ // This method wants to just bring back a list of distinct last items.
+ // Ie: for the input with these two: "pserver|lag-link|l-interface" and "pserver|p-interface|l-interface"
+ // it would just return a single item, "l-interface" since both linkage points end in that same node-type.
+
+ HashSet <String> linkPtSet = new HashSet <String> ();
+
+ if( linkagePtList == null ){
+ String detail = " Bad (null) linkagePtList passed to getLinkageConnectNodeTypes() ";
+ throw new AAIException("AAI_6125", detail);
+ }
+
+ for( int i = 0; i < linkagePtList.size(); i++ ){
+ String [] trailSteps = linkagePtList.get(i).split("\\|");
+ if( trailSteps == null || trailSteps.length == 0 ){
+ String detail = " Bad incomingTrail passed to getLinkageConnectNodeTypes(): [" + linkagePtList + "] ";
+ throw new AAIException("AAI_6125", detail);
+ }
+ String lastStepNT = trailSteps[trailSteps.length - 1];
+ linkPtSet.add(lastStepNT);
+ }
+
+ return linkPtSet;
+
+ }// End getLinkageConnectNodeTypes()
+
+
+ /**
+ * Collect topology 4 model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param modelElement vertex to collect for
+ * @param incomingTrail the incoming trail -- trail of nodeTypes/personnaInfo that got us here (this vertex) from the top
+ * @param currentMap the current map -- map that got us to this point (that we will use as the base of the map we will return)
+ * @param vidsTraversed the vids traversed -- ArrayList of vertexId's that we traversed to get to this point
+ * @param levelCounter the level counter
+ * @param dbMaps the db maps
+ * @param modConstraintHash the mod constraint hash
+ * @param overRideModelId the over ride model id
+ * @param overRideModelVersion the over ride model version
+ * @return Map of the topology
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> collectTopology4Model( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ Multimap <String,String> currentMap, ArrayList <String> vidsTraversed,
+ int levelCounter, DbMaps dbMaps, HashMap <String, TitanVertex> modConstraintHash,
+ String overRideModelId, String overRideModelVersion )
+ throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectTopology4Model");
+
+ Multimap <String, String> thisMap = ArrayListMultimap.create();
+ thisMap.putAll(currentMap);
+
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectTopology4Model() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+ String thisVid = thisLevelVertex.id().toString();
+ HashMap <String, TitanVertex> modConstraintHash2Use = null;
+
+
+ // If this element represents a resource or service model, then we will replace this element with
+ // the "top" element of that resource or service model. That model-element already points to its
+ // topology, so it will graft in that model's topology.
+ // EXCEPT - if this element defines "linkage-points" defined, then we need to do some extra
+ // processing for how we join to that model.
+
+ // Find out what widget-model (and thereby what aai-node-type) this element represents.
+ // Even if this element is pointing to a service or resource model, it must have a
+ // first element which is a single widget-type model.
+ String firstElementModelInfo = "";
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+ if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) && overRideModelId != null && !overRideModelId.equals("") ){
+ firstElementModelInfo = "," + overRideModelId + "," + overRideModelVersion;
+ }
+
+ vidsTraversed.add(thisVid);
+ TitanVertex elementVtxForThisLevel = null;
+ TitanVertex thisElementsModelVtx = getModelThatElementRepresents( thisLevelVertex, incomingTrail );
+ String subModelFirstModId = "";
+ String subModelFirstVersion = "";
+ String modInfo4Trail = "";
+ String modType = getModelType( thisElementsModelVtx, incomingTrail );
+ if( modType.equals("resource") || modType.equals("service") ){
+ // For an element that is referring to a resource or service model, we replace this
+ // this element with the "top" element for that resource/service model so that the
+ // topology of that resource/service model gets included in this topology.
+ // -- Note - since that top element of a service or resource model will point to a widget model,
+ // we have to track what modelId/version it really maps so we can make our recursive call
+ subModelFirstModId = thisElementsModelVtx.<String>property("model-id").orElse(null);
+ subModelFirstVersion = thisElementsModelVtx.<String>property("model-version").orElse(null);
+ modInfo4Trail = "," + subModelFirstModId + "," + subModelFirstVersion;
+ String modelUuid = thisElementsModelVtx.<String>property("model-name-version-id").orElse(null);
+ if( subModelFirstModId == null || subModelFirstModId.equals("") || subModelFirstVersion == null || subModelFirstVersion.equals("") ){
+ String msg = "Bad Model Definition: Bad model-id or model-version. Model UUID = " + modelUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6132");
+ throw new AAIException("AAI_6132", msg);
+ }
+ elementVtxForThisLevel = getTopElementForSvcOrResModel(thisElementsModelVtx);
+ modConstraintHash2Use = getModConstraintHash( thisLevelVertex, modConstraintHash );
+ }
+ else {
+ elementVtxForThisLevel = thisLevelVertex;
+ }
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType + firstElementModelInfo;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType + modInfo4Trail;
+ }
+
+ // Look at the elements pointed to at this level and add on their data
+ Iterable <?> verts = elementVtxForThisLevel.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String vid = tmpVert.id().toString();
+ HashMap <String,Object> elementHash = new HashMap<String, Object>();
+
+ String connectToType = tmpVert.<String>property("aai-node-type").orElse(null);
+ if( connectToType != null && connectToType.equals("model-element") ){
+ // A nice, regular old model-element
+ elementHash.put(vid, tmpVert);
+ }
+ else if( (connectToType != null) && connectToType.equals("constrained-element-set") ){
+ // translate the constrained-element-set into a hash of model-element TitanVertex's
+ String constrainedElementSetUuid = tmpVert.<String>property("constrained-element-set-uuid").orElse(null);
+ if( (modConstraintHash2Use != null) && modConstraintHash2Use.containsKey(constrainedElementSetUuid) ){
+ // This constrained-element-set is being superseded by a different one
+ TitanVertex replacementConstraintVert = modConstraintHash.get(constrainedElementSetUuid);
+ elementHash = getNextStepElementsFromSet( replacementConstraintVert );
+ // Now that we've found and used the replacement constraint, we don't need to carry it along any farther
+ modConstraintHash.remove(constrainedElementSetUuid);
+ }
+ else {
+ elementHash = getNextStepElementsFromSet( tmpVert );
+ }
+ }
+ else {
+ String msg = " model element has [connectedTo] edge to improper nodeType= ["
+ + connectToType + "] trail = [" + incomingTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ for( Map.Entry<String, Object> entry : elementHash.entrySet() ){
+ TitanVertex elVert = (TitanVertex)(entry.getValue());
+ String tmpElVid = elVert.id().toString();
+ String tmpElNT = getElementWidgetType( elVert, thisGuysTrail );
+ String tmpElStepName = getElementStepName( elVert, thisGuysTrail, dbMaps );
+
+ //ArrayList <String> linkagePtList = elVert.<ArrayList>property("linkage-points").orElse(null);
+ Object objVal = elVert.property("linkage-points").orElse(null);
+ ArrayList <String> linkagePtList = makeSureItsAnArrayList( objVal );
+
+ if( linkagePtList != null && !linkagePtList.isEmpty() ){
+ // This is as far as we can go, we will use the linkage point info to define the
+ // rest of this "trail"
+ for( int i = 0; i < linkagePtList.size(); i++ ){
+ Multimap<String, String> tmpMap = collectTopology4LinkagePoint( transId, fromAppId,
+ linkagePtList.get(i), thisGuysTrail, currentMap, dbMaps);
+ thisMap.putAll(tmpMap);
+ }
+ }
+ else {
+ check4EdgeRule(tmpElNT, thisElementNodeType, dbMaps);
+ thisMap.put(thisGuysTrail, tmpElStepName);
+ if( !vidsTraversed.contains(tmpElVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ Multimap<String, String> tmpMap = collectTopology4Model( transId, fromAppId, graph,
+ elVert, thisGuysTrail,
+ currentMap, vidsTraversed, levelCounter,
+ dbMaps, modConstraintHash2Use, subModelFirstModId, subModelFirstVersion );
+ thisMap.putAll(tmpMap);
+ }
+ else {
+ String msg = "Bad Model Definition: looping model-elements found at: [" + tmpElStepName + "]." ;
+ System.out.println( msg );
+ throw new AAIException("AAI_6132", msg);
+ }
+ }
+ }
+ }
+ return thisMap;
+
+ } // End of collectTopology4Model()
+
+
+ /**
+ * Check 4 edge rule.
+ *
+ * @param nodeTypeA the node type A
+ * @param nodeTypeB the node type B
+ * @param dbMaps the db maps
+ * @throws AAIException the AAI exception
+ */
+ public static void check4EdgeRule( String nodeTypeA, String nodeTypeB, DbMaps dbMaps ) throws AAIException {
+ // Throw an exception if there is no defined edge rule for this combination of nodeTypes in DbEdgeRules.
+ String fwdRuleKey = nodeTypeA + "|" + nodeTypeB;
+ String revRuleKey = nodeTypeB + "|" + nodeTypeA;
+ if( !DbEdgeRules.EdgeRules.containsKey(fwdRuleKey)
+ && !DbEdgeRules.EdgeRules.containsKey(revRuleKey) ){
+ // There's no EdgeRule for this -- find out if one of the nodeTypes is invalid or if
+ // they are valid, but there's just no edgeRule for them.
+ if( ! dbMaps.NodeProps.containsKey(nodeTypeA) ){
+ String emsg = " Unrecognized nodeType aa [" + nodeTypeA + "]\n";
+ throw new AAIException("AAI_6115", emsg);
+ }
+ else if( ! dbMaps.NodeProps.containsKey(nodeTypeB) ){
+ String emsg = " Unrecognized nodeType bb [" + nodeTypeB + "]\n";
+ throw new AAIException("AAI_6115", emsg);
+ }
+ else {
+ String msg = " No Edge Rule found for this pair of nodeTypes (order does not matter) ["
+ + nodeTypeA + "], [" + nodeTypeB + "].";
+ throw new AAIException("AAI_6120", msg);
+ }
+ }
+
+ }
+
+
+ /**
+ * Collect topology 4 linkage point.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param linkagePointStr -- Note it is in reverse order from where we connect to it.
+ * @param incomingTrail -- trail of nodeTypes that got us here (this vertex) from the top
+ * @param currentMap the current map -- that got us to this point (that we will use as the base of the map we will return)
+ * @param dbMaps the db maps
+ * @return Map of the topology
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> collectTopology4LinkagePoint( String transId, String fromAppId,
+ String linkagePointStr, String incomingTrail, Multimap <String,String> currentMap, DbMaps dbMaps )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectTopology4LinkagePoint");
+
+ Multimap <String, String> thisMap = ArrayListMultimap.create();
+ thisMap.putAll(currentMap);
+ String thisGuysTrail = incomingTrail;
+ // NOTE - "trails" can have multiple parts now since we track persona info for some.
+ // We just want to look at the node type info - which would be the piece
+ // before any commas (if there are any).
+ String [] trailSteps = incomingTrail.split("\\|");
+ if( trailSteps == null || trailSteps.length == 0 ){
+ String detail = " Bad incomingTrail passed to collectTopology4LinkagePoint(): [" + incomingTrail + "] ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", detail);
+ }
+ String lastStepString = trailSteps[trailSteps.length - 1];
+ String [] stepPieces = lastStepString.split(",");
+ String lastStepNT = stepPieces[0];
+ // It is assumed that the linkagePoint string will be a pipe-delimited string where each
+ // piece is an "aai-node-type". For now, the first thing to connect to is what is on the farthest right.
+ // Example: linkagePoint = "pserver|p-interface|l-interface" would mean that we're connecting to the l-interface
+ // but that after that, we connect to a p-interface followed by a pserver.
+ // It might have been more clear to define it in the other direction, but for now, that is it. (16-07)
+
+ String thisStepNT = "";
+ String [] linkageSteps = linkagePointStr.split("\\|");
+
+ if( linkageSteps == null || linkageSteps.length == 0 ){
+ String detail = " Bad linkagePointStr passed to collectTopology4LinkagePoint(): [" + linkagePointStr + "] ";
+ logline.add("emsg", detail);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", detail);
+ }
+
+ for( int i=(linkageSteps.length - 1); i >= 0; i-- ){
+ thisStepNT = linkageSteps[i];
+ check4EdgeRule(lastStepNT, thisStepNT, dbMaps);
+ thisMap.put(thisGuysTrail, thisStepNT);
+ thisGuysTrail = thisGuysTrail + "|" + thisStepNT;
+ lastStepNT = thisStepNT;
+ }
+
+ return thisMap;
+
+ } // End of collectTopology4LinkagePoint()
+
+
+
+ /**
+ * Gets the next step elements from set.
+ *
+ * @param constrElemSetVtx the constr elem set vtx
+ * @return Hash of the set of model-elements this set represents
+ * @throws AAIException the AAI exception
+ */
+ public static HashMap <String,Object> getNextStepElementsFromSet( TitanVertex constrElemSetVtx )
+ throws AAIException {
+ // Take a constrained-element-set and figure out the total set of all the possible elements that it
+ // represents and return them as a Hash.
+
+ HashMap <String,Object> retElementHash = new HashMap<String, Object>();
+
+ if( constrElemSetVtx == null ){
+ String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx ";
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ String constrNodeType = constrElemSetVtx.<String>property("aai-node-type").orElse(null);
+ String constrElemSetUuid = constrElemSetVtx.<String>property("constrained-element-set-uuid").orElse(null);
+ if( constrNodeType == null || !constrNodeType.equals("constrained-element-set") ){
+ String msg = " getNextStepElementsFromSet() called with wrong type model: [" + constrNodeType + "]. ";
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ ArrayList <TitanVertex> choiceSetVertArray = new ArrayList<TitanVertex>();
+
+ Iterable <?> choiceSetVerts = constrElemSetVtx.query().direction(Direction.OUT).labels("uses").vertices();
+ Iterator <?> vertI = choiceSetVerts.iterator();
+ int setCount = 0;
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex choiceSetVertex = (TitanVertex) vertI.next();
+ String constrSetType = choiceSetVertex.<String>property("aai-node-type").orElse(null);
+ if( constrSetType != null && constrSetType.equals("element-choice-set") ){
+ choiceSetVertArray.add(choiceSetVertex);
+ setCount++;
+ }
+ }
+
+ if( setCount == 0 ){
+ String msg = "No element-choice-set found under constrained-element-set-uuid = " + constrElemSetUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ // Loop through each choice-set and grab the model-elements
+ for( int i = 0; i < setCount; i++ ){
+ Iterable <?> modelElemVerts = (choiceSetVertArray.get(i)).query().direction(Direction.OUT).labels("has").vertices();
+ Iterator <?> mVertI = modelElemVerts.iterator();
+ int elCount = 0;
+ while( mVertI != null && mVertI.hasNext() ){
+ TitanVertex tmpElVertex = (TitanVertex) mVertI.next();
+ String elNodeType = tmpElVertex.<String>property("aai-node-type").orElse(null);
+ if( elNodeType != null && elNodeType.equals("model-element") ){
+ String tmpVid = tmpElVertex.id().toString();
+ retElementHash.put(tmpVid, tmpElVertex);
+ elCount++;
+ }
+ else {
+ // unsupported node type found for this choice-set
+ String msg = "Unsupported nodeType (" + elNodeType
+ + ") found under choice-set under constrained-element-set-uuid = " + constrElemSetUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+ }
+
+ if( elCount == 0 ){
+ String msg = "No model-elements found in choice-set under constrained-element-set-uuid = " + constrElemSetUuid;
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ }
+ return retElementHash;
+
+ } // End of getNextStepElementsFromSet()
+
+
+
+ /**
+ * Gen topo map 4 named Q.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param queryVertex the query vertex
+ * @param namedQueryUuid the named query uuid
+ * @return MultiMap of valid next steps for each potential query-element
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> genTopoMap4NamedQ( String transId, String fromAppId,
+ TitanTransaction graph, TitanVertex queryVertex, String namedQueryUuid )
+ throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "genTopoMap4NamedQ");
+
+ if( graph == null ){
+ String emsg = "null graph object passed to genTopoMap4NamedQ()\n";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6101");
+ throw new AAIException("AAI_6101", emsg);
+ }
+
+ if( queryVertex == null ){
+ String msg = " null queryVertex passed to genTopoMap4NamedQ() ";
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ Multimap <String, String> initialEmptyMap = ArrayListMultimap.create();
+ ArrayList <String> vidsTraversed = new ArrayList <String> ();
+
+ TitanVertex firstElementVertex = null;
+ Iterable <?> verts = queryVertex.query().direction(Direction.OUT).labels("startsWith").vertices();
+ Iterator <?> vertI = verts.iterator();
+ int elCount = 0;
+ while( vertI != null && vertI.hasNext() ){
+ elCount++;
+ firstElementVertex = (TitanVertex) vertI.next();
+ }
+
+ if( elCount > 1 ){
+ String msg = "Illegal query defined: More than one first element defined for = " + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ if( firstElementVertex == null ){
+ String msg = "Could not find first query element = " + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6144");
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ TitanVertex modVtx = getModelThatElementRepresents( firstElementVertex, "" );
+ String modelType = getModelType( modVtx, "" );
+ if( ! modelType.equals("widget") ){
+ String msg = "Bad Named Query Definition: First element must correspond to a widget type model. Named Query UUID = "
+ + namedQueryUuid;
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_6133");
+ throw new AAIException("AAI_6133", msg);
+ }
+
+ Multimap <String, String> collectedMap = collectTopology4NamedQ( transId, fromAppId, graph,
+ firstElementVertex, "",
+ initialEmptyMap, vidsTraversed, 0);
+
+ return collectedMap;
+
+ } // End of genTopoMap4NamedQ()
+
+
+
+ /**
+ * Collect topology 4 named Q.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param thisLevelVertex the this level vertex
+ * @param levelCounter the level counter
+ * @return resultSet
+ * @throws AAIException the AAI exception
+ */
+ public static Multimap<String, String> collectTopology4NamedQ( String transId, String fromAppId, TitanTransaction graph,
+ TitanVertex thisLevelVertex, String incomingTrail,
+ Multimap <String,String> currentMap, ArrayList <String> vidsTraversed, int levelCounter )
+ throws AAIException {
+
+ levelCounter++;
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", transId, fromAppId, "collectTopology4NamedQ");
+
+ Multimap <String, String> thisMap = ArrayListMultimap.create();
+ thisMap.putAll(currentMap);
+
+ String thisVid = thisLevelVertex.id().toString();
+ if( levelCounter > maxLevels ) {
+ String emsg = "collectModelStructure() has looped across more levels than allowed: " + maxLevels + ". ";
+ logline.add("emsg", emsg);
+ aaiLogger.info(logline, false, "AAI_6125");
+ throw new AAIException("AAI_6125", emsg);
+ }
+ String thisGuysTrail = "";
+
+ // find out what widget-model (and thereby what aai-node-type) this element represents
+ String thisElementNodeType = getElementWidgetType( thisLevelVertex, incomingTrail );
+
+ if( incomingTrail.equals("") ){
+ // This is the first one
+ thisGuysTrail = thisElementNodeType;
+ }
+ else {
+ thisGuysTrail = incomingTrail + "|" + thisElementNodeType;
+ }
+ vidsTraversed.add(thisVid);
+
+ // Look at the elements pointed to at this level and add on their data
+ Iterable <?> verts = thisLevelVertex.query().direction(Direction.OUT).labels("connectsTo").vertices();
+ Iterator <?> vertI = verts.iterator();
+
+ while( vertI != null && vertI.hasNext() ){
+ TitanVertex tmpVert = (TitanVertex) vertI.next();
+ String tmpVid = tmpVert.id().toString();
+ String tmpElNT = getElementWidgetType( tmpVert, thisGuysTrail );
+ thisMap.put(thisGuysTrail, tmpElNT);
+ if( !vidsTraversed.contains(tmpVid) ){
+ // This is one we would like to use - so we'll recursively get it's result set to add to ours
+ Multimap<String, String> tmpMap = collectTopology4NamedQ( transId, fromAppId, graph,
+ tmpVert, thisGuysTrail,
+ currentMap, vidsTraversed, levelCounter);
+ thisMap.putAll(tmpMap);
+ }
+ }
+
+ return thisMap;
+
+ } // End of collectTopology4NamedQ()
+
+
+ /**
+ * Gets the model that element represents.
+ *
+ * @param elementVtx the element vtx
+ * @param elementTrail the element trail
+ * @return the model that element represents
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getModelThatElementRepresents( TitanVertex elementVtx, String elementTrail )
+ throws AAIException {
+
+ // Get the model that an element represents
+ TitanVertex modVtx = null;
+ Iterable <?> mverts = elementVtx.query().direction(Direction.OUT).labels("isA").vertices();
+ Iterator <?> mvertI = mverts.iterator();
+ int modCount = 0;
+ while( mvertI != null && mvertI.hasNext() ){
+ modCount++;
+ modVtx = (TitanVertex) mvertI.next();
+ }
+
+ if( modCount > 1 ){
+ String msg = "Illegal element defined: More than one model pointed to by a single element at [" +
+ elementTrail + "].";
+ throw new AAIException("AAI_6125", msg);
+ }
+
+ if( modVtx == null ){
+ String msg = "Bad model or named-query definition: Could not find model for element. ";
+ if( !elementTrail.equals("") ){
+ msg = "Bad model or named-query definition: Could not find model for element at [" + elementTrail + "].";
+ }
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return modVtx;
+
+ }// getModelThatElementRepresents()
+
+
+ /**
+ * Gets the model type.
+ *
+ * @param modelVtx the model vtx
+ * @param elementTrail the element trail
+ * @return the model type
+ * @throws AAIException the AAI exception
+ */
+ public static String getModelType( TitanVertex modelVtx, String elementTrail )
+ throws AAIException {
+
+ // Get the model-type for a vertex that should be pointing to a model.
+
+ if( modelVtx == null ){
+ String msg = " null modelVtx passed to getModelType() ";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String modelType = modelVtx.<String>property("model-type").orElse(null);
+ if( (modelType == null) || modelType.equals("") ){
+ String msg = "Could not find model-type for model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ if( !modelType.equals("widget") && !modelType.equals("resource") && !modelType.equals("service") ){
+ String msg = "Unrecognized model-type, [" + modelType + "] for model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return modelType;
+
+ }// getModelType()
+
+
+ /**
+ * Gets the element step name.
+ *
+ * @param elementVtx the element vtx
+ * @param elementTrail the element trail
+ * @param dbMaps the db maps
+ * @return the element step name
+ * @throws AAIException the AAI exception
+ */
+ public static String getElementStepName( TitanVertex elementVtx, String elementTrail, DbMaps dbMaps)
+ throws AAIException {
+
+ // Get the "step name" for either a model-element or a named-query-element.
+ // Step names look like this for widget-models: "aai-node-type"
+ // Step names look like this for resource/service models: "aai-node-type,model-id,model-version"
+ // NOTE -- if the element points to a resource or service model, then we'll return the
+ // widget-type of the first element (crown widget) for that model.
+ String thisElementNodeType = "?";
+
+ TitanVertex modVtx = getModelThatElementRepresents( elementVtx, elementTrail );
+ String modelType = getModelType( modVtx, elementTrail );
+
+ if( modelType == null ){
+ String msg = " Null modelType passed to getElementWidgetType(). elementTrail = [" + elementTrail + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ if( modelType.equals("widget") ){
+ // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type
+ thisElementNodeType = modVtx.<String>property("model-name").orElse(null);
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+ return thisElementNodeType;
+ }
+ else if( modelType.equals("resource") || modelType.equals("service") ){
+ String modelId = modVtx.<String>property("model-id").orElse(null);
+ String modelVer = modVtx.<String>property("model-version").orElse(null);
+ TitanVertex relatedTopElementModelVtx = getTopElementForSvcOrResModel( modVtx );
+ TitanVertex relatedModelVtx = getModelThatElementRepresents( relatedTopElementModelVtx, elementTrail );
+ thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null);
+
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ String stepName = "";
+ if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) ){
+ // This nodeType that this resource or service model refers to does support persona-related fields, so
+ // we will use model-id and model-version as part of the step name.
+ stepName = thisElementNodeType + "," + modelId + "," + modelVer;
+ }
+ else {
+ stepName = thisElementNodeType;
+ }
+ return stepName;
+ }
+ else {
+ String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ }// getElementStepName()
+
+
+
+ /**
+ * Node type supports persona.
+ *
+ * @param nodeType the node type
+ * @param dbMaps the db maps
+ * @return the boolean
+ * @throws AAIException the AAI exception
+ */
+ public static Boolean nodeTypeSupportsPersona(String nodeType, DbMaps dbMaps)
+ throws AAIException {
+
+ if( nodeType == null || nodeType.equals("") ){
+ return false;
+ }
+
+ // Return true if this type of node supports the properties: "persona-model-id" and "persona-model-version"
+ if( ! dbMaps.NodeProps.containsKey(nodeType) ){
+ String emsg = " Unrecognized nodeType [" + nodeType + "]\n";
+ throw new AAIException("AAI_6115", emsg);
+ }
+
+ Collection <String> props4ThisNT = dbMaps.NodeProps.get(nodeType);
+ if( !props4ThisNT.contains("persona-model-id") || !props4ThisNT.contains("persona-model-version") ){
+ return false;
+ }
+ else {
+ return true;
+ }
+
+ }// nodeTypeSupportsPersona()
+
+
+ /**
+ * Gets the element widget type.
+ *
+ * @param elementVtx the element vtx
+ * @param elementTrail the element trail
+ * @return the element widget type
+ * @throws AAIException the AAI exception
+ */
+ public static String getElementWidgetType( TitanVertex elementVtx, String elementTrail )
+ throws AAIException {
+
+ // Get the associated node-type for the model pointed to by either a
+ // model-element or a named-query-element.
+ // NOTE -- if the element points to a resource or service model, then we'll return the
+ // widget-type of the first element (crown widget) for that model.
+ TitanVertex modVtx = getModelThatElementRepresents( elementVtx, elementTrail );
+ String thisElementNodeType = getModelWidgetType( modVtx, elementTrail );
+ return thisElementNodeType;
+
+ }// End getElementWidgetType()
+
+
+ /**
+ * Gets the mod name ver id.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modId the mod id
+ * @param modVersion the mod version
+ * @return the mod name ver id
+ * @throws AAIException the AAI exception
+ */
+ public static String getModNameVerId(String transId, String fromAppId, TitanTransaction graph,
+ String modId, String modVersion)
+ throws AAIException {
+
+ String modelNameVersionId = "";
+
+ // Given a "model-id" and "model-version", find the unique key ("model-name-version-id") for this model
+ if( modId == null || modId.equals("") || modVersion == null || modVersion.equals("") ){
+ String emsg = " Bad model-id or model-version passed to getModNameVerId(): ["
+ + modId + "], [" + modVersion + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-id",modId).has("model-version",modVersion).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. (model-id = [" + modId +
+ "], model-version = [" + modVersion + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ int count = 0;
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ count++;
+ TitanVertex tmpModVtx = (TitanVertex) modVertsIter.next();
+ modelNameVersionId = tmpModVtx.<String>property("model-name-version-id").orElse(null);
+ if( count > 1 ){
+ String emsg = "More than one model-name-version-id found for passed params to getModNameVerId(): ["
+ + modId + "], [" + modVersion + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ }
+ }
+
+ if( modelNameVersionId.equals("") ){
+ String emsg = "Could not find a model-name-version-id for passed params to getModNameVerId(): ["
+ + modId + "], [" + modVersion + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return modelNameVersionId;
+ }// End getModNameVerId()
+
+
+ /**
+ * Gets the model using UUID.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @return the model using UUID
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getModelUsingUUID( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId )
+ throws AAIException {
+
+ // Given a "model-name-version-id", find the model vertex that this uniquely maps to
+ if( modelNameVersionId == null || modelNameVersionId.equals("") ){
+ String emsg = " Bad modelNameVersionId passed to getModNameVerId(): ["
+ + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ TitanVertex modelVtx = null;
+ int count = 0;
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-name-version-id",modelNameVersionId).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. model-name-version-id = [" + modelNameVersionId +
+ "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ count++;
+ modelVtx = (TitanVertex) modVertsIter.next();
+ if( count > 1 ){
+ String emsg = "More than one model record found for model-name-version-id = ["
+ + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ }
+ }
+
+ if( count == 0 ){
+ String emsg = "No Model record found for model-name-version-id = ["
+ + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return modelVtx;
+ }// End getModelUsingUUID()
+
+
+ /**
+ * Gets the model using persona info.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param personaModId the persona mod id
+ * @param personaModVer the persona mod ver
+ * @return the model using persona info
+ * @throws AAIException the AAI exception
+ */
+ public static TitanVertex getModelUsingPersonaInfo( String transId, String fromAppId, TitanTransaction graph,
+ String personaModId, String personaModVer )
+ throws AAIException {
+
+ // Given a model-id and model-version, find the model vertex that this uniquely maps to
+ if( personaModId == null || personaModId.equals("") ){
+ String emsg = " Bad personaModId passed to getModelUsingPersonaInfo(): ["
+ + personaModId + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+ if( personaModVer == null || personaModVer.equals("") ){
+ String emsg = " Bad personaModVer passed to getModelUsingPersonaInfo(): ["
+ + personaModVer + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ TitanVertex modelVtx = null;
+ int modCount = 0;
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-id",personaModId).has("model-version",personaModVer).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. persona-model-id = [" +
+ personaModId + "], persona-model-version = [" + personaModVer + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ modCount++;
+ modelVtx = (TitanVertex) modVertsIter.next();
+ if( modCount > 1 ){
+ String emsg = "More than one model record found for persona-model-id = [" +
+ personaModId + "], persona-model-version = [" + personaModVer + "]. ";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ }
+ }
+
+ if( modCount == 0 ){
+ String emsg = "No Model record found for persona-model-id = [" +
+ personaModId + "], persona-model-version = [" + personaModVer + "]. ";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return modelVtx;
+ }// End getModelUsingPersonaInfo()
+
+
+
+ /**
+ * Gets the models using name.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelName the model name
+ * @return the models using name
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <TitanVertex> getModelsUsingName( String transId, String fromAppId, TitanTransaction graph,
+ String modelName )
+ throws AAIException {
+
+ // Given a "model-name", find the model vertices that this maps to
+ if( modelName == null || modelName.equals("") ){
+ String emsg = " Bad modelName passed to getModelsUsingName(): ["
+ + modelName + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ ArrayList <TitanVertex> retVtxArr = new ArrayList <TitanVertex> ();
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-name",modelName).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. model-name = [" +
+ modelName + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ TitanVertex tmpModelVtx = (TitanVertex) modVertsIter.next();
+ retVtxArr.add(tmpModelVtx);
+ }
+ }
+
+ return retVtxArr;
+
+ }// End getModelsUsingName()
+
+
+ /**
+ * Gets the model uuids using name.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelName the model name
+ * @return the model uuids using name
+ * @throws AAIException the AAI exception
+ */
+ public static ArrayList <String> getModelUuidsUsingName( String transId, String fromAppId, TitanTransaction graph,
+ String modelName )
+ throws AAIException {
+
+ // Given a modelName find the models maps to
+ if( modelName == null || modelName.equals("") ){
+ String emsg = " Bad modelName passed to getModelUuidsUsingName(): ["
+ + modelName + "]\n";
+ throw new AAIException("AAI_6118", emsg);
+ }
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+
+ Iterable <?> modVerts = null;
+ modVerts = graph.query().has("aai-node-type","model").has("model-name",modelName).vertices();
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. model-name = [" +
+ modelName + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ TitanVertex modelVtx = (TitanVertex) modVertsIter.next();
+ String tmpUuid = modelVtx.<String>property("model-name-version-id").orElse(null);
+ if( (tmpUuid != null) && !tmpUuid.equals("") && !retArr.contains(tmpUuid) ){
+ retArr.add(tmpUuid);
+ }
+ }
+ }
+
+ if( retArr.isEmpty() ){
+ String emsg = "No Model record found for model-name = ["
+ + modelName + "]\n";
+ throw new AAIException("AAI_6132", emsg);
+ }
+
+ return retArr;
+ }// End getModelUuidsUsingName()
+
+
+ /**
+ * Gets the model top widget type.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @param modelId the model id
+ * @param modelName the model name
+ * @return the model top widget type
+ * @throws AAIException the AAI exception
+ */
+ public static String getModelTopWidgetType( String transId, String fromAppId, TitanTransaction graph,
+ String modelNameVersionId, String modelId, String modelName )
+ throws AAIException {
+
+ // Could be given a model's key info, OR, just a (non-unique) modelId.
+ // Either way, they should only map to one single "top" node-type for the first element.
+
+ String nodeType = "?";
+ Iterable <?> modVerts = null;
+ if( modelNameVersionId != null && !modelNameVersionId.equals("") ){
+ modVerts = graph.query().has("aai-node-type","model").has("model-name-version-id",modelNameVersionId).vertices();
+ }
+ else if( modelId != null && !modelId.equals("") ){
+ modVerts = graph.query().has("aai-node-type","model").has("model-id",modelId).vertices();
+ }
+ else if( modelName != null && !modelName.equals("") ){
+ modVerts = graph.query().has("aai-node-type","model").has("model-name",modelName).vertices();
+ }
+ else {
+ String msg = "Neither modelNameVersionId, modelId, nor modelName passed to: getModelTopWidgetType() ";
+ throw new AAIException("AAI_6120", msg);
+ }
+
+ if( modVerts == null ){
+ String emsg = "Model record(s) could not be found for model data passed. (modelId = [" + modelId +
+ "], modelNameVersionId = [" + modelNameVersionId + "]\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ else {
+ String lastNT = "";
+ Iterator <?> modVertsIter = modVerts.iterator();
+ while( modVertsIter.hasNext() ){
+ TitanVertex tmpModVtx = (TitanVertex) modVertsIter.next();
+ String tmpNT = getModelWidgetType( tmpModVtx, "" );
+ if( !lastNT.equals("") ){
+ if( !lastNT.equals(tmpNT) ){
+ String emsg = "Different top-node-types (" + tmpNT + ", " + lastNT
+ + ") found for model data passed. (" +
+ " modelNameVersionId = [" + modelNameVersionId +
+ "], modelId = [" + modelId +
+ "], modelName = [" + modelName +
+ "])\n";
+ throw new AAIException("AAI_6114", emsg);
+ }
+ }
+ lastNT = tmpNT;
+ nodeType = tmpNT;
+ }
+ }
+
+ return nodeType;
+
+ }// End getModelTopWidgetType()
+
+
+ /**
+ * Gets the model widget type.
+ *
+ * @param modVtx the mod vtx
+ * @param elementTrail the element trail
+ * @return the model widget type
+ * @throws AAIException the AAI exception
+ */
+ public static String getModelWidgetType( TitanVertex modVtx, String elementTrail )
+ throws AAIException {
+ // Get the associated node-type for a model.
+ // NOTE -- if the element points to a resource or service model, then we'll return the
+ // widget-type of the first element (crown widget) for that model.
+
+ String modelType = getModelType( modVtx, elementTrail );
+ if( modelType == null ){
+ String msg = " Null modelType passed to getElementWidgetType(). elementTrail = [" + elementTrail + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ String thisElementNodeType = "?";
+ if( modelType.equals("widget") ){
+ // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type
+ thisElementNodeType = modVtx.<String>property("model-name").orElse(null);
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ }
+ else if( modelType.equals("resource") || modelType.equals("service") ){
+ TitanVertex relatedTopElementModelVtx = getTopElementForSvcOrResModel( modVtx );
+ TitanVertex relatedModelVtx = getModelThatElementRepresents( relatedTopElementModelVtx, elementTrail );
+ thisElementNodeType = relatedModelVtx.<String>property("model-name").orElse(null);
+ if( (thisElementNodeType == null) || thisElementNodeType.equals("") ){
+ String msg = "Could not find model-name for the widget model pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+ }
+ else {
+ String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "].";
+ throw new AAIException("AAI_6132", msg);
+ }
+
+ return thisElementNodeType;
+
+ }// getModelWidgetType()
+
+
+ /**
+ * Validate model.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param modelNameVersionId the model name version id
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ public static void validateModel(String transId, String fromAppId, TitanTransaction graph, String modelNameVersionId, String apiVersion )
+ throws AAIException{
+
+ // Note - this will throw an exception if the model either can't be found, or if
+ // we can't figure out its topology map.
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+ propHash.put( "model-name-version-id", modelNameVersionId );
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ TitanVertex modelVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "model", propHash, null, apiVersion);
+ if( modelVtx == null ){
+ String msg = " Could not find model with modelNameVersionId = [" + modelNameVersionId + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ Multimap<String, String> topoMap = ModelBasedProcessing.genTopoMap4Model( transId, fromAppId, graph,
+ modelVtx, modelNameVersionId, dbMaps );
+ //String msg = " model [" + modelNameVersionId + "] topo multiMap looks like: \n[" + topoMap + "]";
+ //System.out.println("INFO -- " + msg );
+ }
+ return;
+
+ }// End validateModel()
+
+
+ /**
+ * Validate named query.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param namedQueryUuid the named query uuid
+ * @param apiVersion the api version
+ * @throws AAIException the AAI exception
+ */
+ public static void validateNamedQuery(String transId, String fromAppId, TitanTransaction graph, String namedQueryUuid, String apiVersion )
+ throws AAIException{
+
+ // Note - this will throw an exception if the named query either can't be found, or if
+ // we can't figure out its topology map.
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+ propHash.put( "named-query-uuid", namedQueryUuid );
+
+ TitanVertex modelVtx = DbMeth.getUniqueNode( transId, fromAppId, graph, "model", propHash, null, apiVersion);
+ if( modelVtx == null ){
+ String msg = " Could not find model with namedQueryUuid = [" + namedQueryUuid + "].";
+ throw new AAIException("AAI_6114", msg);
+ }
+ else {
+ Multimap<String, String> topoMap = ModelBasedProcessing.genTopoMap4NamedQ( "junkTransId", "junkFromAppId",
+ graph, modelVtx, namedQueryUuid );
+ //String msg = " namedQuery [" + namedQueryUuid + "] topo multiMap looks like: \n[" + topoMap + "]";
+ //System.out.println("INFO -- " + msg );
+ }
+ return;
+
+ }// End validateNamedQuery()
+
+
+ public static ArrayList <String> makeSureItsAnArrayList( Object objVal ){
+ // We're sometimes getting a String back on db properties that should be ArrayList<String>
+ // Need to translate them into ArrayLists sometimes...
+
+ ArrayList <String> retArrList = new ArrayList<String>();
+ if( objVal != null ){
+ String className = objVal.getClass().getSimpleName();
+ if( className.equals("ArrayList") ){
+ retArrList = (ArrayList<String>)objVal;
+ }
+ else if( className.equals("String") ){
+ String listString = (String) objVal;
+ listString = listString.replace(" ", "");
+ listString = listString.replace("[", "");
+ listString = listString.replace("]", "");
+ String [] pieces = listString.split(",");
+ if( pieces != null && pieces.length > 0 ){
+ for( int i = 0; i < pieces.length; i++ ){
+ retArrList.add(pieces[i]);
+ }
+ }
+ }
+ }
+
+ return retArrList;
+ }
+
+
+
+ /**
+ * Show result set.
+ *
+ * @param resSet the res set
+ * @param levelCount the level count
+ */
+ public static void showResultSet( ResultSet resSet, int levelCount ) {
+
+ levelCount++;
+ for( int i= 1; i <= levelCount; i++ ){
+ System.out.print("-");
+ }
+ if( resSet.vert == null ){
+ return;
+ }
+ String nt = resSet.vert.<String>property("aai-node-type").orElse(null);
+ System.out.print( "[" + nt + "] ");
+ String propsStr = "";
+
+ //propsStr = propsStr + " newDataDelFlag = " + resSet.getNewDataDelFlag() + ", trail = " + resSet.getLocationInModelSubGraph();
+ //propsStr = propsStr + "limitDesc = [" + resSet.getPropertyLimitDesc() + "]";
+ propsStr = propsStr + " trail = " + resSet.getLocationInModelSubGraph();
+
+ HashMap <String,Object> overrideHash = resSet.getPropertyOverRideHash();
+ if( overrideHash != null && !overrideHash.isEmpty() ){
+ for( Map.Entry<String, Object> entry : overrideHash.entrySet() ){
+ String propName = entry.getKey();
+ Object propVal = entry.getValue();
+ propsStr = propsStr + " [" + propName + " = " + propVal + "]";
+ }
+ }
+ else {
+ Iterator<VertexProperty<Object>> pI = resSet.vert.properties();
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ if( ! tp.key().startsWith("aai")
+ && ! tp.key().equals("source-of-truth")
+ //&& ! tp.key().equals("resource-version")
+ && ! tp.key().startsWith("last-mod")
+ )
+ {
+ propsStr = propsStr + " [" + tp.key() + " = " + tp.value() + "]";
+ }
+ }
+ }
+ // Show the "extra" lookup values too
+ HashMap <String,Object> extraPropHash = resSet.getExtraPropertyHash();
+ if( extraPropHash != null && !extraPropHash.isEmpty() ){
+ for( Map.Entry<String, Object> entry : extraPropHash.entrySet() ){
+ String propName = entry.getKey();
+ Object propVal = entry.getValue();
+ propsStr = propsStr + " [" + propName + " = " + propVal.toString() + "]";
+ }
+ }
+
+ System.out.println( propsStr );
+
+ if( !resSet.subResultSet.isEmpty() ){
+ ListIterator<ResultSet> listItr = resSet.subResultSet.listIterator();
+ while( listItr.hasNext() ){
+ showResultSet( listItr.next(), levelCount );
+ }
+ }
+
+ }// end of showResultSet()
+
+
+}
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java
new file mode 100644
index 0000000..6d24cb3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java
@@ -0,0 +1,321 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.att.eelf.configuration.Configuration;
+import com.thinkaurelius.titan.core.PropertyKey;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanProperty;
+import com.thinkaurelius.titan.core.TitanVertex;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+
+
+public class PropertyNameChange {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ // NOTE -- We're just working with properties that are used for NODES for now.
+
+ TitanGraph graph = null;
+ TitanManagement graphMgt = null;;
+ Boolean preserveData = true;
+ String propName = "";
+ String targetPropName = "";
+ String targetNodeType = "";
+ String skipCommit = "";
+ boolean noCommit = false;
+
+
+ String usageString = "Usage: PropertyNameChange propertyName targetPropertyName nodeType(or NA) skipCommit(true|false) \n";
+ if( args.length != 4 ){
+ String emsg = "Four Parameters are required. \n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ else {
+ propName = args[0];
+ targetPropName = args[1];
+ targetNodeType = args[2];
+ skipCommit = args[3];
+ if ( skipCommit.toLowerCase().equals("true"))
+ noCommit = true;
+ }
+
+ if( propName.equals("") ){
+ String emsg = "Bad parameter - propertyName cannot be empty. \n" + usageString;
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+
+
+ try {
+ AAIConfig.init();
+ ErrorLogHelper.loadProperties();
+ }
+ catch( Exception ae ){
+ String emsg = "Problem with either AAIConfig.init() or ErrorLogHelper.LoadProperties(). ";
+ System.out.println( emsg + "[" + ae.getMessage() + "]");
+ System.exit(1);
+ }
+
+
+ System.out.println(">>> Processing will begin in 5 seconds (unless interrupted). <<<");
+ try {
+ // Give them a chance to back out of this
+ Thread.sleep(5000);
+ } catch ( java.lang.InterruptedException ie) {
+ System.out.println( " DB Schema Update has been aborted. ");
+ System.exit(1);
+ }
+
+ try {
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+ if( graph == null ){
+ String emsg = "Not able to get a graph object in SchemaMod.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ // Make sure this property is in the DB.
+ graphMgt = graph.openManagement();
+ if( graphMgt == null ){
+ String emsg = "Not able to get a graph Management object in SchemaMod.java\n";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ PropertyKey origPropKey = graphMgt.getPropertyKey(propName);
+ if( origPropKey == null ){
+ String emsg = "The propName = [" + propName + "] is not defined in our graph. ";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ origPropKey = graphMgt.getPropertyKey(targetPropName);
+ if( origPropKey == null ){
+ String emsg = "The targetPropName = [" + targetPropName + "] is not defined in our graph. ";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+
+ if ( !targetNodeType.equals("NA")) {
+ if ( graphMgt.getVertexLabel(targetNodeType) == null ) {
+ String emsg = "The targetNodeType = [" + targetNodeType + "] is not defined in our graph. ";
+ System.out.println( emsg );
+ System.exit(1);
+ }
+ }
+
+ // For each node that has this property, update the new from the old and then remove the
+ // old property from that node
+ Iterable <Vertex> verts = null;
+ int vtxCount = 0;
+ String label;
+ long longId;
+
+ int propertyCount;
+
+ Iterator<VertexProperty<Object>> titanProperties = null;
+
+ VertexProperty<Object> tmpProperty = null;
+ Object origVal;
+ Object targetVal;
+
+ if ( targetNodeType.equals("NA")) {
+ verts= graph.query().has(propName).vertices();
+ Iterator <Vertex> it = verts.iterator();
+
+ while( it.hasNext() ){
+
+ TitanVertex tmpVtx = (TitanVertex)it.next();
+ String tmpVid = tmpVtx.id().toString();
+
+ //System.out.println("Show what we have in the vertex before trying to do an update...");
+ //ArrayList <String> retArr = DbMeth.showPropertiesForNode("junkTransId", "junkFromAppId", tmpVtx);
+ //for( String info : retArr ){ System.out.println(info); }
+
+ origVal = tmpVtx.<Object>property(propName).orElse(null);
+ targetVal = tmpVtx.<Object>property(targetPropName).orElse(null);
+
+ label = tmpVtx.label();
+ longId = tmpVtx.longId();
+
+ if ( targetVal != null ) {
+ System.out.println( "vertex [" + label + "] id " + tmpVid + " has " + targetPropName +
+ " with value " + targetVal + ", skip adding with value " + origVal);
+ continue;
+ }
+ vtxCount++;
+ titanProperties = tmpVtx.properties(); // current properties
+
+ propertyCount = 0;
+
+ while( titanProperties.hasNext() ){
+
+ tmpProperty = titanProperties.next();
+
+ if ( propertyCount == 0 )
+ System.out.print( "adding to [" + label + "] vertex id " + tmpVid + " with existing properties " +
+ tmpProperty.toString() );
+ else
+ System.out.print(", " + tmpProperty.toString());
+ ++propertyCount;
+ }
+
+ if ( propertyCount > 0 ) {
+ System.out.println("");
+
+ tmpVtx.property(targetPropName,origVal);
+ System.out.println("INFO -- just did the add using " + longId +
+ " with label " + label + "] and updated it with the orig value (" +
+ origVal.toString() + ")");
+ titanProperties = tmpVtx.properties(); // current properties
+ propertyCount = 0;
+
+
+ while( titanProperties.hasNext() ){
+ tmpProperty = titanProperties.next();
+ if ( propertyCount == 0 )
+ System.out.print( "new property list for [" + label + "] vertex id " + tmpVid + " with existing properties " +
+ tmpProperty.toString() );
+ else
+ System.out.print(", " + tmpProperty.toString());
+ ++propertyCount;
+ }
+
+ if ( propertyCount > 0 )
+ System.out.println("");
+ }
+ }
+ } else {
+ // targetNodeType is NA
+
+ verts= graph.query().has("aai-node-type", targetNodeType).vertices();
+ if( verts != null ){
+ // We did find some matching vertices
+ Iterator <?> it = verts.iterator();
+ Object propVal;
+ while( it.hasNext() ){
+ TitanVertex v = (TitanVertex)it.next();
+ label = v.label();
+ longId = v.longId();
+ targetVal = v.<Object>property(targetPropName).orElse(null);
+ origVal = v.<Object>property(propName).orElse(null);
+
+ if ( origVal == null)
+ continue;
+
+ if ( targetVal != null ) {
+ System.out.println( "vertex [" + label + "] id " + longId + " has " + targetPropName +
+ " with value " + targetVal + ", skip adding with value " + origVal);
+ continue;
+ }
+ titanProperties = v.properties(); // current properties
+ propertyCount = 0;
+ if ( v.<Object>property(propName).orElse(null) != null ) {
+ propVal = v.<Object>property(propName).orElse(null);
+ v.property(targetPropName, propVal);
+ ++vtxCount;
+ while( titanProperties.hasNext() ){
+
+ tmpProperty = titanProperties.next();
+ if ( propertyCount == 0 )
+ System.out.print( "adding to vertex id " + longId + " with existing properties " +
+ tmpProperty.toString() );
+ else
+ System.out.print(", " + tmpProperty.toString());
+ ++propertyCount;
+ }
+
+ if ( propertyCount > 0 )
+ System.out.println("");
+ System.out.println("INFO -- just did the add target [" + targetNodeType + "] using " + longId +
+ " with label " + label + "] and updated it with the orig value (" +
+ propVal.toString() + ")");
+ propertyCount = 0;
+ while( titanProperties.hasNext() ){
+
+ tmpProperty = titanProperties.next();
+ if ( propertyCount == 0 )
+ System.out.print( "new property list for vertex [" + label + "] id " + longId + " with existing properties " +
+ tmpProperty.toString() );
+ else
+ System.out.print(", " + tmpProperty.toString());
+ ++propertyCount;
+ }
+
+ if ( propertyCount > 0 )
+ System.out.println("");
+ }
+ }
+ }
+
+ }
+
+ System.out.println("added properties data for " + vtxCount + " vertexes. noCommit " + noCommit);
+ if ( !noCommit )
+ graph.tx().commit();
+ }
+ catch (Exception ex) {
+ System.out.print("Threw a regular Exception:\n");
+ System.out.println(ex.getMessage());
+ }
+ finally {
+ if( graphMgt != null && graphMgt.isOpen() ){
+ // Any changes that worked correctly should have already done their commits.
+ graphMgt.rollback();
+ }
+ if( graph != null ){
+ // Any changes that worked correctly should have already done their commits.
+ graph.tx().rollback();
+ graph.close();
+ }
+ }
+
+ System.exit(0);
+
+ }// End of main()
+
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ResultSet.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ResultSet.java
new file mode 100644
index 0000000..61de437
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ResultSet.java
@@ -0,0 +1,124 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class ResultSet {
+ TitanVertex vert;
+ String newDataDelFlag;
+ String doNotOutputFlag;
+ String locationInModelSubGraph;
+ ArrayList <ResultSet> subResultSet;
+ String propertyLimitDesc;
+ HashMap <String,Object> propertyOverRideHash;
+ HashMap <String,Object> extraPropertyHash;
+
+ /**
+ * Instantiates a new result set.
+ */
+ public ResultSet(){
+ this.vert = null;
+ this.newDataDelFlag = "";
+ this.doNotOutputFlag = "";
+ this.locationInModelSubGraph = "";
+ this.subResultSet = new ArrayList <ResultSet>();
+ this.propertyLimitDesc = "";
+ this.propertyOverRideHash = new HashMap <String,Object> ();
+ this.extraPropertyHash = new HashMap <String,Object> ();
+ }
+
+ /**
+ * Gets the vert.
+ *
+ * @return the vert
+ */
+ public TitanVertex getVert(){
+ return this.vert;
+ }
+
+ /**
+ * Gets the sub result set.
+ *
+ * @return the sub result set
+ */
+ public ArrayList <ResultSet> getSubResultSet(){
+ return this.subResultSet;
+ }
+
+ /**
+ * Gets the new data del flag.
+ *
+ * @return the new data del flag
+ */
+ public String getNewDataDelFlag(){
+ return this.newDataDelFlag;
+ }
+
+ /**
+ * Gets the do not output flag.
+ *
+ * @return the do not output flag
+ */
+ public String getDoNotOutputFlag(){
+ return this.doNotOutputFlag;
+ }
+
+ /**
+ * Gets the location in model sub graph.
+ *
+ * @return the location in model sub graph
+ */
+ public String getLocationInModelSubGraph(){
+ return this.locationInModelSubGraph;
+ }
+
+ /**
+ * Gets the property limit desc.
+ *
+ * @return the property limit desc
+ */
+ public String getPropertyLimitDesc(){
+ return this.propertyLimitDesc;
+ }
+
+ /**
+ * Gets the property over ride hash.
+ *
+ * @return the property over ride hash
+ */
+ public HashMap <String,Object> getPropertyOverRideHash(){
+ return this.propertyOverRideHash;
+ }
+
+ /**
+ * Gets the extra property hash.
+ *
+ * @return the extra property hash
+ */
+ public HashMap <String,Object> getExtraPropertyHash(){
+ return this.extraPropertyHash;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaGenerator.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaGenerator.java
new file mode 100644
index 0000000..615a870
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaGenerator.java
@@ -0,0 +1,433 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.io.IOException;
+
+import com.thinkaurelius.titan.core.Cardinality;
+import com.thinkaurelius.titan.core.Multiplicity;
+import com.thinkaurelius.titan.core.PropertyKey;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.util.Bytes;
+
+
+
+public class SchemaGenerator{
+
+ private static AAILogger aaiLogger = new AAILogger(SchemaGenerator.class.getName());
+ private static final String FROMAPPID = "AAI-DB";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ // public static void main(String[] args) {
+ // System.out.println("just try the hbase piece ..");
+ // createHBaseLogTableIfNeeded();
+ //}
+
+
+ /**
+ * Load schema into titan.
+ *
+ * @param graph the graph
+ * @param graphMgmt the graph mgmt
+ */
+ public static void loadSchemaIntoTitan(final TitanGraph graph, final TitanManagement graphMgmt) {
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", TRANSID, FROMAPPID, "loadSchemaIntoTitan");
+ LogLine dbLogline = new LogLine();
+ dbLogline.init("aaidbgen", TRANSID, FROMAPPID, "loadSchemaIntoTitan");
+
+ try {
+ AAIConfig.init(TRANSID, FROMAPPID);
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not run AAIConfig.init(). ";
+ dbLogline.add("msg", emsg);
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + ex.getMessage() + "]");
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, false, "AAI_4002");
+ System.exit(1);
+ }
+
+ // NOTE - Titan 0.5.3 doesn't keep a list of legal node Labels.
+ // They are only used when a vertex is actually being created. Titan 1.1 will keep track (we think).
+
+
+ // Use EdgeRules to make sure edgeLabels are defined in the db. NOTE: the multiplicty used here is
+ // always "MULTI". This is not the same as our internal "Many2Many", "One2One", "One2Many" or "Many2One"
+ // We use the same edge-label for edges between many different types of nodes and our internal
+ // multiplicty definitions depends on which two types of nodes are being connected.
+ HashMap<String, String> labelHash = new HashMap<String, String>();
+ Iterator<String> edgeLabelKeyIterator = DbEdgeRules.EdgeRules.keySet().iterator();
+ while( edgeLabelKeyIterator.hasNext() ){
+ // We re-use a lot of labels, so put them in a hash so we only look at each one once.
+ String lKey = edgeLabelKeyIterator.next();
+ Collection <String> labelInfoColl = DbEdgeRules.EdgeRules.get(lKey);
+ Iterator <String> labItr = labelInfoColl.iterator();
+ while( labItr.hasNext() ){
+ // Note - there's never more than one... But it is defined as a multimap, so technically, we need to loop
+ String labInfo = labItr.next();
+ String [] flds = labInfo.split(",");
+ String label = flds[0];
+ labelHash.put(label, "");
+ }
+ }
+
+ for( String key: labelHash.keySet() ){
+ String labelTxt = key;
+ if( graphMgmt.containsRelationType(labelTxt) ){
+ String msg = " EdgeLabel [" + labelTxt + "] already existed. ";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ }
+ else {
+ String msg = "Making EdgeLabel: [" + labelTxt + "]";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ graphMgmt.makeEdgeLabel(labelTxt).multiplicity(Multiplicity.valueOf("MULTI")).make();
+ }
+ }
+
+ IngestModelMoxyOxm moxyMod = new IngestModelMoxyOxm();
+ DbMaps dbMaps = null;
+ try {
+ ArrayList <String> defaultVerLst = new ArrayList <String> ();
+ defaultVerLst.add( AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP) );
+ moxyMod.init( defaultVerLst, false);
+ dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not get the DbMaps object. ";
+ dbLogline.add("msg", emsg);
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + ex.getMessage() + "]");
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, false, "AAI_4000");
+ System.exit(1);
+ }
+
+ // dbMaps.NodeMapIndexedProps dbMaps.NodeMapUniqueProps -- These maps capture which properties
+ // are indexed/unique-indexed per nodeType. But for Titan 0.5.3 we are only using global-level
+ // indexes, so we will translate this to a single hash for use below.
+ HashMap<String, Boolean> propertyIsIndexed = new HashMap<String, Boolean>();
+ HashMap<String, Boolean> propertyIsUnique = new HashMap<String, Boolean>();
+
+ Iterator<String> indexKeyIterator = dbMaps.NodeMapIndexedProps.keySet().iterator();
+ while( indexKeyIterator.hasNext() ){
+ // Our maps list which props are indexed by nodeType, but we just want the list of the indexed properties
+ String iKey = indexKeyIterator.next();
+ Collection <String> indexInfoColl = dbMaps.NodeMapIndexedProps.get(iKey);
+ Iterator <String> indItr = indexInfoColl.iterator();
+ while( indItr.hasNext() ){
+ // Note - there's never more than one... But it is defined as a multimap, so technically, we need to loop
+ String indInfo = indItr.next();
+ String [] flds = indInfo.split(",");
+ for( int i = 0; i < flds.length; i++ ){
+ String propName = flds[i];
+ propertyIsIndexed.put(propName, true);
+ }
+ }
+ }
+
+ Iterator<String> uniqueIndexKeyIterator = dbMaps.NodeMapUniqueProps.keySet().iterator();
+ while( uniqueIndexKeyIterator.hasNext() ){
+ // Our maps list which props are indexed by nodeType, but we just want the list of the unique indexed properties
+ String uiKey = uniqueIndexKeyIterator.next();
+ Collection <String> uniqueIndexInfoColl = dbMaps.NodeMapUniqueProps.get(uiKey);
+ Iterator <String> unIndItr = uniqueIndexInfoColl.iterator();
+ while( unIndItr.hasNext() ){
+ // Note - there's never more than one... But it is defined as a multimap, so technically, we need to loop
+ String unIndInfo = unIndItr.next();
+ String [] flds = unIndInfo.split(",");
+ for( int i = 0; i < flds.length; i++ ){
+ String propName = flds[i];
+ propertyIsUnique.put(propName, true);
+ }
+ }
+ }
+
+ // dbMaps.PropertyDataTypeMap -- key is the property name, value is the data type
+ // In our DB, Cardinality is only either SINGLE or SET. This is also captured in the PropertyDataTypeMap
+ // By default, cardinality is SINGLE, but if the dataType looks like, "Set<String>" -- then the data type is
+ // String, but the cardinality is SET.
+ for( Map.Entry<?,?> entry : dbMaps.PropertyDataTypeMap.entrySet() ){
+ String vName = (String) entry.getKey();
+ String dataTypeStr = (String) entry.getValue();
+ Class<?> dType = String.class; // Default to String
+ String cardinality = "SINGLE"; // Default cardinality to SINGLE
+
+ if(dataTypeStr.equals("Set<String>")){
+ dType = String.class;
+ cardinality = "SET";
+ }
+ else if(dataTypeStr.equals("Set<Integer>")){
+ dType = Integer.class;
+ cardinality = "SET";
+
+ }
+ else if(dataTypeStr.equals("String")){ dType = String.class; }
+ else if(dataTypeStr.equals("Integer")){ dType = Integer.class; }
+ else if(dataTypeStr.equals("Boolean")){ dType = Boolean.class; }
+ else if(dataTypeStr.equals("Character")){ dType = Character.class; }
+ else if(dataTypeStr.equals("Long")){ dType = Long.class; }
+ else if(dataTypeStr.equals("Float")){ dType = Float.class; }
+ else if(dataTypeStr.equals("Double")){ dType = Double.class; }
+ else {
+ // Default to String -- but flag it
+ dType = String.class;
+ String msg = ">>> WARNING >>> UNRECOGNIZED dataType: [" + dataTypeStr + "] found for [" + vName + "] ";
+ System.out.println( "\n" + msg + "\n" );
+ dbLogline.add("msg", msg);
+ }
+
+ if( graphMgmt.containsRelationType(vName) ){
+ String msg = " PropertyKey [" + vName + "] already existed in the DB. ";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ }
+ else {
+ String msg = "Creating PropertyKey: [" + vName + "], ["+ dataTypeStr + "], [" + cardinality + "]";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ PropertyKey propK = graphMgmt.makePropertyKey(vName).dataType(dType).cardinality(Cardinality.valueOf(cardinality)).make();
+ if( propertyIsIndexed.containsKey(vName) ){
+ if( propertyIsUnique.containsKey(vName) ){
+ msg = " Add Unique index for PropertyKey: [" + vName + "]";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ graphMgmt.buildIndex(vName,Vertex.class).addKey(propK).unique().buildCompositeIndex();
+ }
+ else {
+ msg = " Add index for PropertyKey: [" + vName + "]";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ graphMgmt.buildIndex(vName,Vertex.class).addKey(propK).buildCompositeIndex();
+ }
+ }
+ else {
+ msg = " No index added for PropertyKey: [" + vName + "]";
+ System.out.println( msg );
+ dbLogline.add("msg", msg);
+ }
+ }
+ }
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, true, "0");
+ System.out.println("-- About to call graphMgmt commit");
+ graphMgmt.commit();
+
+ }// End of loadSchemaIntoTitan()
+
+
+ public static void createHBaseLogTableIfNeeded( ) {
+ // Check to see if the HBase Logging table exists. If it does not, then create it.
+
+ int ttlDays = 15; // should get this from a property file
+ try {
+ String ttlValDaysStr = AAIConfig.get("hbase.column.ttl.days");
+ if( ttlValDaysStr != null ){
+ int ttlValDaysInt = Integer.parseInt(ttlValDaysStr);
+ ttlDays = ttlValDaysInt;
+ }
+ } catch ( Exception e) { /* don't worry - we'll just use the default */ }
+ int ttlSec = ttlDays * 86400;
+ System.out.println( "Using ttl value of: " + ttlSec );
+
+ String tblName = "aailogging";
+ try {
+ String logTblVal = AAIConfig.get(AAIConstants.HBASE_TABLE_NAME);
+ if( logTblVal != null && !logTblVal.equals("") ){
+ tblName = logTblVal;
+ }
+ } catch ( Exception e) { /* don't worry - we'll just use the default */ }
+ System.out.println( "Using logging table name of: " + tblName );
+
+ List <String> colNames = Arrays.asList("payload", "resource", "transaction");
+ HBaseAdmin hbAdmin = null;
+
+ LogLine logline = new LogLine();
+ logline.init("aaidbgen", TRANSID, FROMAPPID, "createHBaseLogTableIfNeeded");
+ LogLine dbLogline = new LogLine();
+ dbLogline.init("aaidbgen", TRANSID, FROMAPPID, "createHBaseLogTableIfNeeded");
+ try {
+ AAIConfig.init(TRANSID, FROMAPPID);
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not run AAIConfig.init(). ";
+ dbLogline.add("msg", emsg);
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + ex.getMessage() + "]");
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, false, "AAI_4002");
+ System.exit(1);
+ }
+
+ try {
+ System.out.println(" First create an HBaseConfiguration object. ");
+ Configuration hConf = HBaseConfiguration.create();
+
+ String val2Use = null;
+ Boolean setOk = false;
+ try {
+ val2Use = AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM);
+ if( val2Use != null ){
+ hConf.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM, val2Use );
+ setOk = true;
+ }
+ } catch ( Exception e) { /* don't worry */ }
+ if( !setOk ){
+ System.out.println("Warning: we will not be setting " + AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM
+ + " on the HBaseAdmin object." );
+ }
+
+ try {
+ setOk = false;
+ val2Use = AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT);
+ if( val2Use != null ){
+ hConf.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT, val2Use );
+ setOk = true;
+ }
+ } catch ( Exception e) { /* don't worry */ }
+ if( !setOk ){
+ System.out.println("Warning: we will not be setting " + AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT
+ + " on the HBaseAdmin object." );
+ }
+
+ try {
+ setOk = false;
+ val2Use = AAIConfig.get(AAIConstants.HBASE_TABLE_NAME);
+ if( val2Use != null ){
+ hConf.set(AAIConstants.HBASE_TABLE_NAME, val2Use );
+ setOk = true;
+ }
+ } catch ( Exception e) { /* don't worry */ }
+ if( !setOk ){
+ System.out.println("Warning: we will not be setting " + AAIConstants.HBASE_TABLE_NAME
+ + " on the HBaseAdmin object." );
+ }
+
+ try {
+ setOk = false;
+ val2Use = AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT);
+ if( val2Use != null ){
+ hConf.set(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT, val2Use );
+ setOk = true;
+ }
+ } catch ( Exception e) { /* don't worry */ }
+ if( !setOk ){
+ System.out.println("Warning: we will not be setting " + AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT
+ + " on the HBaseAdmin object." );
+ }
+
+ try {
+ setOk = false;
+ val2Use = AAIConfig.get(AAIConstants.HBASE_ZOOKEEPER_ZNODE_PARENT);
+ if( val2Use != null ){
+ hConf.set(AAIConstants.HBASE_ZOOKEEPER_ZNODE_PARENT, val2Use );
+ setOk = true;
+ }
+ } catch ( Exception e) { /* don't worry */ }
+ if( !setOk ){
+ System.out.println("Warning: we will not be setting " + AAIConstants.HBASE_ZOOKEEPER_ZNODE_PARENT
+ + " on the HBaseAdmin object." );
+ }
+
+ System.out.println(" Use the hConf to get an HBaseAdmin object. ");
+ hbAdmin = new HBaseAdmin(hConf);
+
+ System.out.println(" Use the hbAdmin object to check if the table exists or not. ");
+ boolean tblExists = hbAdmin.tableExists(tblName);
+
+ if( tblExists ){
+ System.out.println("HBase Logging Table " + tblName + " already exists.");
+ }
+ else {
+ System.out.println("HBase Logging Table " + tblName + " does not yet exist. We will try to create it.");
+
+ HTableDescriptor tabledescriptor = new HTableDescriptor(Bytes.toBytes(tblName));
+ hbAdmin.createTable(tabledescriptor);
+
+ for( Iterator<String> iter = colNames.iterator(); iter.hasNext(); ) {
+ String colNameStr = iter.next();
+ HColumnDescriptor hColDes = new HColumnDescriptor( colNameStr );
+ hColDes.setTimeToLive(ttlSec);
+ hbAdmin.addColumn(tblName, hColDes);
+ }
+
+ System.out.println("HBase Logging Table " + tblName + " has been added.");
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, true, "0");
+ }
+ }
+ catch (Exception ex){
+ String emsg = " ERROR trying to add the Hbase Logging Table. ";
+ dbLogline.add("msg", emsg);
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + ex.getMessage() + "]");
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, false, "AAI_4000");
+ System.exit(1);
+ }
+ finally {
+ if( hbAdmin != null ){
+ try {
+ hbAdmin.close();
+ }
+ catch( IOException e ){
+ String emsg = " ERROR trying to close the HBaseAdmin object. ";
+ dbLogline.add("msg", emsg);
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + e.getMessage() + "]");
+ aaiLogger.debug(dbLogline, dbLogline.finish(true));
+ aaiLogger.info(logline, false, "AAI_4000");
+ System.exit(1);
+ }
+ }
+ }
+ } // end createHBaseLogTableIfNeeded()
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java
new file mode 100644
index 0000000..93bcdf6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java
@@ -0,0 +1,456 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.UniquePropertyCheck;
+import org.slf4j.MDC;
+
+import com.att.eelf.configuration.Configuration;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.thinkaurelius.titan.core.Cardinality;
+import com.thinkaurelius.titan.core.PropertyKey;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanVertex;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+
+public class SchemaMod {
+
+ private static final String FROMAPPID = "AAI-UTILS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static final String COMPONENT = "SchemaMod";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ SchemaMod.execute(args);
+ System.exit(0);
+
+ }// End of main()
+
+ /**
+ * Execute.
+ *
+ * @param args the args
+ */
+ public static void execute(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ EELFLogger logger = EELFManager.getInstance().getLogger(UniquePropertyCheck.class.getSimpleName());
+ MDC.put("logFilenameAppender", SchemaMod.class.getSimpleName());
+
+ // NOTE -- We're just working with properties that are used for NODES
+ // for now.
+
+ TitanGraph graph = null;
+ TitanManagement graphMgt = null;
+
+ Boolean preserveData = true;
+ String propName = "";
+ String targetDataType = "";
+ String targetIndexInfo = "";
+ String preserveDataFlag = "";
+
+ String usageString = "Usage: SchemaMod propertyName targetDataType targetIndexInfo preserveDataFlag \n";
+ if (args.length != 4) {
+ String emsg = "Four Parameters are required. \n" + usageString;
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ } else {
+ propName = args[0];
+ targetDataType = args[1];
+ targetIndexInfo = args[2];
+ preserveDataFlag = args[3];
+ }
+
+ if (propName.equals("")) {
+ String emsg = "Bad parameter - propertyName cannot be empty. \n" + usageString;
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ } else if (!targetDataType.equals("String") && !targetDataType.equals("Set<String>")
+ && !targetDataType.equals("Integer") && !targetDataType.equals("Long")
+ && !targetDataType.equals("Boolean")) {
+ String emsg = "Unsupported targetDataType. We only support String, Set<String>, Integer, Long or Boolean for now.\n"
+ + usageString;
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ } else if (!targetIndexInfo.equals("uniqueIndex") && !targetIndexInfo.equals("index")
+ && !targetIndexInfo.equals("noIndex")) {
+ String emsg = "Unsupported IndexInfo. We only support: 'uniqueIndex', 'index' or 'noIndex'.\n"
+ + usageString;
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ } else {
+ if (preserveDataFlag.equals("true")) {
+ preserveData = true;
+ } else if (preserveDataFlag.equals("false")) {
+ preserveData = false;
+ } else {
+ String emsg = "Unsupported preserveDataFlag. We only support: 'true' or 'false'.\n" + usageString;
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ }
+ }
+
+ try {
+ AAIConfig.init();
+ ErrorLogHelper.loadProperties();
+ } catch (Exception ae) {
+ String emsg = "Problem with either AAIConfig.init() or ErrorLogHelper.LoadProperties(). ";
+ logAndPrint(logger, emsg + "[" + ae.getMessage() + "]");
+ System.exit(1);
+ }
+
+ DbMaps dbMaps = null;
+ try {
+ ArrayList<String> apiVersions = new ArrayList<String>();
+ apiVersions.add(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ final IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.init(apiVersions, false);
+ dbMaps = m.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ } catch (AAIException ae) {
+ String emsg = "Could not instantiate a copy of DbMaps. ";
+ logAndPrint(logger, emsg + "[" + ae.getMessage() + "]");
+ System.exit(1);
+ } catch (Exception e) {
+ String emsg = "exception, Could not instantiate a copy of DbMaps. ";
+ logAndPrint(logger, emsg + "[" + e.getMessage() + "]");
+ System.exit(1);
+ }
+ // Give a big warning if the DbMaps.PropertyDataTypeMap value does not
+ // agree with what we're doing
+ String warningMsg = "";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName)) {
+ String emsg = "Property Name = [" + propName + "] not found in PropertyDataTypeMap. ";
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ } else {
+ String currentDataType = dbMaps.PropertyDataTypeMap.get(propName);
+ if (!currentDataType.equals(targetDataType)) {
+ warningMsg = "TargetDataType [" + targetDataType + "] does not match what is in DbRules.java ("
+ + currentDataType + ").";
+ }
+ }
+
+ if (!warningMsg.equals("")) {
+ logAndPrint(logger, "\n>>> WARNING <<<< ");
+ logAndPrint(logger, ">>> " + warningMsg + " <<<");
+ }
+
+ logAndPrint(logger, ">>> Processing will begin in 5 seconds (unless interrupted). <<<");
+ try {
+ // Give them a chance to back out of this
+ Thread.sleep(5000);
+ } catch (java.lang.InterruptedException ie) {
+ logAndPrint(logger, " DB Schema Update has been aborted. ");
+ System.exit(1);
+ }
+
+ try {
+ Class dType = null;
+ if (targetDataType.equals("String")) {
+ dType = String.class;
+ } else if (targetDataType.equals("Set<String>")) {
+ dType = String.class;
+ } else if (targetDataType.equals("Integer")) {
+ dType = Integer.class;
+ } else if (targetDataType.equals("Boolean")) {
+ dType = Boolean.class;
+ } else if (targetDataType.equals("Character")) {
+ dType = Character.class;
+ } else if (targetDataType.equals("Long")) {
+ dType = Long.class;
+ } else if (targetDataType.equals("Float")) {
+ dType = Float.class;
+ } else if (targetDataType.equals("Double")) {
+ dType = Double.class;
+ } else {
+ String emsg = "Not able translate the targetDataType [" + targetDataType + "] to a Class variable.\n";
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ }
+ String cardinality = "SINGLE"; // Default cardinality to SINGLE
+
+ if (targetDataType.equals("Set<String>")) {
+ cardinality = "SET";
+ }
+ logAndPrint(logger, " ---- NOTE --- about to open graph (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+ if (graph == null) {
+ String emsg = "Not able to get a graph object in SchemaMod.java\n";
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ }
+
+ // Make sure this property is in the DB.
+ graphMgt = graph.openManagement();
+ if (graphMgt == null) {
+ String emsg = "Not able to get a graph Management object in SchemaMod.java\n";
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ }
+ PropertyKey origPropKey = graphMgt.getPropertyKey(propName);
+ if (origPropKey == null) {
+ String emsg = "The propName = [" + propName + "] is not defined in our graph. ";
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ }
+
+ if (targetIndexInfo.equals("uniqueIndex")) {
+ // Make sure the data in the property being changed can have a
+ // unique-index put on it.
+ // Ie. if there are duplicate values, we will not be able to
+ // migrate the data back into the property.
+ Boolean foundDupesFlag = UniquePropertyCheck.runTheCheckForUniqueness(TRANSID, FROMAPPID,
+ graph.newTransaction(), propName, logger);
+ if (foundDupesFlag) {
+ logAndPrint(logger,
+ "\n\n!!!!!! >> Cannot add a uniqueIndex for the property: [" + propName
+ + "] because duplicate values were found. See the log for details on which"
+ + " nodes have this value. \nThey will need to be resolved (by updating those values to new"
+ + " values or deleting unneeded nodes) using the standard REST-API \n");
+ System.exit(1);
+ }
+ }
+
+ // -------------- If we made it to here - we must be OK with making
+ // this change ------------
+
+ // Rename this property to a backup name (old name with "retired_"
+ // appended plus a dateStr)
+
+ SimpleDateFormat d = new SimpleDateFormat("MMddHHmm");
+ d.setTimeZone(TimeZone.getTimeZone("GMT"));
+ String dteStr = d.format(new Date()).toString();
+ String retiredName = propName + "-" + dteStr + "-RETIRED";
+ graphMgt.changeName(origPropKey, retiredName);
+
+ // Create a new property using the original property name and the
+ // targetDataType
+ PropertyKey freshPropKey = graphMgt.makePropertyKey(propName).dataType(dType)
+ .cardinality(Cardinality.valueOf(cardinality)).make();
+
+ // Create the appropriate index (if any)
+ if (targetIndexInfo.equals("uniqueIndex")) {
+ String freshIndexName = propName + dteStr;
+ graphMgt.buildIndex(freshIndexName, Vertex.class).addKey(freshPropKey).unique().buildCompositeIndex();
+ } else if (targetIndexInfo.equals("index")) {
+ String freshIndexName = propName + dteStr;
+ graphMgt.buildIndex(freshIndexName, Vertex.class).addKey(freshPropKey).buildCompositeIndex();
+ }
+
+ logAndPrint(logger, "Committing schema changes with graphMgt.commit()");
+ graphMgt.commit();
+ graph.tx().commit();
+ graph.close();
+
+ // Get A new graph object
+ logAndPrint(logger, " ---- NOTE --- about to open a second graph object (takes a little while)\n");
+
+ graph = AAIGraph.getInstance().getGraph();
+ if (graph == null) {
+ String emsg = "Not able to get a graph object in SchemaMod.java\n";
+ logAndPrint(logger, emsg);
+ System.exit(1);
+ }
+
+ // For each node that has this property, update the new from the old
+ // and then remove the
+ // old property from that node
+ Iterable<?> verts = null;
+ verts = graph.query().has(retiredName).vertices();
+ Iterator<?> it = verts.iterator();
+ int vtxCount = 0;
+ ArrayList<String> alreadySeenVals = new ArrayList<String>();
+ while (it.hasNext()) {
+ vtxCount++;
+ TitanVertex tmpVtx = (TitanVertex) it.next();
+ String tmpVid = tmpVtx.id().toString();
+
+ // System.out.println("Show what we have in the vertex before
+ // trying to do an update...");
+ // ArrayList <String> retArr =
+ // DbMeth.showPropertiesForNode("junkTransId", "junkFromAppId",
+ // tmpVtx);
+ // for( String info : retArr ){ System.out.println(info); }
+
+ Object origVal = tmpVtx.<Object> property(retiredName).orElse(null);
+ if (preserveData) {
+ tmpVtx.property(propName, origVal);
+ if (targetIndexInfo.equals("uniqueIndex")) {
+ // We're working on a property that is being used as a
+ // unique index
+ String origValStr = "";
+ if (origVal != null) {
+ origValStr = origVal.toString();
+ }
+ if (alreadySeenVals.contains(origValStr)) {
+ // This property is supposed to be unique, but we've
+ // already seen this value in this loop
+ // This should have been caught up in the first part
+ // of SchemaMod, but since it wasn't, we
+ // will just log the problem.
+ logAndPrint(logger,
+ "\n\n ---------- ERROR - could not migrate the old data [" + origValStr
+ + "] for propertyName [" + propName
+ + "] because this property is having a unique index put on it.");
+ showPropertiesAndEdges(TRANSID, FROMAPPID, tmpVtx, logger);
+ logAndPrint(logger, "-----------------------------------\n");
+ } else {
+ // Ok to add this prop in as a unique value
+ tmpVtx.property(propName, origVal);
+ logAndPrint(logger,
+ "INFO -- just did the add of the freshPropertyKey and updated it with the orig value ("
+ + origValStr + ")");
+ }
+ alreadySeenVals.add(origValStr);
+ } else {
+ // We are not working with a unique index
+ tmpVtx.property(propName, origVal);
+ logAndPrint(logger,
+ "INFO -- just did the add of the freshPropertyKey and updated it with the orig value ("
+ + origVal.toString() + ")");
+ }
+ } else {
+ // existing nodes just won't have that property anymore
+ // Not sure if we'd ever actually want to do this -- maybe
+ // we'd do this if the new
+ // data type was not compatible with the old?
+ }
+ tmpVtx.property(retiredName).remove();
+
+ logAndPrint(logger, "INFO -- just did the remove of the " + retiredName + " from this vertex. (vid="
+ + tmpVid + ")");
+ }
+
+ logAndPrint(logger, "Updated data for " + vtxCount + " vertexes. Now call graph2.commit(). ");
+ graph.tx().commit();
+ } catch (Exception ex) {
+ logAndPrint(logger, "Threw a regular Exception: ");
+ logAndPrint(logger, ex.getMessage());
+ } finally {
+ if (graphMgt != null && graphMgt.isOpen()) {
+ // Any changes that worked correctly should have already done
+ // their commits.
+ graphMgt.rollback();
+ }
+ if (graph != null) {
+ // Any changes that worked correctly should have already done
+ // their commits.
+ graph.tx().rollback();
+ graph.close();
+ }
+ }
+
+ }
+
+ /**
+ * Show properties and edges.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @param logger the logger
+ */
+ private static void showPropertiesAndEdges(String transId, String fromAppId, TitanVertex tVert, EELFLogger logger) {
+
+ if (tVert == null) {
+ logAndPrint(logger, "Null node passed to showPropertiesAndEdges.");
+ } else {
+ String nodeType = "";
+ Object ob = tVert.<String> property("aai-node-type");
+ if (ob == null) {
+ nodeType = "null";
+ } else {
+ nodeType = ob.toString();
+ }
+
+ logAndPrint(logger, " AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
+ logAndPrint(logger, " Property Detail: ");
+ Iterator<VertexProperty<Object>> pI = tVert.properties();
+ while (pI.hasNext()) {
+ VertexProperty<Object> tp = pI.next();
+ Object val = tp.value();
+ logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] ");
+ }
+
+ Iterator<Edge> eI = tVert.edges(Direction.BOTH);
+ if (!eI.hasNext()) {
+ logAndPrint(logger, "No edges were found for this vertex. ");
+ }
+ while (eI.hasNext()) {
+ TitanEdge ed = (TitanEdge) eI.next();
+ String lab = ed.label();
+ TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert);
+ if (vtx == null) {
+ logAndPrint(logger,
+ " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
+ } else {
+ String nType = vtx.<String> property("aai-node-type").orElse(null);
+ String vid = vtx.id().toString();
+ logAndPrint(logger, "Found an edge (" + lab + ") from this vertex to a [" + nType
+ + "] node with VtxId = " + vid);
+ }
+ }
+ }
+ } // End of showPropertiesAndEdges()
+
+ /**
+ * Log and print.
+ *
+ * @param logger the logger
+ * @param msg the msg
+ */
+ protected static void logAndPrint(EELFLogger logger, String msg) {
+ System.out.println(msg);
+ logger.info(msg);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java
new file mode 100644
index 0000000..a9090ef
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java
@@ -0,0 +1,255 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbgen;
+
+import java.util.ArrayList;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConfig;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.UUID;
+
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+
+
+public class UpdateEdgeTags {
+
+ private static final String FROMAPPID = "AAI-DB";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ //private static AAILogger aaiLogger = new AAILogger(UpdateEdgeTags.class.getName());
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ if( args == null || args.length != 1 ){
+ String msg = "usage: UpdateEdgeTags edgeRuleKey (edgeRuleKey can be either, all, or a rule key like 'nodeTypeA|nodeTypeB') \n";
+ System.out.println(msg);
+ System.exit(1);
+ }
+ String edgeRuleKeyVal = args[0];
+
+ TitanGraph graph = null;
+
+ HashMap <String,Object> edgeRuleHash = new HashMap <String,Object>();
+ HashMap <String,Object> edgeRulesFullHash = new HashMap <String,Object>();
+ HashMap <String,Object> edgeRuleLabelToKeyHash = new HashMap <String,Object>();
+ ArrayList <String> labelMapsToMultipleKeys = new <String> ArrayList ();
+
+ int tagCount = DbEdgeRules.EdgeInfoMap.size();
+ // Loop through all the edge-rules make sure they look right and
+ // collect info about which labels support duplicate ruleKeys.
+ Iterator<String> edgeRulesIterator = DbEdgeRules.EdgeRules.keySet().iterator();
+ while( edgeRulesIterator.hasNext() ){
+ String ruleKey = edgeRulesIterator.next();
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ // For now, we only look for one type of edge between two nodes.
+ String fullRuleString = ruleItr.next();
+ edgeRulesFullHash.put(ruleKey,fullRuleString);
+ // An EdgeRule is comma-separated and the first item is the edgeLabel
+ String [] rules = fullRuleString.split(",");
+ //System.out.println( "rules.length = " + rules.length + ", tagCount = " + tagCount );
+ if( rules.length != tagCount ){
+ String detail = "Bad EdgeRule data (itemCount=" + rules.length + ") for key = [" + ruleKey + "].";
+ System.out.println(detail);
+ System.exit(0);
+ }
+ String edgeLabel = rules[0];
+ if( edgeRuleLabelToKeyHash.containsKey(edgeLabel) ){
+ // This label maps to more than one edge rule - we'll have to figure out
+ // which rule applies when we look at each edge that uses this label.
+ // So we take it out of mapping hash and add it to the list of ones that
+ // we'll need to look up later.
+ edgeRuleLabelToKeyHash.remove(edgeLabel);
+ labelMapsToMultipleKeys.add(edgeLabel);
+ }
+ else {
+ edgeRuleLabelToKeyHash.put(edgeLabel, ruleKey);
+ }
+ }
+ }
+
+ if( ! edgeRuleKeyVal.equals( "all" ) ){
+ // If they passed in a (non-"all") argument, that is the single edgeRule that they want to update.
+ // Note - the key looks like "nodeA|nodeB" as it appears in DbEdgeRules.EdgeRules
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(edgeRuleKeyVal);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ // For now, we only look for one type of edge between two nodes (Ie. for one key).
+ String edRule = ruleItr.next();
+ edgeRuleHash.put(edgeRuleKeyVal, edRule);
+ System.out.println("Adding this rule to list of rules to do: key = " + edgeRuleKeyVal + ", rule = [" + edRule + "]");
+ }
+ else {
+ String msg = " Error - Unrecognized edgeRuleKey: [" + edgeRuleKeyVal + "]. ";
+ System.out.println(msg);
+ System.exit(0);
+ }
+ }
+ else {
+ // They didn't pass a target ruleKey in, so we'll work on all types of edges
+ edgeRuleHash.putAll(edgeRulesFullHash);
+ }
+
+ try {
+ AAIConfig.init(TRANSID, FROMAPPID);
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n");
+ ErrorLogHelper.loadProperties();
+
+ graph = AAIGraph.getInstance().getGraph();
+
+ if( graph == null ){
+ String emsg = "null graph object in updateEdgeTags() \n";
+ System.out.println(emsg);
+ System.exit(0);
+ }
+ }
+ catch (AAIException e1) {
+ String msg = e1.getErrorObject().toString();
+ System.out.println(msg);
+ System.exit(0);
+ }
+ catch (Exception e2) {
+ String msg = e2.toString();
+ System.out.println(msg);
+ e2.printStackTrace();
+ System.exit(0);
+ }
+
+ TitanTransaction g = graph.newTransaction();
+ try {
+ Iterable <?> edges = graph.query().edges();
+ Iterator <?> edgeItr = edges.iterator();
+
+ // Loop through all edges and update their tags if they are a type we are interested in.
+ // Sorry about looping over everything, but for now, I can't find a way to just select one type of edge at a time...!?
+ StringBuffer sb;
+ boolean missingEdge = false;
+ while( edgeItr != null && edgeItr.hasNext() ){
+ TitanEdge tmpEd = (TitanEdge) edgeItr.next();
+ String edLab = tmpEd.label().toString();
+
+ // Since we have edgeLabels that can be used for different pairs of node-types, we have to
+ // look to see what nodeTypes this edge is connecting (if it is a label that could do this).
+ String derivedEdgeKey = "";
+ if( labelMapsToMultipleKeys.contains(edLab) ){
+ // need to figure out which key is right for this edge
+ derivedEdgeKey = DbMeth.deriveEdgeRuleKeyForThisEdge( TRANSID, FROMAPPID, g, tmpEd );
+ }
+ else {
+ // This kind of label only maps to one key -- so we can just look it up.
+ if ( edgeRuleLabelToKeyHash.get(edLab) == null ) {
+ if ( !missingEdge ) {
+ System.out.print("DEBUG - missing edge(s) in edgeRuleLabelToKeyHash " + edgeRuleLabelToKeyHash.toString());
+ missingEdge = true;
+ }
+ sb = new StringBuffer();
+ Vertex vIn = null;
+ Vertex vOut = null;
+ Object obj = null;
+ vIn = tmpEd.vertex(Direction.IN);
+ if ( vIn != null ){
+ obj = vIn.<String>property("aai-node-type").orElse(null);
+ if ( obj != null ) {
+ sb.append("from node-type " + obj.toString());
+
+ obj = vIn.id();
+ sb.append(" id " + obj.toString());
+ } else {
+ sb.append(" missing from node-type ");
+ }
+ } else {
+ sb.append(" missing inbound vertex ");
+ }
+ vOut = tmpEd.vertex(Direction.OUT);
+ if ( vOut != null ) {
+ obj = vOut.<String>property("aai-node-type").orElse(null);
+ if ( obj != null ) {
+ sb.append(" to node-type " + obj.toString());
+ obj = vOut.id();
+ sb.append(" id " + obj.toString());
+ } else {
+ sb.append(" missing to node-type ");
+ }
+ } else {
+ sb.append(" missing to vertex ");
+ }
+ System.out.println("DEBUG - null entry for [" + edLab + "] between " + sb.toString());
+ continue;
+ }
+ derivedEdgeKey = edgeRuleLabelToKeyHash.get(edLab).toString();
+ }
+
+ if( edgeRuleHash.containsKey(derivedEdgeKey) ){
+ // this is an edge that we want to update
+ System.out.print("DEBUG - key = " + derivedEdgeKey + ", label = " + edLab
+ + ", for id = " + tmpEd.id().toString() + ", set: ");
+ HashMap <String,Object> edgeTagPropHash = DbMeth.getEdgeTagPropPutHash(TRANSID, FROMAPPID, derivedEdgeKey);
+ for( Map.Entry<String, Object> entry : edgeTagPropHash.entrySet() ){
+ System.out.print( "[" + entry.getKey() + " = " + entry.getValue() + "] " );
+ tmpEd.property( entry.getKey(), entry.getValue() );
+ }
+ System.out.print("\n");
+ }
+ } // End of looping over all edges
+ graph.tx().commit();
+ System.out.println("DEBUG - committed updates for listed edges " );
+ }
+ catch (Exception e2) {
+ String msg = e2.toString();
+ System.out.println(msg);
+ e2.printStackTrace();
+ if( graph != null ){
+ graph.tx().rollback();
+ }
+ System.exit(0);
+ }
+
+ System.exit(0);
+
+ }// end of main()
+
+
+
+
+
+}
+
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/AAIGraph.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/AAIGraph.java
new file mode 100644
index 0000000..d445636
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/AAIGraph.java
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import java.util.UUID;
+
+import org.openecomp.aai.dbgen.SchemaGenerator;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+
+/**
+ * Database Mapping class which acts as the middle man between the REST
+ * interface objects and Titan DB objects. This class provides methods to commit
+ * the objects received on the REST interface into the Titan graph database as
+ * vertices and edges. Transactions are also managed here by using a TitanGraph
+ * object to load, commit/rollback and shutdown for each request. The data model
+ * rules such as keys/required properties are handled by calling DBMeth methods
+ * which are driven by a specification file in json.
+ *
+
+ */
+public class AAIGraph {
+
+ protected static AAILogger aaiLogger = new AAILogger(AAIGraph.class.getName());
+ protected LogLine logline = new LogLine();
+ protected LogLine vlogline = new LogLine();
+ protected LogLine tlogline = new LogLine();
+
+ protected TitanGraph graph = null;
+ protected static final String COMPONENT = "aaidbmap";
+
+ /**
+ * Instantiates a new AAI graph.
+ */
+ private AAIGraph() {
+ LogLine alogline = new LogLine();
+ alogline.init(COMPONENT, UUID.randomUUID().toString(), "AAI-INIT", "AAI Graph loading");
+ try {
+ graph = TitanFactory.open(AAIConstants.AAI_CONFIG_FILENAME);
+
+ if (AAIConfig.get("storage.backend", "hbase").equals("inmemory")) {
+ // Load the propertyKeys, indexes and edge-Labels into the DB
+ TitanManagement graphMgt = graph.openManagement();
+
+ System.out.println("-- loading schema into Titan");
+ SchemaGenerator.loadSchemaIntoTitan( graph, graphMgt );
+ }
+
+ if (graph != null) {
+ aaiLogger.info(alogline, true, "0");
+ } else {
+ aaiLogger.info(alogline, false, "AAI_5102");
+ throw new AAIException("AAI_5102");
+ }
+ } catch (Exception e) {
+ aaiLogger.info(alogline, false, "AAI_5101");
+ //throw new AAIException("AAI_5101", e);
+ }
+ }
+
+ private static class Helper {
+ private static final AAIGraph INSTANCE = new AAIGraph();
+ }
+
+ /**
+ * Gets the single instance of AAIGraph.
+ *
+ * @return single instance of AAIGraph
+ */
+ public static AAIGraph getInstance() {
+ return Helper.INSTANCE;
+
+ }
+
+ /**
+ * Graph commit.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public void graphCommit() throws AAIException {
+ try {
+ graph.tx().commit();
+ } catch (Exception e) {
+ throw new AAIException("AAI_5103", e);
+ }
+ }
+
+ /**
+ * Graph rollback.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public void graphRollback() throws AAIException {
+ try {
+ graph.addVertex();
+ graph.tx().rollback();
+ } catch (Exception e) {
+ throw new AAIException("AAI_5104", e);
+ }
+ }
+
+ /**
+ * Graph shutdown.
+ */
+ public void graphShutdown() {
+ graph.close();
+ }
+
+ /**
+ * Gets the graph.
+ *
+ * @return the graph
+ */
+ public TitanGraph getGraph() {
+ return graph;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/ActionsGraph.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/ActionsGraph.java
new file mode 100644
index 0000000..f8bc94d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/ActionsGraph.java
@@ -0,0 +1,418 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.exceptions.DynamicException;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.domain.model.AncestryItem;
+import org.openecomp.aai.domain.model.AncestryItems;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.RestController;
+import org.openecomp.aai.util.RestObject;
+import org.openecomp.aai.util.RestURL;
+import org.openecomp.aai.util.StoreNotificationEvent;
+import org.openecomp.aai.domain.yang.GenericVnf;
+import com.google.common.base.CaseFormat;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+/**
+ * Database Mapping class which acts as the middle man between the REST interface objects
+ * for the Search namespace
+
+ */
+public class ActionsGraph {
+
+ private final int URI_OFFSET = 20; // length of cloud-infrastructure/ to be replaced
+ private LogLine logline = new LogLine();
+ private LogLine vlogline = new LogLine();
+ private LogLine tlogline = new LogLine();
+ private final String COMPONENT = "aaidbmap";
+ protected AAILogger aaiLogger = new AAILogger(ActionsGraph.class.getName());
+
+ /**
+ * Needs cloud region for node type.
+ *
+ * @param nodeType the node type
+ * @return true, if successful
+ */
+ private boolean needsCloudRegionForNodeType( String nodeType ) {
+ switch ( nodeType ) {
+ case "volume-group":
+ case "tenant":
+ case "flavor":
+ case "image":
+ case "dvs-switch":
+ case "oam-network":
+ case "availability-zone":
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * ProcessUpdate based on the request provided.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param updateRequest the update request
+ * @param aaiExtMap the aai ext map
+ * @throws AAIException the AAI exception
+ */
+ public void propertyUpdate (String fromAppId,
+ String transId,
+ DynamicEntity updateRequest,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+ logline.init(COMPONENT, transId, fromAppId, "propertyUpdate");
+ AAIException ex = null;
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ TitanVertex updatedVertex = null;
+ // Build a hash with properties to update
+ HashMap <String,Object> propHash = new HashMap<String, Object>();
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(aaiExtMap.getApiVersion());
+ String reqVers = aaiExtMap.getApiVersion().substring(1);
+ int vers = (new Integer(reqVers)).intValue();
+ String defaultRegionId = null;
+ String defaultRegionOwner = null;
+
+ if ((String)updateRequest.get("updateNodeType") == null)
+ throw new AAIException("AAI_6120", "Missing update-node-type");
+ String updateNodeType = ((String)updateRequest.get("updateNodeType")).toLowerCase().trim();
+ if (!dbMaps.NodeProps.containsKey(updateNodeType)) {
+ throw new AAIException("AAI_6120", "Invalid update-node-type:" + updateNodeType);
+ } else {
+ logline.add("update-node-type", updateNodeType);
+ }
+
+ HashMap <String,Object> keyHash = new HashMap<String, Object>();
+ LinkedHashMap <String,Object> depNodeKeyHash = new LinkedHashMap<String, Object>();
+ String updateNodeURI = null;
+ try {
+ updateNodeURI = (String)updateRequest.get("updateNodeUri");
+ } catch (DynamicException de) {
+ // nothing to do - as it is not supported in pre v6 version
+ }
+
+ String depNodeType = null;
+
+ // Build a hash with keys to uniquely identify the update Node
+ // and a hash for the keys to get the dependent Node
+ if (updateNodeURI == null) {
+ List<DynamicEntity> keyParams = updateRequest.get("updateNodeKey");
+
+ if( keyParams == null || keyParams.isEmpty())
+ throw new AAIException("AAI_6120", "update-node-key missing");
+ for( DynamicEntity keyData : keyParams ){
+ String nodeTypeAndKeyName = ((String)keyData.get("keyName")).toLowerCase().trim();
+ if (nodeTypeAndKeyName.indexOf(".") > 0) {
+ String nodeType = nodeTypeAndKeyName.substring(0, nodeTypeAndKeyName.indexOf("."));
+ String keyName = nodeTypeAndKeyName.substring(nodeTypeAndKeyName.indexOf(".") + 1);
+ if (!nodeType.equals(updateNodeType)) // if its not a key for the updateNodeType - it must be a key
+ // for the dependent node
+ depNodeKeyHash.put(nodeTypeAndKeyName, ((String)keyData.get("keyValue")).trim());
+ else
+ keyHash.put(keyName, ((String)keyData.get("keyValue")).trim());
+ } else { // we support keyname without nodetype for a non dependent node
+ keyHash.put(nodeTypeAndKeyName, ((String)keyData.get("keyValue")).trim());
+ }
+ }
+ depNodeType = DbMeth.figureDepNodeTypeForRequest(transId, fromAppId, updateNodeType, depNodeKeyHash, aaiExtMap.getApiVersion());
+ } else {
+ LinkedHashMap <String,Object> returnHash = RestURL.getKeyHashes(updateNodeURI);
+ Set<String> returnKeySet = returnHash.keySet();
+ Iterator<String> iter = returnKeySet.iterator();
+ String updateNodeKey = null;
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ if (key.startsWith(updateNodeType + ".")) {
+ keyHash.put(key.substring(key.indexOf(".") + 1), returnHash.get(key)); // this hash does not need nodetype in name/key
+ updateNodeKey = key;
+ } else {
+ if (depNodeType == null) { // get the parent dependent node, first one after its own key
+ depNodeType = key.substring(0, key.indexOf("."));
+ logline.add("depNodeType", depNodeType);
+ returnHash.remove(updateNodeKey); // remove this node's key
+ depNodeKeyHash.putAll(returnHash);
+ logline.add("depNodeKeyHash", depNodeKeyHash.toString());
+ break;
+ }
+ }
+ }
+ }
+
+ if( keyHash == null || keyHash.isEmpty()){
+ throw new AAIException("AAI_6120", "update-node-key or update-node-uri missing or invalid");
+ } else {
+ logline.add("keyHash", keyHash.toString());
+ }
+
+ List <DynamicEntity> actionList = updateRequest.get("action");
+ for (DynamicEntity action: actionList) {
+ if (!((String)action.get("actionType")).toLowerCase().trim().equals("replace")) {
+ throw new AAIException("AAI_6120", "Invalid action-type:" + (String)action.get("actionType") );
+ }
+
+ List <DynamicEntity> actionDataList = action.get("actionData");
+ Collection <String> valProps = dbMaps.NodeProps.get(updateNodeType);
+ String type = "";
+ String propName = "";
+ String detail = "";
+ String trimmedValue = "";
+ Object propValue = null;
+ for( DynamicEntity actionData : actionDataList ){
+ propName = ((String)actionData.get("propertyName")).toLowerCase().trim();
+ if (! valProps.contains(propName)) {
+ aaiLogger.info(logline, false, "AAI_6102");
+ detail = "property = " + propName + " is not valid for nodeType = " + updateNodeType;
+ throw new AAIException("AAI_6102", detail);
+ }
+ type = dbMaps.PropertyDataTypeMap.get(propName);
+ if (type.matches("Boolean|String|Integer|Long")) {
+ trimmedValue = ((String)actionData.get("propertyValue")).trim();
+ if (type.equals("Boolean")) {
+ propValue = new Boolean(trimmedValue);
+ } else if (type.equals("Integer")) {
+ propValue = new Integer(trimmedValue);
+ } else if (type.equals("Long")) {
+ propValue = new Long(trimmedValue);
+ } else {
+ propValue = trimmedValue;
+ }
+ propHash.put(propName, propValue);
+ }
+ }
+ }
+
+ if( propHash == null || propHash.isEmpty()){
+ throw new AAIException("AAI_6120", "action-data not found");
+ } else {
+ logline.add("action-data", propHash.toString());
+ }
+
+ propHash.putAll(keyHash); // combine keys and props to send to patchAaiNode
+
+ if (depNodeKeyHash.isEmpty() || depNodeType == null || depNodeType.equals(""))
+ // update the properties for updateNode
+ updatedVertex = DbMeth.patchAaiNode(transId, fromAppId, g, updateNodeType, propHash, null, aaiExtMap.getApiVersion());
+ else {
+ TitanVertex depNode = DbMeth.getUniqueNodeWithDepParams(transId, fromAppId, g, depNodeType, depNodeKeyHash, aaiExtMap.getApiVersion());
+ // update the properties for updateNode
+ updatedVertex = DbMeth.patchAaiNode(transId, fromAppId, g, updateNodeType, propHash, depNode, aaiExtMap.getApiVersion());
+ }
+
+ // UEB Event added to table
+ String updateNodeURL = setupUEBEventObject(fromAppId, transId, g, updateNodeType, updatedVertex, aaiExtMap.getApiVersion());
+ String vnfName = null;
+ try {
+ String vnfId = (String) keyHash.get("vnf-id");
+ if ( updateNodeType.equals("generic-vnf") ) {
+ vnfName = retrieveGenricVnfName(fromAppId, transId, vnfId);
+ if ( vnfName == null ) {
+ logline.add("msg", "no notify to INSTAR, equipment-role is not VRR/VIPE");
+ }
+ }
+
+ } catch (Exception e) {
+ vlogline.add("msg", "no notify to INSTAR, exception retrieving vnfName");
+ ex = new AAIException("AAI_4000", e);
+ return;
+ }
+ success = true;
+ } catch (AAIException e) {
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ success = false;
+ throw e;
+ } catch (Exception e) {
+ aaiLogger.info(logline, false, "AAI_5105");
+ success = false;
+ throw new AAIException("AAI_5105", e);
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+ }
+
+ /**
+ * Setup UEB event object.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param graph the graph
+ * @param updateNodeType the update node type
+ * @param updatedVertex the updated vertex
+ * @param apiVersion the api version
+ * @return the string
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public String setupUEBEventObject (String fromAppId,
+ String transId,
+ TitanTransaction graph,
+ String updateNodeType,
+ TitanVertex updatedVertex,
+ String apiVersion) throws AAIException, UnsupportedEncodingException {
+
+ String currentApiVersion = AAIConfig.get("aai.notification.current.version");
+ String action = "UPDATE";
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ long startTime = System.currentTimeMillis() ;
+ aaiExtMap.setStartTime(startTime);
+ aaiExtMap.setCheckpointTime(startTime);
+ aaiExtMap.setTransId(transId);
+ aaiExtMap.setFromAppId(fromAppId);
+
+ HashMap<String, String> allKeys = new HashMap<String, String>();
+ LinkedHashMap<String, LinkedHashMap<String,Object>> keyList = new LinkedHashMap<String, LinkedHashMap<String,Object>>();
+ GraphHelpersMoxy graphHelpers = new GraphHelpersMoxy();
+ AncestryItems ancestry = new AncestryItems();
+
+ String updatedNodeURL = RestURL.get(graph, updatedVertex, currentApiVersion, false, true);
+ AAIResource aaiRes = RestURL.parseUri(allKeys, keyList, updatedNodeURL, aaiExtMap);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer.get(currentApiVersion);
+ DynamicJAXBContext notificationJaxbContext = aaiResources.getJaxbContext();
+ DynamicEntity eh = notificationJaxbContext
+ .getDynamicType("inventory.aai.openecomp.org." + currentApiVersion + ".NotificationEventHeader")
+ .newDynamicEntity();
+
+ eh.set("entityType", updateNodeType);
+ eh.set("action", action);
+ eh.set("sourceName", fromAppId);
+ eh.set("version", currentApiVersion);
+ eh.set("entityLink", updatedNodeURL);
+
+ if (!graphHelpers.isEventEnabled(action, aaiRes.getNamespace(), aaiRes.getSimpleName())) {
+ return updatedNodeURL;
+ }
+
+ // get ourselves this time
+ graphHelpers.getAncestry(graph, keyList, allKeys, aaiRes, ancestry, true, aaiRes.getFullName(),
+ notificationJaxbContext, aaiExtMap);
+
+ for (Map.Entry<String,AncestryItem> ent : ancestry.getAncestryItems().entrySet()) {
+ AncestryItem anc = ent.getValue();
+ eh.set("topEntityType", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,anc.getAaiResource().getSimpleName()));
+ break;
+ }
+
+ DynamicEntity topObject;
+ try {
+ topObject = graphHelpers.unpackAncestry(graph, ancestry, aaiRes.getFullName(), notificationJaxbContext, aaiExtMap);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_5105", e);
+ throw ex;
+ }
+
+ StoreNotificationEvent sne = new StoreNotificationEvent();
+ sne.storeDynamicEvent(notificationJaxbContext, currentApiVersion, eh, topObject);
+
+ return updatedNodeURL;
+
+ }
+
+
+
+ /**
+ * Retrieve genric vnf name.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param vnfId the vnf id
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ private String retrieveGenricVnfName(String fromAppId, String transId, String vnfId) throws AAIException {
+ AAIException ex = null;
+ String vnfName = null;
+ String encodedVnfId = null;
+ LogLine mylogline = new LogLine();
+ try {
+ mylogline.init("aairestctrl", transId, "AAI", "retrieveGenricVnfName");
+
+ RestObject<GenericVnf> restObjGenericVnf = new RestObject<GenericVnf>();
+ GenericVnf genericVnf = new GenericVnf();
+ restObjGenericVnf.set(genericVnf);
+
+ encodedVnfId = RestURL.encodeURL(vnfId);
+ mylogline.add("encodedVnfId", encodedVnfId);
+
+ String path = RestController.REST_APIPATH_GENERIC_VNF + encodedVnfId;
+ mylogline.add("url", path);
+
+ RestController.<GenericVnf> Get(genericVnf, fromAppId, transId, path, restObjGenericVnf,
+ false);
+
+ genericVnf = restObjGenericVnf.get();
+
+ if ( ( genericVnf.getEquipmentRole() != null ) &&
+ ( genericVnf.getEquipmentRole().equals("VRR") ||
+ genericVnf.getEquipmentRole().equals("VIPE") ) ) {
+ vnfName = genericVnf.getVnfName();
+ }
+ vlogline.add("vnfName", vnfName);
+
+ } catch (AAIException ae) {
+ ex = ae;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_7115", e);
+ } finally {
+ if (ex == null) {
+ aaiLogger.info(mylogline, true, "0");
+ } else {
+ aaiLogger.error(ex.getErrorObject(), mylogline, ex);
+ aaiLogger.info(mylogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return vnfName;
+ }
+}
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/GraphHelpersMoxy.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/GraphHelpersMoxy.java
new file mode 100644
index 0000000..081c6a3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/GraphHelpersMoxy.java
@@ -0,0 +1,2136 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.exceptions.DynamicException;
+import org.eclipse.persistence.jaxb.JAXBMarshaller;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResourceKey;
+import org.openecomp.aai.domain.model.AAIResourceKeys;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.domain.model.AncestryItem;
+import org.openecomp.aai.domain.model.AncestryItems;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessage;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessageDatum;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.exceptions.AAIExceptionWithInfo;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.extensions.ExtensionController;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.RestProviders;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.PojoUtils;
+import org.openecomp.aai.util.StoreNotificationEvent;
+
+import com.google.common.base.CaseFormat;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class GraphHelpersMoxy {
+
+ protected LogLine logline = new LogLine();
+ protected LogLine vlogline = new LogLine();
+ protected LogLine tlogline = new LogLine();
+ protected final String COMPONENT = "aaidbmap";
+ protected AAILogger aaiLogger = new AAILogger(GraphHelpersMoxy.class.getName());
+
+ /**
+ * Do checkpoint.
+ *
+ * @param location the location
+ * @param aaiExtMap the aai ext map
+ */
+ private void doCheckpoint(String location, AAIExtensionMap aaiExtMap) {
+
+ long now = System.currentTimeMillis();
+// long lastCheckpoint = aaiExtMap.getCheckpointTime();
+// long totalElapsed = now - aaiExtMap.getStartTime();
+//
+// long sinceLastCheckpoint = now - lastCheckpoint;
+ //System.out.println("CHECKPOINT|" + aaiExtMap.getFullResourceName() + "|" + location + "|" + sinceLastCheckpoint + "|" + totalElapsed);
+
+ // System.out.println(now + "|" + "CHECKPOINT|" + location + "|" + sinceLastCheckpoint + "|" + totalElapsed);
+ aaiExtMap.setCheckpointTime(now);
+
+ }
+
+ /**
+ * Handle put.
+ *
+ * @param objectFromRequest the object from request
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handlePut(String objectFromRequest,
+ HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList, HashMap<String, String> allKeys,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handlePut");
+
+ boolean success = true;
+ TitanTransaction g = null;
+ Response response = null;
+ try {
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ g.rollback();
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ aaiExtMap.setGraph(g);
+
+ boolean objectExisted[] = new boolean[1];
+ objectExisted[0] = false;
+
+ DynamicEntity meObject;
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+
+ if (aaiRes.isAllowDirectWrite() == false) {
+ throw new AAIException("AAI_3006");
+ }
+
+ String objectNameForExtensions = aaiRes.getFullName().replace("/", "");
+ // see if this node has parent nodes before doing this...
+ AAIResource parent = aaiRes.getParent();
+
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ AncestryItems ancestry = new AncestryItems();
+ TitanVertex parentVertex = null;
+ if (parent.getResourceType().equals("node")) {
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, false, aaiRes.getFullName(), jaxbContext,
+ aaiExtMap);
+ parentVertex = ancestry.getAncestryItems().get(parent.getFullName()).getVertex();
+ } else {
+ if (parent.getParent().getResourceType() != null && parent.getParent().getResourceType().equals("node")) {
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, false, aaiRes.getFullName(), jaxbContext,
+ aaiExtMap);
+ parentVertex = ancestry.getAncestryItems().get(parent.getParent().getFullName()).getVertex();
+ }
+ }
+
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ String dynamicClass = aaiRes.getResourceClassName();
+
+ if (aaiExtMap.getHttpServletRequest().getContentType() == null || // default to json
+ aaiExtMap.getHttpServletRequest().getContentType().contains("application/json")) {
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ if (objectFromRequest.length() == 0) {
+ objectFromRequest = "{}";
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+
+ StringReader reader = new StringReader(objectFromRequest);
+
+ meObject = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+
+ if (meObject == null) {
+ throw new AAIException("AAI_5105");
+ }
+
+ // set up the extension and call the pre-extension if it's found
+ aaiExtMap.setAncestry(ancestry);
+ aaiExtMap.setObjectFromRequest(meObject);
+ aaiExtMap.setObjectFromRequestType(dynamicClass);
+ aaiExtMap.setJaxbContext(jaxbContext);
+
+ String topObjectSimpleResourceName = aaiResources.getAaiResources().get(aaiExtMap.getTopObjectFullResourceName()).getSimpleName();
+
+ ExtensionController ext = new ExtensionController();
+ ext.runExtension(aaiExtMap.getApiVersion(),
+ CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, aaiExtMap.getNamespace()),
+ topObjectSimpleResourceName,
+ "DynamicAdd" + objectNameForExtensions + "PreProc",
+ aaiExtMap,
+ true);
+
+ TitanVertex meVertex = putObject(g, aaiRes, allKeys, lookupHashMapList, meObject, parentVertex, objectExisted,
+ jaxbContext, ancestry, aaiExtMap);
+
+ AncestryItems newAncestry = new AncestryItems();
+ // get ourselves this time
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, newAncestry, true, aaiRes.getFullName(), jaxbContext,
+ aaiExtMap);
+
+ String eventAction = "CREATE";
+ if (objectExisted[0] == true) {
+ eventAction = "UPDATE";
+ }
+
+ aaiExtMap.setEventAction(eventAction);
+
+ meVertex = newAncestry.getAncestryItems().get(aaiRes.getFullName()).getVertex();
+
+ storeNotificationEvent(g, eventAction, meVertex, meObject, aaiRes, newAncestry, aaiResources, aaiExtMap);
+
+ ext.runExtension(aaiExtMap.getApiVersion(),
+ CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, aaiExtMap.getNamespace()),
+ topObjectSimpleResourceName,
+ "DynamicAdd" + objectNameForExtensions + "PostProc",
+ aaiExtMap,
+ false);
+
+ int versionNumber = 0;
+ String apiVersion = aaiExtMap.getApiVersion();
+ if (apiVersion != null && apiVersion.matches("v\\d+")) {
+ versionNumber = Integer.parseInt(apiVersion.replaceFirst("v", ""));
+ }
+
+
+ if (aaiExtMap.getPrecheckAddedList().size() > 0) {
+ HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>();
+
+ String[] chunks = aaiExtMap.getFullResourceName().split("/");
+
+ String keyString = "";
+ if (chunks.length > 0) {
+ HashMap<String,Object> thisResourceKeys = lookupHashMapList.get(aaiExtMap.getFullResourceName());
+
+ for (Map.Entry<String,Object> ent : thisResourceKeys.entrySet()) {
+ keyString += ent.getKey() + "=" + ent.getValue() + " ";
+ }
+ }
+
+ for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) {
+ ArrayList<String> templateVars = new ArrayList<String>();
+
+ templateVars.add("PUT " + aaiRes.getSimpleName());
+ templateVars.add(keyString);
+ List<String> keys = new ArrayList<String>();
+ templateVars.add(msg.getAaiResponseMessageResourceType());
+ for (AAIResponseMessageDatum dat : msg.getAaiResponseMessageData().getAAIResponseMessageDatum()) {
+ keys.add(dat.getAaiResponseMessageDatumKey() + "=" + dat.getAaiResponseMessageDatumValue());
+ }
+ templateVars.add(StringUtils.join(keys, ", "));
+ exceptionList.put(new AAIException("AAI_0004", msg.getAaiResponseMessageResourceType()),
+ templateVars);
+ }
+ response = Response
+ .status(Status.ACCEPTED).entity(ErrorLogHelper
+ .getRESTAPIInfoResponse(aaiExtMap.getHttpHeaders().getAcceptableMediaTypes(), exceptionList, logline))
+ .build();
+ } else if (versionNumber >= 5 && objectExisted[0] == false) {
+ response = Response.status(Status.CREATED).build();
+ } else {
+ response = Response.ok().build();
+ }
+
+ success = true;
+
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+
+
+ }
+
+ /**
+ * Handle delete.
+ *
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param resourceVersion the resource version
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleDelete(HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ HashMap<String, String> allKeys, String resourceVersion, AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleDelete");
+
+ Response response = null;
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ aaiExtMap.setGraph(g);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+ if (aaiRes.isAllowDirectWrite() == false) {
+ throw new AAIException("AAI_3006");
+ }
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ aaiExtMap.setEventAction("DELETE");
+ String topObjectSimpleResourceName = aaiResources.getAaiResources().get(aaiExtMap.getTopObjectFullResourceName()).getSimpleName();
+ deleteObject(g, lookupHashMapList, allKeys, jaxbContext, resourceVersion,
+ aaiRes, aaiResources, topObjectSimpleResourceName, aaiExtMap);
+
+ response = Response.noContent().build();
+ success = true;
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * Handle get by name.
+ *
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param depth the depth
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleGetByName(HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ HashMap<String, String> allKeys, int depth, AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleGetByName");
+
+ Response response = null;
+
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ aaiExtMap.setGraph(g);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+ if (aaiRes.isAllowDirectRead() == false) {
+ throw new AAIException("AAI_3005");
+ }
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ AncestryItems ancestry = new AncestryItems();
+
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, false, aaiRes.getFullName(), jaxbContext,
+ aaiExtMap);
+
+ TitanVertex parentVertex = null;
+
+ if (aaiRes.getParent() != null) {
+ AAIResource parent = aaiRes.getParent();
+ if (parent.getResourceType().equals("node")) {
+ parentVertex = ancestry.getAncestryItems().get(parent.getFullName()).getVertex();
+ } else {
+ if (parent.getParent() != null && parent.getParent().getResourceType().equals("node")) {
+ parentVertex = ancestry.getAncestryItems().get(parent.getParent().getFullName()).getVertex();
+ }
+ }
+ }
+
+ String dnHypResourceType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiRes.getSimpleName());
+ String titanDnHypResourceType = dnHypResourceType;
+ if ("cvlan-tag-entry".equals(dnHypResourceType)) {
+ titanDnHypResourceType = "cvlan-tag";
+ }
+ doCheckpoint("GET_SINGLE_BY_NAME_PRE_GET_NODES", aaiExtMap);
+ ArrayList<TitanVertex> vertices = new ArrayList<TitanVertex>();
+ if (parentVertex == null) {
+ vertices = DbMeth.getNodes(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g,
+ titanDnHypResourceType, lookupHashMapList.get(aaiRes.getFullName()), true, aaiRes.getApiVersion());
+ } else {
+ vertices = DbMeth.getConnectedNodes(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g,
+ titanDnHypResourceType, lookupHashMapList.get(aaiRes.getFullName()), parentVertex,
+ aaiRes.getApiVersion(), false);
+ }
+ doCheckpoint("GET_SINGLE_BY_NAME_POST_GET_NODES", aaiExtMap);
+ String dynamicClass = aaiRes.getResourceClassName();
+ DynamicType meObjectType = jaxbContext.getDynamicType(dynamicClass);
+
+ String outsideObjectDynamicClass = aaiRes.getParent().getResourceClassName();
+ DynamicType parentObjectType = jaxbContext.getDynamicType(outsideObjectDynamicClass);
+
+ DynamicEntity parentObject = parentObjectType.newDynamicEntity();
+
+ DynamicEntity meObject = meObjectType.newDynamicEntity();
+
+ DynamicEntity returnSingleObject = meObjectType.newDynamicEntity();
+
+ int vertCount = 0;
+ List<DynamicEntity> returnList = new ArrayList<DynamicEntity>();
+ for (TitanVertex vert : vertices) {
+
+ meObject = getObject(g, vert, vert, aaiRes, null, depth, ancestry, jaxbContext, aaiExtMap.getApiVersion(),
+ aaiExtMap);
+
+ returnSingleObject = meObject;
+
+ returnList.add(meObject);
+
+ vertCount++;
+
+ }
+
+ if (vertCount == 0) { // return not found if no vertices found
+ throw new AAIException("AAI_6114", "no nodes found for " + lookupHashMapList.get(aaiRes.getFullName()).toString());
+ }
+
+ parentObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,aaiRes.getSimpleName()), returnList);
+
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+
+ for (MediaType mt : aaiExtMap.getHttpHeaders().getAcceptableMediaTypes()) {
+ if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE);
+ }
+ }
+
+ StringWriter writer = new StringWriter();
+
+ if (vertCount > 1) {
+ marshaller.marshal(parentObject, writer);
+ response = Response.ok(parentObject).entity(writer.toString()).build();
+ } else {
+ marshaller.marshal(meObject, writer);
+ response = Response.ok(returnSingleObject).entity(writer.toString()).build();
+ }
+
+ success = true;
+
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * Handle get single by key.
+ *
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param depth the depth
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleGetSingleByKey(HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ HashMap<String, String> allKeys, int depth, AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleGetSingleByKey");
+
+ DynamicEntity meObject = null;
+ StringWriter writer = new StringWriter();
+
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ aaiExtMap.setGraph(g);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+ if (aaiRes.isAllowDirectRead() == false) {
+ throw new AAIException("AAI_3005");
+ }
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ AncestryItems ancestry = new AncestryItems();
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, true, aaiRes.getFullName(), jaxbContext, aaiExtMap);
+
+ TitanVertex meVertex = ancestry.getAncestryItems().get(aaiExtMap.getFullResourceName()).getVertex();
+
+ meObject = getObject(g, meVertex, meVertex, aaiRes, null, depth, ancestry, jaxbContext, aaiExtMap.getApiVersion(),
+ aaiExtMap);
+
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+
+ for (MediaType mt : aaiExtMap.getHttpHeaders().getAcceptableMediaTypes()) {
+ if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+ }
+ }
+
+ marshaller.marshal(meObject, writer);
+
+ success = true;
+
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return Response.ok(meObject).entity(writer.toString()).build();
+ }
+
+ /**
+ * Handle get all.
+ *
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param depth the depth
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleGetAll(LinkedHashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ HashMap<String, String> allKeys, int depth, AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleGetAll");
+
+ DynamicEntity outsideObject = null;
+ StringWriter writer = new StringWriter();
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ aaiExtMap.setGraph(g);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+ if (aaiRes.isAllowDirectRead() == false) {
+ throw new AAIException("AAI_3006");
+ }
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ AncestryItems ancestry = new AncestryItems();
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, true, aaiRes.getFullName(), jaxbContext, aaiExtMap);
+
+ String outsideObjectDynamicClass = aaiRes.getResourceClassName();
+ DynamicType outsideObjectObjectType = jaxbContext.getDynamicType(outsideObjectDynamicClass);
+
+ outsideObject = outsideObjectObjectType.newDynamicEntity();
+
+ getObjects(g, outsideObject, aaiRes, depth, ancestry, jaxbContext, aaiExtMap);
+
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+
+ for (MediaType mt : aaiExtMap.getHttpHeaders().getAcceptableMediaTypes()) {
+ if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+ }
+ }
+
+ marshaller.marshal(outsideObject, writer);
+
+ success = true;
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return Response.ok(outsideObject).entity(writer.toString()).build();
+ }
+
+ /**
+ * Handle update rel.
+ *
+ * @param objectFromRequest the object from request
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleUpdateRel(String objectFromRequest,
+ HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList, HashMap<String, String> allKeys,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleUpdateRel");
+
+ boolean success = true;
+ TitanTransaction g = null;
+
+ try {
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ aaiExtMap.setGraph(g);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ AncestryItems ancestry = new AncestryItems();
+
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, true, aaiRes.getFullName(), jaxbContext,
+ aaiExtMap);
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ String dynamicClass;
+ if ("v2".equals(aaiExtMap.getApiVersion()))
+ dynamicClass = "inventory.aai.openecomp.org.Relationship";
+ else
+ dynamicClass = "inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".Relationship";
+
+ if (aaiExtMap.getHttpServletRequest().getContentType() == null ||
+ aaiExtMap.getHttpServletRequest().getContentType().contains("application/json")) {
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+
+ StringReader reader = new StringReader(objectFromRequest);
+
+ DynamicEntity relationship = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+
+ TitanVertex meVertex = ancestry.getAncestryItems().get(aaiExtMap.getFullResourceName()).getVertex();
+
+ RelationshipGraph.updRelationship(g, meVertex, jaxbContext, relationship, aaiExtMap);
+
+ success = true;
+
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+
+ return Response.ok().build();
+
+ }
+
+ /**
+ * Handle delete rel.
+ *
+ * @param objectFromRequest the object from request
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleDeleteRel(String objectFromRequest,
+ HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList, HashMap<String, String> allKeys,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleDeleteRel");
+
+ Response response = null;
+ boolean success = true;
+ TitanTransaction g = null;
+ // boolean hasPayload = false;
+ try {
+
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ aaiExtMap.setGraph(g);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get(aaiExtMap.getFullResourceName());
+
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ AncestryItems ancestry = new AncestryItems();
+
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, true, aaiRes.getFullName(), jaxbContext,
+ aaiExtMap);
+
+ DynamicEntity relationship = null;
+
+ String dynamicClass;
+ if ("v2".equals(aaiExtMap.getApiVersion())) {
+ dynamicClass = "inventory.aai.openecomp.org.Relationship";
+ } else {
+ dynamicClass = "inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".Relationship";
+ }
+ if (objectFromRequest.length() > 0) {
+ // hasPayload = true;
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ if (aaiExtMap.getHttpServletRequest().getContentType().contains("application/json")) {
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+
+ StringReader reader = new StringReader(objectFromRequest);
+
+ relationship = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+
+ } else {
+ throw new AAIException("AAI_3102", "You must supply a relationship");
+ }
+ TitanVertex meVertex = ancestry.getAncestryItems().get(aaiExtMap.getFullResourceName()).getVertex();
+
+ RelationshipGraph.delRelationship(g ,meVertex, jaxbContext, relationship, aaiExtMap);
+
+ response = Response.noContent().build();
+ success = true;
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ success = false;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ success = false;
+ throw ex;
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+
+ }
+
+
+ /**
+ * Handle example.
+ *
+ * @param aaiRes the aai res
+ * @param aaiExtMap the aai ext map
+ * @param singleton the singleton
+ * @param getChildren the get children
+ * @return the response
+ * @throws AAIException the AAI exception
+ */
+ public Response handleExample(AAIResource aaiRes, AAIExtensionMap aaiExtMap, boolean singleton, boolean getChildren)
+ throws AAIException {
+
+ AAIException ex = null;
+
+ LogLine hLogline = new LogLine();
+ hLogline.init(COMPONENT, aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), "handleExample");
+
+ try {
+ Response response = null;
+ if (aaiRes.getResourceType().equals("container")) {
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ PojoUtils pu = new PojoUtils();
+
+
+ DynamicType baseObjectType = jaxbContext.getDynamicType(aaiRes.getSimpleName());
+ DynamicEntity baseObject = baseObjectType.newDynamicEntity();
+
+ DynamicEntity singletonObject = null;
+
+ AAIResources children = aaiRes.getChildren();
+
+ HashMap<String, AAIResource> childResHash = children.getAaiResources();
+
+ for (Map.Entry<String, AAIResource> entry : childResHash.entrySet()) {
+
+ AAIResource aaiChildRes = entry.getValue();
+
+ DynamicType childObjectType = jaxbContext.getDynamicType(aaiChildRes.getSimpleName());
+ DynamicEntity childObject = childObjectType.newDynamicEntity();
+
+ pu.getDynamicExampleObject(childObject, aaiChildRes, singleton);
+
+ // attach this object to its parent
+ List<DynamicEntity> dynamicEntityList = new ArrayList<DynamicEntity>();
+
+ if (aaiChildRes.getChildren().getAaiResources().size() > 0 && getChildren == true) {
+ getExampleWithChildren(aaiChildRes, childObject, singleton, jaxbContext, aaiExtMap);
+ }
+ singletonObject = childObject;
+
+ dynamicEntityList.add(childObject);
+
+ baseObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,aaiChildRes.getSimpleName()), dynamicEntityList);
+ }
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+
+ for (MediaType mt : aaiExtMap.getHttpHeaders().getAcceptableMediaTypes()) {
+ if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE);
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ }
+ }
+
+ if (singleton == true) {
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(singletonObject, writer);
+ response = Response.ok(singletonObject).entity(writer.toString()).build();
+ } else {
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(baseObject, writer);
+
+ response = Response.ok(baseObject).entity(writer.toString()).build();
+ }
+ }
+ return response;
+ } catch (AAIExceptionWithInfo e) {
+ ex = e;
+ throw ex;
+ } catch (AAIException e) {
+ ex = e;
+ throw ex;
+ } catch (Exception e) {
+ ex = new AAIException("AAI_5105", e);
+ throw ex;
+ } finally {
+ AAIGraph.getInstance().graphRollback();
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(hLogline, true, "0");
+ else {
+ aaiLogger.info(hLogline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ }
+
+ /**
+ * Gets the example with children.
+ *
+ * @param aaiRes the aai res
+ * @param baseObject the base object
+ * @param singleton the singleton
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return the example with children
+ * @throws AAIException the AAI exception
+ * @throws ClassNotFoundException the class not found exception
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ */
+ public void getExampleWithChildren(AAIResource aaiRes, DynamicEntity baseObject, boolean singleton, DynamicJAXBContext jaxbContext,
+ AAIExtensionMap aaiExtMap)
+ throws AAIException, ClassNotFoundException, InstantiationException, IllegalAccessException,
+ NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
+
+ AAIResources children = aaiRes.getChildren();
+
+ if (!(children.getAaiResources().size() > 0)) {
+ return;
+ }
+
+ PojoUtils pu = new PojoUtils();
+
+ HashMap<String, AAIResource> childResHash = children.getAaiResources();
+
+ for (Map.Entry<String, AAIResource> entry : childResHash.entrySet()) {
+
+ AAIResource aaiChildRes = entry.getValue();
+
+ if (aaiChildRes.getResourceType().equals("container")) {
+
+ DynamicType childObjectType = jaxbContext.getDynamicType(aaiChildRes.getSimpleName());
+
+ DynamicEntity childObject = childObjectType.newDynamicEntity();
+
+ if (aaiChildRes.getChildren().getAaiResources().size() > 0) {
+ getExampleWithChildren(aaiChildRes, childObject, singleton, jaxbContext, aaiExtMap);
+ }
+
+ baseObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiChildRes.getSimpleName()), childObject);
+
+ } else if (aaiChildRes.getResourceType().equals("node")) {
+
+ DynamicType childObjectType = jaxbContext.getDynamicType(aaiChildRes.getSimpleName());
+ DynamicEntity childObject = childObjectType.newDynamicEntity();
+
+ pu.getDynamicExampleObject(childObject, aaiChildRes, singleton);
+
+ // attach this object to its parent
+
+ List<DynamicEntity> dynamicEntityList = new ArrayList<DynamicEntity>();
+
+ if (aaiChildRes.getChildren().getAaiResources().size() > 0) {
+ getExampleWithChildren(aaiChildRes, childObject, singleton, jaxbContext, aaiExtMap);
+ }
+
+ dynamicEntityList.add(childObject);
+
+ baseObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,aaiChildRes.getSimpleName()), dynamicEntityList);
+
+ }
+ }
+ }
+
+ /**
+ * Put object.
+ *
+ * @param g the g
+ * @param aaiRes the aai res
+ * @param allKeys the all keys
+ * @param lookupHashMapList the lookup hash map list
+ * @param meObject the me object
+ * @param parentVertex the parent vertex
+ * @param objectExisted the object existed
+ * @param jaxbContext the jaxb context
+ * @param ancestry the ancestry
+ * @param aaiExtMap the aai ext map
+ * @return the titan vertex
+ * @throws AAIException the AAI exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws ClassNotFoundException the class not found exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ public TitanVertex putObject(TitanTransaction g, AAIResource aaiRes, HashMap<String, String> allKeys, HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ DynamicEntity meObject, TitanVertex parentVertex, boolean[] objectExisted, DynamicJAXBContext jaxbContext,
+ AncestryItems ancestry, AAIExtensionMap aaiExtMap)
+ throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
+ ClassNotFoundException, InstantiationException, NoSuchMethodException, SecurityException {
+
+ String dnHypResourceType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiRes.getSimpleName());
+ String titanDnHypResourceType = dnHypResourceType;
+
+ // we still have a special case for cvlan-tag-entry
+ if ("cvlan-tag-entry".equals(dnHypResourceType)) {
+ titanDnHypResourceType = "cvlan-tag";
+ }
+
+ TitanVertex meVertex = parentVertex;
+ if ("node".equals(aaiRes.getResourceType())) {
+
+ PojoUtils pu = new PojoUtils();
+ HashMap<String, Object> propHash = new HashMap<String, Object>();
+
+ // this fills in the keys from the URI, if there are any (there won't be with children)
+ if (lookupHashMapList != null) {
+ pu.setPropHashKeys(aaiRes, propHash, aaiRes.getPropertyDataTypeMap(),
+ lookupHashMapList.get(aaiRes.getFullName()), aaiExtMap);
+ }
+
+ // map the properties from the payload to the attribute hash for use with graph layer
+ pu.fillPropHashFromDynamicObject(aaiRes, meObject, propHash, aaiRes.getPropertyDataTypeMap(), aaiExtMap);
+
+ // check required fields
+ checkRequiredProps(dnHypResourceType, aaiRes.getRequiredFields(), propHash);
+
+ // put the vertex in the graph
+
+ if (AAIConfig.get("aai.use.unique.key", "false").equals("true")) {
+
+ String newUniqueKey = allKeys.get(aaiRes.getFullName());
+ propHash.put("aai-unique-key", newUniqueKey);
+ AncestryItem a = ancestry.getAncestryItems().get(aaiRes.getFullName());
+
+ TitanVertex existingVert = null;
+ if (a != null) {
+ existingVert = a.getVertex();
+ }
+ doCheckpoint("PUT_OBJECT_PRE_PERSIST_AAI_NODES_WITHOUT_VERTEX", aaiExtMap);
+ meVertex = DbMeth.persistAaiNode(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g,
+ titanDnHypResourceType, propHash, true, parentVertex, aaiExtMap.getApiVersion(), objectExisted, existingVert);
+ doCheckpoint("PUT_OBJECT_POST_PERSIST_AAI_NODES_WITHOUT_VERTEX", aaiExtMap);
+ } else {
+ doCheckpoint("PUT_OBJECT_PRE_PERSIST_AAI_NODES_WITH_VERTEX", aaiExtMap);
+ meVertex = DbMeth.persistAaiNode(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g,
+ titanDnHypResourceType, propHash, true, parentVertex, aaiExtMap.getApiVersion(), objectExisted);
+ doCheckpoint("PUT_OBJECT_POST_PERSIST_AAI_NODES_WITH_VERTEX", aaiExtMap);
+ }
+
+ // attach this vertex to its parent
+ if (parentVertex != null) {
+ doCheckpoint("PUT_OBJECT_PRE_PERSIST_AAI_EDGE", aaiExtMap);
+ DbMeth.persistAaiEdge(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, parentVertex, meVertex,
+ aaiExtMap.getApiVersion(), "parentChild");
+ doCheckpoint("PUT_OBJECT_POST_PERSIST_AAI_EDGE", aaiExtMap);
+ }
+ try {
+ DynamicEntity relationshipList = meObject.get("relationshipList");
+ RelationshipGraph.updRelationships(g, meVertex, jaxbContext, relationshipList, aaiExtMap);
+ } catch (DynamicException e) { // it's ok, they don't all have relationshipList
+ ;
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+ if (aaiRes.getChildren().getAaiResources().size() > 0 || aaiRes.getRecurseToResource() != null) {
+ // reflect on the object to get children, then put the child
+
+ HashMap<String, AAIResource> children = aaiRes.getChildren().getAaiResources();
+
+ if (aaiRes.getRecurseToResource() != null) {
+ AAIResource recurseToResource = aaiRes.getRecurseToResource();
+ children.put(recurseToResource.getFullName(), recurseToResource);
+ }
+
+ for (Entry<String, AAIResource> ent : children.entrySet()) {
+ AAIResource aaiChildRes = ent.getValue();
+
+ if ("container".equals(aaiChildRes.getResourceType())) {
+
+ // make a new container and attach it to the baseObject
+
+ DynamicEntity childObject = meObject
+ .get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiChildRes.getSimpleName()));
+
+ if (childObject != null) {
+ if (aaiChildRes.getChildren().getAaiResources().size() > 0) {
+ // add this container name to the key, in lower case, natch
+
+
+ allKeys.put(aaiChildRes.getFullName(),
+ allKeys.get(aaiRes.getFullName()) + "/" +
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,aaiChildRes.getSimpleName()).toLowerCase());
+
+ putObject(g, aaiChildRes, allKeys, null, childObject, meVertex, new boolean[1], jaxbContext, ancestry, aaiExtMap);
+ }
+ }
+ } else if ("node".equals(aaiChildRes.getResourceType())) {
+
+ if (meObject != null) {
+
+ String childDnHypResourceType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,
+ aaiChildRes.getSimpleName());
+ // expect to find this attached to the node
+
+ // for now, i think there's only one of these.
+ String titanChildDnHypResourceType = childDnHypResourceType;
+ if ("cvlan-tag-entry".equals(childDnHypResourceType)) {
+ titanChildDnHypResourceType = "cvlan-tag";
+ }
+ List<DynamicEntity> objList = meObject
+ .get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiChildRes.getSimpleName()));
+ doCheckpoint("PUT_OBJECT_PRE_GET_CONNECTED_NODES", aaiExtMap);
+ List<TitanVertex> deleteCandidateList = DbMeth.getConnectedChildren(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, meVertex, titanChildDnHypResourceType);
+ doCheckpoint("PUT_OBJECT_POST_GET_CONNECTED_NODES", aaiExtMap);
+ if (objList != null) {
+
+ for (DynamicEntity childObjFromList : objList) {
+
+ // figure out the keys from the payload and apply it to the allKeys hash
+ AAIResourceKeys aaiResKeys = aaiChildRes.getAaiResourceKeys();
+ String childKey = allKeys.get(aaiRes.getFullName()) + "/" +
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,aaiChildRes.getSimpleName()).toLowerCase();
+ for (AAIResourceKey rk : aaiResKeys.getAaiResourceKey()) {
+ String dnCamKeyName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,rk.getKeyName());
+ childKey += "/" + childObjFromList.get(dnCamKeyName);
+ }
+
+ // this will potentially overwrite the last one, but that's ok since
+ // we want to use it the next time we call persist AAI node
+ // all children should persisted under this node before this goes away
+ allKeys.put(aaiChildRes.getFullName(), childKey);
+
+
+ TitanVertex vert = putObject(g, aaiChildRes, allKeys, null, childObjFromList, meVertex,
+ new boolean[1], jaxbContext, ancestry, aaiExtMap);
+ deleteCandidateList.remove(vert);
+
+ }
+ }
+ for (TitanVertex deleteVertex : deleteCandidateList) {
+ String resourceVersion = "";
+ if (deleteVertex.property("resource-version").orElse(null) != null) {
+ resourceVersion = deleteVertex.<String>property("resource-version").orElse(null);
+ }
+ doCheckpoint("PUT_OBJECT_PRE_DELETE_EXTRA_NODE", aaiExtMap);
+ DbMeth.removeAaiNode(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g,
+ deleteVertex, "USE_DEFAULT", aaiExtMap.getApiVersion(), resourceVersion);
+ doCheckpoint("PUT_OBJECT_POST_DELETE_EXTRA_NODE", aaiExtMap);
+ }
+ }
+ }
+ }
+ }
+ return meVertex;
+ }
+
+ /**
+ * Delete object.
+ *
+ * @param g the g
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param jaxbContext the jaxb context
+ * @param resourceVersion the resource version
+ * @param aaiRes the aai res
+ * @param aaiResources the aai resources
+ * @param topObjectSimpleResourceName the top object simple resource name
+ * @param aaiExtMap the aai ext map
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void deleteObject(TitanTransaction g, HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ HashMap<String, String> allKeys, DynamicJAXBContext jaxbContext, String resourceVersion,
+ AAIResource aaiRes, AAIResources aaiResources, String topObjectSimpleResourceName, AAIExtensionMap aaiExtMap) throws AAIException, UnsupportedEncodingException {
+
+ AncestryItems ancestry = new AncestryItems();
+ getAncestry(g, lookupHashMapList, allKeys, aaiRes, ancestry, true, aaiRes.getFullName(), jaxbContext, aaiExtMap);
+
+ TitanVertex meVertex = ancestry.getAncestryItems().get(aaiRes.getFullName()).getVertex();
+
+ String objectNameForExtensions = aaiRes.getFullName().replace("/", "");
+ aaiRes.getSimpleName();
+
+ ExtensionController ext = new ExtensionController();
+ ext.runExtension(aaiExtMap.getApiVersion(),
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiRes.getNamespace()),
+ topObjectSimpleResourceName,
+ "DynamicDel" + objectNameForExtensions + "PreProc",
+ aaiExtMap,
+ true);
+
+ storeNotificationEvent(g, "DELETE", meVertex, null, aaiRes, ancestry, aaiResources, aaiExtMap);
+
+ doCheckpoint("HANDLE_DELETE_PRE_DELETE", aaiExtMap);
+ DbMeth.removeAaiNode(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, meVertex, "USE_DEFAULT",
+ aaiExtMap.getApiVersion(), resourceVersion);
+
+ ext.runExtension(aaiExtMap.getApiVersion(),
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiRes.getNamespace()),
+ topObjectSimpleResourceName,
+ "DynamicDel" + objectNameForExtensions + "PostProc",
+ aaiExtMap,
+ false);
+
+ doCheckpoint("HANDLE_DELETE_POST_DELETE", aaiExtMap);
+
+ }
+
+ /**
+ * Gets the objects.
+ *
+ * @param g the g
+ * @param outsideObject the outside object
+ * @param aaiRes the aai res
+ * @param depth the depth
+ * @param ancestry the ancestry
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return the objects
+ * @throws ClassNotFoundException the class not found exception
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void getObjects(TitanTransaction g, DynamicEntity outsideObject, AAIResource aaiRes, int depth, AncestryItems ancestry,
+ DynamicJAXBContext jaxbContext, AAIExtensionMap aaiExtMap)
+ throws ClassNotFoundException, InstantiationException, IllegalAccessException, AAIException,
+ IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException,
+ UnsupportedEncodingException {
+
+ if (aaiRes.getResourceType().equals("container")) {
+
+ AAIResources children = aaiRes.getChildren();
+
+ if (!(children.getAaiResources().size() > 0)) {
+ return;
+ }
+
+ HashMap<String, AAIResource> childResHash = children.getAaiResources();
+ if (aaiRes.getRecurseToResource() != null) {
+ AAIResource recurseToResource = aaiRes.getRecurseToResource();
+ childResHash.put(recurseToResource.getFullName(), recurseToResource);
+ }
+ for (Map.Entry<String, AAIResource> entry : childResHash.entrySet()) {
+
+ AAIResource aaiChildRes = entry.getValue();
+
+ DynamicType childObjectType = jaxbContext.getDynamicType(aaiChildRes.getSimpleName());
+
+ String dnHypResourceType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,
+ aaiChildRes.getSimpleName());
+ String titanDnHypResourceType = dnHypResourceType;
+ if ("cvlan-tag-entry".equals(dnHypResourceType)) {
+ titanDnHypResourceType = "cvlan-tag";
+ }
+
+ TitanVertex parentVertex = null;
+
+ if (aaiRes.getParent() != null) {
+ AAIResource parent = aaiRes.getParent();
+ if (parent.getResourceType().equals("node")) {
+ parentVertex = ancestry.getAncestryItems().get(parent.getFullName()).getVertex();
+ } else {
+ if (parent.getParent() != null && parent.getParent().getResourceType().equals("node")) {
+ parentVertex = ancestry.getAncestryItems().get(parent.getParent().getFullName()).getVertex();
+ }
+ }
+ }
+
+ doCheckpoint("GET_OBJECTS_PRE_GET_NODES", aaiExtMap);
+ ArrayList<TitanVertex> vertices = new ArrayList<TitanVertex>();
+ if (parentVertex == null) {
+ vertices = DbMeth.getNodes(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(),
+ g, titanDnHypResourceType, new HashMap<String, Object>(), true,
+ aaiChildRes.getApiVersion());
+ } else {
+ vertices = DbMeth.getConnectedChildren(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, parentVertex, titanDnHypResourceType);
+ }
+ doCheckpoint("GET_OBJECTS_POST_GET_NODES", aaiExtMap);
+ List<DynamicEntity> childDynamicEntityList = new ArrayList<DynamicEntity>();
+
+ for (TitanVertex vert : vertices) {
+
+ DynamicEntity childObject = childObjectType.newDynamicEntity();
+
+ childObject = getObject(g, vert, vert, aaiChildRes, null, depth, ancestry, jaxbContext, aaiExtMap.getApiVersion(),
+ aaiExtMap);
+
+ childDynamicEntityList.add(childObject);
+ }
+ outsideObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,aaiChildRes.getSimpleName()), childDynamicEntityList);
+ }
+ }
+ }
+
+
+ /**
+ * Gets the object.
+ *
+ * @param g the g
+ * @param meVertex the me vertex
+ * @param baseVertex the base vertex
+ * @param aaiRes the aai res
+ * @param topologyUntilThisOne the topology until this one
+ * @param depth the depth
+ * @param ancestry the ancestry
+ * @param jaxbContext the jaxb context
+ * @param apiVersion the api version
+ * @param aaiExtMap the aai ext map
+ * @return the object
+ * @throws AAIException the AAI exception
+ */
+ public DynamicEntity getObject(TitanTransaction g, TitanVertex meVertex, TitanVertex baseVertex, AAIResource aaiRes,
+ String topologyUntilThisOne, int depth, AncestryItems ancestry,
+ DynamicJAXBContext jaxbContext, String apiVersion, AAIExtensionMap aaiExtMap) throws AAIException {
+
+ DynamicEntity meObject;
+ try {
+
+ DynamicType meObjectType = jaxbContext.getDynamicType(aaiRes.getResourceClassName());
+
+ meObject = meObjectType.newDynamicEntity();
+
+ PojoUtils pu = new PojoUtils();
+
+ boolean doTopology = false;
+ if (topologyUntilThisOne != null) {
+ doTopology = true;
+ }
+
+ if (doTopology == true) {
+ if (aaiRes.getFullName().equals(topologyUntilThisOne)) {
+ doTopology = false;
+ }
+ }
+
+ if (doTopology == true) {
+ String notificationVersion = AAIConfig.get("aai.notification.current.version");
+
+ AAIResources aaiNotificationResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(notificationVersion);
+
+ DynamicJAXBContext notificationJaxbContext = aaiNotificationResources.getJaxbContext();
+
+ meObject = unpackAncestry(g, ancestry, topologyUntilThisOne, notificationJaxbContext, aaiExtMap);
+ } else {
+ pu.getAaiDynamicObjectFromVertex(aaiRes, meObject, baseVertex, aaiRes.getPropertyDataTypeMap());
+
+ DynamicEntity newRelationshipList = RelationshipGraph.getRelationships(g, meVertex, apiVersion, aaiExtMap);
+
+ try {
+ meObject.set("relationshipList", newRelationshipList);
+ } catch (DynamicException e) {
+ ;
+ }
+
+ if (aaiRes.getChildren() != null || aaiRes.getRecurseToResource() != null) {
+
+ if (depth == -1 || depth > 0) {
+ int nextDepth = depth;
+ if (depth != -1) {
+ nextDepth--;
+ }
+
+ if (aaiRes.getChildren().getAaiResources().size() > 0 || aaiRes.getRecurseToResource() != null) {
+ getDescendants(g, baseVertex, meVertex, nextDepth, meObject, aaiRes, ancestry,
+ apiVersion, jaxbContext, aaiExtMap);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new AAIException("AAI_3000", e);
+ }
+ return meObject;
+
+ }
+
+ /**
+ * Gets the descendants.
+ *
+ * @param g the g
+ * @param baseVertex the base vertex
+ * @param stopTopologyVertex the stop topology vertex
+ * @param depth the depth
+ * @param baseObject the base object
+ * @param aaiRes the aai res
+ * @param ancestry the ancestry
+ * @param apiVersion the api version
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return the descendants
+ * @throws AAIException the AAI exception
+ * @throws ClassNotFoundException the class not found exception
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private void getDescendants(TitanTransaction g, TitanVertex baseVertex, TitanVertex stopTopologyVertex, int depth, DynamicEntity baseObject,
+ AAIResource aaiRes, AncestryItems ancestry,
+ String apiVersion, DynamicJAXBContext jaxbContext, AAIExtensionMap aaiExtMap) throws AAIException,
+ ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException, NoSuchMethodException, SecurityException, UnsupportedEncodingException {
+
+
+ if (aaiRes.getChildren() == null) {
+ return;
+ }
+
+ AAIResources children = aaiRes.getChildren();
+
+ PojoUtils pu = new PojoUtils();
+
+ HashMap<String, AAIResource> childResHash = children.getAaiResources();
+
+ if (aaiRes.getRecurseToResource() != null) {
+ AAIResource recurseToResource = aaiRes.getRecurseToResource();
+ childResHash.put(recurseToResource.getFullName(), recurseToResource);
+ }
+
+ // check to see if we're stopping topology at this level. this prevents us from digging
+ // into the sibling objects which we're not supposed to include here
+
+ for (Map.Entry<String, AAIResource> entry : childResHash.entrySet()) {
+
+ AAIResource aaiChildRes = entry.getValue();
+
+ if (aaiChildRes.getResourceType().equals("container")) {
+ // make a new container and attach it to the baseObject
+
+ DynamicType childObjectType = jaxbContext.getDynamicType(aaiChildRes.getResourceClassName());
+
+ DynamicEntity childObject = childObjectType.newDynamicEntity();
+
+ baseObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiChildRes.getSimpleName()),
+ childObject);
+ if (aaiChildRes.getChildren() != null || aaiChildRes.getRecurseToResource() != null) {
+ if (aaiChildRes.getChildren().getAaiResources().size() > 0 || aaiChildRes.getRecurseToResource() != null) {
+ getDescendants(g, baseVertex, stopTopologyVertex, depth, childObject, aaiChildRes,
+ ancestry, apiVersion, jaxbContext, aaiExtMap);
+ }
+ }
+ } else if (aaiChildRes.getResourceType().equals("node")) {
+
+ String dnHypResourceType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,
+ aaiChildRes.getSimpleName());
+ // expect to find this attached to the node
+
+ // for now, i think there's only one of these.
+ String titanDnHypResourceType = dnHypResourceType;
+ if ("cvlan-tag-entry".equals(dnHypResourceType)) {
+ titanDnHypResourceType = "cvlan-tag";
+ }
+ List<DynamicEntity> childList = new ArrayList<DynamicEntity>();
+ // load the set of children into childList, and then attach it
+ // to the parent
+
+ if (depth == -1 || depth >= 0) {
+ int nextDepth = depth;
+ if (depth != -1) {
+ nextDepth--;
+ }
+ if (depth == 0) {
+ // we want to stop when we get to zero, but AFTER we process these connected nodes
+ nextDepth = -2;
+ }
+
+ doCheckpoint("GET_DESCENDANTS_PRE_GET_CONNECTED_NODES", aaiExtMap);
+ ArrayList<TitanVertex> vertices = DbMeth.getConnectedChildren(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, baseVertex, titanDnHypResourceType);
+
+ doCheckpoint("GET_DESCENDANTS_POST_GET_CONNECTED_NODES", aaiExtMap);
+ for (TitanVertex childVert : vertices) {
+
+ DynamicType childObjectType = jaxbContext.getDynamicType(aaiChildRes.getResourceClassName());
+
+ DynamicEntity childObject = childObjectType.newDynamicEntity();
+
+ pu.getAaiDynamicObjectFromVertex(aaiChildRes, childObject, childVert,
+ aaiChildRes.getPropertyDataTypeMap());
+
+ // add this child object to the list
+ childList.add(childObject);
+ try {
+ childObject.set("relationshipList", RelationshipGraph.getRelationships(g, childVert, apiVersion, aaiExtMap));
+ } catch (DynamicException e) {
+ ;
+ } catch (Exception e1) {
+ throw e1;
+ }
+
+ if (nextDepth >= 0 || nextDepth == -1) {
+ if (aaiChildRes.getChildren().getAaiResources().size() > 0 || aaiChildRes.getRecurseToResource() != null) {
+ getDescendants(g, childVert, stopTopologyVertex, nextDepth, childObject, aaiChildRes,
+ ancestry, apiVersion, jaxbContext, aaiExtMap);
+ }
+ }
+ }
+ }
+ baseObject.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiChildRes.getSimpleName()),
+ childList);
+ }
+ }
+ }
+
+ /**
+ * Gets the ancestry.
+ *
+ * @param g the g
+ * @param lookupHashMapList the lookup hash map list
+ * @param allKeys the all keys
+ * @param aaiRes the aai res
+ * @param ancestry the ancestry
+ * @param includeSelf the include self
+ * @param selfFullName the self full name
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return the ancestry
+ * @throws AAIException the AAI exception
+ */
+ public void getAncestry(TitanTransaction g, HashMap<String, LinkedHashMap<String, Object>> lookupHashMapList,
+ HashMap<String, String> allKeys, AAIResource aaiRes, AncestryItems ancestry, boolean includeSelf,
+ String selfFullName, DynamicJAXBContext jaxbContext, AAIExtensionMap aaiExtMap) throws AAIException {
+
+
+ AAIResource parent = aaiRes.getParent();
+
+ if (parent != null && !parent.getFullName().equals("/Inventory")) {
+ getAncestry(g, lookupHashMapList, allKeys, parent, ancestry, includeSelf, selfFullName, jaxbContext,
+ aaiExtMap);
+ }
+ PojoUtils pu = new PojoUtils();
+ if (aaiRes.getResourceType().equals("node")) {
+ // we're at the top, get me the vertex
+ // it'll be the hyphencased node name, unless it's a cvlan-tag, i
+ // think?
+ String dnHypResourceType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiRes.getSimpleName());
+ if (dnHypResourceType.equals("cvlan-tag-entry")) {
+ dnHypResourceType = "cvlan-tag";
+ }
+ HashMap<String, Object> propHash = lookupHashMapList.get(aaiRes.getFullName());
+ if (propHash != null) {
+
+ boolean stop = false;
+ if (includeSelf == false && aaiRes.getFullName().equals(selfFullName)) {
+ stop = true;
+ }
+
+ // try first to the get the unique node by its key
+
+ TitanVertex vert = null;
+ if (AAIConfig.get("aai.use.unique.key", "false").equals("true")) {
+ try {
+ HashMap<String,Object> keyPropHash = new HashMap<String,Object>();
+
+ keyPropHash.put("aai-unique-key", allKeys.get(aaiRes.getFullName()));
+ String key = allKeys.get(aaiRes.getFullName());
+ doCheckpoint("GET_ANCESTRY_PRE_GET_BY_KEY|" + key, aaiExtMap);
+ DbMeth d = new DbMeth();
+ vert = d.getNodeByUniqueKey(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, key);
+ doCheckpoint("GET_ANCESTRY_POST_GET_BY_KEY|" + key + ",VERT=" + vert, aaiExtMap);
+ } catch (Exception e1) {
+ if (stop == true) {
+ return;
+ }
+ }
+ }
+
+ // try again, i couldn't find it by the key
+ if (vert == null && stop != true) {
+ // the parent will be 1 or 2 nodes up
+ TitanVertex depNode = null;
+
+ if (parent != null) {
+ if (parent.getResourceType().equals("node")) {
+ depNode = ancestry.getAncestryItems().get(parent.getFullName()).getVertex();
+ } else if (parent.getParent().getResourceType() != null
+ && parent.getParent().getResourceType().equals("node")) {
+ depNode = ancestry.getAncestryItems().get(parent.getParent().getFullName()).getVertex();
+ }
+ }
+
+ doCheckpoint("GET_ANCESTRY_PRE_GET_UNIQUE_NODE", aaiExtMap);
+ vert = DbMeth.getUniqueNode(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, dnHypResourceType,
+ propHash, depNode, aaiExtMap.getApiVersion());
+ doCheckpoint("GET_ANCESTRY_POST_GET_UNIQUE_NODE", aaiExtMap);
+
+ }
+ if (vert != null) {
+ try {
+
+ String notificationVersion = AAIConfig.get("aai.notification.current.version");
+
+ if (aaiRes != null && aaiRes.getApiVersion().matches("v[2-6]$") && aaiRes.getFullName() != null ) {
+ String[] fullNameSplit = aaiRes.getFullName().split("/");
+ if (fullNameSplit.length > 3) {
+ if (fullNameSplit[3] != null && CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, fullNameSplit[3]).matches("tenant|image|flavor|volume\\-group|availability\\-zone|oam\\-network|dvs\\-switch")) {
+ notificationVersion = aaiRes.getApiVersion();
+ }
+ }
+ }
+
+
+ AAIResources aaiNotificationResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(notificationVersion);
+
+ DynamicJAXBContext notificationJaxbContext = aaiNotificationResources.getJaxbContext();
+
+ String resFullName = aaiRes.getFullName();
+ if (aaiNotificationResources.getAaiResources().containsKey(resFullName)) {
+ AAIResource notificationRes = aaiNotificationResources.getAaiResources().get(aaiRes.getFullName());
+
+ AncestryItem ancestryItem = new AncestryItem();
+
+ ancestryItem.setFullResourceName(notificationRes.getFullName());
+ ancestryItem.setAaiResource(notificationRes);
+ ancestryItem.setVertex(vert);
+
+ DynamicType meObjectType = notificationJaxbContext.getDynamicType(notificationRes.getResourceClassName());
+
+ DynamicEntity notificationObject = pu.getDynamicTopologyObject(aaiRes,
+ meObjectType,
+ notificationRes.getNodeNameProps(),
+ notificationRes.getNodeKeyProps(),
+ notificationRes.getPropertyDataTypeMap(),
+ vert);
+
+ ancestryItem.setObj(notificationObject);
+ ancestry.getAncestryItems().put(aaiRes.getFullName(), ancestryItem);
+ }
+ } catch (Exception e) {
+ throw new AAIException("AAI_3000", e);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Unpack ancestry.
+ *
+ * @param g the g
+ * @param ancestry the ancestry
+ * @param topologyUntilThisOne the topology until this one
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return the dynamic entity
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws ClassNotFoundException the class not found exception
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ public DynamicEntity unpackAncestry (TitanTransaction g, AncestryItems ancestry, String topologyUntilThisOne, DynamicJAXBContext jaxbContext, AAIExtensionMap aaiExtMap)
+ throws UnsupportedEncodingException, AAIException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+
+ LinkedHashMap<String,AncestryItem> ancestryHash = ancestry.getAncestryItems();
+ String apiVersion = AAIConfig.get("aai.notification.current.version", "v7");
+
+ DynamicEntity outsideObject = null;
+
+ for (Map.Entry<String,AncestryItem> ent : ancestryHash.entrySet()) {
+
+ AncestryItem anc = ent.getValue();
+
+ AAIResource aaiRes = anc.getAaiResource();
+
+ DynamicEntity ancestryObj = (DynamicEntity) anc.getObj();
+ TitanVertex ancestryVertex = anc.getVertex();
+
+ if (outsideObject == null) {
+ outsideObject = ancestryObj;
+ }
+
+ if (topologyUntilThisOne.equals(aaiRes.getFullName())) {
+ PojoUtils pu = new PojoUtils();
+ pu.getAaiDynamicObjectFromVertex(aaiRes, ancestryObj, ancestryVertex, aaiRes.getPropertyDataTypeMap());
+
+ DynamicEntity newRelationshipList = RelationshipGraph.getRelationships(g, ancestryVertex, apiVersion, aaiExtMap);
+
+ try {
+ ancestryObj.set("relationshipList", newRelationshipList);
+ } catch (DynamicException e) {
+ ;
+ }
+ if (aaiRes.getChildren() != null) {
+ if (aaiRes.getChildren().getAaiResources().size() > 0) {
+ getDescendants(g, ancestryVertex, ancestryVertex, -1, ancestryObj, aaiRes, ancestry,
+ apiVersion, jaxbContext, aaiExtMap);
+ }
+ }
+ } else {
+ if (aaiRes.getChildren() != null) {
+
+ for (Map.Entry<String,AAIResource> childEnt : aaiRes.getChildren().getAaiResources().entrySet()) {
+
+ String childEntFullName = childEnt.getKey();
+ AAIResource childRes = childEnt.getValue();
+
+ // this could be a direct descendant
+ if (ancestryHash.containsKey(childEntFullName)) {
+
+ AncestryItem childAnc = ancestryHash.get(childEntFullName);
+ DynamicEntity childObj = (DynamicEntity) childAnc.getObj();
+
+ TitanVertex childVertex = childAnc.getVertex();
+
+ if (topologyUntilThisOne.equals(childRes.getFullName())) {
+ PojoUtils pu = new PojoUtils();
+ pu.getAaiDynamicObjectFromVertex(childRes, childObj, childVertex, childRes.getPropertyDataTypeMap());
+
+ DynamicEntity newRelationshipList = RelationshipGraph.getRelationships(g, childVertex, apiVersion, aaiExtMap);
+
+ try {
+ childObj.set("relationshipList", newRelationshipList);
+ } catch (DynamicException e) {
+ ;
+ }
+ if (childRes.getChildren() != null) {
+ if (childRes.getChildren().getAaiResources().size() > 0) {
+ getDescendants(g, childVertex, childVertex, -1, childObj, childRes, ancestry,
+ apiVersion, jaxbContext, aaiExtMap);
+ }
+ }
+ }
+ List<DynamicEntity> cList = new ArrayList<DynamicEntity>();
+ cList.add(childObj);
+ // we're going to include this
+ ancestryObj.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,childRes.getSimpleName()), cList);
+
+ }
+
+ // or a grandchild
+ if (childRes.getChildren() != null) {
+
+ for (Map.Entry<String,AAIResource> grandchildEnt : childRes.getChildren().getAaiResources().entrySet()) {
+
+ String grandchildEntFullName = grandchildEnt.getKey();
+ AAIResource grandchildRes = grandchildEnt.getValue();
+
+ if (ancestryHash.containsKey(grandchildEntFullName)) {
+
+ // we need to attach the parent
+ AncestryItem grandchildAnc = ancestryHash.get(grandchildEntFullName);
+ DynamicEntity grandchildObj = (DynamicEntity) grandchildAnc.getObj();
+ TitanVertex grandchildVertex = grandchildAnc.getVertex();
+ // we're going to include this
+
+ if (topologyUntilThisOne.equals(grandchildRes.getFullName())) {
+ PojoUtils pu = new PojoUtils();
+ pu.getAaiDynamicObjectFromVertex(grandchildRes, grandchildObj, grandchildVertex, grandchildRes.getPropertyDataTypeMap());
+
+ DynamicEntity newRelationshipList = RelationshipGraph.getRelationships(g, grandchildVertex, apiVersion, aaiExtMap);
+
+ try {
+ grandchildObj.set("relationshipList", newRelationshipList);
+ } catch (DynamicException e) {
+ ;
+ }
+ if (childRes.getChildren() != null) {
+ if (childRes.getChildren().getAaiResources().size() > 0) {
+ getDescendants(g, grandchildVertex, grandchildVertex, -1, grandchildObj, grandchildRes, ancestry,
+ apiVersion, jaxbContext, aaiExtMap);
+ }
+ }
+ }
+
+ List<DynamicEntity> gcList = new ArrayList<DynamicEntity>();
+
+ gcList.add(grandchildObj);
+
+ DynamicEntity childObj = jaxbContext.newDynamicEntity(childRes.getResourceClassName());
+
+ childObj.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,grandchildRes.getSimpleName()), gcList);
+
+ ancestryObj.set(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,childRes.getSimpleName()), childObj);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return outsideObject;
+ }
+
+ /**
+ * Checks if is event enabled.
+ *
+ * @param action the action
+ * @param namespace the namespace
+ * @param simpleName the simple name
+ * @return true, if is event enabled
+ * @throws AAIException the AAI exception
+ */
+ public boolean isEventEnabled(String action, String namespace, String simpleName) throws AAIException {
+ boolean isEventEnabled = true;
+ if ((AAIConfig.get("aai.notificationEvent.disable.aaiEvent.global." + action, "false").equals("true"))
+ || (AAIConfig
+ .get("aai.notificationEvent.disable.aaiEvent.graph." + namespace + "Graph." + action, "false")
+ .equals("true"))
+ || (AAIConfig.get("aai.notificationEvent.disable.aaiEvent.object." + simpleName + "." + action, "false")
+ .equals("true"))) {
+ isEventEnabled = false;
+ }
+ return isEventEnabled;
+ }
+
+ /**
+ * Check required props.
+ *
+ * @param dnHypResourceType the dn hyp resource type
+ * @param requiredProps the required props
+ * @param propHash the prop hash
+ * @throws AAIException the AAI exception
+ */
+ private void checkRequiredProps(String dnHypResourceType, Collection<String> requiredProps,
+ HashMap<String, Object> propHash) throws AAIException {
+ ArrayList<String> missingFields = new ArrayList<String>();
+ ArrayList<String> emptyFields = new ArrayList<String>();
+
+ for (String reqProp : requiredProps) {
+ if (propHash.containsKey(reqProp)) {
+ if (propHash.get(reqProp) == null) {
+ missingFields.add(reqProp);
+ } else {
+ Object tmpObj = propHash.get(reqProp);
+ if (tmpObj.toString().trim().equals("")) {
+ emptyFields.add(reqProp);
+ }
+ }
+ } else {
+ missingFields.add(reqProp);
+ }
+ }
+
+ if (missingFields.size() > 0) {
+ StringBuffer missing = new StringBuffer();
+ boolean isFirst = true;
+ for (String missingAttr : missingFields) {
+ if (!isFirst) {
+ missing.append(",");
+ }
+ missing.append(missingAttr);
+ isFirst = false;
+ }
+ String reqP = missingFields.get(0);
+ logline.add("property", reqP);
+ logline.add("nodeType", dnHypResourceType);
+ aaiLogger.info(logline, false, "AAI_6103");
+ String detail = "[REST] Required property = " + missing + " not passed for nodeType = " + dnHypResourceType;
+ throw new AAIException("AAI_6103", detail);
+ }
+ if (emptyFields.size() > 0) {
+ StringBuffer empty = new StringBuffer();
+ boolean isFirst = true;
+ for (String emptyAttr : emptyFields) {
+ if (!isFirst) {
+ empty.append(",");
+ }
+ empty.append(emptyAttr);
+ isFirst = false;
+ }
+ String reqP = emptyFields.get(0);
+ logline.add("property", reqP);
+ logline.add("nodeType", dnHypResourceType);
+ aaiLogger.info(logline, false, "AAI_6104");
+ String detail = "[REST] Required property = " + empty + " for nodeType = " + dnHypResourceType
+ + " was passed with no data";
+ throw new AAIException("AAI_6104", detail);
+ }
+
+ }
+
+ /**
+ * Store notification event.
+ *
+ * @param g the g
+ * @param eventAction the event action
+ * @param meVertex the me vertex
+ * @param meObject the me object
+ * @param aaiRes the aai res
+ * @param ancestry the ancestry
+ * @param aaiResources the aai resources
+ * @param aaiExtMap the aai ext map
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void storeNotificationEvent(TitanTransaction g, String eventAction, TitanVertex meVertex, DynamicEntity meObject,
+ AAIResource aaiRes, AncestryItems ancestry, AAIResources aaiResources, AAIExtensionMap aaiExtMap) throws AAIException, UnsupportedEncodingException {
+
+ storeNotificationEvent(g, eventAction, meVertex, meObject, aaiRes, ancestry, aaiResources, aaiExtMap, "");
+
+ }
+
+ /**
+ * Store notification event.
+ *
+ * @param g the g
+ * @param eventAction the event action
+ * @param meVertex the me vertex
+ * @param meObject the me object
+ * @param aaiRes the aai res
+ * @param ancestry the ancestry
+ * @param aaiResources the aai resources
+ * @param aaiExtMap the aai ext map
+ * @param overrideUri the override uri
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void storeNotificationEvent(TitanTransaction g, String eventAction, TitanVertex meVertex, DynamicEntity meObject,
+ AAIResource aaiRes, AncestryItems ancestry, AAIResources aaiResources, AAIExtensionMap aaiExtMap, String overrideUri)
+ throws AAIException, UnsupportedEncodingException {
+
+ String notificationVersion = AAIConfig.get("aai.notification.current.version");
+
+ AAIResources aaiNotificationResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(notificationVersion);
+
+ DynamicJAXBContext notificationJaxbContext = aaiNotificationResources.getJaxbContext();
+
+ DynamicEntity notificationHeader = notificationJaxbContext
+ .getDynamicType("inventory.aai.openecomp.org." + notificationVersion + ".NotificationEventHeader")
+ .newDynamicEntity();
+
+ boolean storeEvent = isEventEnabled((String) notificationHeader.get("action"), aaiExtMap.getNamespace(),
+ aaiRes.getSimpleName());
+
+ if (storeEvent == true) {
+ // get the parent/gp/greatGp vertex, it will be the container
+ if (overrideUri.length() > 0) {
+ notificationHeader.set("entityLink", overrideUri);
+ } else {
+ notificationHeader.set("entityLink", aaiExtMap.getNotificationUri());
+ }
+ notificationHeader.set("action", eventAction);
+ String entityType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiRes.getSimpleName());
+
+ if (entityType.equals("cvlan-tag-entry")) {
+ entityType = "cvlan-tag";
+ }
+ notificationHeader.set("entityType", entityType);
+
+ String topEntityType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiRes.getSimpleName());
+
+ if (topEntityType.equals("cvlan-tag-entry")) {
+ topEntityType = "cvlan-tag";
+ }
+ notificationHeader.set("topEntityType", topEntityType);
+
+ notificationHeader.set("sourceName", aaiExtMap.getFromAppId());
+
+ notificationHeader.set("version", notificationVersion);
+
+ StoreNotificationEvent sne = new StoreNotificationEvent();
+
+ AAIResource aaiActualRes = aaiRes;
+
+ if (aaiExtMap.getTopObjectFullResourceName().equals(aaiExtMap.getFullResourceName())) {
+
+ aaiActualRes = aaiRes;
+ if (!aaiRes.getApiVersion().equals(notificationVersion)) {
+ aaiActualRes = aaiNotificationResources.getAaiResources().get(aaiRes.getFullName());
+ }
+
+ // -1 depth means get all the children to any depth
+ meObject = getObject(g, meVertex, meVertex, aaiActualRes, null, -1, ancestry,
+ notificationJaxbContext, notificationVersion, aaiExtMap);
+
+ sne.storeDynamicEvent(notificationJaxbContext, notificationVersion, notificationHeader, meObject);
+ aaiExtMap.setObjectFromResponse(meObject);
+ aaiExtMap.setObjectFromResponseType(aaiActualRes.getResourceClassName());
+ } else {
+ AAIResource topRes = aaiNotificationResources.getAaiResources().get(aaiExtMap.getTopObjectFullResourceName());
+ TitanVertex topVertex = ancestry.getAncestryItems().get(aaiExtMap.getTopObjectFullResourceName())
+ .getVertex();
+
+ aaiActualRes = topRes;
+ if (!aaiRes.getApiVersion().equals(notificationVersion)) {
+ aaiActualRes = aaiNotificationResources.getAaiResources().get(topRes.getFullName());
+ }
+ // -1 depth means get all the children to any depth
+ DynamicEntity topObject = getObject(g, meVertex, topVertex, aaiActualRes, aaiRes.getFullName(), -1,
+ ancestry, notificationJaxbContext, notificationVersion, aaiExtMap);
+
+ notificationHeader.set("topEntityType",
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, topRes.getSimpleName()));
+
+ sne.storeDynamicEvent(notificationJaxbContext, notificationVersion, notificationHeader, topObject);
+ aaiExtMap.setObjectFromResponse(topObject);
+ aaiExtMap.setObjectFromResponseType(aaiActualRes.getResourceClassName());
+ }
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/RelationshipGraph.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/RelationshipGraph.java
new file mode 100644
index 0000000..4ca6b92
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/RelationshipGraph.java
@@ -0,0 +1,299 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.map.MultiValueMap;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dbgen.DbEdgeGroup;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.RestURL;
+
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class RelationshipGraph {
+
+ /**
+ * this method processes the one relationship for the startVertex that is
+ * sent.
+ *
+ * @param g the g
+ * @param startVertex the start vertex
+ * @param jaxbContext the jaxb context
+ * @param rel the rel
+ * @param aaiExtMap the aai ext map
+ * @throws AAIException the AAI exception
+ */
+ public static void updRelationship(TitanTransaction g, TitanVertex startVertex,
+ DynamicJAXBContext jaxbContext,
+ DynamicEntity rel,
+ AAIExtensionMap aaiExtMap)
+ throws AAIException {
+ String apiVersion = aaiExtMap.getApiVersion();
+ String transId = aaiExtMap.getTransId();
+ String fromAppId = aaiExtMap.getFromAppId();
+ MultiValueMap relatedNodesMap = new MultiValueMap();
+
+ if( rel != null ){
+ HashMap<String, Object> propFilterHash = new HashMap<String, Object>();
+ poplatePropertyHashWithRelData(rel, apiVersion, propFilterHash);
+ String relNodeType = (String)rel.get("relatedTo");
+ relatedNodesMap.put(relNodeType, propFilterHash);
+ }
+ DbEdgeGroup.replaceEdgeGroup(transId, fromAppId, g, startVertex,
+ "ONLY_PASSED_COUSINS_REL", relatedNodesMap, apiVersion);
+
+ }
+
+ /**
+ * Poplate property hash with rel data.
+ *
+ * @param rel the rel
+ * @param apiVersion the api version
+ * @param propFilterHash the prop filter hash
+ * @throws AAIException the AAI exception
+ */
+ private static void poplatePropertyHashWithRelData(DynamicEntity rel, String apiVersion,
+ HashMap<String, Object> propFilterHash) throws AAIException {
+
+ for( DynamicEntity relData: (List<DynamicEntity>)rel.get("relationshipData")) {
+ String prop = ((String)relData.get("relationshipKey")).toLowerCase().trim();
+ propFilterHash.put(prop, ((String)relData.get("relationshipValue")).trim());
+ }
+ }
+
+ /**
+ * this method gets any relationships for the startVertex being processed
+ * and sets the related-link.
+ *
+ * @param g the g
+ * @param startVertex the start vertex
+ * @param apiVersion the api version
+ * @param aaiExtMap the aai ext map
+ * @return the relationships
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static DynamicEntity getRelationships(TitanTransaction g, TitanVertex startVertex,
+ String apiVersion, AAIExtensionMap aaiExtMap)
+ throws AAIException, UnsupportedEncodingException {
+
+ DynamicType relationshipsType = null;
+ DynamicType relationshipType = null;
+ DynamicType relationshipDataType = null;
+ DynamicType relatedToPropertyType = null;
+
+ Boolean setRelatedToProperty = true;
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(apiVersion);
+
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ //String apiVersion = aaiExtMap.getApiVersion();
+ String transId = aaiExtMap.getTransId();
+ String fromAppId = aaiExtMap.getFromAppId();
+
+ HashMap <String, String> vidToNodeTypeHash = new HashMap <String, String>();
+ HashMap <String, TitanVertex> vidToVertexHash = new HashMap <String, TitanVertex>();
+
+ if ("v2".equals( apiVersion)) {
+ relationshipsType = jaxbContext.getDynamicType("inventory.aai.openecomp.org.RelationshipList");
+ relationshipType = jaxbContext.getDynamicType("inventory.aai.openecomp.org.Relationship");
+ relationshipDataType = jaxbContext.getDynamicType("inventory.aai.openecomp.org.RelationshipData");
+ setRelatedToProperty = false;
+ } else {
+ relationshipsType = jaxbContext.getDynamicType("inventory.aai.openecomp.org." + apiVersion + ".RelationshipList");
+ relationshipType = jaxbContext.getDynamicType("inventory.aai.openecomp.org." + apiVersion + ".Relationship");
+ relationshipDataType = jaxbContext.getDynamicType("inventory.aai.openecomp.org." + apiVersion + ".RelationshipData");
+ relatedToPropertyType = jaxbContext.getDynamicType("inventory.aai.openecomp.org." + apiVersion + ".RelatedToProperty");
+ if (relatedToPropertyType == null) {
+ setRelatedToProperty = false; // some versions do not support this
+ }
+ }
+
+ DynamicEntity relationships = relationshipsType.newDynamicEntity();
+ List<DynamicEntity> listOfRelationships = new ArrayList<DynamicEntity>();
+
+ DbEdgeGroup.getEdgeGroup(transId,
+ fromAppId,
+ g,
+ startVertex,
+ vidToNodeTypeHash,
+ vidToVertexHash,
+ "ONLY_COUSIN_REL",
+ AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ // Convert the found relationships to a RelationshipList DynamicEntity
+ for( Map.Entry<String, TitanVertex> entry : vidToVertexHash.entrySet() ){
+
+ List<DynamicEntity> relationshipDataList = new ArrayList<DynamicEntity>();
+ List<DynamicEntity> relatedToPropertyList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity relationship = relationshipType.newDynamicEntity();
+
+ TitanVertex relNode = entry.getValue();
+ String relNodeVid = entry.getKey();
+ String relNodeType = vidToNodeTypeHash.get(relNodeVid);
+ String relNodeURL = RestURL.get(g, relNode, apiVersion);
+
+ HashMap <String, Object> nodeKeyPropsHash = RestURL.getKeyHashes(g, relNode, AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ Iterator <Map.Entry<String,Object>>keyIterator = nodeKeyPropsHash.entrySet().iterator();
+ while( keyIterator.hasNext() ){
+ DynamicEntity relationshipData = relationshipDataType.newDynamicEntity();
+ Map.Entry <String,Object>pair = (Map.Entry<String,Object>)keyIterator.next();
+ String key = pair.getKey();
+
+ if (!key.contains(".")) {
+ key = relNodeType + "." + key;
+ }
+
+ String value = "";
+ if( pair.getValue() != null ){
+ value = pair.getValue().toString();
+ }
+
+ relationshipData.set("relationshipKey", key);
+ relationshipData.set("relationshipValue", value);
+
+ relationshipDataList.add(relationshipData);
+ }
+
+ if (setRelatedToProperty) {
+ HashMap <String, Object> nodeNamePropsHash = DbMeth.getNodeNamePropHash(transId, fromAppId, g, relNode, AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ Iterator <Map.Entry<String,Object>>nameIterator = nodeNamePropsHash.entrySet().iterator();
+ while( nameIterator.hasNext() ){
+ DynamicEntity relatedToProperty = relatedToPropertyType.newDynamicEntity();
+ Map.Entry <String,Object>pair = (Map.Entry<String,Object>)nameIterator.next();
+ String key = pair.getKey();
+
+ if (!key.contains(".")) {
+ key = relNodeType + "." + key;
+ }
+
+ String value = "";
+ if( pair.getValue() != null ){
+ value = pair.getValue().toString();
+ }
+ relatedToProperty.set("propertyKey", key);
+ relatedToProperty.set("propertyValue", value);
+
+ relatedToPropertyList.add(relatedToProperty);
+
+ }
+ relationship.set("relatedToProperty", relatedToPropertyList);
+ }
+ relationship.set("relatedTo", relNodeType);
+ relationship.set("relatedLink", relNodeURL);
+ relationship.set("relationshipData", relationshipDataList);
+
+ listOfRelationships.add(relationship);
+ }
+ relationships.set("relationship", listOfRelationships);
+ return relationships;
+ }
+
+ /**
+ * this method processes any relationships for the startVertex being
+ * processed.
+ *
+ * @param g the g
+ * @param startVertex the start vertex
+ * @param jaxbContext the jaxb context
+ * @param relationshipList the relationship list
+ * @param aaiExtMap the aai ext map
+ * @throws AAIException the AAI exception
+ */
+ public static void updRelationships(TitanTransaction g, TitanVertex startVertex,
+ DynamicJAXBContext jaxbContext,
+ DynamicEntity relationshipList,
+ AAIExtensionMap aaiExtMap)
+ throws AAIException {
+
+ String apiVersion = aaiExtMap.getApiVersion();
+ String transId = aaiExtMap.getTransId();
+ String fromAppId = aaiExtMap.getFromAppId();
+ MultiValueMap relatedNodesMap = new MultiValueMap();
+ if (relationshipList != null) {
+ if( relationshipList.get("relationship") != null ){
+ List <DynamicEntity> relListTmp = relationshipList.get("relationship");
+ for( DynamicEntity rel: relListTmp) {
+ HashMap<String, Object> propFilterHash = new HashMap<String, Object>();
+ poplatePropertyHashWithRelData(rel, apiVersion, propFilterHash);
+ String relNodeType = (String)rel.get("relatedTo");
+ relatedNodesMap.put(relNodeType, propFilterHash);
+
+
+ }
+ }
+ DbEdgeGroup.replaceEdgeGroup(transId, fromAppId, g, startVertex,
+ "ALL_COUSIN_REL", relatedNodesMap, apiVersion);
+ }
+ }
+
+ /**
+ * this method deletes the relationship sent in for the startVertex being
+ * processed.
+ *
+ * @param g the g
+ * @param startVertex the start vertex
+ * @param jaxbContext the jaxb context
+ * @param rel the rel
+ * @param aaiExtMap the aai ext map
+ * @throws AAIException the AAI exception
+ */
+ public static void delRelationship(TitanTransaction g, TitanVertex startVertex,
+ DynamicJAXBContext jaxbContext,
+ DynamicEntity rel,
+ AAIExtensionMap aaiExtMap)
+ throws AAIException {
+
+ String apiVersion = aaiExtMap.getApiVersion();
+ String transId = aaiExtMap.getTransId();
+ String fromAppId = aaiExtMap.getFromAppId();
+ MultiValueMap relatedNodesMap = new MultiValueMap();
+
+ if( rel != null ){
+ HashMap<String, Object> propFilterHash = new HashMap<String, Object>();
+ poplatePropertyHashWithRelData(rel, apiVersion, propFilterHash);
+ String relNodeType = (String)rel.get("relatedTo");
+ relatedNodesMap.put(relNodeType, propFilterHash);
+ }
+
+ DbEdgeGroup.deleteEdgeGroup(transId, fromAppId, g, startVertex,
+ relatedNodesMap, apiVersion);
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/SearchGraph.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/SearchGraph.java
new file mode 100644
index 0000000..1dde5b7
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmap/SearchGraph.java
@@ -0,0 +1,1475 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.exceptions.DynamicException;
+import org.eclipse.persistence.jaxb.JAXBMarshaller;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.dbgen.ModelBasedProcessing;
+import org.openecomp.aai.dbgen.ResultSet;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResourceKey;
+import org.openecomp.aai.domain.model.AAIResourceKeys;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIApiServerURLBase;
+import org.openecomp.aai.util.AAIApiVersion;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.PojoUtils;
+import org.openecomp.aai.util.RestURL;
+import org.openecomp.aai.util.StoreNotificationEvent;
+
+import com.google.common.base.CaseFormat;
+import com.thinkaurelius.titan.core.TitanGraphQuery;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+/**
+ * Database Mapping class which acts as the middle man between the REST interface objects
+ * for the Search namespace
+
+ */
+public class SearchGraph {
+
+ private LogLine logline = new LogLine();
+ private final String COMPONENT = "aaidbmap";
+ protected AAILogger aaiLogger = new AAILogger(SearchGraph.class.getName());
+
+
+ /**
+ * Get the search result based on the includeNodeType and depth provided.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param startNodeType the start node type
+ * @param startNodeKeyParams the start node key params
+ * @param includeNodeTypes the include node types
+ * @param depth the depth
+ * @param aaiExtMap the aai ext map
+ * @return Response
+ * @throws AAIException the AAI exception
+ */
+ public Response runGenericQuery (String fromAppId,
+ String transId,
+ String startNodeType,
+ List <String> startNodeKeyParams,
+ List <String> includeNodeTypes,
+ final int depth,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+ DynamicEntity searchResults = null;
+ Response response = null;
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ logline.init(COMPONENT, transId, fromAppId, "runGenericQuery");
+
+ if( startNodeType == null ){
+ String emsg = "null start-node-type passed to the generic query\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ } else {
+ logline.add("start-node-type", startNodeType);
+ }
+
+ if( startNodeKeyParams == null ){
+ String emsg = "no key param passed to the generic query\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ } else {
+ logline.add("key", startNodeKeyParams.toString());
+ }
+
+ if( includeNodeTypes == null ){
+ String emsg = "no include params passed to the generic query\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ } else {
+ logline.add("include", includeNodeTypes.toString());
+ }
+
+ if (depth > 6) {
+ String emsg = "The maximum depth supported by the generic query is 6\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ } else {
+ logline.add("depth", depth);
+ }
+
+ // Build a hash with keys to uniquely identify the start Node
+ HashMap <String,Object> propHash = new HashMap<String, Object>();
+ String keyName = null, keyValue = null;
+
+ String keyNameString = "";
+ for( String keyData : startNodeKeyParams ){
+ int colonIndex = keyData.indexOf(":");
+ if( colonIndex <= 0 ){
+ String emsg = "Bad key param passed in: [" + keyData + "]\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ keyName = keyData.substring(0, colonIndex);
+ keyValue = keyData.substring(colonIndex + 1);
+ propHash.put(keyName, keyValue);
+
+ keyNameString += keyName.toLowerCase() + "|";
+ }
+ }
+
+ // there is an issue with service-instance - it is a unique node but still dependent
+ // for now lets use getUniqueNode() to get the startNode if startNodeType is service-instance
+ TitanVertex startNode = null;
+ if (startNodeType.equalsIgnoreCase("service-instance")) {
+ Iterable <?> verts = g.query().has(keyName.substring(keyName.indexOf('.') + 1), keyValue).vertices();
+ Iterator <?> vertI = verts.iterator();
+ if( vertI != null && vertI.hasNext()) {
+ // We found a vertex that meets the input criteria.
+ startNode = (TitanVertex) vertI.next();
+
+ if( vertI.hasNext() ){
+ // Since this routine is looking for a unique node for the given input values, if
+ // more than one is found - it's a problem.
+ String detail = "More than one Node found by getUniqueNode for params: " + startNodeKeyParams.toString() + "\n";
+ throw new AAIException("AAI_6112", detail);
+ }
+ }
+ else {
+ // No Vertex was found for this key - throw a not-found exception
+ String msg = "No Node of type " + "service-instance" + " found for properties: " + startNodeKeyParams.toString();
+ logline.add("msg", msg);
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ } else {
+ // Look for the start node based on the key params
+ startNode = DbMeth.getUniqueNodeWithDepParams(transId,
+ fromAppId,
+ g,
+ startNodeType,
+ propHash,
+ aaiExtMap.getApiVersion());
+ }
+ if( startNode == null ){
+ String emsg = "No Node of type " +
+ startNodeType +
+ " found for properties: " +
+ startNodeKeyParams.toString();
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6114", emsg);
+ }
+
+
+ Collection <Vertex> ver = new HashSet <Vertex> ();
+
+ if (includeNodeTypes.contains(startNodeType) || depth == 0 || includeNodeTypes.contains("all") )
+ ver.add(startNode);
+
+ if (depth != 0) {
+ // Now look for a node of includeNodeType within a given depth
+ startNode.graph().traversal().withSideEffect("x", ver).V(startNode)
+ .repeat(__.both().store("x")).times(depth).iterate();
+ }
+
+ if( ver.isEmpty()){
+ logline.add("msg", "No nodes found - apipe was null/empty");
+ }
+ else {
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+ if (aaiExtMap.getApiVersion().equals("v2")) {
+ searchResults = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.SearchResults");
+ } else {
+ searchResults = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." +
+ aaiExtMap.getApiVersion() +
+ ".SearchResults");
+ }
+ ArrayList <DynamicEntity> resultDataList = new ArrayList<DynamicEntity>();
+ for (Vertex thisNode: ver){
+ String nodeType = thisNode.<String>property("aai-node-type").orElse(null);
+ if (depth == 0 || includeNodeTypes.contains(nodeType) || includeNodeTypes.contains("all")) {
+ // DbMeth.showPropertiesForNode( transId, fromAppId, thisNode );
+ String thisNodeURL = RestURL.getSearchUrl(g, (TitanVertex)thisNode, aaiExtMap.getApiVersion());
+ DynamicEntity resultData = null;
+ if (aaiExtMap.getApiVersion().equals("v2")) {
+ resultData = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.ResultData");
+ } else {
+ resultData = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." +
+ aaiExtMap.getApiVersion() +
+ ".ResultData");
+ }
+
+ resultData.set("resourceType", nodeType);
+ resultData.set("resourceLink", thisNodeURL);
+ resultDataList.add(resultData);
+ }
+ }
+ searchResults.set("resultData", resultDataList);
+ response = getResponseFromDynamicEntity(searchResults, jaxbContext, aaiExtMap);
+
+ logline.add("msg", ver.size() + " node(s) traversed, " + resultDataList.size() + " found");
+ }
+ success = true;
+ } catch (AAIException e) {
+ success = false;
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ throw e;
+ } catch (Exception e) {
+ success = false;
+ aaiLogger.info(logline, false, "AAI_5105");
+ throw new AAIException("AAI_5105", e);
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+
+ }
+ aaiLogger.info(logline, true, "0");
+ return response;
+ }
+
+ /**
+ * Run nodes query.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param targetNodeType the target node type
+ * @param edgeFilterParams the edge filter params
+ * @param filterParams the filter params
+ * @param aaiExtMap the aai ext map
+ * @return Response
+ * @throws AAIException the AAI exception
+ */
+ public Response runNodesQuery (String fromAppId,
+ String transId,
+ String targetNodeType,
+ List <String> edgeFilterParams,
+ List <String> filterParams,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+
+ DynamicEntity searchResults = null;
+ Response response = null;
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ logline.init(COMPONENT, transId, fromAppId, "runNodesQuery");
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ int resCount = 0;
+
+ if( targetNodeType == null || targetNodeType == "" ){
+ String emsg = "null or empty target-node-type passed to the node query\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ logline.add("start-node-type", targetNodeType);
+ }
+
+ if( ! dbMaps.NodeProps.containsKey(targetNodeType) ){
+ String emsg = " Unrecognized nodeType [" + targetNodeType + "] passed to node query.\n";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6115", emsg);
+ }
+
+ if( filterParams.isEmpty() && edgeFilterParams.isEmpty()){
+ // For now, it's ok to pass no filter params. We'll just return ALL the nodes of the requested type.
+ String wmsg = "No filters passed to the node query\n";
+ logline.add("warn-msg", wmsg);
+ filterParams = new ArrayList <String>();
+ edgeFilterParams = new ArrayList <String>();
+ }
+ else {
+ if( !filterParams.isEmpty())
+ logline.add("filterParams", "[" + filterParams.toString() + "]");
+ if( !edgeFilterParams.isEmpty())
+ logline.add("edgeFilterParams", "[" + edgeFilterParams.toString() + "]");
+ }
+
+ Collection <TitanVertex> resultSetVertices = new ArrayList <TitanVertex> ();
+ String queryStringForMsg = "";
+ TitanGraphQuery tgQ = g.query().has("aai-node-type", targetNodeType);
+ queryStringForMsg = "has(\"aai-node-type\"," + targetNodeType + ")";
+
+ for( String filter : filterParams ) {
+ if( (tgQ != null) && (tgQ instanceof TitanGraphQuery) ){
+ String [] pieces = filter.split(":");
+ if( pieces.length < 2 ){
+ String emsg = "bad filter passed to node query: [" + filter + "]";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String propName = pieces[0];
+ String filterType = pieces[1];
+ if( filterType.equals("EQUALS")){
+ if( pieces.length != 3 ){
+ String emsg = "No value passed for filter: [" + filter + "]";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String value = pieces[2];
+ queryStringForMsg = queryStringForMsg + ".has(" + propName + "," + value + ")";
+ tgQ = tgQ.has(propName,value);
+ }
+ }
+ else if( filterType.equals("DOES-NOT-EQUAL")){
+ if( pieces.length != 3 ){
+ String emsg = "No value passed for filter: [" + filter + "]";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ else {
+ String value = pieces[2];
+ queryStringForMsg = queryStringForMsg + ".hasNot(" + propName + "," + value + ")";
+ tgQ = tgQ.hasNot(propName,value);
+ }
+ }
+ else if( filterType.equals("EXISTS")){
+ queryStringForMsg = queryStringForMsg + ".has(" + propName + ")";
+ tgQ = tgQ.has(propName);
+ }
+ else if( filterType.equals("DOES-NOT-EXIST")){
+ queryStringForMsg = queryStringForMsg + ".hasNot(" + propName + ")";
+ tgQ = tgQ.hasNot(propName);
+ }
+ else {
+ String emsg = "bad filterType passed: [" + filterType + "]";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ }
+ }
+ }
+ if( (tgQ != null) && (tgQ instanceof TitanGraphQuery) ){
+ Iterable <?> targetNodeIterable = (Iterable<TitanVertex>) tgQ.vertices();
+ Iterator <?> targetNodeIterator = targetNodeIterable.iterator();
+
+ if (!edgeFilterParams.isEmpty()) {
+ // edge-filter=pserver:EXISTS: OR pserver:EXISTS:hostname:XXX
+ // edge-filter=pserver:DOES-NOT-EXIST: OR pserver:DOES-NOT-EXIST:hostname:XXX
+ String filter = edgeFilterParams.get(0); // we process and allow only one edge filter for now
+ String [] pieces = filter.split(":");
+ if( pieces.length < 2 || pieces.length == 3 || pieces.length > 4){
+ String emsg = "bad edge-filter passed: [" + filter + "]";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ } else {
+ String nodeType = pieces[0].toLowerCase();
+ String filterType = pieces[1].toUpperCase();
+ if (!filterType.equals("EXISTS") && !filterType.equals("DOES-NOT-EXIST")) {
+ String emsg = "bad filterType passed: [" + filterType + "]";
+ logline.add("emsg", emsg);
+ throw new AAIException("AAI_6120", emsg);
+ }
+ String propName = null, propValue = null;
+ if( pieces.length >= 3) {
+ propName = pieces[2].toLowerCase();
+ propValue = pieces[3];
+ }
+ String edgeLabel = getEdgeLabel(targetNodeType, nodeType);
+ Iterator<Vertex> relatedToIterable = null;
+ while( targetNodeIterator.hasNext() ){
+ TitanVertex targetNodeVertex = (TitanVertex)targetNodeIterator.next();
+ relatedToIterable = targetNodeVertex.vertices(Direction.BOTH, edgeLabel);
+ Iterator <?> relatedToIterator = relatedToIterable;
+ if( filterType.equals("DOES-NOT-EXIST") && propName == null){
+ if (!relatedToIterator.hasNext()) {
+ resultSetVertices.add(targetNodeVertex);
+ }
+ } else {
+ while (relatedToIterator.hasNext()) {
+ TitanVertex relatedToVertex = (TitanVertex)relatedToIterator.next();
+ if (filterType.equals("EXISTS")) {
+ if (propName == null)
+ resultSetVertices.add(targetNodeVertex);
+ else {
+ // check for matching property
+ if (relatedToVertex.<String>property(propName).orElse(null) != null && relatedToVertex.<String>property(propName).equals(propValue))
+ resultSetVertices.add(targetNodeVertex);
+ }
+ } else if (filterType.equals("DOES-NOT-EXIST")) {
+ // check for matching property
+ if (relatedToVertex.<String>property(propName).orElse(null) != null && !relatedToVertex.<String>property(propName).equals(propValue))
+ resultSetVertices.add(targetNodeVertex);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ while( targetNodeIterator.hasNext() ){
+ TitanVertex targetNodeVertex = (TitanVertex)targetNodeIterator.next();
+ resultSetVertices.add(targetNodeVertex);
+ }
+ }
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+ if (aaiExtMap.getApiVersion().equals("v2")) {
+ searchResults = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.SearchResults");
+ } else {
+ searchResults = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." +
+ aaiExtMap.getApiVersion() +
+ ".SearchResults");
+ }
+ ArrayList <DynamicEntity> resultDataList = new ArrayList<DynamicEntity>();
+ for (TitanVertex thisNode: resultSetVertices){
+ resCount++;
+ String nodeType = thisNode.<String>property("aai-node-type").orElse(null);
+ String thisNodeURL = RestURL.getSearchUrl(g, thisNode, aaiExtMap.getApiVersion());
+ DynamicEntity resultData = null;
+ if (aaiExtMap.getApiVersion().equals("v2")) {
+ resultData = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.ResultData");
+
+ } else {
+ resultData = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." +
+ aaiExtMap.getApiVersion() + ".ResultData");
+ }
+ resultData.set("resourceType", nodeType);
+ resultData.set("resourceLink", thisNodeURL);
+ resultDataList.add(resultData);
+ }
+ searchResults.set("resultData", resultDataList);
+ response = getResponseFromDynamicEntity(searchResults, jaxbContext, aaiExtMap);
+ }
+ logline.add("count", resCount);
+ success = true;
+ } catch (AAIException e) {
+ success = false;
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ throw e;
+ } catch (Exception e) {
+ success = false;
+ aaiLogger.info(logline, false, "AAI_5105");
+ throw new AAIException("AAI_5105", e);
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return response;
+ }
+
+ /**
+ * Map result.
+ *
+ * @param g the g
+ * @param logline the logline
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @param resultDetail the result detail
+ * @param includeNodeTypes the include node types
+ * @param resultSet the result set
+ * @param invItemCount the inv item count
+ * @param levelCount the level count
+ * @return the dynamic entity
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public DynamicEntity mapResult(TitanTransaction g, LogLine logline,
+ DynamicJAXBContext jaxbContext,
+ AAIExtensionMap aaiExtMap,
+ String resultDetail,
+ ArrayList<String> includeNodeTypes,
+ ResultSet resultSet,
+ int invItemCount,
+ int levelCount )
+ throws UnsupportedEncodingException, AAIException {
+
+ ArrayList <String> retArr = new ArrayList <String> ();
+ DynamicEntity item = null;
+
+ if (aaiExtMap.getApiVersion().equals("v2")) {
+ item = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.InventoryItem");
+ } else {
+ item = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryItem");
+ }
+
+ levelCount++;
+ TitanVertex node = resultSet.getVert();
+ if( node == null ){
+ retArr.add("null Node object returned");
+ }
+ else {
+ String nt = node.<String>property("aai-node-type").orElse(null);
+
+ if ((includeNodeTypes.contains("all")) ||
+ (includeNodeTypes.contains(nt.toLowerCase()))) { // include this node in resultSet only if its one of
+ // the included node types or its include "all"
+
+ retArr.add( levelCount + " " + nt + ", " + node.id().toString() + ";");
+ item.set("inventoryItemType", nt);
+
+ String thisNodeURL = node.<String>property("aai-unique-key").orElse(null);
+ String permanentURL = aaiExtMap.getUriInfo().getQueryParameters().getFirst("permanenturl");
+ if (thisNodeURL != null && !thisNodeURL.equals("")) {
+ thisNodeURL = AAIApiServerURLBase.get() + AAIApiVersion.get() + "/" + thisNodeURL;
+ } else if ("true".equals(permanentURL)) {
+ thisNodeURL = RestURL.getSearchUrl(g, node, aaiExtMap.getApiVersion());
+ }
+ else {
+ thisNodeURL = AAIApiServerURLBase.get() + AAIApiVersion.get() + "/resources/id/" + node.id();
+ }
+ item.set("inventoryItemLink", thisNodeURL);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ Collection <String> indexProperties = dbMaps.NodeMapIndexedProps.get(nt);
+
+ ArrayList <DynamicEntity> itemDataList = new ArrayList<DynamicEntity>();
+
+ Iterator<VertexProperty<Object>> pI = node.properties();
+
+ ArrayList<String> defB = new ArrayList<String>();
+
+ if (AAIConfig.getDefaultBools().containsKey(nt)) {
+ for (String db : AAIConfig.getDefaultBools().get(nt)) {
+ defB.add(db);
+ }
+ }
+
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ String propKey = tp.key();
+ if (!propKey.equals("aai-node-type") &&
+ (!dbMaps.ReservedPropNames.containsKey((String)propKey)) && // do not return internal properties
+ ((resultDetail.equalsIgnoreCase("all") ||
+ ((resultDetail.equalsIgnoreCase("summary") && // only include indexed properties
+ // if summary detail required
+ indexProperties.contains(propKey))) ))){
+ if (defB.contains(propKey)) {
+ defB.remove(propKey);
+ }
+ DynamicEntity invItemData = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." +
+ aaiExtMap.getApiVersion() +
+ ".InventoryItemData");
+ invItemData.set("propertyName", tp.key());
+ String propVal = "";
+ if( tp.value() != null ){
+ propVal = tp.value().toString();
+ }
+ invItemData.set("propertyValue", propVal);
+ itemDataList.add(invItemData);
+ }
+ }
+
+ for (String db : defB) {
+ if ((resultDetail.equalsIgnoreCase("all") ||
+ ((resultDetail.equalsIgnoreCase("summary") && // only include indexed properties
+ // if summary detail required
+ indexProperties.contains(db))) )) {
+ DynamicEntity invItemData = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." +
+ aaiExtMap.getApiVersion() +
+ ".InventoryItemData");
+ invItemData.set("propertyName", db);
+ invItemData.set("propertyValue", "false");
+ itemDataList.add(invItemData);
+ }
+ }
+
+ item.set("inventoryItemData", itemDataList);
+ }
+
+ if( !resultSet.getSubResultSet().isEmpty() ){
+ DynamicEntity taggedInventoryItemList = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".TaggedInventoryItemList");
+
+ ListIterator<ResultSet> listItr = resultSet.getSubResultSet().listIterator();
+ ArrayList<DynamicEntity> inventoryItemList = new ArrayList<DynamicEntity>();
+
+ boolean hasItems = false;
+ while( listItr.hasNext() ){
+
+ DynamicEntity invItem = mapResult(g, logline,
+ jaxbContext,
+ aaiExtMap,
+ resultDetail,
+ includeNodeTypes,
+ listItr.next(),
+ invItemCount,
+ levelCount );
+ if (invItem != null) {
+ hasItems = true;
+ inventoryItemList.add(invItem); // dont add if excluded nodes
+ }
+ }
+
+ if (item != null && hasItems == true) {
+ taggedInventoryItemList.set("inventoryItem", inventoryItemList);
+ ArrayList<DynamicEntity> til = new ArrayList<DynamicEntity>();
+ til.add(taggedInventoryItemList);
+ item.set("taggedInventoryItemList", til);
+ }
+ }
+ }
+ if (!retArr.isEmpty())
+ logline.add("msg" + invItemCount, retArr.toString());
+ return item;
+
+ }// end of mapResult()
+
+
+ /**
+ * Gets the edge label.
+ *
+ * @param targetNodeType the target node type
+ * @param nodeType the node type
+ * @return the edge label
+ * @throws AAIException the AAI exception
+ */
+ public static String getEdgeLabel(String targetNodeType, String nodeType) throws AAIException{
+ String edRule = "";
+ String edgeLabel = "???";
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(targetNodeType + "|" + nodeType);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ // For now, we only look for one type of edge between two nodes.
+ // We're just pulling off the edgeLabel which is the first thing on the list.
+ edRule = ruleItr.next();
+ String [] rules = edRule.split(",");
+ edgeLabel = rules[0];
+ }
+ else {
+ edRuleColl = DbEdgeRules.EdgeRules.get(nodeType + "|" + targetNodeType);
+ ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ edRule = ruleItr.next();
+ String [] rules = edRule.split(",");
+ edgeLabel = rules[0];
+ } else {
+ // No edge rule found for this
+ String detail = "No EdgeRule found for passed nodeTypes: " + nodeType + ", " + targetNodeType + ".";
+ throw new AAIException("AAI_6120", detail);
+ }
+ }
+ return edgeLabel;
+ }
+
+
+ /**
+ * Run named query.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param queryParameters the query parameters
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ */
+ public Response runNamedQuery(String fromAppId, String transId, String queryParameters,
+ AAIExtensionMap aaiExtMap) throws JAXBException, AAIException {
+ // TODO Auto-generated method stub
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ //String dynamicClass = aaiRes.getResourceClassName();
+
+ DynamicEntity inventoryItems;
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+ if (aaiExtMap.getHttpServletRequest().getContentType() == null || // default to json
+ aaiExtMap.getHttpServletRequest().getContentType().contains("application/json")) {
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ if (queryParameters.length() == 0) {
+ queryParameters = "{}";
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+ String dynamicClass = "inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".ModelAndNamedQuerySearch";
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+
+ StringReader reader = new StringReader(queryParameters);
+
+ DynamicEntity modelAndNamedQuerySearch = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+
+ if (modelAndNamedQuerySearch == null) {
+ throw new AAIException("AAI_5105");
+ }
+
+ HashMap<String,Object> namedQueryLookupHash = new HashMap<String,Object>();
+
+ DynamicEntity qp = modelAndNamedQuerySearch.get("queryParameters");
+
+ String namedQueryUuid = null;
+ if (qp.isSet("namedQuery")) {
+ DynamicEntity namedQuery = (DynamicEntity) qp.get("namedQuery");
+
+ if (namedQuery.isSet("namedQueryUuid")) {
+ namedQueryUuid = namedQuery.get("namedQueryUuid");
+ }
+ if (namedQuery.isSet("namedQueryName")) {
+ namedQueryLookupHash.put("named-query-name", namedQuery.get("namedQueryName"));
+ }
+ if (namedQuery.isSet("namedQueryVersion")) {
+ namedQueryLookupHash.put("named-query-version", namedQuery.get("namedQueryVersion"));
+ }
+ }
+
+ if (namedQueryUuid == null) {
+ ArrayList<TitanVertex> namedQueryVertices = DbMeth.getNodes(transId, fromAppId, g, "named-query", namedQueryLookupHash, false);
+
+ for (TitanVertex vert : namedQueryVertices) {
+ namedQueryUuid = vert.<String>property("named-query-uuid").orElse(null);
+ // there should only be one, we'll pick the first if not
+ break;
+ }
+ }
+
+ ArrayList<HashMap<String,Object>> startNodeFilterHash = new ArrayList<HashMap<String,Object>>();
+
+ mapInstanceFilters((DynamicEntity)modelAndNamedQuerySearch.get("instanceFilters"),
+ startNodeFilterHash, jaxbContext);
+
+ ArrayList<ResultSet> resultSet = ModelBasedProcessing.queryByNamedQuery(transId, fromAppId, g,
+ namedQueryUuid, startNodeFilterHash, aaiExtMap.getApiVersion() );
+
+ inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems");
+
+ HashMap<Object,String> objectToVertMap = new HashMap<Object,String>();
+ ArrayList<DynamicEntity> invItemList = unpackResultSet(g, resultSet, jaxbContext, aaiResources, objectToVertMap, aaiExtMap);
+
+ inventoryItems.set("inventoryResponseItem", invItemList);
+ success = true;
+ } catch (AAIException e) {
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ success = false;
+ throw e;
+ } catch (Exception e) {
+ aaiLogger.info(logline, false, "AAI_5105");
+ success = false;
+ throw new AAIException("AAI_5105", e);
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+
+ return getResponseFromDynamicEntity(inventoryItems, jaxbContext, aaiExtMap);
+ }
+
+ /**
+ * Execute model operation.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param queryParameters the query parameters
+ * @param isDelete the is delete
+ * @param aaiExtMap the aai ext map
+ * @return the response
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws DynamicException the dynamic exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public Response executeModelOperation(String fromAppId, String transId, String queryParameters, boolean isDelete,
+ AAIExtensionMap aaiExtMap) throws JAXBException, AAIException, DynamicException, UnsupportedEncodingException {
+ // TODO Auto-generated method stub
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(aaiExtMap.getApiVersion());
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ //String dynamicClass = aaiRes.getResourceClassName();
+ Response response;
+ boolean success = true;
+ TitanTransaction g = null;
+ try {
+
+ g = AAIGraph.getInstance().getGraph().newTransaction();
+
+
+ if (aaiExtMap.getHttpServletRequest().getContentType() == null || // default to json
+ aaiExtMap.getHttpServletRequest().getContentType().contains("application/json")) {
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ if (queryParameters.length() == 0) {
+ queryParameters = "{}";
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+ String dynamicClass = "inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".ModelAndNamedQuerySearch";
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+
+ StringReader reader = new StringReader(queryParameters);
+
+ DynamicEntity modelAndNamedQuerySearch = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+
+ if (modelAndNamedQuerySearch == null) {
+ throw new AAIException("AAI_5105");
+ }
+
+ HashMap<String,Object> modelQueryLookupHash = new HashMap<String,Object>();
+
+ String modelNameVersionId = null;
+ String modelName = null;
+ String modelId = null;
+ String modelVersion = null;
+ String topNodeType = null;
+
+ if (modelAndNamedQuerySearch.isSet("topNodeType")) {
+ topNodeType = modelAndNamedQuerySearch.get("topNodeType");
+ }
+ if (modelAndNamedQuerySearch.isSet("queryParameters")) {
+ DynamicEntity qp = modelAndNamedQuerySearch.get("queryParameters");
+
+ if (qp.isSet("model")) {
+ DynamicEntity model = (DynamicEntity) qp.get("model");
+
+ if (model.isSet("modelNameVersionId")) {
+ modelNameVersionId = model.get("modelNameVersionId");
+ }
+ if (model.isSet("modelName")) {
+ modelName = model.get("modelName");
+ modelQueryLookupHash.put("model-name", modelName);
+ }
+ if (model.isSet("modelId")) {
+ modelId = model.get("modelId");
+ modelQueryLookupHash.put("model-id", modelId);
+ }
+ if (model.isSet("modelVersion")) {
+ modelVersion = model.get("modelVersion");
+ modelQueryLookupHash.put("model-version", modelVersion);
+ }
+ }
+
+ if (modelNameVersionId == null ) {
+ if (modelId != null || modelName != null) {
+ ArrayList<TitanVertex> modelVertices = DbMeth.getNodes(transId, fromAppId, g, "model", modelQueryLookupHash, false);
+ for (TitanVertex vert : modelVertices) {
+ modelNameVersionId = vert.<String>property("model-name-version-id").orElse(null);
+ // there should only be one, we'll pick the first if not
+ break;
+ }
+ } else {
+ throw new AAIException("AAI_6132", "Could not determine model to use.");
+ }
+ }
+ }
+ ArrayList< HashMap<String,Object> > startNodeFilterHash = new ArrayList< HashMap<String,Object> >();
+
+ String resourceVersion = mapInstanceFilters((DynamicEntity)modelAndNamedQuerySearch.get("instanceFilters"),
+ startNodeFilterHash, jaxbContext);
+
+ if (isDelete) {
+
+ ArrayList<ResultSet> resultSet = ModelBasedProcessing.queryByModel(transId, fromAppId, g,
+ modelNameVersionId, modelId, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion() );
+
+ new ArrayList<DynamicEntity>();
+
+ HashMap<Object,String> objectToVertMap = new HashMap<Object,String>();
+ ArrayList<DynamicEntity> invItemList = unpackResultSet(g, resultSet, jaxbContext, aaiResources, objectToVertMap, aaiExtMap);
+
+ ResultSet rs = resultSet.get(0);
+
+ TitanVertex firstVert = rs.getVert();
+ String restURL = RestURL.get(g, firstVert);
+
+ HashMap<String,String> delResult = ModelBasedProcessing.runDeleteByModel( transId, fromAppId, g,
+ modelNameVersionId, topNodeType, startNodeFilterHash.get(0), aaiExtMap.getApiVersion(), resourceVersion );
+
+ String resultStr = "";
+ for (Map.Entry<String,String> ent : delResult.entrySet()) {
+ resultStr += "v[" + ent.getKey() + "] " + ent.getValue() + ",\n";
+ }
+ resultStr.trim();
+
+ DynamicEntity inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems");
+ DynamicEntity topInvItem = remapInventoryItems(invItemList.get(0), jaxbContext, delResult, objectToVertMap, aaiExtMap);
+
+ List<DynamicEntity> newInvItemList = new ArrayList<DynamicEntity>();
+ newInvItemList.add(topInvItem);
+ inventoryItems.set("inventoryResponseItem", newInvItemList);
+
+ // put the inventoryItems in a UEB notification object
+ String notificationVersion = AAIConfig.get("aai.notification.current.version");
+
+ AAIResources aaiNotificationResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer
+ .get(notificationVersion);
+
+ DynamicJAXBContext notificationJaxbContext = aaiNotificationResources.getJaxbContext();
+
+ DynamicEntity notificationHeader = notificationJaxbContext
+ .getDynamicType("inventory.aai.openecomp.org." + notificationVersion + ".NotificationEventHeader")
+ .newDynamicEntity();
+
+ notificationHeader.set("entityLink", restURL);
+ notificationHeader.set("action", "DELETE");
+
+ notificationHeader.set("entityType", "inventory-response-items");
+ notificationHeader.set("topEntityType", "inventory-response-items");
+ notificationHeader.set("sourceName", aaiExtMap.getFromAppId());
+ notificationHeader.set("version", notificationVersion);
+
+ StoreNotificationEvent sne = new StoreNotificationEvent();
+
+ sne.storeDynamicEvent(notificationJaxbContext, notificationVersion, notificationHeader, inventoryItems);
+
+ response = Response.ok(resultStr).build();
+
+ } else {
+ ArrayList<ResultSet> resultSet = ModelBasedProcessing.queryByModel( transId, fromAppId, g,
+ modelNameVersionId, null, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion() );
+
+ DynamicEntity inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems");
+
+ new ArrayList<DynamicEntity>();
+ HashMap<Object,String> objectToVertMap = new HashMap<Object,String>();
+ ArrayList<DynamicEntity> invItemList = unpackResultSet(g, resultSet, jaxbContext, aaiResources, objectToVertMap, aaiExtMap);
+
+ inventoryItems.set("inventoryResponseItem", invItemList);
+
+ response = getResponseFromDynamicEntity(inventoryItems, jaxbContext, aaiExtMap);
+ }
+ success = true;
+ } catch (AAIException e) {
+ success = false;
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ throw e;
+ } catch (Exception e) {
+ success = false;
+ aaiLogger.info(logline, false, "AAI_5105");
+ throw new AAIException("AAI_5105", e);
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return response;
+ }
+
+ /**
+ *
+ *
+ * @param g the g
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param avZoVtx the av zo vtx
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return zone type of AvailabilityZone
+ * @throws AAIException the AAI exception
+ */
+ private DynamicEntity getAvailabilityZone(TitanTransaction g, String fromAppId,
+ String transId,
+ TitanVertex avZoVtx,
+ DynamicJAXBContext jaxbContext,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+ logline.init(COMPONENT, transId, fromAppId, "getAvailabilityZone");
+ String azName = avZoVtx.<String>property("availability-zone-name").toString();
+ logline.add("availability-zone-name", avZoVtx.<String>property("availability-zone-name").toString());
+
+ DynamicEntity zone = null;
+
+ if (aaiExtMap.getApiVersion().equals("v2"))
+ zone = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.AvailabilityZone");
+ else
+ zone = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".AvailabilityZone");
+
+ try {
+ zone.set("availabilityZoneName", azName);
+ if (avZoVtx.<String>property("hypervisor-type") != null) {
+ zone.set("hypervisorType", avZoVtx.<String>property("hypervisor-type").orElse(null));
+ }
+ if (avZoVtx.<String>property("operational-state") != null) {
+ zone.set("operationalState", (avZoVtx.<String>property("operational-state").orElse(null)));
+ }
+
+ String defaultApiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+
+ zone.set("relationshipList", RelationshipGraph.getRelationships(g, avZoVtx, defaultApiVersion, aaiExtMap));
+
+ } catch (AAIException e) {
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ throw e;
+ } catch (Exception e) {
+ aaiLogger.info(logline, false, "AAI_5105");
+ throw new AAIException("AAI_5105", e);
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return zone;
+ }
+
+
+ /**
+ *
+ *
+ * @param g the g
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param swVtx the sw vtx
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return DvsSwitch
+ * @throws AAIException the AAI exception
+ */
+ private DynamicEntity getDvsSwitch(TitanTransaction g, String fromAppId,
+ String transId,
+ TitanVertex swVtx,
+ DynamicJAXBContext jaxbContext,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+ logline.init(COMPONENT, transId, fromAppId, "getDvsSwitch");
+ logline.add("switch-name", swVtx.<String>property("switch-name").toString());
+ DynamicEntity dvs = null;
+ if (aaiExtMap.getApiVersion().equals("v2"))
+ dvs = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.DvsSwitch");
+ else
+ dvs = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".DvsSwitch");
+
+ try {
+ if (swVtx.<String>property("switch-name") != null) {
+ dvs.set("switchName", swVtx.<String>property("switch-name").orElse(null));
+ }
+ if (swVtx.<String>property("vcenter-url") != null) {
+ dvs.set("vcenterUrl", swVtx.<String>property("vcenter-url").orElse(null));
+ }
+ String defaultApiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+
+ dvs.set("relationshipList", RelationshipGraph.getRelationships(g, swVtx, defaultApiVersion, aaiExtMap));
+
+
+ } catch (AAIException e) {
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ throw e;
+ } catch (Exception e) {
+ aaiLogger.info(logline, false, "AAI_5105");
+ throw new AAIException("AAI_5105", e);
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return dvs;
+ }
+
+
+ /**
+ *
+ *
+ * @param g the g
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param oamVtx the oam vtx
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return oam type of OamNetwork
+ * @throws AAIException the AAI exception
+ */
+ private DynamicEntity getOamNetwork(TitanTransaction g, String fromAppId,
+ String transId,
+ TitanVertex oamVtx,
+ DynamicJAXBContext jaxbContext,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+ logline.init(COMPONENT, transId, fromAppId, "getOamNetwork");
+ String networkUuid = oamVtx.<String>property("network-uuid").toString();
+ logline.add("oam-network", networkUuid );
+
+ DynamicEntity oam = null;
+ if (aaiExtMap.getApiVersion().equals("v2"))
+ oam = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org.OamNetwork");
+ else
+ oam = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".OamNetwork");
+
+ try {
+ oam.set("networkUuid", networkUuid);
+ if (oamVtx.<String>property("network-name") != null) {
+ oam.set("networkName", oamVtx.<String>property("network-name").orElse(null));
+ }
+
+ Object cvt = oamVtx.<String>property("cvlan-tag");
+ if (cvt instanceof Long) {
+ oam.set("cvlanTag", (Long) cvt);
+ }
+ if (cvt instanceof Integer) {
+ Integer tmp = (Integer) cvt;
+ oam.set("cvlanTag", (Long) tmp.longValue());
+ }
+ if (oamVtx.<String>property("ipv4-oam-gateway-address") != null) {
+ oam.set("ipv4OamGatewayAddress", oamVtx.<String>property("ipv4-oam-gateway-address").orElse(null));
+ }
+ Object len = oamVtx.<String>property("ipv4-oam-gateway-address-prefix-length");
+ if (len instanceof Integer) {
+ oam.set("ipv4OamGatewayAddressPrefixLength", (Integer) len);
+ }
+
+ String defaultApiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+
+ DynamicEntity relationships = RelationshipGraph.getRelationships(g, oamVtx, defaultApiVersion, aaiExtMap);
+ oam.set("relationshipList", relationships);
+
+ } catch (AAIException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new AAIException("AAI_5105", e);
+ }
+ aaiLogger.info(logline, true, "0");
+ return oam;
+ }
+
+
+
+ /**
+ * Gets the response from dynamic entity.
+ *
+ * @param searchResult the search result
+ * @param jaxbContext the jaxb context
+ * @param aaiExtMap the aai ext map
+ * @return the response from dynamic entity
+ * @throws JAXBException the JAXB exception
+ */
+ private Response getResponseFromDynamicEntity(DynamicEntity searchResult,
+ DynamicJAXBContext jaxbContext,
+ AAIExtensionMap aaiExtMap) throws JAXBException {
+ Response response = null;
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+
+ for (MediaType mt : aaiExtMap.getHttpHeaders().getAcceptableMediaTypes()) {
+ if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "property-value");
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+ }
+ }
+
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(searchResult, writer);
+
+ response = Response.ok(searchResult).entity(writer.toString()).build();
+ return response;
+ }
+
+ /**
+ * Map instance filters.
+ *
+ * @param instanceFilters the instance filters
+ * @param startNodeFilterHash the start node filter hash
+ * @param jaxbContext the jaxb context
+ * @return the string
+ */
+ private String mapInstanceFilters(DynamicEntity instanceFilters, ArrayList<HashMap<String,Object>> startNodeFilterHash, DynamicJAXBContext jaxbContext) {
+
+ if (instanceFilters == null || !instanceFilters.isSet("instanceFilter")) {
+ return null;
+ }
+ @SuppressWarnings("unchecked")
+ List<DynamicEntity> instanceFilter = (ArrayList<DynamicEntity>)instanceFilters.get("instanceFilter");
+ String resourceVersion = null;
+
+ for (DynamicEntity instFilt : instanceFilter) {
+ List<DynamicEntity> any = instFilt.get("any");
+ HashMap<String,Object> thisNodeFilterHash = new HashMap<String,Object>();
+ for (DynamicEntity anyEnt : any) {
+ String clazz = anyEnt.getClass().getCanonicalName();
+ String simpleClazz = anyEnt.getClass().getSimpleName();
+
+ String nodeType = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, simpleClazz);
+
+ DynamicType anyEntType = jaxbContext.getDynamicType(clazz);
+
+ for (String propName : anyEntType.getPropertiesNames()) {
+ // hyphencase the prop and throw it on the hash
+ if (anyEnt.isSet(propName)) {
+ thisNodeFilterHash.put(nodeType + "." + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName), anyEnt.get(propName));
+ if (propName.equals("resourceVersion") && resourceVersion == null) {
+ resourceVersion = (String)anyEnt.get(propName);
+ }
+ }
+ }
+ }
+ startNodeFilterHash.add(thisNodeFilterHash);
+ }
+ return resourceVersion;
+ }
+
+ /**
+ * Remap inventory items.
+ *
+ * @param invResultItem the inv result item
+ * @param jaxbContext the jaxb context
+ * @param includeTheseVertices the include these vertices
+ * @param objectToVertMap the object to vert map
+ * @param aaiExtMap the aai ext map
+ * @return the dynamic entity
+ */
+ private DynamicEntity remapInventoryItems(DynamicEntity invResultItem, DynamicJAXBContext jaxbContext,
+ HashMap<String,String> includeTheseVertices, HashMap<Object,String> objectToVertMap, AAIExtensionMap aaiExtMap) {
+
+
+ DynamicEntity inventoryItem = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItem");
+ Object item = invResultItem.get("item");
+ inventoryItem.set("modelName", invResultItem.get("modelName"));
+ inventoryItem.set("item", item);
+ inventoryItem.set("extraProperties", invResultItem.get("extraProperties"));
+
+ String vertexId = "";
+
+ if (objectToVertMap.containsKey(item)) {
+ vertexId = objectToVertMap.get(item);
+ }
+
+ if (includeTheseVertices.containsKey(vertexId)) {
+ if (invResultItem.isSet("inventoryResponseItems")) {
+ List<DynamicEntity> invItemList = new ArrayList<DynamicEntity>();
+ DynamicEntity inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems");
+ DynamicEntity subInventoryResponseItems = invResultItem.get("inventoryResponseItems");
+ List<DynamicEntity> subInventoryResponseItemList = subInventoryResponseItems.get("inventoryResponseItem");
+ for (DynamicEntity ent : subInventoryResponseItemList) {
+ DynamicEntity invItem = remapInventoryItems(ent, jaxbContext, includeTheseVertices, objectToVertMap, aaiExtMap);
+ if (invItem != null) {
+ invItemList.add(invItem);
+ }
+ }
+ if (invItemList != null) {
+ inventoryItems.set("inventoryResponseItem", invItemList);
+ inventoryItem.set("inventoryResponseItems", inventoryItems);
+ }
+ }
+ }
+ return inventoryItem;
+ }
+
+ /**
+ * Unpack result set.
+ *
+ * @param g the g
+ * @param resultSetList the result set list
+ * @param jaxbContext the jaxb context
+ * @param aaiResources the aai resources
+ * @param objectToVertMap the object to vert map
+ * @param aaiExtMap the aai ext map
+ * @return the array list
+ * @throws AAIException the AAI exception
+ */
+ // this should return an inventoryItem
+ private ArrayList<DynamicEntity> unpackResultSet(TitanTransaction g, ArrayList<ResultSet> resultSetList,
+ DynamicJAXBContext jaxbContext,
+ AAIResources aaiResources,
+ HashMap<Object,String> objectToVertMap,
+ AAIExtensionMap aaiExtMap) throws AAIException {
+
+ ArrayList<DynamicEntity> resultList = new ArrayList<DynamicEntity>();
+
+ for (ResultSet resultSet : resultSetList) {
+
+ DynamicEntity inventoryItem = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItem");
+ DynamicEntity inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems");
+
+ // add this inventoryItem to the resultList for this level
+ resultList.add(inventoryItem);
+
+ TitanVertex vert = resultSet.getVert();
+
+ Long vertId = (Long)vert.longId();
+
+ String aaiNodeType = vert.<String>property("aai-node-type").orElse(null);
+
+ String simpleName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL,aaiNodeType);
+ // find an aaiResource with this node as the last element
+
+ AAIResource aaiRes = null;
+ for (Map.Entry<String,AAIResource> ent: aaiResources.getAaiResources().entrySet()) {
+ AAIResource res = ent.getValue();
+ if (res.getSimpleName().equals(simpleName)) {
+ aaiRes = res;
+ break;
+ }
+ }
+
+ if (aaiRes != null) {
+ PojoUtils pu = new PojoUtils();
+ DynamicEntity thisObj = jaxbContext.newDynamicEntity(aaiRes.getResourceClassName());
+
+ if (resultSet.getExtraPropertyHash() != null) {
+ HashMap<String,Object> extraProperties = resultSet.getExtraPropertyHash();
+
+ DynamicEntity extraPropertiesEntity = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".ExtraProperties");
+
+ List<DynamicEntity> extraPropsList = new ArrayList<DynamicEntity>();
+
+ for (Map.Entry<String,Object> ent : extraProperties.entrySet()) {
+ String propName = ent.getKey();
+ Object propVal = ent.getValue();
+
+ DynamicEntity extraPropEntity = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".ExtraProperty");
+
+ extraPropEntity.set("propertyName", propName);
+ extraPropEntity.set("propertyValue", propVal);
+
+ extraPropsList.add(extraPropEntity);
+
+ }
+ extraPropertiesEntity.set("extraProperty", extraPropsList);
+ inventoryItem.set("extraProperties", extraPropertiesEntity);
+ }
+ String propertyLimitDesc = resultSet.getPropertyLimitDesc();
+
+ if (propertyLimitDesc != null && propertyLimitDesc.length() > 0) {
+
+ if ("SHOW-NONE".equalsIgnoreCase(propertyLimitDesc)) {
+ HashMap<String,Object> emptyPropertyOverRideHash = new HashMap<String,Object>();
+ pu.getAaiDynamicObjectFromVertex(aaiRes, thisObj, vert, aaiRes.getPropertyDataTypeMap(), emptyPropertyOverRideHash);
+ } else if ("SHOW-ALL".equalsIgnoreCase(propertyLimitDesc)) {
+ pu.getAaiDynamicObjectFromVertex(aaiRes, thisObj, vert, aaiRes.getPropertyDataTypeMap());
+ } else if ("NAME-AND-KEYS-ONLY".equalsIgnoreCase(propertyLimitDesc)) {
+ AAIResourceKeys aaiResKeys = aaiRes.getAaiResourceKeys();
+ HashMap<String,Object> keysAndNamesPropHash = new HashMap<String,Object>();
+ for (AAIResourceKey aaiResKey : aaiResKeys.getAaiResourceKey()) {
+ keysAndNamesPropHash.put(aaiResKey.getKeyName(), "dummy");
+ }
+ for (String nodeNameProp : aaiRes.getNodeNameProps().get(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,simpleName))) {
+ keysAndNamesPropHash.put(nodeNameProp, "dummy");
+ }
+ pu.getAaiDynamicObjectFromVertex(aaiRes, thisObj, vert, aaiRes.getPropertyDataTypeMap(), keysAndNamesPropHash);
+ }
+ } else {
+ if (resultSet.getPropertyOverRideHash() != null && resultSet.getPropertyOverRideHash().size() > 0) {
+ HashMap<String,Object> propertyOverRideHash = resultSet.getPropertyOverRideHash();
+ pu.getAaiDynamicObjectFromVertex(aaiRes, thisObj, vert, aaiRes.getPropertyDataTypeMap(), propertyOverRideHash);
+ } else {
+ pu.getAaiDynamicObjectFromVertex(aaiRes, thisObj, vert, aaiRes.getPropertyDataTypeMap());
+ }
+ }
+
+ if (thisObj != null) {
+ inventoryItem.set("item", thisObj);
+
+ objectToVertMap.put(thisObj, vertId.toString());
+
+ String modelName = null;
+ try {
+ String personaModelId = (String)vert.<String>property("persona-model-id").orElse(null);
+ String personaModelVersion = (String)vert.<String>property("persona-model-version").orElse(null);
+
+ if ( (personaModelId != null && personaModelVersion != null)
+ && (personaModelId.length() > 0 && personaModelVersion.length() > 0) ) {
+ HashMap<String,Object> modelLookupHash = new HashMap<String,Object>();
+
+ modelLookupHash.put("model-id", personaModelId);
+ modelLookupHash.put("model-version", personaModelVersion);
+
+ TitanVertex modelVert = DbMeth.getUniqueNode(aaiExtMap.getTransId(),
+ aaiExtMap.getFromAppId(), g, "model", modelLookupHash, null);
+
+ modelName = modelVert.<String>property("model-name").orElse(null);
+ // there should only be one, we'll pick the first if not
+ if (modelName.length() > 0) {
+ inventoryItem.set("modelName", modelName);
+ }
+ }
+ } catch (DynamicException e) {
+ ; // it's ok, dynamic object might not have these fields
+ } catch (AAIException e) {
+ if (e.getErrorObject().getErrorCode().equals("6114")) {
+ // it's ok, couldn't find a matching model
+ } else {
+ throw e;
+ }
+ }
+
+ if (resultSet.getSubResultSet() != null) {
+ ArrayList<ResultSet> subResultSet = resultSet.getSubResultSet();
+ if (subResultSet != null) {
+ ArrayList<DynamicEntity> res = unpackResultSet(g, subResultSet, jaxbContext, aaiResources, objectToVertMap, aaiExtMap);
+ if (res.size() > 0) {
+ inventoryItems.set("inventoryResponseItem", res);
+ inventoryItem.set("inventoryResponseItems", inventoryItems);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return resultList;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/DbEdgeRules.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/DbEdgeRules.java
new file mode 100644
index 0000000..d29791a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/DbEdgeRules.java
@@ -0,0 +1,300 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmodel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimap;
+
+public class DbEdgeRules {
+
+ /*
+ * The EdgeRules data is set up as a key (fromNodeTypeA|toNodeTypeB) mapped
+ * to a string which holds the info we need to build an edge from nodeTypeA
+ * to nodeTypeB. Note -- the MultiMap will let us define more than one type
+ * of edge between a given pair of nodeTypes, but for now we never define
+ * more than one.
+ *
+ * The edgeInfo part is comma separated and looks like this:
+ * "edgeLabel,direction,multiplicityRule,isParent,usesResource,hasDelTarget,SVC-INFRA" This
+ * format is encoded into the EdgeInfoMap below.
+ * MultiplicityRule can be either "Many2Many", "Many2One", "One2Many" or "One2One"
+ * The values for the things after multiplicityRule can be either "true", "false" or "reverse". "reverse" is
+ * really saying that this tag does apply, but the edge will be traversed
+ * the opposite way from the same tag that just has "true".
+ */
+ public static final Map<Integer, String> EdgeInfoMap;
+ static {
+ EdgeInfoMap = new HashMap<Integer, String>();
+ EdgeInfoMap.put(0, "edgeLabel");
+ EdgeInfoMap.put(1, "direction");
+ EdgeInfoMap.put(2, "multiplicityRule");
+ EdgeInfoMap.put(3, "isParent");
+ EdgeInfoMap.put(4, "usesResource");
+ EdgeInfoMap.put(5, "hasDelTarget");
+ EdgeInfoMap.put(6, "SVC-INFRA");
+ }
+
+ public static Integer firstTagIndex = 3;
+
+ public static final Multimap<String, String> EdgeRules = new ImmutableSetMultimap.Builder<String, String>()
+ .putAll("cloud-region|l3-network",
+ "uses,OUT,Many2Many,false,false,false,false")
+ .putAll("cloud-region|tenant",
+ "has,OUT,One2Many,true,false,false,reverse")
+ .putAll("cloud-region|image",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("cloud-region|flavor",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("cloud-region|availability-zone",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("cloud-region|volume-group",
+ "has,OUT,One2Many,true,true,false,false")
+ .putAll("cloud-region|group-assignment",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("cloud-region|snapshot",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("customer|service-subscription",
+ "subscribesTo,OUT,Many2Many,true,false,false,reverse")
+ .putAll("generic-vnf|l-interface",
+ "hasLInterface,OUT,Many2Many,true,false,false,true")
+ .putAll("generic-vnf|availability-zone",
+ "hasAvailabilityZone,OUT,Many2Many,false,false,false,true")
+ .putAll("generic-vnf|lag-interface",
+ "hasLAGInterface,OUT,Many2Many,true,false,false,true")
+ .putAll("generic-vnf|l3-network",
+ "usesL3Network,OUT,Many2Many,false,true,false,true")
+ .putAll("generic-vnf|pserver",
+ "runsOnPserver,OUT,Many2Many,false,true,false,true")
+ .putAll("generic-vnf|vserver",
+ "runsOnVserver,OUT,One2Many,false,true,false,true")
+ .putAll("generic-vnf|service-instance",
+ "hasInstance,OUT,Many2Many,false,true,false,true")
+ .putAll("group-assignment|tenant",
+ "has,OUT,Many2Many,false,false,false,false")
+ .putAll("group-assignment|pserver",
+ "has,OUT,One2Many,false,false,false,false")
+ .putAll("image|metadata", "hasMetaData,OUT,Many2Many,true,false,false,false")
+ .putAll("image|metadatum",
+ "hasMetaDatum,OUT,Many2Many,true,false,false,false")
+ .putAll("l-interface|l3-interface-ipv4-address-list",
+ "hasIpAddress,OUT,Many2Many,true,false,false,true")
+ .putAll("l-interface|l3-interface-ipv6-address-list",
+ "hasIpAddress,OUT,Many2Many,true,false,false,true")
+ .putAll("l-interface|logical-link",
+ "usesLogicalLink,OUT,Many2Many,false,false,true,true")
+ .putAll("l-interface|vlan","hasVlan,OUT,Many2Many,true,false,false,false")
+ .putAll("l3-interface-ipv4-address-list|l3-network",
+ "isMemberOf,OUT,Many2Many,false,false,false,true")
+ .putAll("l3-interface-ipv6-address-list|l3-network",
+ "isMemberOf,OUT,Many2Many,false,false,false,true")
+ .putAll("l3-interface-ipv4-address-list|subnet",
+ "isMemberOf,OUT,Many2Many,false,false,false,true")
+ .putAll("l3-interface-ipv6-address-list|subnet",
+ "isMemberOf,OUT,Many2Many,false,false,false,true")
+ .putAll("l3-network|subnet",
+ "hasSubnet,OUT,Many2Many,true,false,false,reverse")
+ .putAll("l3-network|service-instance",
+ "hasInstance,OUT,Many2Many,false,false,false,reverse")
+ .putAll("l3-network|ctag-assignment",
+ "hasCtagAssignment,OUT,Many2Many,true,false,false,true")
+ .putAll("l3-network|segmentation-assignment",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("lag-interface|p-interface",
+ "usesPInterface,OUT,Many2Many,false,true,false,true")
+ .putAll("lag-interface|l-interface",
+ "hasLInterface,OUT,Many2Many,true,false,false,true")
+ .putAll("logical-link|pnf",
+ "bridgedTo,OUT,Many2Many,false,false,false,false")
+ .putAll("logical-link|logical-link",
+ "uses,OUT,One2Many,false,false,false,true")
+ .putAll("model|model-element",
+ "startsWith,OUT,One2Many,true,false,false,false")
+ .putAll("model-element|model",
+ "isA,OUT,Many2One,false,false,false,false")
+ .putAll("model|metadatum",
+ "hasMetaData,OUT,One2Many,true,false,false,false")
+ .putAll("model-element|model-element",
+ "connectsTo,OUT,One2Many,true,false,false,false")
+ .putAll("model-element|model-constraint",
+ "uses,OUT,One2Many,true,false,false,false")
+ .putAll("model-element|constrained-element-set",
+ "connectsTo,OUT,One2Many,true,false,false,false")
+ .putAll("model-constraint|constrained-element-set",
+ "uses,OUT,One2Many,true,false,false,false")
+ .putAll("constrained-element-set|element-choice-set",
+ "uses,OUT,One2Many,true,false,false,false")
+ .putAll("element-choice-set|model-element",
+ "has,OUT,One2Many,true,false,false,false")
+ .putAll("named-query|model",
+ "relatedTo,OUT,One2Many,false,false,false,false")
+ .putAll("named-query|named-query-element",
+ "startsWith,OUT,One2One,true,false,false,false")
+ .putAll("named-query-element|named-query-element",
+ "connectsTo,OUT,Many2Many,true,false,false,false")
+ .putAll("named-query-element|model",
+ "isA,OUT,Many2One,false,false,false,false")
+ .putAll("named-query-element|property-constraint",
+ "uses,OUT,One2Many,true,false,false,false")
+ .putAll("named-query-element|related-lookup",
+ "uses,OUT,One2Many,true,false,false,false")
+ .putAll("p-interface|l-interface",
+ "hasLInterface,OUT,Many2Many,true,false,false,true")
+ .putAll("p-interface|physical-link",
+ "usesPhysicalLink,OUT,Many2Many,false,false,true,false")
+ .putAll("p-interface|logical-link",
+ "usesLogicalLink,OUT,Many2One,false,false,false,true")
+ .putAll("pserver|cloud-region","locatedIn,OUT,Many2One,false,false,false,true")
+ .putAll("pserver|availability-zone","existsIn,OUT,Many2One,false,false,false,true")
+ .putAll("pserver|lag-interface",
+ "hasLAGInterface,OUT,Many2Many,true,false,false,true")
+ .putAll("pserver|p-interface",
+ "hasPinterface,OUT,Many2Many,true,true,false,true")
+ .putAll("pnf|p-interface",
+ "hasPinterface,OUT,Many2Many,true,true,false,true")
+ .putAll("pnf|lag-interface",
+ "has,OUT,One2Many,true,false,false,true")
+ .putAll("service-instance|pnf",
+ "uses,OUT,One2Many,false,true,false,false")
+ .putAll("service-subscription|service-instance",
+ "hasInstance,OUT,Many2Many,true,false,false,reverse")
+ .putAll("tenant|l3-network",
+ "usesL3Network,OUT,Many2Many,false,false,false,false")
+ .putAll("tenant|service-subscription",
+ "relatedTo,OUT,Many2Many,false,false,false,false")
+ .putAll("tenant|vserver", "owns,OUT,One2Many,true,false,false,reverse")
+ .putAll("vlan|l3-interface-ipv4-address-list",
+ "hasIpAddress,OUT,Many2Many,true,false,false,true")
+ .putAll("vlan|l3-interface-ipv6-address-list",
+ "hasIpAddress,OUT,Many2Many,true,false,false,true")
+ .putAll("vserver|flavor", "hasFlavor,OUT,Many2One,false,false,false,true")
+ .putAll("vserver|image", "hasImage,OUT,Many2One,false,false,false,true")
+ .putAll("vserver|ipaddress",
+ "hasIpAddress,OUT,Many2Many,true,true,false,false")
+ .putAll("vserver|l-interface",
+ "hasLInterface,OUT,Many2Many,true,false,false,true")
+ .putAll("vserver|pserver",
+ "runsOnPserver,OUT,Many2One,false,true,false,true")
+ .putAll("vserver|volume", "hasVolume,OUT,Many2Many,true,true,false,true")
+ .putAll("vserver|vnfc", "hosts,OUT,Many2Many,false,true,false,true")
+ .putAll("vserver|snapshot", "uses,OUT,One2One,false,false,false,true")
+ .putAll("service-instance|metadatum", "hasMetaData,OUT,Many2Many,true,false,false,false")
+ .putAll("service-instance|logical-link", "uses,OUT,Many2Many,false,false,true,false")
+ .putAll("service-instance|vlan", "dependsOn,OUT,One2Many,false,true,false,false")
+ .putAll("service-instance|service-instance", "dependsOn,OUT,One2Many,false,true,false,false")
+ .putAll("logical-link|generic-vnf", "bridgedTo,OUT,Many2Many,false,false,false,false")
+ .putAll("logical-link|pserver", "bridgedTo,OUT,Many2Many,false,false,false,false")
+ .putAll("volume-group|tenant", "belongsTo,OUT,Many2Many,false,false,false,true")
+ .putAll("vf-module|volume-group", "uses,OUT,One2One,false,false,false,true")
+ .putAll("vserver|vf-module", "isPartOf,OUT,Many2One,false,false,false,true")
+ .putAll("vf-module|l3-network", "uses,OUT,Many2Many,false,false,false,true")
+ .putAll("vf-module|vnfc", "uses,OUT,One2Many,false,false,true,true")
+ .putAll("generic-vnf|vf-module", "has,OUT,One2Many,true,false,false,true")
+ .putAll("generic-vnf|volume-group", "uses,OUT,One2Many,false,false,false,true")
+ .putAll("generic-vnf|vnfc", "uses,OUT,One2Many,false,false,true,true")
+ .putAll("vlan|logical-link", "usesLogicalLink,OUT,One2One,false,false,true,true")
+ .build();
+
+ public static final Multimap<String, String> DefaultDeleteScope = new ImmutableSetMultimap.Builder<String, String>()
+ .putAll("customer", "CASCADE_TO_CHILDREN")
+ .putAll("cloud-region", "THIS_NODE_ONLY")
+ .putAll("service-subscription", "CASCADE_TO_CHILDREN")
+ .putAll("service-instance", "CASCADE_TO_CHILDREN")
+ .putAll("tenant", "CASCADE_TO_CHILDREN")
+ .putAll("vserver", "CASCADE_TO_CHILDREN")
+ .putAll("volume", "THIS_NODE_ONLY")
+ .putAll("ipaddress", "THIS_NODE_ONLY")
+ .putAll("image", "ERROR_4_IN_EDGES_OR_CASCADE")
+ .putAll("pserver", "ERROR_4_IN_EDGES_OR_CASCADE")
+ .putAll("availability-zone", "ERROR_IF_ANY_IN_EDGES")
+ .putAll("flavor", "ERROR_IF_ANY_IN_EDGES")
+ .putAll("metadata", "THIS_NODE_ONLY")
+ .putAll("metadatum", "THIS_NODE_ONLY")
+ .putAll("model", "ERROR_4_IN_EDGES_OR_CASCADE")
+ .putAll("model-element", "CASCADE_TO_CHILDREN")
+ .putAll("named-query", "CASCADE_TO_CHILDREN")
+ .putAll("named-query-element", "CASCADE_TO_CHILDREN")
+ .putAll("collect-lookup", "THIS_NODE_ONLY")
+ .putAll("service", "ERROR_IF_ANY_IN_EDGES")
+ .putAll("l-interface", "CASCADE_TO_CHILDREN")
+ .putAll("vlan", "CASCADE_TO_CHILDREN")
+ .putAll("p-interface", "CASCADE_TO_CHILDREN")
+ .putAll("l3-interface-ipv6-address-list", "THIS_NODE_ONLY")
+ .putAll("l3-interface-ipv4-address-list", "THIS_NODE_ONLY")
+ .putAll("logical-link", "THIS_NODE_ONLY")
+ .putAll("physical-link", "THIS_NODE_ONLY")
+ .putAll("lag-interface", "CASCADE_TO_CHILDREN")
+ .putAll("l3-network", "CASCADE_TO_CHILDREN")
+ .putAll("subnet", "THIS_NODE_ONLY")
+ .putAll("vnfc", "THIS_NODE_ONLY")
+ .putAll("volume-group", "THIS_NODE_ONLY")
+ .putAll("ctag-assignment", "THIS_NODE_ONLY")
+ .putAll("pnf", "CASCADE_TO_CHILDREN")
+ .putAll("vf-module", "THIS_NODE_ONLY")
+ .putAll("snapshot", "THIS_NODE_ONLY")
+ .putAll("group-assignment", "THIS_NODE_ONLY")
+ .putAll("segmentation-assignment", "THIS_NODE_ONLY")
+ .putAll("generic-vnf", "CASCADE_TO_CHILDREN").build();
+
+ // NOTE -- Sorry, this is ugly, but we are mapping the nodeTypeCategory two
+ // ways just to
+ // make the code a little less bulky. But that means that we need to ensure
+ // that
+ // nodeTypeCategory and nodeTypeCatMap are kept in synch.
+
+ // NodeTypeCategory: key is: nodeTypeCategory, value is:
+ // "nodeTypes,keyProperties,AltKeyProps,depNode4UniquenessFlag"
+ public static final Multimap<String, String> NodeTypeCategory = new ImmutableSetMultimap.Builder<String, String>()
+ .putAll("vnf", "generic-vnf,vnf-id,,true").build();
+
+ // NodeTypeCatMap: key is nodeType; value is: "nodeTypeCategory"
+ // So -- we're assuming that a nodeType can only be in one nodeTypeCategory.
+ public static final Map<String, String> NodeTypeCatMap;
+ static {
+ NodeTypeCatMap = new HashMap<String, String>();
+ NodeTypeCatMap.put("generic-vnf", "vnf");
+ }
+
+ // ReservedPropNames: keys are property names of (node) properties that are
+ // common to all nodes and
+ // should not be removed if not passed in on an UPDATE request.
+ public static final Map<String, String> ReservedPropNames;
+ static {
+ ReservedPropNames = new HashMap<String, String>();
+ ReservedPropNames.put("source-of-truth", "");
+ ReservedPropNames.put("last-mod-source-of-truth", "");
+ ReservedPropNames.put("aai-created-ts", "");
+ ReservedPropNames.put("aai-last-mod-ts", "");
+ }
+
+ // This just lists which node types can be connected to themselves recursively.
+ // It's temporary - since DbEdgeRules is going to be overhauled in 16-10, this will
+ // get generated automatically. But for 1607, it can work like this.
+ public static final Map<String, String> CanBeRecursiveNT;
+ static {
+ CanBeRecursiveNT = new HashMap<String, String>();
+ CanBeRecursiveNT.put("model-element", "");
+ CanBeRecursiveNT.put("named-query-element", "");
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/RestRules.java b/ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/RestRules.java
new file mode 100644
index 0000000..9b66236
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/RestRules.java
@@ -0,0 +1,274 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmodel;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.openecomp.aai.exceptions.AAIException;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multimap;
+
+public class RestRules {
+
+ // resource, "package-name path/namespace,resource,plural,gp1,gp2,gp3,gp4,gp5"
+ // when the nodetype is used for the first time in a relationship use the nodetype as the resource
+ // this entry will be used for generating the REST URL
+ // if that nodetype can also be a child of another node - then add a new name for the resource to make it unique
+ // and use that in the ChildMap to be used by the code generator
+ // this works if the nodetypes are in the same namespace. If they are in different namespaces we will have
+ // to re-look at this.
+
+ public static final Multimap<String, String> ResourceMap =
+ new ImmutableSetMultimap.Builder<String, String>()
+ .putAll("dvs-switch", "CloudInfrastructure,dvs-switch,dvs-switches,,,,,")
+ .putAll("availability-zone", "CloudInfrastructure,availability-zone,availability-zones,,,,,")
+ .putAll("oam-network", "CloudInfrastructure,oam-network,oam-networks,,,,,")
+ .putAll("virtual-data-center", "CloudInfrastructure,virtual-data-center,virtual-data-centers,,,,,")
+ .putAll("network-profile", "CloudInfrastructure,network-profile,network-profiles,,,,,")
+ .putAll("volume-group", "CloudInfrastructure,volume-group,volume-groups,,,,,")
+ .putAll("pserver", "CloudInfrastructure,pserver,pservers,,,,,")
+ .putAll("p-interface", "CloudInfrastructure,p-interface,p-interfaces,pserver,,,,")
+ .putAll("l-interface", "CloudInfrastructure,l-interface,l-interfaces,p-interface,pserver,,,")
+ .putAll("vlan", "CloudInfrastructure,vlan,vlans,l-interface,p-interface,pserver,,")
+ .putAll("l3-interface-ipv4-address-list", "CloudInfrastructure,l3-interface-ipv4-address-list,,vlan,l-interface,p-interface,pserver,")
+ .putAll("l3-interface-ipv6-address-list", "CloudInfrastructure,l3-interface-ipv6-address-list,,vlan,l-interface,p-interface,pserver,")
+ .putAll("cloud-infrastructure-pservers-pserver-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list", "CloudInfrastructure,l3-interface-ipv4-address-list,,l-interface,p-interface,pserver,,")
+ .putAll("cloud-infrastructure-pservers-pserver-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list", "CloudInfrastructure,l3-interface-ipv6-address-list,,l-interface,p-interface,pserver,,")
+ .putAll("lag-interface", "CloudInfrastructure,lag-interface,lag-interfaces,pserver,,,,")
+ .putAll("cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface", "CloudInfrastructure,l-interface,l-interfaces,lag-interface,pserver,,,")
+ .putAll("cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan", "CloudInfrastructure,vlan,vlans,l-interface,lag-interface,pserver,,")
+ .putAll("cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "CloudInfrastructure,l3-interface-ipv4-address-list,,vlan,l-interface,lag-interface,pserver,")
+ .putAll("cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "CloudInfrastructure,l3-interface-ipv6-address-list,,vlan,l-interface,lag-interface,pserver,")
+ .putAll("cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list", "CloudInfrastructure,l3-interface-ipv4-address-list,,l-interface,lag-interface,pserver,,")
+ .putAll("cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list", "CloudInfrastructure,l3-interface-ipv6-address-list,,l-interface,lag-interface,pserver,,")
+ .putAll("complex", "CloudInfrastructure,complex,complexes,,,,,")
+ .putAll("ctag-pool", "CloudInfrastructure,ctag-pool,ctag-pools,complex,,,,")
+ .putAll("image", "CloudInfrastructure,image,images,,,,,")
+ .putAll("metadatum", "CloudInfrastructure,metadatum,metadata,image,,,,")
+ .putAll("flavor", "CloudInfrastructure,flavor,flavors,,,,,")
+ .putAll("tenant", "CloudInfrastructure,tenant,tenants,,,,,")
+ .putAll("vserver", "CloudInfrastructure,vserver,vservers,tenant,,,,")
+ .putAll("volume", "CloudInfrastructure,volume,volumes,vserver,tenant,,,")
+ .putAll("cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface", "CloudInfrastructure,l-interface,l-interfaces,vserver,tenant,,,")
+ .putAll("cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-vlans-vlan", "CloudInfrastructure,vlan,vlans,l-interface,vserver,tenant,,")
+ .putAll("cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "CloudInfrastructure,l3-interface-ipv4-address-list,,vlan,l-interface,vserver,tenant,")
+ .putAll("cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "CloudInfrastructure,l3-interface-ipv6-address-list,,vlan,l-interface,vserver,tenant,")
+ .putAll("cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-l3-interface-ipv4-address-list", "CloudInfrastructure,l3-interface-ipv4-address-list,,l-interface,vserver,tenant,,")
+ .putAll("cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-l3-interface-ipv6-address-list", "CloudInfrastructure,l3-interface-ipv6-address-list,,l-interface,vserver,tenant,,")
+ .putAll("service-capability", "ServiceDesignAndCreation,service-capability,service-capabilities,,,,,")
+ .putAll("service", "ServiceDesignAndCreation,service,services,,,,,")
+ .putAll("model", "ServiceDesignAndCreation,model,models,,,,,")
+ .putAll("named-query", "ServiceDesignAndCreation,named-query,named-queries,,,,,")
+ .putAll("named-query-element", "ServiceDesignAndCreation,named-query-element,named-query-elements,named-query,,,,")
+ .putAll("license-key-resource", "LicenseManagement,license-key-resource,license-key-resources,,,,,")
+ .putAll("customer", "Business,customer,customers,,,,,")
+ .putAll("service-subscription", "Business,service-subscription,service-subscriptions,customer,,,,")
+ .putAll("service-instance", "Business,service-instance,service-instances,service-subscription,customer,,,")
+ .putAll("business-customers-customer-service-subscriptions-service-subscription-service-instances-service-instance-metadata-metadatum", "Business,metadatum,metadata,service-instance,service-subscription,customer,,")
+ .putAll("connector", "Business,connector,connectors,,,,,")
+ .putAll("business-connectors-connector-metadata-metadatum", "Business,metadatum,metadata,connector,,,,")
+ .putAll("generic-vnf", "Network,generic-vnf,generic-vnfs,,,,,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface", "Network,lag-interface,lag-interfaces,generic-vnf,,,,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface", "Network,l-interface,l-interfaces,lag-interface,generic-vnf,,,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,lag-interface,generic-vnf,,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,lag-interface,generic-vnf,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,lag-interface,generic-vnf,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,lag-interface,generic-vnf,,")
+ .putAll("network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,lag-interface,generic-vnf,,")
+ .putAll("network-generic-vnfs-generic-vnf-l-interfaces-l-interface", "Network,l-interface,l-interfaces,generic-vnf,,,,")
+ .putAll("network-generic-vnfs-generic-vnf-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,generic-vnf,,,")
+ .putAll("network-generic-vnfs-generic-vnf-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,generic-vnf,,")
+ .putAll("network-generic-vnfs-generic-vnf-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,generic-vnf,,")
+ .putAll("network-generic-vnfs-generic-vnf-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,generic-vnf,,,")
+ .putAll("network-generic-vnfs-generic-vnf-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,generic-vnf,,,")
+ .putAll("logical-link", "Network,logical-link,logical-links,,,,,")
+ .putAll("physical-link", "Network,physical-link,physical-links,,,,,")
+ .putAll("vpn-binding", "Network,vpn-binding,vpn-bindings,,,,,")
+ .putAll("site-pair-set", "Network,site-pair-set,site-pair-sets,,,,,")
+ .putAll("routing-instance", "Network,routing-instance,routing-instances,site-pair-set,,,,")
+ .putAll("site-pair", "Network,site-pair,site-pairs,routing-instance,site-pair-set,,,")
+ .putAll("class-of-service", "Network,class-of-service,classes-of-service,site-pair,routing-instance,site-pair-set,,")
+ .putAll("multicast-configuration", "Network,multicast-configuration,multicast-configurations,,,,,")
+ .putAll("vce", "Network,vce,vces,,,,,")
+ .putAll("port-group", "Network,port-group,port-groups,vce,,,,")
+ .putAll("cvlan-tag", "Network,cvlan-tag-entry,cvlan-tags,port-group,vce,,,")
+ .putAll("newvce", "Network,newvce,newvces,,,,,")
+ .putAll("network-newvces-newvce-l-interfaces-l-interface", "Network,l-interface,l-interfaces,newvce,,,,")
+ .putAll("network-newvces-newvce-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,newvce,,,")
+ .putAll("network-newvces-newvce-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,newvce,,")
+ .putAll("network-newvces-newvce-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,newvce,,")
+ .putAll("network-newvces-newvce-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,newvce,,,")
+ .putAll("network-newvces-newvce-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,newvce,,,")
+ .putAll("vpe", "Network,vpe,vpes,,,,,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface", "Network,lag-interface,lag-interfaces,vpe,,,,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface", "Network,l-interface,l-interfaces,lag-interface,vpe,,,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,lag-interface,vpe,,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,lag-interface,vpe,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,lag-interface,vpe,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,lag-interface,vpe,,")
+ .putAll("network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,lag-interface,vpe,,")
+ .putAll("network-vpes-vpe-l-interfaces-l-interface", "Network,l-interface,l-interfaces,vpe,,,,")
+ .putAll("network-vpes-vpe-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,vpe,,,")
+ .putAll("network-vpes-vpe-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,vpe,,")
+ .putAll("network-vpes-vpe-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,vpe,,")
+ .putAll("network-vpes-vpe-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,vpe,,,")
+ .putAll("network-vpes-vpe-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,vpe,,,")
+ .putAll("vpls-pe", "Network,vpls-pe,vpls-pes,,,,,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface", "Network,p-interface,p-interfaces,vpls-pe,,,,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface", "Network,l-interface,l-interfaces,p-interface,vpls-pe,,,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,p-interface,vpls-pe,,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,p-interface,vpls-pe,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,p-interface,vpls-pe,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,p-interface,vpls-pe,,")
+ .putAll("network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,p-interface,vpls-pe,,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface", "Network,lag-interface,lag-interfaces,vpls-pe,,,,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface", "Network,l-interface,l-interfaces,lag-interface,vpls-pe,,,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan", "Network,vlan,vlans,l-interface,lag-interface,vpls-pe,,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,vlan,l-interface,lag-interface,vpls-pe,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,vlan,l-interface,lag-interface,vpls-pe,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list", "Network,l3-interface-ipv4-address-list,,l-interface,lag-interface,vpls-pe,,")
+ .putAll("network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list", "Network,l3-interface-ipv6-address-list,,l-interface,lag-interface,vpls-pe,,")
+ .putAll("lag-link", "Network,lag-link,lag-links,,,,,")
+ .putAll("l3-network", "Network,l3-network,l3-networks,,,,,")
+ .putAll("ctag-assignment", "Network,ctag-assignment,ctag-assignments,l3-network,,,,")
+ .putAll("subnet", "Network,subnet,subnets,l3-network,,,,")
+ .putAll("vnfc", "Network,vnfc,vnfcs,,,,,")
+ .build();
+
+ // resource, "parent,child1,child2,child3,child4,child5,child6"
+ public static final Multimap<String, String> ChildMap =
+ new ImmutableSetMultimap.Builder<String, String>()
+ .putAll("Vce", "vce,port-group,cvlan-tag,,,,")
+ .putAll("Service", "service,,,,,,")
+ .putAll("LicenseKeyResource", "license-key-resource,,,,,,")
+ .putAll("Pserver", "pserver,p-interface,l-interface,vlan,l3-interface-ipv4-address-list,l3-interface-ipv6-address-list,cloud-infrastructure-pservers-pserver-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list,cloud-infrastructure-pservers-pserver-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list,lag-interface,cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface,cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan,cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list,cloud-infrastructure-pservers-pserver-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list,")
+ .putAll("VplsPe", "vpls-pe,network-vpls-pes-vpls-pe-p-interfaces-p-interface,network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface,network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-vlans-vlan,network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-vpls-pes-vpls-pe-p-interfaces-p-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-vpls-pes-vpls-pe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list,")
+ .putAll("LagLink", "lag-link,,,,,,")
+ .putAll("Complex", "complex,ctag-pool,,,,,")
+ .putAll("NetworkProfile", "network-profile,,,,,,")
+ .putAll("MulticastConfiguration", "multicast-configuration,,,,,,")
+ .putAll("OamNetwork", "oam-network,,,,,,")
+ .putAll("Newvce", "newvce,network-newvces-newvce-l-interfaces-l-interface,network-newvces-newvce-l-interfaces-l-interface-vlans-vlan,network-newvces-newvce-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-newvces-newvce-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-newvces-newvce-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-newvces-newvce-l-interfaces-l-interface-l3-interface-ipv6-address-list,")
+ .putAll("VolumeGroup", "volume-group,,,,,,")
+ .putAll("PhysicalLink", "physical-link,,,,,,")
+ .putAll("Image", "image,metadatum,,,,,")
+ .putAll("SitePairSet", "site-pair-set,routing-instance,site-pair,class-of-service,,,")
+ .putAll("VpnBinding", "vpn-binding,,,,,,")
+ .putAll("DvsSwitch", "dvs-switch,,,,,,")
+ .putAll("ServiceCapability", "service-capability,,,,,,")
+ .putAll("Model", "model,,,,,,")
+ .putAll("NamedQuery", "named-query,named-query-element,,,,,")
+ .putAll("NamedQueryElement", "named-query-element,named-query-element,named-query-element,named-query-element,named-query-element,named-query-element,")
+ .putAll("Tenant", "tenant,vserver,volume,cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface,cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-vlans-vlan,cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-l3-interface-ipv4-address-list,cloud-infrastructure-tenants-tenant-vservers-vserver-l-interfaces-l-interface-l3-interface-ipv6-address-list,")
+ .putAll("GenericVnf", "generic-vnf,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-generic-vnfs-generic-vnf-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list,network-generic-vnfs-generic-vnf-l-interfaces-l-interface,network-generic-vnfs-generic-vnf-l-interfaces-l-interface-vlans-vlan,network-generic-vnfs-generic-vnf-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-generic-vnfs-generic-vnf-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-generic-vnfs-generic-vnf-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-generic-vnfs-generic-vnf-l-interfaces-l-interface-l3-interface-ipv6-address-list,")
+ .putAll("Customer", "customer,service-subscription,service-instance,business-customers-customer-service-subscriptions-service-subscription-service-instances-service-instance-metadata-metadatum,,,")
+ .putAll("Flavor", "flavor,,,,,,")
+ .putAll("L3Network", "l3-network,ctag-assignment,subnet,,,,")
+ .putAll("VirtualDataCenter", "virtual-data-center,,,,,,")
+ .putAll("LogicalLink", "logical-link,,,,,,")
+ .putAll("Connector", "connector,business-connectors-connector-metadata-metadatum,,,,,")
+ .putAll("AvailabilityZone", "availability-zone,,,,,,")
+ .putAll("Vnfc", "vnfc,,,,,,")
+ .putAll("Vpe", "vpe,network-vpes-vpe-lag-interfaces-lag-interface,network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface,network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan,network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-vpes-vpe-lag-interfaces-lag-interface-l-interfaces-l-interface-l3-interface-ipv6-address-list,network-vpes-vpe-l-interfaces-l-interface,network-vpes-vpe-l-interfaces-l-interface-vlans-vlan,network-vpes-vpe-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv4-address-list,network-vpes-vpe-l-interfaces-l-interface-vlans-vlan-l3-interface-ipv6-address-list,network-vpes-vpe-l-interfaces-l-interface-l3-interface-ipv4-address-list,network-vpes-vpe-l-interfaces-l-interface-l3-interface-ipv6-address-list,")
+ .build();
+
+
+
+
+
+ /**
+ * Gets the res rules.
+ *
+ * @param resource the resource
+ * @return the res rules
+ * @throws AAIException the AAI exception
+ */
+ public static String [] getResRules(String resource) throws AAIException{
+ try {
+
+ if (resource.equals("cloud-region")) {
+
+ String[] tmp = {null,null,null};
+ return tmp;
+ }
+ String resRule = "";
+ Collection <String> resRuleColl = ResourceMap.get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, resource));
+ Iterator <String> ruleItr = resRuleColl.iterator();
+ if (ruleItr.hasNext()){
+ // For now, we only look for one type of edge between two nodes.
+ resRule = ruleItr.next();
+ }
+ else {
+ // No edge rule found for this
+ String detail = "No rule found for resource: " + resource;
+ throw new AAIException("AAI_4012", detail);
+ }
+
+ String [] rules = resRule.split(",", 8);
+ if( rules.length != 8 ){
+ String detail = "(itemCount=" + rules.length + ") for resource: " + resource;
+ throw new AAIException("AAI_4012", detail);
+ }
+
+ for (int i=1; i < 8; i++) {
+ if (rules[i].equals(""))
+ rules[i] = null;
+ }
+ return rules;
+ } catch (Exception e) {
+ // No rule found for this
+ String detail = "Exception when looking for rule: No rule found for resource: " + resource;
+ throw new AAIException("AAI_4012", detail);
+ }
+ }
+
+ /**
+ * Gets the child rules.
+ *
+ * @param resource the resource
+ * @return the child rules
+ * @throws AAIException the AAI exception
+ */
+ public static String [] getChildRules(String resource) throws AAIException{
+ try {
+ String childRule = "";
+ Collection <String> childRuleColl = ChildMap.get(resource);
+ Iterator <String> ruleItr = childRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ childRule = ruleItr.next();
+ }
+ else {
+ // No rule found for this
+ String detail = "No child rule found for resource: " + resource;
+ throw new AAIException("AAI_4012", detail);
+ }
+ return childRule.split(",");
+ } catch (Exception e) {
+ // No rule found for this
+ String detail = "Exception when looking for rule: No child rule found for resource: " + resource;
+ throw new AAIException("AAI_4012", detail);
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java
new file mode 100644
index 0000000..78cf8c6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap;
+
+import java.io.IOException;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.HttpMethod;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.google.inject.ConfigurationException;
+
+public class AAIDmaapEventJMSConsumer implements MessageListener {
+
+ private final static String COMPONENT = "aaiDmaapEvent";
+
+ private AAILogger aaiLogger = new AAILogger(AAIDmaapEventJMSConsumer.class.getName());
+
+ private AAIDmaapPublisher adp = null;
+
+ public AAIDmaapEventJMSConsumer() throws org.apache.commons.configuration.ConfigurationException {
+ super();
+ LogLineBuilder llBuilder = new LogLineBuilder("AAIDmaapEventJMSConsumer", "AAIDmaapEventJMSConsumer");
+ LogLine logline = llBuilder.build(COMPONENT, "AAIDmaapEventJMSConsumerInit");
+
+ if (this.adp == null) {
+ try {
+ PropertiesConfiguration config = new PropertiesConfiguration(
+ AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "/aaiEventDMaaPPublisher.properties");
+ config.setProperty("DME2preferredRouterFilePath",
+ AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "/preferredRoute.txt");
+ config.save();
+ this.adp = new AAIDmaapPublisher(
+ AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "/aaiEventDMaaPPublisher.properties");
+ } catch (IOException | ConfigurationException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000",
+ "Error updating dmaap config file for aai event.");
+ aaiLogger.error(errorObject, logline, e);
+ }
+ }
+
+ }
+
+ @Override
+ public void onMessage(Message message) {
+
+ String jsmMessageTxt = "";
+ String aaiEvent = "";
+ String transId = "";
+ String fromAppId = "";
+
+ LogLineBuilder llBuilder = new LogLineBuilder("AAIDmaapEventJMSConsumer", "AAIDmaapEventJMSConsumer");
+ LogLine logline = llBuilder.build(COMPONENT, "AAIEventSendToDmaap");
+
+ if (message instanceof TextMessage) {
+ try {
+ jsmMessageTxt = ((TextMessage) message).getText();
+ JSONObject jo = new JSONObject(jsmMessageTxt);
+
+ if (jo.getString("aaiEvent") != null && !jo.getString("aaiEvent").isEmpty()) {
+ aaiEvent = jo.getString("aaiEvent");
+ } else {
+ return;
+ }
+ if (jo.getString("transId") != null) {
+ transId = jo.getString("transId");
+ }
+ if (jo.getString("fromAppId") != null) {
+ fromAppId = jo.getString("fromAppId");
+ }
+
+ llBuilder = new LogLineBuilder(transId, fromAppId);
+ logline = llBuilder.build(COMPONENT, "AAIEventSendToDmaap");
+
+ this.adp.getMRBatchingPublisher().send(jo.getString("message"));
+
+ }catch (IOException e) {
+ if (e instanceof java.net.SocketException) {
+ if (e.getMessage().contains("Connection reset")) {
+ } else {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_7304",
+ "Error reaching DMaaP to send event. " + aaiEvent);
+ aaiLogger.error(errorObject, logline, e);
+ }
+ } else {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_7304",
+ "Error reaching DMaaP to send event. " + aaiEvent);
+ aaiLogger.error(errorObject, logline, e);
+ }
+ } catch (JMSException | JSONException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_7350",
+ "Error parsing aaievent jsm message for sending to dmaap. " + jsmMessageTxt);
+ aaiLogger.error(errorObject, logline, e);
+ }
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java
new file mode 100644
index 0000000..8c182cf
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsTemplate;
+
+public class AAIDmaapEventJMSProducer {
+ @Autowired
+ private JmsTemplate jmsTemplate;
+
+ public void sendMessageToDefaultDestination(final String transId, final String fromAppId, final String message) {
+ JSONObject jo = new JSONObject();
+ try {
+ jo.put("transId", transId);
+ jo.put("fromAppId", fromAppId);
+ jo.put("aaiEvent", message);
+
+ jmsTemplate.convertAndSend(jo.toString());
+ } catch (JSONException e) {
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapPublisher.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapPublisher.java
new file mode 100644
index 0000000..e14d2c4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapPublisher.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.json.JSONObject;
+
+import com.att.nsa.mr.client.MRBatchingPublisher;
+import com.att.nsa.mr.client.MRClientFactory;
+import com.att.nsa.mr.client.MRPublisher.message;
+
+public class AAIDmaapPublisher {
+ private String publisherPropertyFile;
+
+ private MRBatchingPublisher pub = null;
+
+ public AAIDmaapPublisher(String publisherPropertyFile) throws FileNotFoundException, IOException {
+ this.publisherPropertyFile = publisherPropertyFile;
+ this.pub = MRClientFactory.createBatchingPublisher(this.publisherPropertyFile);
+
+ }
+
+ public List<message> publishAndClose(JSONObject payload) throws IOException, InterruptedException {
+ this.pub.send(payload.toString());
+ return pub.close(60, TimeUnit.SECONDS);
+ }
+
+ public MRBatchingPublisher getMRBatchingPublisher() {
+ return this.pub;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIClient.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIClient.java
new file mode 100644
index 0000000..374b6e0
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIClient.java
@@ -0,0 +1,164 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap.aaiWorkload.consumer;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.UUID;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+
+import org.json.JSONObject;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+
+public class AAIClient {
+
+ private Client restClient = null;
+ private int baseTimeout = 5000;
+ private int numRetriesOnTimeout = 0;
+
+ public AAIClient() throws KeyManagementException, NoSuchAlgorithmException, AAIException, UnrecoverableKeyException, KeyStoreException, CertificateException, IOException {
+
+ this.restClient = initClient();
+ }
+
+ /**
+ *
+ * @param baseTimeout
+ * min value of 5000ms
+ * @param numRetriesOnTimeout
+ * max value 5 (will default to 4 for any value higher
+ * @throws KeyManagementException
+ * @throws NoSuchAlgorithmException
+ * @throws AAIException
+ * @throws UnrecoverableKeyException
+ * @throws KeyStoreException
+ * @throws CertificateException
+ * @throws IOException
+ */
+ public AAIClient(int baseTimeout, int numRetriesOnTimeout)
+ throws KeyManagementException, NoSuchAlgorithmException, AAIException, UnrecoverableKeyException, KeyStoreException, CertificateException, IOException {
+ this.restClient = initClient();
+ if (baseTimeout > 0) {
+ this.baseTimeout = baseTimeout;
+ }
+ if (numRetriesOnTimeout > 0) {
+ this.numRetriesOnTimeout = numRetriesOnTimeout;
+ }
+ if (this.numRetriesOnTimeout > 5) {
+ this.numRetriesOnTimeout = 5;
+ }
+ }
+
+ /**
+ * @return
+ * @throws AAIException
+ * @throws NoSuchAlgorithmException
+ * @throws KeyManagementException
+ * @throws KeyStoreException
+ * @throws IOException
+ * @throws CertificateException
+ * @throws UnrecoverableKeyException
+ */
+ private Client initClient()
+ throws AAIException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
+ ClientConfig config = new DefaultClientConfig();
+
+ SSLContext ctx = null;
+
+ String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME);
+ String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD);
+ String keystore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_KEYSTORE_FILENAME);
+ String keystore_password = AAIConfig.get(AAIConstants.AAI_KEYSTORE_PASSWD);
+
+ System.setProperty("javax.net.ssl.trustStore", truststore_path);
+ System.setProperty("javax.net.ssl.trustStorePassword", truststore_password);
+ HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+ public boolean verify(String string, SSLSession ssls) {
+ return true;
+ }
+ });
+
+ ctx = SSLContext.getInstance("TLSv1.2");
+ KeyManagerFactory kmf = null;
+ kmf = KeyManagerFactory.getInstance("SunX509");
+ FileInputStream fin = new FileInputStream(keystore_path);
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ char[] pwd = keystore_password.toCharArray();
+ ks.load(fin, pwd);
+ kmf.init(ks, pwd);
+
+ ctx.init(kmf.getKeyManagers(), null, null);
+ config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(new HostnameVerifier() {
+ @Override
+ public boolean verify(String s, SSLSession sslSession) {
+ return true;
+ }
+ }, ctx));
+
+ return Client.create(config);
+ }
+
+ public ClientResponse put(String restUri, JSONObject eventBody, String sourceName) throws Exception {
+
+ int tries = 1;
+ ClientResponse response;
+ WebResource webResource;
+ while (true) {
+ try {
+ this.restClient.setConnectTimeout(tries * this.baseTimeout);
+ webResource = restClient.resource(AAIConfig.get("aai.server.url") + restUri);
+ response = webResource.accept("application/json").header("X-FromAppId", "aaiWorkload-dmaap-" + sourceName).header("X-TransactionId", UUID.randomUUID())
+ .type("application/json").put(ClientResponse.class, eventBody.toString());
+ return response;
+ } catch (Exception e) {
+ if (e instanceof SocketTimeoutException && tries < this.numRetriesOnTimeout + 1) {
+ tries++;
+ } else {
+ throw e;
+
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadConsumer.java
new file mode 100644
index 0000000..db1ddf1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadConsumer.java
@@ -0,0 +1,207 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap.aaiWorkload.consumer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.UUID;
+import java.util.logging.Level;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.att.aft.dme2.api.DME2Exception;
+import com.att.nsa.mr.client.MRClientFactory;
+import com.att.nsa.mr.client.MRConsumer;
+
+public class AAIWorkloadConsumer {
+
+ private static String fromAppId = "AAIWorkloadConsumerScheduledTask";
+ private static String COMPONENT = "DMAAP-AAI-WORKLOAD";
+ private AAILogger aaiLogger = new AAILogger(AAIWorkloadConsumer.class.getName());
+
+ private String preferredRouterFilePath;
+ private String aaiWorkloadConsumerPropertiesFile;
+ private String aaiWorkloadStatusPublisherPropertiesFile;
+ private String aaiWorkloadPublisherPropertiesFile;
+ private String dmaapPropertyHome = "";
+ private String dmaapConusmerId = "";
+
+ private MRConsumer aaiWorkloadConsumer;
+
+ public AAIWorkloadConsumer() throws Exception {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, "N/A", fromAppId, "AAIWorkloadConsumer");
+ aaiLogger.debug(logline, "Initalize the AAIWorkloadConsumer");
+
+ this.dmaapPropertyHome = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES;
+ if (this.dmaapPropertyHome == null) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Property AAI_HOME_ETC_APP_PROPERTIES is not set. Stopping AAIWorkloadConsumer.");
+ aaiLogger.error(errorObject, logline, null);
+ throw new Exception("Property AAI_HOME_ETC_APP_PROPERTIES is not set. Stopping AAIWorkloadConsumer.");
+ }
+
+ if (System.getProperty("lrmHost") != null && !System.getProperty("lrmHost").isEmpty()) {
+ this.dmaapConusmerId = System.getProperty("lrmHost");
+ } else {
+ this.dmaapConusmerId = UUID.randomUUID().toString();
+ }
+
+ processPropertyFiles();
+
+ this.aaiWorkloadConsumer = MRClientFactory.createConsumer(this.aaiWorkloadConsumerPropertiesFile);
+ aaiLogger.debug(logline, "Initalization completed.");
+
+ }
+
+ private void processPropertyFiles() throws FileNotFoundException, UnknownHostException, ConfigurationException {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, "N/A", fromAppId, "processPropertyFiles");
+
+ this.preferredRouterFilePath = this.dmaapPropertyHome + "preferredRoute.txt";
+ this.aaiWorkloadConsumerPropertiesFile = this.dmaapPropertyHome + "aaiWorkloadConsumer.properties";
+ this.aaiWorkloadPublisherPropertiesFile = this.dmaapPropertyHome + "aaiWorkloadPublisher.properties";
+ this.aaiWorkloadStatusPublisherPropertiesFile = this.dmaapPropertyHome + "aaiWorkloadStatusPublisher.properties";
+
+ aaiLogger.debug(logline, "Preferred router file path: " + this.preferredRouterFilePath);
+ aaiLogger.debug(logline, "AAI Workload Consumer Properties path: " + this.aaiWorkloadConsumerPropertiesFile);
+ aaiLogger.debug(logline, "AAI Workload Publisher Properties path: " + this.aaiWorkloadPublisherPropertiesFile);
+ aaiLogger.debug(logline, "AAI Workload StatusPublisher Properties path: " + this.aaiWorkloadStatusPublisherPropertiesFile);
+
+ File fo = new File(this.preferredRouterFilePath);
+ if (!fo.exists()) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Dmaap Route file " + preferredRouterFilePath + " does not exist.");
+ aaiLogger.error(errorObject, logline, null);
+ throw new FileNotFoundException("Dmaap Route file " + preferredRouterFilePath + " does not exist");
+ }
+
+ fo = new File(this.aaiWorkloadConsumerPropertiesFile);
+ if (!fo.exists()) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Dmaap consumer property file " + aaiWorkloadConsumerPropertiesFile + " does not exist.");
+ aaiLogger.error(errorObject, logline, null);
+ throw new FileNotFoundException("Dmaap consumer property file " + aaiWorkloadConsumerPropertiesFile + " does not exist.");
+ }
+
+ fo = new File(this.aaiWorkloadPublisherPropertiesFile);
+ if (!fo.exists()) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Dmaap publisher property file " + this.aaiWorkloadPublisherPropertiesFile + " does not exist.");
+ aaiLogger.error(errorObject, logline, null);
+ throw new FileNotFoundException("Dmaap publisher property file " + this.aaiWorkloadPublisherPropertiesFile + " does not exist.");
+ }
+
+ fo = new File(this.aaiWorkloadStatusPublisherPropertiesFile);
+ if (!fo.exists()) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000",
+ "Dmaap publisher property file " + this.aaiWorkloadStatusPublisherPropertiesFile + " does not exist");
+ aaiLogger.error(errorObject, logline, null);
+ throw new FileNotFoundException("Dmaap publisher property file " + this.aaiWorkloadStatusPublisherPropertiesFile + " does not exist");
+ }
+
+ modifyProperties();
+
+ }
+
+ private void modifyProperties() throws ConfigurationException {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, "N/A", fromAppId, "modifyProperties");
+
+ PropertiesConfiguration config = new PropertiesConfiguration(this.aaiWorkloadConsumerPropertiesFile);
+ if (config.getProperty("id") == null || config.getProperty("id").equals("") || config.getProperty("id").equals("aaiConsumerId")) {
+ config.setProperty("id", this.dmaapConusmerId);
+ aaiLogger.debug(logline, "Updated " + this.aaiWorkloadConsumerPropertiesFile + " id property to this.dmaapConusmerId.");
+ }
+ config.setProperty("DME2preferredRouterFilePath", this.preferredRouterFilePath);
+ config.save();
+ aaiLogger.debug(logline, "Updated " + this.aaiWorkloadConsumerPropertiesFile + " DME2preferredRouterFilePath property to " + this.preferredRouterFilePath);
+
+ config = new PropertiesConfiguration(this.aaiWorkloadPublisherPropertiesFile);
+ config.setProperty("DME2preferredRouterFilePath", this.preferredRouterFilePath);
+ config.save();
+ aaiLogger.debug(logline, "Updated " + this.aaiWorkloadPublisherPropertiesFile + " DME2preferredRouterFilePath property to " + this.preferredRouterFilePath);
+
+ config = new PropertiesConfiguration(this.aaiWorkloadStatusPublisherPropertiesFile);
+ config.setProperty("DME2preferredRouterFilePath", this.preferredRouterFilePath);
+ config.save();
+ aaiLogger.debug(logline, "Updated " + this.aaiWorkloadStatusPublisherPropertiesFile + " DME2preferredRouterFilePath property to " + this.preferredRouterFilePath);
+
+ }
+
+ public void startProcessing() throws Exception {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, "N/A", fromAppId, "startProcessing");
+
+ int fetchFailCounter = 0;
+ AAIWorkloadEventProcessor awep = null;
+// com.att.aft.dme2.api.util.configuration.DME2LoggingConfig.getInstance().initializeDME2Logger().setLevel(Level.SEVERE);
+ while (AAIConfig.get("aai.dmaap.workload.enableEventProcessing").equals("true")) {
+
+ try {
+ if (System.getProperty("org.openecomp.aai.serverStarted") != null && System.getProperty("org.openecomp.aai.serverStarted").equals("true")) {
+ Iterable<String> eventMessages = aaiWorkloadConsumer.fetch();
+ for (String eventMessage : eventMessages) {
+ String transId = UUID.randomUUID().toString();
+ aaiLogger.debug(logline, "Processing new dmaap message from the aaiWorkload topic." + transId);
+ aaiLogger.debug(logline, "Processing new dmaap message from the aaiWorkload topic: " + eventMessage);
+ awep = new AAIWorkloadEventProcessor(this.aaiWorkloadPublisherPropertiesFile, this.aaiWorkloadStatusPublisherPropertiesFile, transId);
+ awep.process(eventMessage);
+ }
+ fetchFailCounter = 0;
+ }
+ } catch (DME2Exception e) {
+ if (e.getErrorCode().equals("AFT-DME2-0999")) {
+ // do nothing as this is the standard http timeout
+ } else {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Exiting due to dmaap consumer client throwing dme2 error.");
+ aaiLogger.error(errorObject, logline, e);
+ this.aaiWorkloadConsumer.close();
+ throw e;
+ }
+ } catch (IOException e) {
+ fetchFailCounter++;
+ if (fetchFailCounter > 10) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Exiting due to fetch throwing io exception. More than 10 times.");
+ aaiLogger.error(errorObject, logline, e);
+ this.aaiWorkloadConsumer.close();
+ throw e;
+ }
+ } catch (Exception e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Exiting due to unknown exception.");
+ aaiLogger.error(errorObject, logline, e);
+ this.aaiWorkloadConsumer.close();
+ throw e;
+ }
+ }
+ this.aaiWorkloadConsumer.close();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventProcessor.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventProcessor.java
new file mode 100644
index 0000000..4a788dd
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventProcessor.java
@@ -0,0 +1,340 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap.aaiWorkload.consumer;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.List;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.javatuples.Pair;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.openecomp.aai.dmaap.AAIDmaapPublisher;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.nsa.mr.client.MRPublisher.message;
+import com.sun.jersey.api.client.ClientResponse;
+
+public class AAIWorkloadEventProcessor {
+
+ private static String fromAppId = "AAIWorkloadConsumerScheduledTask";
+ private static String COMPONENT = "DMAAP-AAI-WORKLOAD";
+ private AAILogger aaiLogger = new AAILogger(AAIWorkloadEventProcessor.class.getName());
+ private String transId = "";
+
+ private JSONObject event;
+ private JSONObject eventHeader;
+ private JSONObject eventBody;
+
+ private JSONObject responseHeader;
+ private JSONObject responseBody;
+ private String aaiWorkloadPublisherPropertiesFile;
+ private String aaiWorkloadStatusPublisherPropertiesFile;
+
+
+ /**
+ *
+ * @param aaiWorkloadPublisherPropertiesFile
+ * @param aaiWorkloadStatusPublisherPropertiesFile
+ * @param transId
+ */
+ public AAIWorkloadEventProcessor(String aaiWorkloadPublisherPropertiesFile, String aaiWorkloadStatusPublisherPropertiesFile, String transId) {
+ this.transId = transId;
+ this.aaiWorkloadPublisherPropertiesFile = aaiWorkloadPublisherPropertiesFile;
+ this.aaiWorkloadStatusPublisherPropertiesFile = aaiWorkloadStatusPublisherPropertiesFile;
+ }
+
+ /**
+ *
+ * @param eventMessage
+ * @return
+ */
+ public Pair<AAIWorkloadEventStatus, String> process(String eventMessage) {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, this.transId, fromAppId, "process(String eventMessage)");
+
+ Pair<AAIWorkloadEventStatus, String> status = null;
+
+ this.event = null;
+ this.eventHeader = null;
+ this.eventBody = null;
+
+ try {
+ aaiLogger.debug(logline, "Processing event: " + eventMessage);
+ this.event = new JSONObject(eventMessage);
+ } catch (JSONException je) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "ERROR: Event is not valid JSON." + je.getMessage());
+ aaiLogger.error(errorObject, logline, je);
+ return this.statusPair(AAIWorkloadEventStatus.FAILUE, "ERROR: Event is not valid JSON." + je.getMessage());
+ }
+
+ try {
+ aaiLogger.debug(logline, "Validating event header.");
+ this.validateEventHeader(this.event);
+ this.generateEventResponseHeader();
+ } catch (JSONException je) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "ERROR: Event header is not valid." + je.getMessage());
+ aaiLogger.error(errorObject, logline, je);
+ return this.statusPair(AAIWorkloadEventStatus.FAILUE, "ERROR: Event header is not valid." + je.getMessage());
+ }
+
+ try {
+ aaiLogger.debug(logline, "Generating status event header.");
+ this.generateEventResponseHeader();
+ } catch (JSONException je) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Failed to create response header." + je.getMessage());
+ aaiLogger.error(errorObject, logline, je);
+ this.responseHeader = null;
+ }
+
+ try {
+ aaiLogger.debug(logline, "Processing event body.");
+ eventBody = this.event.getJSONObject("event-body");
+ } catch (JSONException je) {
+ try {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "ERROR: Event body not valid JSON." + je.getMessage());
+ aaiLogger.error(errorObject, logline, je);
+ status = this.statusPair(AAIWorkloadEventStatus.FAILUE, "ERROR: Event body not valid JSON." + je.getMessage());
+ this.publishStatusResponse(status);
+ return status;
+ } catch (JSONException | IOException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "WARNING: Failed to pulish status " + e.getMessage());
+ aaiLogger.error(errorObject, logline, je);
+ return this.statusPair(AAIWorkloadEventStatus.FAILED_TO_PUBLISH_STATUS, "WARNING: Failed to pulish status " + e.getMessage());
+ }
+ }
+
+ // initialize aai client, on failure to initialize republish the event.
+ AAIClient aaiClient = null;
+ try {
+ aaiClient = new AAIClient();
+ } catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | CertificateException | AAIException | IOException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "ERROR: AAI Client failed to initalize." + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ return this.republishEvent();
+ }
+
+ // put to aai, on socket timeout exception republish the event
+ ClientResponse resp = null;
+ try {
+ aaiLogger.debug(logline, "Calling aai bulk add on event body.");
+ resp = aaiClient.put("bulkadd", this.eventBody, this.eventHeader.getString("source-name"));
+ } catch (Exception e) {
+ if (e instanceof SocketTimeoutException) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "AAI client timed out during put. Attempting to republish to topic. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ return this.republishEvent();
+ } else if (e instanceof SSLHandshakeException) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "AAI client handshake error during put. Attempting to republish to topic. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ return this.republishEvent();
+ } else {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "AAI Unknown error during put. Failure. Attempting to republish to topic. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ status = this.statusPair(AAIWorkloadEventStatus.FAILUE, "AAI Unknown error during put. Failure.");
+ try {
+ this.publishStatusResponse(status);
+ } catch (JSONException | IOException e1) {
+ errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Failed to publish status. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ }
+ return status;
+ }
+ }
+
+ int respStatusCode = resp.getStatus();
+ String responsePayload = resp.getEntity(String.class);
+
+ if (responsePayload == null) {
+ responsePayload = "";
+ }
+
+ aaiLogger.debug(logline, "AAI response status code. " + respStatusCode);
+ aaiLogger.debug(logline, "AAI response status payload. " + responsePayload);
+
+ try {
+ JSONObject responsePayloadJO = new JSONObject(responsePayload);
+ JSONObject updatedResponsePayloadJO = new JSONObject();
+ updatedResponsePayloadJO.put("aai-put-status", respStatusCode);
+ updatedResponsePayloadJO.put("aai-put-response", responsePayloadJO);
+ responsePayload = updatedResponsePayloadJO.toString();
+
+ if (respStatusCode == 201) {
+ aaiLogger.debug(logline, "Successfully bulk add. ");
+ this.publishStatusResponse(this.statusPair(AAIWorkloadEventStatus.SUCCESS, responsePayload));
+ } else {
+ aaiLogger.debug(logline, "Unsuccessfully bulk add. ");
+ this.publishStatusResponse(this.statusPair(AAIWorkloadEventStatus.FAILUE, responsePayload));
+ }
+ } catch (JSONException e) {
+
+ } catch (FileNotFoundException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Failed to publish status due to status publisher property file not found. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ } catch (IOException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Connection issue reaching status publisher. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ }
+
+ aaiLogger.debug(logline, "Event processed successfully.");
+ return this.statusPair(AAIWorkloadEventStatus.SUCCESS, "Event processed successfully.");
+
+ }
+
+ /**
+ * Publishes the status message to the aaiWorkload status topic.
+ *
+ * @param statusPair
+ * @throws JSONException
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void publishStatusResponse(Pair<AAIWorkloadEventStatus, String> statusPair) throws JSONException, FileNotFoundException, IOException {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, this.transId, fromAppId, "publishStatusResponse(Pair<AAIWorkloadEventStatus, String> statusPair)");
+
+ aaiLogger.debug(logline, "Publishing status response.");
+
+ if (this.responseHeader == null) {
+ aaiLogger.debug(logline, "Status response header failed to be created, no status to publish.");
+ } else {
+ this.responseBody = new JSONObject();
+ this.responseBody.put("status", statusPair.getValue0().toString());
+ this.responseBody.put("status-message", statusPair.getValue1());
+ JSONObject responsePayload = new JSONObject();
+ responsePayload.put("status-event-header", this.responseHeader);
+ responsePayload.put("status-event-body", this.responseBody);
+
+ try {
+ aaiLogger.debug(logline, "Publishing status message. " + responsePayload);
+ publish(this.aaiWorkloadStatusPublisherPropertiesFile, responsePayload);
+ } catch (InterruptedException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Caught exception when publishing status message. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ }
+ }
+
+ }
+
+ /**
+ * Republish the event to aaiworkload queue. Retry a max of 5 times.
+ *
+ * @return
+ */
+ private Pair<AAIWorkloadEventStatus, String> republishEvent() {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, this.transId, fromAppId, "republishEvent()");
+
+ int count = 0;
+ while (count < 5) {
+ count++;
+ try {
+ aaiLogger.debug(logline, "Republishing message to aai workload topic.");
+ publish(this.aaiWorkloadPublisherPropertiesFile, this.event);
+ aaiLogger.debug(logline, "Republishing successful.");
+ return this.statusPair(AAIWorkloadEventStatus.REPUBLISHED, "Put to aai timed out multiple times, possible issue with server.");
+ } catch (Exception e) {
+ if (e instanceof IOException || e instanceof InterruptedException) {
+ // retries on io exception up to 3 times.
+ } else {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", "Failed to republish due to unknown error. " + e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ return this.statusPair(AAIWorkloadEventStatus.FAILED_TO_REPUBLISH, "Failed to republish due to unknown error. " + e.getMessage());
+ }
+ }
+
+ }
+
+ return this.statusPair(AAIWorkloadEventStatus.FAILED_TO_REPUBLISH, "Failed to republish event 5 times.");
+
+ }
+
+ private List<message> publish(String publisherPropFile, JSONObject responsePayload) throws FileNotFoundException, IOException, InterruptedException {
+ AAIDmaapPublisher awdp = new AAIDmaapPublisher(publisherPropFile);
+ return awdp.publishAndClose(responsePayload);
+ }
+
+ /**
+ * Using the event header generate the status response header.
+ *
+ * @throws JSONException
+ */
+ private void generateEventResponseHeader() throws JSONException {
+ this.responseHeader = new JSONObject(this.eventHeader.toString());
+ this.responseHeader.put("id", this.eventHeader.getString("id") + "status");
+ this.responseHeader.put("entity-type", "STATUS");
+ }
+
+ /**
+ * Validates that the event header has the id and source name for
+ * processing. (needed for status response msg)
+ *
+ * @param event
+ * @throws JSONException
+ */
+ private void validateEventHeader(JSONObject event) throws JSONException {
+ eventHeader = event.getJSONObject("event-header");
+ if (this.eventHeader.getString("id") == null || this.eventHeader.getString("id").isEmpty()) {
+ throw new JSONException("Event header id missing.");
+ } else if (this.eventHeader.getString("source-name") == null || this.eventHeader.getString("source-name").isEmpty()) {
+ throw new JSONException("Event header source-name missing.");
+ }
+ }
+
+ private Pair<AAIWorkloadEventStatus, String> statusPair(AAIWorkloadEventStatus status, String msg) {
+ if (msg == null) {
+ msg = "";
+ }
+ return new Pair<AAIWorkloadEventStatus, String>(status, msg);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public JSONObject getEventHeader() {
+ return eventHeader;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public JSONObject getEventBody() {
+ return eventBody;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventStatus.java b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventStatus.java
new file mode 100644
index 0000000..626a70b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventStatus.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dmaap.aaiWorkload.consumer;
+
+public enum AAIWorkloadEventStatus {
+ SUCCESS, AAI_CLIENT_TIMEOUT, FAILED_TO_REPUBLISH, FAILUE, REPUBLISHED, FAILED_TO_PUBLISH_STATUS
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResource.java
new file mode 100644
index 0000000..c6efbb3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResource.java
@@ -0,0 +1,675 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.model;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import com.google.common.collect.Multimap;
+
+
+public class AAIResource {
+ private AAIResource parent;
+ private AAIResources children;
+
+ private AAIResourceKeys aaiResourceKeys;
+
+ private String namespace; // /Network/Vces/Vce/PortGroups/PortGroup/CvlanTags/CvlanTag -> "Network"
+
+ private String resourceType; // node or container
+ private String resourceClassName; // (dynamic entity)
+ private String simpleName; // Vce
+ private String fullName; // /Network/Vces/Vce/PortGroups/PortGroup/CvlanTags/CvlanTag
+ private String uri; // /network/vces/vce/{vnf-id}/port-groups/port-group/{interface-name}/cvlan-tags/cvlan-tag/{cvlan-tag}
+ private String apiVersion;
+ private String relationshipListClass;
+ private String relationshipUtils;
+
+ private Map<String, String> PropertyDataTypeMap;
+ private Multimap<String, String> NodeMapIndexedProps;
+ private Multimap<String, String> NodeAltKey1Props;
+ private Multimap<String, String> NodeDependencies;
+ private Multimap<String, String> NodeKeyProps;
+ private Multimap<String, String> NodeReqProps;
+ private Multimap<String, String> NodeNameProps;
+ private Multimap<String, String> NodeUniqueProps;
+
+ // if new dataTypes are added - make sure to update getAllFields() method below
+ private ArrayList<String> stringFields;
+ private ArrayList<String> stringListFields;
+ private ArrayList<String> longFields;
+ private ArrayList<String> intFields;
+ private ArrayList<String> shortFields;
+ private ArrayList<String> booleanFields;
+
+ private ArrayList<String> requiredFields;
+ private ArrayList<String> orderedFields;
+ private AAIResource recurseToResource;
+ private boolean allowDirectWrite;
+ private boolean allowDirectRead;
+ private ArrayList<String> autoGenUuidFields;
+
+ /**
+ * Gets the parent.
+ *
+ * @return the parent
+ */
+ public AAIResource getParent() {
+ return parent;
+ }
+
+ /**
+ * Sets the parent.
+ *
+ * @param parent the new parent
+ */
+ public void setParent(AAIResource parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Gets the children.
+ *
+ * @return the children
+ */
+ public AAIResources getChildren() {
+ if (this.children == null) {
+ this.children = new AAIResources();
+ }
+ return this.children;
+ }
+
+ /**
+ * Gets the aai resource keys.
+ *
+ * @return the aai resource keys
+ */
+ public AAIResourceKeys getAaiResourceKeys() {
+ if (aaiResourceKeys == null) {
+ aaiResourceKeys = new AAIResourceKeys();
+ }
+ return aaiResourceKeys;
+ }
+
+ /**
+ * Gets the namespace.
+ *
+ * @return the namespace
+ */
+ public String getNamespace() {
+ return namespace;
+ }
+
+ /**
+ * Sets the namespace.
+ *
+ * @param namespace the new namespace
+ */
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ /**
+ * Gets the resource type.
+ *
+ * @return the resource type
+ */
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ /**
+ * Sets the resource type.
+ *
+ * @param resourceType the new resource type
+ */
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ /**
+ * Gets the simple name.
+ *
+ * @return the simple name
+ */
+ public String getSimpleName() {
+ return simpleName;
+ }
+
+ /**
+ * Sets the simple name.
+ *
+ * @param simpleName the new simple name
+ */
+ public void setSimpleName(String simpleName) {
+ this.simpleName = simpleName;
+ }
+
+ /**
+ * Gets the full name.
+ *
+ * @return the full name
+ */
+ public String getFullName() {
+ return fullName;
+ }
+
+ /**
+ * Sets the full name.
+ *
+ * @param fullName the new full name
+ */
+ public void setFullName(String fullName) {
+ this.fullName = fullName;
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @return the uri
+ */
+ public String getUri() {
+ return uri;
+ }
+
+ /**
+ * Sets the uri.
+ *
+ * @param uri the new uri
+ */
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Gets the resource class name.
+ *
+ * @return the resource class name
+ */
+ public String getResourceClassName() {
+ return resourceClassName;
+ }
+
+ /**
+ * Sets the resource class name.
+ *
+ * @param resourceClassName the new resource class name
+ */
+ public void setResourceClassName(String resourceClassName) {
+ this.resourceClassName = resourceClassName;
+ }
+
+ /**
+ * Gets the property data type map.
+ *
+ * @return the property data type map
+ */
+ public Map<String, String> getPropertyDataTypeMap() {
+ return PropertyDataTypeMap;
+ }
+
+ /**
+ * Sets the property data type map.
+ *
+ * @param propertyDataTypeMap the property data type map
+ */
+ public void setPropertyDataTypeMap(Map<String, String> propertyDataTypeMap) {
+ PropertyDataTypeMap = propertyDataTypeMap;
+ }
+
+ /**
+ * Gets the node map indexed props.
+ *
+ * @return the node map indexed props
+ */
+ public Multimap<String, String> getNodeMapIndexedProps() {
+ return NodeMapIndexedProps;
+ }
+
+ /**
+ * Sets the node map indexed props.
+ *
+ * @param nodeMapIndexedProps the node map indexed props
+ */
+ public void setNodeMapIndexedProps(Multimap<String, String> nodeMapIndexedProps) {
+ NodeMapIndexedProps = nodeMapIndexedProps;
+ }
+
+ /**
+ * Gets the node key props.
+ *
+ * @return the node key props
+ */
+ public Multimap<String, String> getNodeKeyProps() {
+ return NodeKeyProps;
+ }
+
+ /**
+ * Sets the node key props.
+ *
+ * @param nodeKeyProps the node key props
+ */
+ public void setNodeKeyProps(Multimap<String, String> nodeKeyProps) {
+ this.NodeKeyProps = nodeKeyProps;
+ }
+
+ /**
+ * Gets the node name props.
+ *
+ * @return the node name props
+ */
+ public Multimap<String, String> getNodeNameProps() {
+ return NodeNameProps;
+ }
+
+ /**
+ * Sets the node name props.
+ *
+ * @param nodeNameProps the node name props
+ */
+ public void setNodeNameProps(Multimap<String, String> nodeNameProps) {
+
+ NodeNameProps = nodeNameProps;
+ }
+
+ /**
+ * Gets the node unique props.
+ *
+ * @return the node unique props
+ */
+ public Multimap<String, String> getNodeUniqueProps() {
+ return NodeUniqueProps;
+ }
+
+ /**
+ * Sets the node unique props.
+ *
+ * @param nodeUniqueProps the node unique props
+ */
+ public void setNodeUniqueProps(Multimap<String, String> nodeUniqueProps) {
+ NodeUniqueProps = nodeUniqueProps;
+ }
+
+ /**
+ * Gets the node req props.
+ *
+ * @return the node req props
+ */
+ public Multimap<String, String> getNodeReqProps() {
+ return NodeReqProps;
+ }
+
+ /**
+ * Sets the node req props.
+ *
+ * @param nodeReqProps the node req props
+ */
+ public void setNodeReqProps(Multimap<String, String> nodeReqProps) {
+ NodeReqProps = nodeReqProps;
+ }
+
+ /**
+ * Gets the api version.
+ *
+ * @return the api version
+ */
+ public String getApiVersion() {
+ return apiVersion;
+ }
+
+ /**
+ * Sets the api version.
+ *
+ * @param apiVersion the new api version
+ */
+ public void setApiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ }
+
+ /**
+ * Gets the relationship list class.
+ *
+ * @return the relationship list class
+ */
+ public String getRelationshipListClass() {
+ return relationshipListClass;
+ }
+
+ /**
+ * Sets the relationship list class.
+ *
+ * @param relationshipListClass the new relationship list class
+ */
+ public void setRelationshipListClass(String relationshipListClass) {
+ this.relationshipListClass = relationshipListClass;
+ }
+
+ /**
+ * Gets the relationship utils.
+ *
+ * @return the relationship utils
+ */
+ public String getRelationshipUtils() {
+ return relationshipUtils;
+ }
+
+ /**
+ * Sets the relationship utils.
+ *
+ * @param relationshipUtils the new relationship utils
+ */
+ public void setRelationshipUtils(String relationshipUtils) {
+ this.relationshipUtils = relationshipUtils;
+ }
+
+ /**
+ * Gets the string fields.
+ *
+ * @return the string fields
+ */
+ public ArrayList<String> getStringFields() {
+ if (this.stringFields == null) {
+ this.stringFields = new ArrayList<String>();
+ }
+ return this.stringFields;
+ }
+
+ /**
+ * Sets the string fields.
+ *
+ * @param stringFields the new string fields
+ */
+ public void setStringFields(ArrayList<String> stringFields) {
+ this.stringFields = stringFields;
+ }
+
+ /**
+ * Gets the string list fields.
+ *
+ * @return the string list fields
+ */
+ public ArrayList<String> getStringListFields() {
+ if (this.stringListFields == null) {
+ this.stringListFields = new ArrayList<String>();
+ }
+ return this.stringListFields;
+ }
+
+ /**
+ * Sets the string list fields.
+ *
+ * @param stringListFields the new string list fields
+ */
+ public void setStringListFields(ArrayList<String> stringListFields) {
+ this.stringListFields = stringListFields;
+ }
+
+ /**
+ * Gets the long fields.
+ *
+ * @return the long fields
+ */
+ public ArrayList<String> getLongFields() {
+ if (this.longFields == null) {
+ this.longFields = new ArrayList<String>();
+ }
+ return longFields;
+ }
+
+ /**
+ * Sets the long fields.
+ *
+ * @param longFields the new long fields
+ */
+ public void setLongFields(ArrayList<String> longFields) {
+ this.longFields = longFields;
+ }
+
+ /**
+ * Gets the int fields.
+ *
+ * @return the int fields
+ */
+ public ArrayList<String> getIntFields() {
+ if (this.intFields == null) {
+ this.intFields = new ArrayList<String>();
+ }
+ return intFields;
+ }
+
+ /**
+ * Sets the int fields.
+ *
+ * @param intFields the new int fields
+ */
+ public void setIntFields(ArrayList<String> intFields) {
+ this.intFields = intFields;
+ }
+
+ /**
+ * Gets the short fields.
+ *
+ * @return the short fields
+ */
+ public ArrayList<String> getShortFields() {
+ if (this.shortFields == null) {
+ this.shortFields = new ArrayList<String>();
+ }
+ return shortFields;
+ }
+
+ /**
+ * Sets the short fields.
+ *
+ * @param shortFields the new short fields
+ */
+ public void setShortFields(ArrayList<String> shortFields) {
+ this.shortFields = shortFields;
+ }
+
+ /**
+ * Gets the boolean fields.
+ *
+ * @return the boolean fields
+ */
+ public ArrayList<String> getBooleanFields() {
+ if (this.booleanFields == null) {
+ this.booleanFields = new ArrayList<String>();
+ }
+ return booleanFields;
+ }
+
+ /**
+ * Sets the boolean fields.
+ *
+ * @param booleanFields the new boolean fields
+ */
+ public void setBooleanFields(ArrayList<String> booleanFields) {
+ this.booleanFields = booleanFields;
+ }
+
+ /**
+ * Gets the required fields.
+ *
+ * @return the required fields
+ */
+ public ArrayList<String> getRequiredFields() {
+ if (this.requiredFields == null) {
+ this.requiredFields = new ArrayList<String>();
+ }
+ return requiredFields;
+ }
+
+ /**
+ * Sets the required fields.
+ *
+ * @param requiredFields the new required fields
+ */
+ public void setRequiredFields(ArrayList<String> requiredFields) {
+ this.requiredFields = requiredFields;
+ }
+
+ /**
+ * Gets the ordered fields.
+ *
+ * @return the ordered fields
+ */
+ public ArrayList<String> getOrderedFields() {
+ if (this.orderedFields == null) {
+ this.orderedFields = new ArrayList<String>();
+ }
+ return this.orderedFields;
+ }
+
+ /**
+ * Gets the all fields.
+ *
+ * @return the all fields
+ */
+ public ArrayList<String> getAllFields() {
+
+ ArrayList<String> allFields = new ArrayList<String>();
+ allFields.addAll(getBooleanFields());
+ allFields.addAll(getStringListFields());
+ allFields.addAll(getStringFields());
+ allFields.addAll(getIntFields());
+ allFields.addAll(getLongFields());
+ allFields.addAll(getShortFields());
+
+ return allFields;
+ }
+
+ /**
+ * Gets the plural name.
+ *
+ * @return the plural name
+ */
+ public String getPluralName() {
+
+ if (simpleName.contains("List") || simpleName.contains("-list") )
+ return "";
+ String[] fullNameList = getFullName().split("/");
+ return fullNameList[fullNameList.length - 2];
+ }
+
+ /**
+ * Sets the node alt key 1 props.
+ *
+ * @param _dbRulesNodeAltKey1Props the db rules node alt key 1 props
+ */
+ public void setNodeAltKey1Props(Multimap<String, String> _dbRulesNodeAltKey1Props) {
+ this.NodeAltKey1Props = _dbRulesNodeAltKey1Props;
+ }
+
+ /**
+ * Gets the node alt key 1 props.
+ *
+ * @return the node alt key 1 props
+ */
+ public Multimap<String,String> getNodeAltKey1Props() {
+ return this.NodeAltKey1Props;
+ }
+
+ /**
+ * Sets the node dependencies.
+ *
+ * @param _dbRulesNodeDependencies the db rules node dependencies
+ */
+ public void setNodeDependencies(Multimap<String, String> _dbRulesNodeDependencies) {
+ this.NodeDependencies = _dbRulesNodeDependencies;
+ }
+
+ /**
+ * Gets the node dependencies.
+ *
+ * @return the node dependencies
+ */
+ public Multimap<String,String> getNodeDependencies() {
+ return this.NodeDependencies;
+ }
+
+ /**
+ * Gets the recurse to resource.
+ *
+ * @return the recurse to resource
+ */
+ public AAIResource getRecurseToResource() {
+ return this.recurseToResource;
+ }
+
+ /**
+ * Sets the recurse to resource.
+ *
+ * @param ancestor the new recurse to resource
+ */
+ public void setRecurseToResource(AAIResource ancestor) {
+ this.recurseToResource = ancestor;
+
+ }
+
+ /**
+ * Sets the allow direct write.
+ *
+ * @param allowDirectWrite the new allow direct write
+ */
+ public void setAllowDirectWrite(boolean allowDirectWrite) {
+ this.allowDirectWrite = allowDirectWrite;
+ }
+
+ /**
+ * Checks if is allow direct write.
+ *
+ * @return true, if is allow direct write
+ */
+ public boolean isAllowDirectWrite() {
+ return this.allowDirectWrite;
+ }
+
+ /**
+ * Sets the allow direct read.
+ *
+ * @param allowDirectRead the new allow direct read
+ */
+ public void setAllowDirectRead(boolean allowDirectRead) {
+ this.allowDirectRead = allowDirectRead;
+ }
+
+ /**
+ * Checks if is allow direct read.
+ *
+ * @return true, if is allow direct read
+ */
+ public boolean isAllowDirectRead() {
+ return this.allowDirectRead;
+ }
+
+ /**
+ * Gets the auto gen uuid fields.
+ *
+ * @return the auto gen uuid fields
+ */
+ public ArrayList<String> getAutoGenUuidFields() {
+ if (this.autoGenUuidFields == null) {
+ this.autoGenUuidFields = new ArrayList<String>();
+ }
+ return this.autoGenUuidFields;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKey.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKey.java
new file mode 100644
index 0000000..aa3c1e5
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKey.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.model;
+
+import com.google.common.base.CaseFormat;
+
+public class AAIResourceKey {
+ private String keyName;
+ private String keyType;
+ private String pathParamName;
+ private String dnCamKeyName;
+
+ /**
+ * Gets the key name.
+ *
+ * @return the key name
+ */
+ public String getKeyName() {
+ return keyName;
+ }
+
+ /**
+ * Sets the key name.
+ *
+ * @param keyName the new key name
+ */
+ public void setKeyName(String keyName) {
+ this.keyName = keyName;
+ }
+
+ /**
+ * Gets the key type.
+ *
+ * @return the key type
+ */
+ public String getKeyType() {
+ return keyType;
+ }
+
+ /**
+ * Sets the key type.
+ *
+ * @param t the new key type
+ */
+ public void setKeyType(String t) {
+ this.keyType = t;
+ }
+
+ /**
+ * Gets the path param name.
+ *
+ * @return the path param name
+ */
+ public String getPathParamName() {
+ return pathParamName;
+ }
+
+ /**
+ * Sets the path param name.
+ *
+ * @param pathParamName the new path param name
+ */
+ public void setPathParamName(String pathParamName) {
+ this.pathParamName = pathParamName;
+ }
+
+ /**
+ * Gets the dn cam key name.
+ *
+ * @return the dn cam key name
+ */
+ public String getDnCamKeyName() {
+ return dnCamKeyName;
+ }
+
+ /**
+ * Sets the dn cam key name.
+ *
+ * @param dnCamKeyName the new dn cam key name
+ */
+ public void setDnCamKeyName(String dnCamKeyName) {
+ this.dnCamKeyName = dnCamKeyName;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKeys.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKeys.java
new file mode 100644
index 0000000..8082cd7
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKeys.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AAIResourceKeys {
+ private List<AAIResourceKey> aaiResourceKey;
+
+ /**
+ * Gets the aai resource key.
+ *
+ * @return the aai resource key
+ */
+ public List<AAIResourceKey> getAaiResourceKey() {
+ if (aaiResourceKey == null) {
+ aaiResourceKey = new ArrayList<AAIResourceKey>();
+ }
+ return aaiResourceKey;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResources.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResources.java
new file mode 100644
index 0000000..0a91ca6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResources.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.model;
+
+import java.util.HashMap;
+
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+
+public class AAIResources {
+
+ private DynamicJAXBContext jaxbContext;
+
+ private HashMap<String, AAIResource> aaiResources;
+ private HashMap<String, AAIResource> resourceLookup;
+
+
+ /**
+ * Gets the aai resources.
+ *
+ * @return the aai resources
+ */
+ public HashMap<String, AAIResource> getAaiResources() {
+ if (aaiResources == null) {
+ aaiResources = new HashMap<String, AAIResource>();
+ }
+ return aaiResources;
+ }
+
+ /**
+ * Gets the jaxb context.
+ *
+ * @return the jaxb context
+ */
+ public DynamicJAXBContext getJaxbContext() {
+ return jaxbContext;
+ }
+
+ /**
+ * Sets the jaxb context.
+ *
+ * @param jaxbContext the new jaxb context
+ */
+ public void setJaxbContext(DynamicJAXBContext jaxbContext) {
+ this.jaxbContext = jaxbContext;
+ }
+
+ /**
+ * Gets the resource lookup.
+ *
+ * @return the resource lookup
+ */
+ public HashMap<String, AAIResource> getResourceLookup() {
+ if (resourceLookup == null) {
+ resourceLookup = new HashMap<String, AAIResource>();
+ }
+ return resourceLookup;
+ }
+
+ /**
+ * Sets the resource lookup.
+ *
+ * @param resourceLookup the resource lookup
+ */
+ public void setResourceLookup(HashMap<String, AAIResource> resourceLookup) {
+ this.resourceLookup = resourceLookup;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItem.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItem.java
new file mode 100644
index 0000000..4edd103
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItem.java
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.model;
+
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class AncestryItem {
+
+ private String fullResourceName;
+
+ private AAIResource aaiResource;
+
+ private TitanVertex vertex;
+
+ private Object obj;
+
+ /**
+ * Gets the full resource name.
+ *
+ * @return the full resource name
+ */
+ public String getFullResourceName() {
+ return fullResourceName;
+ }
+
+ /**
+ * Sets the full resource name.
+ *
+ * @param fullResourceName the new full resource name
+ */
+ public void setFullResourceName(String fullResourceName) {
+ this.fullResourceName = fullResourceName;
+ }
+
+ /**
+ * Gets the aai resource.
+ *
+ * @return the aai resource
+ */
+ public AAIResource getAaiResource() {
+ return aaiResource;
+ }
+
+ /**
+ * Sets the aai resource.
+ *
+ * @param aaiResource the new aai resource
+ */
+ public void setAaiResource(AAIResource aaiResource) {
+ this.aaiResource = aaiResource;
+ }
+
+ /**
+ * Gets the vertex.
+ *
+ * @return the vertex
+ */
+ public TitanVertex getVertex() {
+ return vertex;
+ }
+
+ /**
+ * Sets the vertex.
+ *
+ * @param vertex the new vertex
+ */
+ public void setVertex(TitanVertex vertex) {
+ this.vertex = vertex;
+ }
+
+ /**
+ * Gets the obj.
+ *
+ * @return the obj
+ */
+ public Object getObj() {
+ return obj;
+ }
+
+ /**
+ * Sets the obj.
+ *
+ * @param obj the new obj
+ */
+ public void setObj(Object obj) {
+ this.obj = obj;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItems.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItems.java
new file mode 100644
index 0000000..e9be3ad
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItems.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.model;
+
+import java.util.LinkedHashMap;
+
+public class AncestryItems {
+
+ private LinkedHashMap<String, AncestryItem> ancestryItems;
+
+ /**
+ * Gets the ancestry items.
+ *
+ * @return the ancestry items
+ */
+ public LinkedHashMap<String, AncestryItem> getAncestryItems() {
+ if (ancestryItems == null) {
+ ancestryItems = new LinkedHashMap<String, AncestryItem>();
+ }
+ return ancestryItems;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/NotificationEvent.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/NotificationEvent.java
new file mode 100644
index 0000000..865d045
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/NotificationEvent.java
@@ -0,0 +1,564 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2016.01.06 at 05:38:00 PM EST
+//
+
+
+package org.openecomp.aai.domain.notificationEvent;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.w3c.dom.Element;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="cambria.partition" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="event-header" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="timestamp" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="source-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="domain" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="sequence-number" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="severity" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="event-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="version" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="action" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="top-entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="entity-link" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="status" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;any processContents='lax' namespace='##other' minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "cambriaPartition",
+ "eventHeader",
+ "entity"
+})
+@XmlRootElement(name = "NotificationEvent")
+public class NotificationEvent {
+
+ @XmlElement(name = "cambria.partition")
+ protected String cambriaPartition;
+ @XmlElement(name = "event-header")
+ protected NotificationEvent.EventHeader eventHeader;
+ @XmlAnyElement(lax = true)
+ protected Object entity;
+
+ /**
+ * Gets the value of the eventHeader property.
+ *
+ * @return
+ * possible object is
+ * {@link NotificationEvent.EventHeader }
+ *
+ */
+ public NotificationEvent.EventHeader getEventHeader() {
+ return eventHeader;
+ }
+
+ /**
+ * Sets the value of the eventHeader property.
+ *
+ * @param value
+ * allowed object is
+ * {@link NotificationEvent.EventHeader }
+ *
+ */
+ public void setEventHeader(NotificationEvent.EventHeader value) {
+ this.eventHeader = value;
+ }
+
+ /**
+ * Gets the value of the any property.
+ *
+ * @return
+ * possible object is
+ * {@link Object }
+ * {@link Element }
+ *
+ */
+ public Object getEntity() {
+ return entity;
+ }
+
+ /**
+ * Sets the value of the any property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Object }
+ * {@link Element }
+ *
+ */
+ public void setEntity(Object value) {
+ this.entity = value;
+ }
+
+ /**
+ * Gets the value of the cambriaPartition property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getCambriaPartition() {
+ return cambriaPartition;
+ }
+
+ /**
+ * Sets the value of the cambriaPartition property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setCambriaPartition(String value) {
+ this.cambriaPartition = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="timestamp" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="source-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="domain" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="sequence-number" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="severity" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="event-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="version" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="action" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="top-entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="entity-link" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="status" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "id",
+ "timestamp",
+ "sourceName",
+ "domain",
+ "sequenceNumber",
+ "severity",
+ "eventType",
+ "version",
+ "action",
+ "entityType",
+ "topEntityType",
+ "entityLink",
+ "status"
+ })
+ public static class EventHeader {
+
+ @XmlElement(required = true)
+ protected String id;
+ @XmlElement(required = true)
+ protected String timestamp;
+ @XmlElement(name = "source-name", required = true)
+ protected String sourceName;
+ @XmlElement(required = true)
+ protected String domain;
+ @XmlElement(name = "sequence-number", required = true)
+ protected String sequenceNumber;
+ @XmlElement(required = true)
+ protected String severity;
+ @XmlElement(name = "event-type", required = true)
+ protected String eventType;
+ @XmlElement(required = true)
+ protected String version;
+ @XmlElement(required = true)
+ protected String action;
+ @XmlElement(name = "entity-type", required = true)
+ protected String entityType;
+ @XmlElement(name = "top-entity-type", required = true)
+ protected String topEntityType;
+ @XmlElement(name = "entity-link", required = true)
+ protected String entityLink;
+ @XmlElement(required = true)
+ protected String status;
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the timestamp property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ /**
+ * Sets the value of the timestamp property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTimestamp(String value) {
+ this.timestamp = value;
+ }
+
+ /**
+ * Gets the value of the sourceName property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getSourceName() {
+ return sourceName;
+ }
+
+ /**
+ * Sets the value of the sourceName property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSourceName(String value) {
+ this.sourceName = value;
+ }
+
+ /**
+ * Gets the value of the domain property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getDomain() {
+ return domain;
+ }
+
+ /**
+ * Sets the value of the domain property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setDomain(String value) {
+ this.domain = value;
+ }
+
+ /**
+ * Gets the value of the sequenceNumber property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getSequenceNumber() {
+ return sequenceNumber;
+ }
+
+ /**
+ * Sets the value of the sequenceNumber property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSequenceNumber(String value) {
+ this.sequenceNumber = value;
+ }
+
+ /**
+ * Gets the value of the severity property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getSeverity() {
+ return severity;
+ }
+
+ /**
+ * Sets the value of the severity property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSeverity(String value) {
+ this.severity = value;
+ }
+
+ /**
+ * Gets the value of the eventType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getEventType() {
+ return eventType;
+ }
+
+ /**
+ * Sets the value of the eventType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setEventType(String value) {
+ this.eventType = value;
+ }
+
+ /**
+ * Gets the value of the version property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Sets the value of the version property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVersion(String value) {
+ this.version = value;
+ }
+
+ /**
+ * Gets the value of the action property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getAction() {
+ return action;
+ }
+
+ /**
+ * Sets the value of the action property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setAction(String value) {
+ this.action = value;
+ }
+
+ /**
+ * Gets the value of the entityType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getEntityType() {
+ return entityType;
+ }
+
+ /**
+ * Sets the value of the entityType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setEntityType(String value) {
+ this.entityType = value;
+ }
+
+ /**
+ * Gets the value of the topEntityType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getTopEntityType() {
+ return topEntityType;
+ }
+
+ /**
+ * Sets the value of the topEntityType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTopEntityType(String value) {
+ this.topEntityType = value;
+ }
+
+ /**
+ * Gets the value of the entityLink property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getEntityLink() {
+ return entityLink;
+ }
+
+ /**
+ * Sets the value of the entityLink property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setEntityLink(String value) {
+ this.entityLink = value;
+ }
+
+ /**
+ * Gets the value of the status property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the value of the status property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setStatus(String value) {
+ this.status = value;
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/ObjectFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/ObjectFactory.java
new file mode 100644
index 0000000..c331aab
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/ObjectFactory.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2016.01.06 at 05:38:00 PM EST
+//
+
+
+package org.openecomp.aai.domain.notificationEvent;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.openecomp.aai.domain.notificationEvent package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.openecomp.aai.domain.notificationEvent
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link NotificationEvent }.
+ *
+ * @return the notification event
+ */
+ public NotificationEvent createNotificationEvent() {
+ return new NotificationEvent();
+ }
+
+ /**
+ * Create an instance of {@link NotificationEvent.EventHeader }
+ *
+ * @return the event header
+ */
+ public NotificationEvent.EventHeader createNotificationEventEventHeader() {
+ return new NotificationEvent.EventHeader();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessage.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessage.java
new file mode 100644
index 0000000..b3f0324
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessage.java
@@ -0,0 +1,125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.responseMessage;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "aaiResponseMessageCode",
+ "aaiResponseMessageResourceType",
+ "aaiResponseMessageDescription",
+ "aaiResponseMessageData",
+})
+@XmlRootElement(name = "aai-response-message", namespace = "http://org.openecomp.aai.inventory")
+public class AAIResponseMessage {
+
+ @XmlElement(name = "aai-response-message-code", required = true)
+ protected String aaiResponseMessageCode;
+ @XmlElement(name = "aai-response-message-resource-type")
+ protected String aaiResponseMessageResourceType;
+ @XmlElement(name = "aai-response-message-description")
+ protected String aaiResponseMessageDescription;
+ @XmlElement(name = "aai-response-message-data")
+ protected AAIResponseMessageData aaiResponseMessageData;
+
+ /**
+ * Gets the aai response message code.
+ *
+ * @return the aai response message code
+ */
+ public String getAaiResponseMessageCode() {
+ return aaiResponseMessageCode;
+ }
+
+ /**
+ * Sets the aai response message code.
+ *
+ * @param aaiResponseMessageCode the new aai response message code
+ */
+ public void setAaiResponseMessageCode(String aaiResponseMessageCode) {
+ this.aaiResponseMessageCode = aaiResponseMessageCode;
+ }
+
+ /**
+ * Gets the aai response message resource type.
+ *
+ * @return the aai response message resource type
+ */
+ public String getAaiResponseMessageResourceType() {
+ return aaiResponseMessageResourceType;
+ }
+
+ /**
+ * Sets the aai response message resource type.
+ *
+ * @param aaiResponseMessageResourceType the new aai response message resource type
+ */
+ public void setAaiResponseMessageResourceType(
+ String aaiResponseMessageResourceType) {
+ this.aaiResponseMessageResourceType = aaiResponseMessageResourceType;
+ }
+
+ /**
+ * Gets the aai response message description.
+ *
+ * @return the aai response message description
+ */
+ public String getAaiResponseMessageDescription() {
+ return aaiResponseMessageDescription;
+ }
+
+ /**
+ * Sets the aai response message description.
+ *
+ * @param aaiResponseMessageDescription the new aai response message description
+ */
+ public void setAaiResponseMessageDescription(
+ String aaiResponseMessageDescription) {
+ this.aaiResponseMessageDescription = aaiResponseMessageDescription;
+ }
+
+ /**
+ * Gets the aai response message data.
+ *
+ * @return the aai response message data
+ */
+ public AAIResponseMessageData getAaiResponseMessageData() {
+ if (aaiResponseMessageData == null) {
+ aaiResponseMessageData = new AAIResponseMessageData();
+ }
+ return aaiResponseMessageData;
+ }
+
+ /**
+ * Sets the AAI response message data.
+ *
+ * @param aaiResponseMessageData the new AAI response message data
+ */
+ public void setAAIResponseMessageData(
+ AAIResponseMessageData aaiResponseMessageData) {
+ this.aaiResponseMessageData = aaiResponseMessageData;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageData.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageData.java
new file mode 100644
index 0000000..16f9c6d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageData.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.responseMessage;
+
+
+//
+//This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+//See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+//Any modifications to this file will be lost upon recompilation of the source schema.
+//Generated on: 2015.09.11 at 11:53:27 AM EDT
+//
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "aaiResponseMessageDatum",
+ "any"
+})
+@XmlRootElement(name = "aai-response-message-data", namespace = "http://org.openecomp.aai.inventory")
+public class AAIResponseMessageData {
+
+ @XmlElement(name = "aai-response-message-datum")
+ protected List<AAIResponseMessageDatum> aaiResponseMessageDatum;
+ @XmlAnyElement(lax = true)
+ protected List<Object> any;
+
+ /**
+ * Gets the AAI response message datum.
+ *
+ * @return the AAI response message datum
+ */
+ public List<AAIResponseMessageDatum> getAAIResponseMessageDatum() {
+ if (aaiResponseMessageDatum == null) {
+ aaiResponseMessageDatum = new ArrayList<AAIResponseMessageDatum>();
+ }
+ return this.aaiResponseMessageDatum;
+ }
+
+ /**
+ * Gets the any.
+ *
+ * @return the any
+ */
+ public List<Object> getAny() {
+ if (any == null) {
+ any = new ArrayList<Object>();
+ }
+ return this.any;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageDatum.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageDatum.java
new file mode 100644
index 0000000..8b64651
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageDatum.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.responseMessage;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "aaiResponseMessageDatumKey",
+ "aaiResponseMessageDatumValue",
+
+})
+
+@XmlRootElement(name = "aai-response-message-datum", namespace = "http://org.openecomp.aai.inventory")
+public class AAIResponseMessageDatum {
+
+ @XmlElement(name = "aai-response-message-datum-key", required = true)
+ protected String aaiResponseMessageDatumKey;
+ @XmlElement(name = "aai-response-message-datum-value", required = true)
+ protected String aaiResponseMessageDatumValue;
+
+ /**
+ * Gets the aai response message datum key.
+ *
+ * @return the aai response message datum key
+ */
+ public String getAaiResponseMessageDatumKey() {
+ return aaiResponseMessageDatumKey;
+ }
+
+ /**
+ * Sets the aai response message datum key.
+ *
+ * @param aaiResponseMessageDatumKey the new aai response message datum key
+ */
+ public void setAaiResponseMessageDatumKey(String aaiResponseMessageDatumKey) {
+ this.aaiResponseMessageDatumKey = aaiResponseMessageDatumKey;
+ }
+
+ /**
+ * Gets the aai response message datum value.
+ *
+ * @return the aai response message datum value
+ */
+ public String getAaiResponseMessageDatumValue() {
+ return aaiResponseMessageDatumValue;
+ }
+
+ /**
+ * Sets the aai response message datum value.
+ *
+ * @param aaiResponseMessageDatumValue the new aai response message datum value
+ */
+ public void setAaiResponseMessageDatumValue(String aaiResponseMessageDatumValue) {
+ this.aaiResponseMessageDatumValue = aaiResponseMessageDatumValue;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessages.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessages.java
new file mode 100644
index 0000000..95a03a9
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessages.java
@@ -0,0 +1,118 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.responseMessage;
+
+
+//
+//This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+//See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+//Any modifications to this file will be lost upon recompilation of the source schema.
+//Generated on: 2015.09.11 at 11:53:27 AM EDT
+//
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="flavor" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="flavor-id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="flavor-name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="flavor-vcpus" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ * &lt;element name="flavor-ram" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ * &lt;element name="flavor-disk" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ * &lt;element name="flavor-ephemeral" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ * &lt;element name="flavor-swap" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="flavor-is-public" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ * &lt;element name="flavor-selflink" type="{urn:ietf:params:xml:ns:yang:ietf-inet-types}uri" minOccurs="0"/>
+ * &lt;element name="flavor-disabled" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;element ref="{http://org.openecomp.aai.inventory/v8}relationship-list" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "aaiResponseMessage",
+ "any"
+})
+@XmlRootElement(name = "aai-response-messages", namespace = "http://org.openecomp.aai.inventory")
+public class AAIResponseMessages {
+ @XmlElement(name = "aai-response-message")
+ protected List<AAIResponseMessage> aaiResponseMessage;
+ @XmlAnyElement(lax = true)
+ protected List<Object> any;
+
+ /**
+ * Gets the AAI response message.
+ *
+ * @return the AAI response message
+ */
+ public List<AAIResponseMessage> getAAIResponseMessage() {
+ if (aaiResponseMessage == null) {
+ aaiResponseMessage = new ArrayList<AAIResponseMessage>();
+ }
+ return this.aaiResponseMessage;
+ }
+
+ /**
+ * Gets the any.
+ *
+ * @return the any
+ */
+ public List<Object> getAny() {
+ if (any == null) {
+ any = new ArrayList<Object>();
+ }
+ return this.any;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/package-info.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/package-info.java
new file mode 100644
index 0000000..cfb4981
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/package-info.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.06.15 at 03:03:58 PM EDT
+//
+
+@javax.xml.bind.annotation.XmlSchema(
+ namespace = "http://org.openecomp.aai.inventory",
+ elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.openecomp.aai.domain.responseMessage;
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/Fault.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/Fault.java
new file mode 100644
index 0000000..f32268b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/Fault.java
@@ -0,0 +1,382 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.02.11 at 04:54:39 PM EST
+//
+
+
+package org.openecomp.aai.domain.restPolicyException;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="requestError">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="policyException">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "requestError"
+})
+@XmlRootElement(name = "Fault")
+public class Fault {
+
+ @XmlElement(required = true)
+ protected Fault.RequestError requestError;
+
+ /**
+ * Gets the value of the requestError property.
+ *
+ * @return
+ * possible object is
+ * {@link Fault.RequestError }
+ *
+ */
+ public Fault.RequestError getRequestError() {
+ return requestError;
+ }
+
+ /**
+ * Sets the value of the requestError property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Fault.RequestError }
+ *
+ */
+ public void setRequestError(Fault.RequestError value) {
+ this.requestError = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="policyException">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "policyException"
+ })
+ public static class RequestError {
+
+ @XmlElement(required = true)
+ protected Fault.RequestError.PolicyException policyException;
+
+ /**
+ * Gets the value of the policyException property.
+ *
+ * @return
+ * possible object is
+ * {@link Fault.RequestError.PolicyException }
+ *
+ */
+ public Fault.RequestError.PolicyException getPolicyException() {
+ return policyException;
+ }
+
+ /**
+ * Sets the value of the policyException property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Fault.RequestError.PolicyException }
+ *
+ */
+ public void setPolicyException(Fault.RequestError.PolicyException value) {
+ this.policyException = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "messageId",
+ "text",
+ "variables"
+ })
+ public static class PolicyException {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ @XmlElement(required = true)
+ protected String text;
+ @XmlElement(required = true)
+ protected Fault.RequestError.PolicyException.Variables variables;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the text property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the value of the text property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setText(String value) {
+ this.text = value;
+ }
+
+ /**
+ * Gets the value of the variables property.
+ *
+ * @return
+ * possible object is
+ * {@link Fault.RequestError.PolicyException.Variables }
+ *
+ */
+ public Fault.RequestError.PolicyException.Variables getVariables() {
+ return variables;
+ }
+
+ /**
+ * Sets the value of the variables property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Fault.RequestError.PolicyException.Variables }
+ *
+ */
+ public void setVariables(Fault.RequestError.PolicyException.Variables value) {
+ this.variables = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "variable"
+ })
+ public static class Variables {
+
+ protected List<String> variable;
+
+ /**
+ * Gets the value of the variable property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the variable property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getVariable().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link String }
+ *
+ * @return the variable
+ */
+ public List<String> getVariable() {
+ if (variable == null) {
+ variable = new ArrayList<String>();
+ }
+ return this.variable;
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/ObjectFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/ObjectFactory.java
new file mode 100644
index 0000000..3cf31ed
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/ObjectFactory.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.02.11 at 04:54:39 PM EST
+//
+
+
+package org.openecomp.aai.domain.restPolicyException;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.openecomp.aai.domain.restPolicyException package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.openecomp.aai.domain.restPolicyException
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link Fault }.
+ *
+ * @return the fault
+ */
+ public Fault createFault() {
+ return new Fault();
+ }
+
+ /**
+ * Create an instance of {@link Fault.RequestError }
+ *
+ * @return the request error
+ */
+ public Fault.RequestError createFaultRequestError() {
+ return new Fault.RequestError();
+ }
+
+ /**
+ * Create an instance of {@link Fault.RequestError.PolicyException }
+ *
+ * @return the policy exception
+ */
+ public Fault.RequestError.PolicyException createFaultRequestErrorPolicyException() {
+ return new Fault.RequestError.PolicyException();
+ }
+
+ /**
+ * Create an instance of {@link Fault.RequestError.PolicyException.Variables }
+ *
+ * @return the variables
+ */
+ public Fault.RequestError.PolicyException.Variables createFaultRequestErrorPolicyExceptionVariables() {
+ return new Fault.RequestError.PolicyException.Variables();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/PolicyException.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/PolicyException.java
new file mode 100644
index 0000000..a55ce62
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/PolicyException.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.restPolicyException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "messageId",
+ "text",
+ "variables"
+})
+public class PolicyException {
+
+ @JsonProperty("messageId")
+ private String messageId;
+ @JsonProperty("text")
+ private String text;
+ @JsonProperty("variables")
+ private List<String> variables = new ArrayList<String>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ * Gets the message id.
+ *
+ * @return The messageId
+ */
+ @JsonProperty("messageId")
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the message id.
+ *
+ * @param messageId The messageId
+ */
+ @JsonProperty("messageId")
+ public void setMessageId(String messageId) {
+ this.messageId = messageId;
+ }
+
+ /**
+ * Gets the text.
+ *
+ * @return The text
+ */
+ @JsonProperty("text")
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the text.
+ *
+ * @param text The text
+ */
+ @JsonProperty("text")
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /**
+ * Gets the variables.
+ *
+ * @return The variables
+ */
+ @JsonProperty("variables")
+ public List<String> getVariables() {
+ return variables;
+ }
+
+ /**
+ * Sets the variables.
+ *
+ * @param variables The variables
+ */
+ @JsonProperty("variables")
+ public void setVariables(List<String> variables) {
+ this.variables = variables;
+ }
+
+ /**
+ * Gets the additional properties.
+ *
+ * @return the additional properties
+ */
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ /**
+ * Sets the additional property.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RESTResponse.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RESTResponse.java
new file mode 100644
index 0000000..eb9deb2
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RESTResponse.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.restPolicyException;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "requestError"
+})
+public class RESTResponse {
+
+ @JsonProperty("requestError")
+ private RequestError requestError;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ * Gets the request error.
+ *
+ * @return The requestError
+ */
+ @JsonProperty("requestError")
+ public RequestError getRequestError() {
+ return requestError;
+ }
+
+ /**
+ * Sets the request error.
+ *
+ * @param requestError The requestError
+ */
+ @JsonProperty("requestError")
+ public void setRequestError(RequestError requestError) {
+ this.requestError = requestError;
+ }
+
+ /**
+ * Gets the additional properties.
+ *
+ * @return the additional properties
+ */
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ /**
+ * Sets the additional property.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RequestError.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RequestError.java
new file mode 100644
index 0000000..a4d4e74
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RequestError.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.restPolicyException;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "policyException"
+})
+public class RequestError {
+
+ @JsonProperty("policyException")
+ private PolicyException policyException;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ * Gets the policy exception.
+ *
+ * @return The policyException
+ */
+ @JsonProperty("policyException")
+ public PolicyException getPolicyException() {
+ return policyException;
+ }
+
+ /**
+ * Sets the policy exception.
+ *
+ * @param policyException The policyException
+ */
+ @JsonProperty("policyException")
+ public void setPolicyException(PolicyException policyException) {
+ this.policyException = policyException;
+ }
+
+ /**
+ * Gets the additional properties.
+ *
+ * @return the additional properties
+ */
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ /**
+ * Sets the additional property.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/Info.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/Info.java
new file mode 100644
index 0000000..6a1f8e4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/Info.java
@@ -0,0 +1,385 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.10.28 at 05:53:17 PM EDT
+//
+
+
+package org.openecomp.aai.domain.restResponseInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="responseMessages" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="responseMessage" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "responseMessages"
+})
+@XmlRootElement(name = "Info")
+public class Info {
+
+ protected Info.ResponseMessages responseMessages;
+
+ /**
+ * Gets the value of the responseMessages property.
+ *
+ * @return
+ * possible object is
+ * {@link Info.ResponseMessages }
+ *
+ */
+ public Info.ResponseMessages getResponseMessages() {
+ return responseMessages;
+ }
+
+ /**
+ * Sets the value of the responseMessages property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Info.ResponseMessages }
+ *
+ */
+ public void setResponseMessages(Info.ResponseMessages value) {
+ this.responseMessages = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="responseMessage" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "responseMessage"
+ })
+ public static class ResponseMessages {
+
+ protected List<Info.ResponseMessages.ResponseMessage> responseMessage;
+
+ /**
+ * Gets the value of the responseMessage property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the responseMessage property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getResponseMessage().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Info.ResponseMessages.ResponseMessage }
+ *
+ * @return the response message
+ */
+ public List<Info.ResponseMessages.ResponseMessage> getResponseMessage() {
+ if (responseMessage == null) {
+ responseMessage = new ArrayList<Info.ResponseMessages.ResponseMessage>();
+ }
+ return this.responseMessage;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "messageId",
+ "text",
+ "variables"
+ })
+ public static class ResponseMessage {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ @XmlElement(required = true)
+ protected String text;
+ @XmlElement(required = true)
+ protected Info.ResponseMessages.ResponseMessage.Variables variables;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the text property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the value of the text property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setText(String value) {
+ this.text = value;
+ }
+
+ /**
+ * Gets the value of the variables property.
+ *
+ * @return
+ * possible object is
+ * {@link Info.ResponseMessages.ResponseMessage.Variables }
+ *
+ */
+ public Info.ResponseMessages.ResponseMessage.Variables getVariables() {
+ return variables;
+ }
+
+ /**
+ * Sets the value of the variables property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Info.ResponseMessages.ResponseMessage.Variables }
+ *
+ */
+ public void setVariables(Info.ResponseMessages.ResponseMessage.Variables value) {
+ this.variables = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "variable"
+ })
+ public static class Variables {
+
+ protected List<String> variable;
+
+ /**
+ * Gets the value of the variable property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the variable property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getVariable().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link String }
+ *
+ * @return the variable
+ */
+ public List<String> getVariable() {
+ if (variable == null) {
+ variable = new ArrayList<String>();
+ }
+ return this.variable;
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/ObjectFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/ObjectFactory.java
new file mode 100644
index 0000000..7044958
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/ObjectFactory.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.10.28 at 05:53:17 PM EDT
+//
+
+
+package org.openecomp.aai.domain.restResponseInfo;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.openecomp.aai.domain.restResponseInfo package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.openecomp.aai.domain.restResponseInfo
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link Info }.
+ *
+ * @return the info
+ */
+ public Info createInfo() {
+ return new Info();
+ }
+
+ /**
+ * Create an instance of {@link Info.ResponseMessages }
+ *
+ * @return the response messages
+ */
+ public Info.ResponseMessages createInfoResponseMessages() {
+ return new Info.ResponseMessages();
+ }
+
+ /**
+ * Create an instance of {@link Info.ResponseMessages.ResponseMessage }
+ *
+ * @return the response message
+ */
+ public Info.ResponseMessages.ResponseMessage createInfoResponseMessagesResponseMessage() {
+ return new Info.ResponseMessages.ResponseMessage();
+ }
+
+ /**
+ * Create an instance of {@link Info.ResponseMessages.ResponseMessage.Variables }
+ *
+ * @return the variables
+ */
+ public Info.ResponseMessages.ResponseMessage.Variables createInfoResponseMessagesResponseMessageVariables() {
+ return new Info.ResponseMessages.ResponseMessage.Variables();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/Fault.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/Fault.java
new file mode 100644
index 0000000..3356a54
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/Fault.java
@@ -0,0 +1,382 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.02.11 at 04:54:29 PM EST
+//
+
+
+package org.openecomp.aai.domain.restServiceException;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="requestError">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="serviceException">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "requestError"
+})
+@XmlRootElement(name = "Fault")
+public class Fault {
+
+ @XmlElement(required = true)
+ protected Fault.RequestError requestError;
+
+ /**
+ * Gets the value of the requestError property.
+ *
+ * @return
+ * possible object is
+ * {@link Fault.RequestError }
+ *
+ */
+ public Fault.RequestError getRequestError() {
+ return requestError;
+ }
+
+ /**
+ * Sets the value of the requestError property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Fault.RequestError }
+ *
+ */
+ public void setRequestError(Fault.RequestError value) {
+ this.requestError = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="serviceException">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "serviceException"
+ })
+ public static class RequestError {
+
+ @XmlElement(required = true)
+ protected Fault.RequestError.ServiceException serviceException;
+
+ /**
+ * Gets the value of the serviceException property.
+ *
+ * @return
+ * possible object is
+ * {@link Fault.RequestError.ServiceException }
+ *
+ */
+ public Fault.RequestError.ServiceException getServiceException() {
+ return serviceException;
+ }
+
+ /**
+ * Sets the value of the serviceException property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Fault.RequestError.ServiceException }
+ *
+ */
+ public void setServiceException(Fault.RequestError.ServiceException value) {
+ this.serviceException = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="variables">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "messageId",
+ "text",
+ "variables"
+ })
+ public static class ServiceException {
+
+ @XmlElement(required = true)
+ protected String messageId;
+ @XmlElement(required = true)
+ protected String text;
+ @XmlElement(required = true)
+ protected Fault.RequestError.ServiceException.Variables variables;
+
+ /**
+ * Gets the value of the messageId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the value of the messageId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setMessageId(String value) {
+ this.messageId = value;
+ }
+
+ /**
+ * Gets the value of the text property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the value of the text property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setText(String value) {
+ this.text = value;
+ }
+
+ /**
+ * Gets the value of the variables property.
+ *
+ * @return
+ * possible object is
+ * {@link Fault.RequestError.ServiceException.Variables }
+ *
+ */
+ public Fault.RequestError.ServiceException.Variables getVariables() {
+ return variables;
+ }
+
+ /**
+ * Sets the value of the variables property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Fault.RequestError.ServiceException.Variables }
+ *
+ */
+ public void setVariables(Fault.RequestError.ServiceException.Variables value) {
+ this.variables = value;
+ }
+
+
+ /**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+ @XmlAccessorType(XmlAccessType.FIELD)
+ @XmlType(name = "", propOrder = {
+ "variable"
+ })
+ public static class Variables {
+
+ protected List<String> variable;
+
+ /**
+ * Gets the value of the variable property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the variable property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getVariable().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link String }
+ *
+ * @return the variable
+ */
+ public List<String> getVariable() {
+ if (variable == null) {
+ variable = new ArrayList<String>();
+ }
+ return this.variable;
+ }
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ObjectFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ObjectFactory.java
new file mode 100644
index 0000000..09c59b3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ObjectFactory.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.02.11 at 04:54:29 PM EST
+//
+
+
+package org.openecomp.aai.domain.restServiceException;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.openecomp.aai.domain.restServiceException package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.openecomp.aai.domain.restServiceException
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link Fault }.
+ *
+ * @return the fault
+ */
+ public Fault createFault() {
+ return new Fault();
+ }
+
+ /**
+ * Create an instance of {@link Fault.RequestError }
+ *
+ * @return the request error
+ */
+ public Fault.RequestError createFaultRequestError() {
+ return new Fault.RequestError();
+ }
+
+ /**
+ * Create an instance of {@link Fault.RequestError.ServiceException }
+ *
+ * @return the service exception
+ */
+ public Fault.RequestError.ServiceException createFaultRequestErrorServiceException() {
+ return new Fault.RequestError.ServiceException();
+ }
+
+ /**
+ * Create an instance of {@link Fault.RequestError.ServiceException.Variables }
+ *
+ * @return the variables
+ */
+ public Fault.RequestError.ServiceException.Variables createFaultRequestErrorServiceExceptionVariables() {
+ return new Fault.RequestError.ServiceException.Variables();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RESTResponse.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RESTResponse.java
new file mode 100644
index 0000000..9aa55f4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RESTResponse.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.restServiceException;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "requestError"
+})
+public class RESTResponse {
+
+ @JsonProperty("requestError")
+ private RequestError requestError;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ * Gets the request error.
+ *
+ * @return The requestError
+ */
+ @JsonProperty("requestError")
+ public RequestError getRequestError() {
+ return requestError;
+ }
+
+ /**
+ * Sets the request error.
+ *
+ * @param requestError The requestError
+ */
+ @JsonProperty("requestError")
+ public void setRequestError(RequestError requestError) {
+ this.requestError = requestError;
+ }
+
+ /**
+ * Gets the additional properties.
+ *
+ * @return the additional properties
+ */
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ /**
+ * Sets the additional property.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RequestError.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RequestError.java
new file mode 100644
index 0000000..edc465e
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RequestError.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.restServiceException;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "serviceException"
+})
+public class RequestError {
+
+ @JsonProperty("serviceException")
+ private ServiceException serviceException;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ * Gets the service exception.
+ *
+ * @return The serviceException
+ */
+ @JsonProperty("serviceException")
+ public ServiceException getServiceException() {
+ return serviceException;
+ }
+
+ /**
+ * Sets the service exception.
+ *
+ * @param serviceException The serviceException
+ */
+ @JsonProperty("serviceException")
+ public void setServiceException(ServiceException serviceException) {
+ this.serviceException = serviceException;
+ }
+
+ /**
+ * Gets the additional properties.
+ *
+ * @return the additional properties
+ */
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ /**
+ * Sets the additional property.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ServiceException.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ServiceException.java
new file mode 100644
index 0000000..5687269
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ServiceException.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.restServiceException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "messageId",
+ "text",
+ "variables"
+})
+public class ServiceException {
+
+ @JsonProperty("messageId")
+ private String messageId;
+ @JsonProperty("text")
+ private String text;
+ @JsonProperty("variables")
+ private List<String> variables = new ArrayList<String>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ * Gets the message id.
+ *
+ * @return The messageId
+ */
+ @JsonProperty("messageId")
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ * Sets the message id.
+ *
+ * @param messageId The messageId
+ */
+ @JsonProperty("messageId")
+ public void setMessageId(String messageId) {
+ this.messageId = messageId;
+ }
+
+ /**
+ * Gets the text.
+ *
+ * @return The text
+ */
+ @JsonProperty("text")
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the text.
+ *
+ * @param text The text
+ */
+ @JsonProperty("text")
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /**
+ * Gets the variables.
+ *
+ * @return The variables
+ */
+ @JsonProperty("variables")
+ public List<String> getVariables() {
+ return variables;
+ }
+
+ /**
+ * Sets the variables.
+ *
+ * @param variables The variables
+ */
+ @JsonProperty("variables")
+ public void setVariables(List<String> variables) {
+ this.variables = variables;
+ }
+
+ /**
+ * Gets the additional properties.
+ *
+ * @return the additional properties
+ */
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ /**
+ * Sets the additional property.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/IncludeNodeFilter.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/IncludeNodeFilter.java
new file mode 100644
index 0000000..eee4d6d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/IncludeNodeFilter.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import org.w3c.dom.Element;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="include-node-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "includeNodeType",
+ "any"
+})
+public class IncludeNodeFilter {
+
+ @XmlElement(name = "include-node-type", required = true)
+ protected String includeNodeType;
+ @XmlAnyElement(lax = true)
+ protected List<Object> any;
+
+ /**
+ * Gets the value of the includeNodeType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getIncludeNodeType() {
+ return includeNodeType;
+ }
+
+ /**
+ * Sets the value of the includeNodeType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setIncludeNodeType(String value) {
+ this.includeNodeType = value;
+ }
+
+ /**
+ * Gets the value of the any property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the any property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getAny().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Object }
+ * {@link Element }
+ *
+ * @return the any
+ */
+ public List<Object> getAny() {
+ if (any == null) {
+ any = new ArrayList<Object>();
+ }
+ return this.any;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItem.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItem.java
new file mode 100644
index 0000000..d6b0fe9
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItem.java
@@ -0,0 +1,197 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for inventory-item complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="inventory-item">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="inventory-item-type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="inventory-item-link" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * &lt;element name="inventory-item-data" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;element name="tagged-inventory-item-list" type="{http://org.openecomp.aai.inventory/v8}tagged-inventory-item-list" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "inventory-item", propOrder = {
+ "inventoryItemType",
+ "inventoryItemLink",
+ "inventoryItemData",
+ "taggedInventoryItemList"
+})
+public class InventoryItem {
+
+ @XmlElement(name = "inventory-item-type")
+ protected String inventoryItemType;
+ @XmlElement(name = "inventory-item-link")
+ protected String inventoryItemLink;
+ @XmlElement(name = "inventory-item-data")
+ protected List<InventoryItemData> inventoryItemData;
+ @XmlElement(name = "tagged-inventory-item-list")
+ protected List<TaggedInventoryItemList> taggedInventoryItemList;
+
+ /**
+ * Gets the value of the inventoryItemType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getInventoryItemType() {
+ return inventoryItemType;
+ }
+
+ /**
+ * Sets the value of the inventoryItemType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setInventoryItemType(String value) {
+ this.inventoryItemType = value;
+ }
+
+ /**
+ * Gets the value of the inventoryItemLink property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getInventoryItemLink() {
+ return inventoryItemLink;
+ }
+
+ /**
+ * Sets the value of the inventoryItemLink property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setInventoryItemLink(String value) {
+ this.inventoryItemLink = value;
+ }
+
+ /**
+ * Gets the value of the inventoryItemData property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the inventoryItemData property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getInventoryItemData().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link InventoryItemData }
+ *
+ * @return the inventory item data
+ */
+ public List<InventoryItemData> getInventoryItemData() {
+ if (inventoryItemData == null) {
+ inventoryItemData = new ArrayList<InventoryItemData>();
+ }
+ return this.inventoryItemData;
+ }
+
+ /**
+ * Gets the value of the taggedInventoryItemList property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the taggedInventoryItemList property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getTaggedInventoryItemList().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link TaggedInventoryItemList }
+ *
+ * @return the tagged inventory item list
+ */
+ public List<TaggedInventoryItemList> getTaggedInventoryItemList() {
+ if (taggedInventoryItemList == null) {
+ taggedInventoryItemList = new ArrayList<TaggedInventoryItemList>();
+ }
+ return this.taggedInventoryItemList;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItemData.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItemData.java
new file mode 100644
index 0000000..7025e6f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItemData.java
@@ -0,0 +1,155 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import org.w3c.dom.Element;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "propertyName",
+ "propertyValue",
+ "any"
+})
+public class InventoryItemData {
+
+ @XmlElement(name = "property-name", required = true)
+ protected String propertyName;
+ @XmlElement(name = "property-value", required = true)
+ protected String propertyValue;
+ @XmlAnyElement(lax = true)
+ protected List<Object> any;
+
+ /**
+ * Gets the value of the propertyName property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets the value of the propertyName property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPropertyName(String value) {
+ this.propertyName = value;
+ }
+
+ /**
+ * Gets the value of the propertyValue property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPropertyValue() {
+ return propertyValue;
+ }
+
+ /**
+ * Sets the value of the propertyValue property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPropertyValue(String value) {
+ this.propertyValue = value;
+ }
+
+ /**
+ * Gets the value of the any property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the any property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getAny().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Object }
+ * {@link Element }
+ *
+ * @return the any
+ */
+ public List<Object> getAny() {
+ if (any == null) {
+ any = new ArrayList<Object>();
+ }
+ return this.any;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/ObjectFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/ObjectFactory.java
new file mode 100644
index 0000000..7b12188
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/ObjectFactory.java
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.openecomp.aai.domain.search package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.openecomp.aai.domain.search
+ *
+ */
+ public ObjectFactory() {
+ }
+
+
+
+ /**
+ * Create an instance of {@link StartNodeFilter }.
+ *
+ * @return the start node filter
+ */
+ public StartNodeFilter createStartNodeFilter() {
+ return new StartNodeFilter();
+ }
+
+ /**
+ * Create an instance of {@link SecondaryFilter }.
+ *
+ * @return the secondary filter
+ */
+ public SecondaryFilter createSecondaryFilter() {
+ return new SecondaryFilter();
+ }
+
+ /**
+ * Create an instance of {@link IncludeNodeFilter }.
+ *
+ * @return the include node filter
+ */
+ public IncludeNodeFilter createIncludeNodeFilter() {
+ return new IncludeNodeFilter();
+ }
+
+ /**
+ * Create an instance of {@link InventoryItem }.
+ *
+ * @return the inventory item
+ */
+ public InventoryItem createInventoryItem() {
+ return new InventoryItem();
+ }
+
+ /**
+ * Create an instance of {@link InventoryItemData }.
+ *
+ * @return the inventory item data
+ */
+ public InventoryItemData createInventoryItemData() {
+ return new InventoryItemData();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/SecondaryFilter.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/SecondaryFilter.java
new file mode 100644
index 0000000..7c972ad
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/SecondaryFilter.java
@@ -0,0 +1,183 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import org.w3c.dom.Element;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="filter-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "propertyName",
+ "filterType",
+ "propertyValue",
+ "any"
+})
+public class SecondaryFilter {
+
+ @XmlElement(name = "property-name", required = true)
+ protected String propertyName;
+ @XmlElement(name = "filter-type", required = true)
+ protected String filterType;
+ @XmlElement(name = "property-value", required = true)
+ protected String propertyValue;
+ @XmlAnyElement(lax = true)
+ protected List<Object> any;
+
+ /**
+ * Gets the value of the propertyName property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets the value of the propertyName property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPropertyName(String value) {
+ this.propertyName = value;
+ }
+
+ /**
+ * Gets the value of the filterType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getFilterType() {
+ return filterType;
+ }
+
+ /**
+ * Sets the value of the filterType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setFilterType(String value) {
+ this.filterType = value;
+ }
+
+ /**
+ * Gets the value of the propertyValue property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPropertyValue() {
+ return propertyValue;
+ }
+
+ /**
+ * Sets the value of the propertyValue property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPropertyValue(String value) {
+ this.propertyValue = value;
+ }
+
+ /**
+ * Gets the value of the any property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the any property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getAny().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Object }
+ * {@link Element }
+ *
+ * @return the any
+ */
+ public List<Object> getAny() {
+ if (any == null) {
+ any = new ArrayList<Object>();
+ }
+ return this.any;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/StartNodeFilter.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/StartNodeFilter.java
new file mode 100644
index 0000000..92edb2c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/StartNodeFilter.java
@@ -0,0 +1,155 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import org.w3c.dom.Element;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "propertyName",
+ "propertyValue",
+ "any"
+})
+public class StartNodeFilter {
+
+ @XmlElement(name = "property-name", required = true)
+ protected String propertyName;
+ @XmlElement(name = "property-value", required = true)
+ protected String propertyValue;
+ @XmlAnyElement(lax = true)
+ protected List<Object> any;
+
+ /**
+ * Gets the value of the propertyName property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets the value of the propertyName property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPropertyName(String value) {
+ this.propertyName = value;
+ }
+
+ /**
+ * Gets the value of the propertyValue property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getPropertyValue() {
+ return propertyValue;
+ }
+
+ /**
+ * Sets the value of the propertyValue property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setPropertyValue(String value) {
+ this.propertyValue = value;
+ }
+
+ /**
+ * Gets the value of the any property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the any property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getAny().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Object }
+ * {@link Element }
+ *
+ * @return the any
+ */
+ public List<Object> getAny() {
+ if (any == null) {
+ any = new ArrayList<Object>();
+ }
+ return this.any;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/TaggedInventoryItemList.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/TaggedInventoryItemList.java
new file mode 100644
index 0000000..e0b1d16
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/TaggedInventoryItemList.java
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+
+package org.openecomp.aai.domain.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for tagged-inventory-item-list complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="tagged-inventory-item-list">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="inventory-item" type="{http://org.openecomp.aai.inventory/v8}inventory-item" maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "tagged-inventory-item-list", propOrder = {
+ "inventoryItem"
+})
+public class TaggedInventoryItemList {
+
+ @XmlElement(name = "inventory-item")
+ protected List<InventoryItem> inventoryItem;
+
+ /**
+ * Gets the value of the inventoryItem property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the inventoryItem property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getInventoryItem().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link InventoryItem }
+ *
+ * @return the inventory item
+ */
+ public List<InventoryItem> getInventoryItem() {
+ if (inventoryItem == null) {
+ inventoryItem = new ArrayList<InventoryItem>();
+ }
+ return this.inventoryItem;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/package-info.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/package-info.java
new file mode 100644
index 0000000..740fcc1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/search/package-info.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.08.26 at 06:45:14 PM EDT
+//
+
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://org.openecomp.aai.inventory/v8", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.openecomp.aai.domain.search;
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntries.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntries.java
new file mode 100644
index 0000000..83f5b35
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntries.java
@@ -0,0 +1,131 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2015.03.20 at 09:46:47 AM CDT
+//
+
+
+package org.openecomp.aai.domain.translog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="update" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="update-node-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="update-node-key" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="key-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="key-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;element name="action" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="action-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="action-data" maxOccurs="unbounded" minOccurs="0">
+ * &lt;complexType>
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * &lt;/element>
+ * &lt;any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "transactionLogEntries"
+})
+@XmlRootElement(name = "transaction-log-entries", namespace = "http://org.openecomp.aai.inventory")
+public class TransactionLogEntries {
+
+ protected List<TransactionLogEntry> transactionLogEntries;
+
+ /**
+ * Gets the transaction log entries.
+ *
+ * @return the transaction log entries
+ */
+ public List<TransactionLogEntry> getTransactionLogEntries() {
+ if (transactionLogEntries == null) {
+ transactionLogEntries = new ArrayList<TransactionLogEntry>();
+ }
+ return this.transactionLogEntries;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntry.java b/ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntry.java
new file mode 100644
index 0000000..a8fdab3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntry.java
@@ -0,0 +1,438 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.domain.translog;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import com.sun.xml.txw2.annotation.XmlCDATA;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "transactionLogEntryId",
+ "status",
+ "rqstDate",
+ "respDate",
+ "sourceId",
+ "resourceId",
+ "resourceType",
+ "rqstBuf",
+ "respBuf",
+ "notificationPayload",
+ "notificationId",
+ "notificationStatus",
+ "notificationTopic",
+ "notificationEntityLink",
+ "notificationAction"
+})
+@XmlRootElement(name = "transaction-log-entry", namespace = "http://org.openecomp.aai.inventory")
+public class TransactionLogEntry {
+
+ @XmlElement(name = "transaction-log-entry-id", required = true)
+ protected String transactionLogEntryId;
+ @XmlElement(name = "status")
+ protected String status;
+ @XmlElement(name = "rqst-date")
+ protected String rqstDate;
+ @XmlElement(name = "resp-date")
+ protected String respDate;
+ @XmlElement(name = "source-id")
+ protected String sourceId;
+ @XmlElement(name = "resource-id")
+ protected String resourceId;
+ @XmlElement(name = "resource-type")
+ protected String resourceType;
+ @XmlElement(name = "rqst-buf")
+ protected String rqstBuf;
+ @XmlElement(name = "resp-buf")
+ protected String respBuf;
+ @XmlElement(name = "notification-payload")
+ protected String notificationPayload;
+ @XmlElement(name = "notification-id")
+ protected String notificationId;
+ @XmlElement(name = "notification-status")
+ protected String notificationStatus;
+ @XmlElement(name = "notification-topic")
+ private String notificationTopic;
+ @XmlElement(name = "notification-entity-link")
+ private String notificationEntityLink;
+ @XmlElement(name = "notification-action")
+ private String notificationAction;
+
+ /**
+ * Gets the value of the transcationLogEntryId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getTransactionLogEntryId() {
+ return transactionLogEntryId;
+ }
+
+ /**
+ * Sets the value of the transactionLogEntryId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setTransactionLogEntryId(String value) {
+ this.transactionLogEntryId = value;
+ }
+
+ /**
+ * Gets the value of the status property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the value of the status property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setStatus(String value) {
+ this.status = value;
+ }
+
+ /**
+ * Gets the value of the rqstDate property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+
+ public String getRqstDate() {
+ return rqstDate;
+ }
+
+ /**
+ * Sets the value of the rqstDate property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setRqstDate(String value) {
+ this.rqstDate = value;
+ }
+
+
+ /**
+ * Gets the value of the respDate property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+
+ public String getRespDate() {
+ return respDate;
+ }
+
+ /**
+ * Sets the value of the respDate property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setRespDate(String value) {
+ this.respDate = value;
+ }
+ /**
+ * Gets the value of the sourceId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getSourceId() {
+ return sourceId;
+ }
+
+ /**
+ * Sets the value of the sourceId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setSourceId(String value) {
+ this.sourceId = value;
+ }
+
+ /**
+ * Gets the value of the resourceId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getResourceId() {
+ return resourceId;
+ }
+
+ /**
+ * Sets the value of the resourceId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setResourceId(String value) {
+ this.resourceId = value;
+ }
+
+ /**
+ * Gets the value of the resourceType property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ /**
+ * Sets the value of the resourceType property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setResourceType(String value) {
+ this.resourceType = value;
+ }
+
+ /**
+ * Gets the value of the rqstBuf property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getRqstBuf() {
+ return rqstBuf;
+ }
+
+ /**
+ * Sets the value of the rqstBuf property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ @XmlCDATA
+ public void setRqstBuf(String value) {
+ this.rqstBuf = value;
+ }
+
+ /**
+ * Gets the value of the respBuf property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getrespBuf() {
+ return respBuf;
+ }
+
+ /**
+ * Sets the value of the respBuf property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ @XmlCDATA
+ public void setrespBuf(String value) {
+ this.respBuf = value;
+ }
+
+ /**
+ * Gets the value of the notificationPayload property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNotificationPayload() {
+ return notificationPayload;
+ }
+
+ /**
+ * Sets the value of the notificationPayload property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ @XmlCDATA
+ public void setNotificationPayload(String value) {
+ this.notificationPayload = value;
+ }
+
+
+ /**
+ * Gets the value of the notificationId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNotificationId() {
+ return notificationId;
+ }
+
+ /**
+ * Sets the value of the notificationId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNotificationId(String value) {
+ this.notificationId = value;
+ }
+
+ /**
+ * Gets the value of the notificationId property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNotificationStatus() {
+ return notificationStatus;
+ }
+
+ /**
+ * Sets the value of the notificationId property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setNotificationStatus(String value) {
+ this.notificationStatus = value;
+ }
+
+ /**
+ * Gets the value of the notificationTopic property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNotificationTopic() {
+ return notificationTopic;
+ }
+
+ /**
+ * Sets the value of the notificationTopic property.
+ *
+ * @param topic the new notification topic
+ */
+ public void setNotificationTopic(String topic) {
+ this.notificationTopic = topic;
+ }
+
+ /**
+ * Gets the value of the notificationEntityLink property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getNotificationEntityLink() {
+ return notificationEntityLink;
+ }
+
+ /**
+ * Sets the value of the notificationEntityLink property.
+ *
+ * @param entityLink the new notification entity link
+ */
+ public void setNotificationEntityLink(String entityLink) {
+ this.notificationEntityLink = entityLink;
+ }
+
+ /**
+ * Sets the value of the notificationAction property.
+ *
+ * @return the notification action
+ */
+ public String getNotificationAction() {
+ return notificationAction;
+ }
+
+ /**
+ * Sets the value of the notificationAction property.
+ *
+ * @param action the new notification action
+ */
+ public void setNotificationAction(String action) {
+ this.notificationAction = action;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIException.java b/ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIException.java
new file mode 100644
index 0000000..5a3747b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIException.java
@@ -0,0 +1,164 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.exceptions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+
+public class AAIException extends Exception {
+
+ protected ErrorObject errorObject = ErrorObject.DefaultErrorObject;
+ //protected Throwable cause; we don't need to have a cuase here - just set the parents class's cause
+ private List<String> templateVars = new ArrayList<>();
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Instantiates a new AAI exception.
+ */
+ public AAIException() {
+ }
+
+ /**
+ * Instantiates a new AAI exception.
+ *
+ * @param code the code
+ */
+ public AAIException(String code) {
+ super(code);
+ errorObject = ErrorLogHelper.getErrorObject(code);
+ }
+
+ /**
+ * Instantiates a new AAI exception.
+ *
+ * @param code the code
+ * @param details the details
+ */
+ public AAIException(String code, String details) {
+ this(code);
+ errorObject.setDetails(details);
+ }
+
+ /**
+ * Instantiates a new AAI exception.
+ *
+ * @param code the code
+ * @param cause the cause
+ */
+ public AAIException(String code, Throwable cause) {
+ this(code);
+ if (cause != null) {
+ if (cause.getMessage() == null)
+ errorObject.setDetails(cause.toString());
+ else
+ errorObject.setDetails(cause.getMessage());
+ }
+ this.initCause(cause);
+ }
+
+ /**
+ * Instantiates a new AAI exception.
+ *
+ * @param code the code
+ * @param cause the cause
+ * @param details the details
+ */
+ public AAIException(String code, Throwable cause, String details) {
+ this(code);
+ if (cause != null) {
+ if (cause.getMessage() == null)
+ errorObject.setDetails(cause.toString() + "-" + details);
+ else
+ errorObject.setDetails(cause.getMessage() + "-" + details);
+ }
+ this.initCause(cause);
+ }
+
+ /**
+ * Gets the error object.
+ *
+ * @return the error object
+ */
+ public ErrorObject getErrorObject() {
+ return this.errorObject;
+ }
+
+ /**
+ * Gets the stack top.
+ *
+ * @return the stack top
+ */
+ public String getStackTop() {
+ StringBuffer stackMessage = new StringBuffer();
+ stackMessage.append("");
+ if( this.getCause() != null) {
+ StackTraceElement[] elements = this.getCause().getStackTrace();
+ int i = 0;
+ for(StackTraceElement element : elements){
+ if(i < 3){
+ stackMessage.append(" ClassName- ");
+ stackMessage.append(element.getClassName());
+ stackMessage.append(" :LineNumber- ");
+ stackMessage.append(element.getLineNumber());
+ stackMessage.append(" :MethodName- ");
+ stackMessage.append(element.getMethodName());
+ }
+ i++;
+ }
+ }
+ return stackMessage.toString();
+ }
+
+ /**
+ * Gets the template vars.
+ *
+ * @return the template vars
+ */
+ public List<String> getTemplateVars() {
+ return templateVars;
+ }
+
+ /**
+ * Sets the template vars.
+ *
+ * @param templateVars the new template vars
+ */
+ public void setTemplateVars(List<String> templateVars) {
+ this.templateVars = templateVars;
+ }
+
+ /*
+ public String toString() {
+ StringBuffer response = new StringBuffer(super.toString());
+ if (errorObject != null)
+ response.append(" ").append(errorObject.toString());
+ if (cause != null)
+ response.append(" cause=").append(getStackTop());
+ return response.toString();
+ }
+ */
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIExceptionWithInfo.java b/ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIExceptionWithInfo.java
new file mode 100644
index 0000000..f1b1539
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIExceptionWithInfo.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.exceptions;
+
+import java.util.HashMap;
+
+public class AAIExceptionWithInfo extends AAIException {
+
+ HashMap<String, Object> infoHash;
+ String info;
+
+ /**
+ * Instantiates a new AAI exception with info.
+ *
+ * @param infoHash the info hash
+ * @param info the info
+ */
+ public AAIExceptionWithInfo(HashMap<String, Object> infoHash, String info) {
+ super();
+ setInfoHash(infoHash);
+ setInfo(info);
+ }
+
+ /**
+ * Instantiates a new AAI exception with info.
+ *
+ * @param code the code
+ * @param infoHash the info hash
+ * @param info the info
+ */
+ public AAIExceptionWithInfo(String code, HashMap<String, Object> infoHash, String info) {
+ super(code);
+ setInfoHash(infoHash);
+ setInfo(info);
+ }
+
+ /**
+ * Instantiates a new AAI exception with info.
+ *
+ * @param code the code
+ * @param details the details
+ * @param infoHash the info hash
+ * @param info the info
+ */
+ public AAIExceptionWithInfo(String code, String details, HashMap<String, Object> infoHash, String info) {
+ super(code, details);
+ setInfoHash(infoHash);
+ setInfo(info);
+ }
+
+ /**
+ * Instantiates a new AAI exception with info.
+ *
+ * @param code the code
+ * @param cause the cause
+ * @param infoHash the info hash
+ * @param info the info
+ */
+ public AAIExceptionWithInfo(String code, Throwable cause, HashMap<String, Object> infoHash, String info) {
+ super(code, cause);
+ setInfoHash(infoHash);
+ setInfo(info);
+ }
+
+ /**
+ * Instantiates a new AAI exception with info.
+ *
+ * @param code the code
+ * @param cause the cause
+ * @param details the details
+ * @param infoHash the info hash
+ * @param info the info
+ */
+ public AAIExceptionWithInfo(String code, Throwable cause, String details, HashMap<String, Object> infoHash, String info) {
+ super(code, cause, details);
+ setInfoHash(infoHash);
+ setInfo(info);
+ }
+
+ /**
+ * Gets the info hash.
+ *
+ * @return the info hash
+ */
+ public HashMap<String, Object> getInfoHash() {
+ return infoHash;
+ }
+
+ /**
+ * Sets the info hash.
+ *
+ * @param infoHash the info hash
+ */
+ public void setInfoHash(HashMap<String, Object> infoHash) {
+ this.infoHash = infoHash;
+ }
+
+ /**
+ * Gets the info.
+ *
+ * @return the info
+ */
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * Sets the info.
+ *
+ * @param info the new info
+ */
+ public void setInfo(String info) {
+ this.info = info;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java b/ajsc-aai/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java
new file mode 100644
index 0000000..4fc05dd
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java
@@ -0,0 +1,880 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.extensions;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.domain.model.AncestryItems;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessages;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class AAIExtensionMap {
+ // =======================================================================
+ // Attribute | Type
+ // =======================================================================
+ // message | java.lang.String (RW)
+ // ----------------------------------------------------------------------
+ // templateVars | java.lang.ArrayList<String> (RW)
+ // -----------------------------------------------------------------------
+ // preExtException | java.lang.Exception (RW)
+ // -----------------------------------------------------------------------
+ // preExtErrorCallback | java.lang.reflect.Method (RW)
+ // -----------------------------------------------------------------------
+ // postExtException | java.lang.Exception (RW)
+ // -----------------------------------------------------------------------
+ // postExtErrorCallback | java.lang.reflect.Method (RW)
+ // -----------------------------------------------------------------------
+ // servletRequest | javax.servlet.http.HttpServletRequest (RO)
+ // -----------------------------------------------------------------------
+ // headers | javax.ws.rs.core.HttpHeaders (RO)
+ // -----------------------------------------------------------------------
+ // objFromRequest | $TYPE {ObjFromRequestType) (RO)
+ // -----------------------------------------------------------------------
+ // logline | Logline
+ // -----------------------------------------------------------------------
+ // aaiLogger | AAILogger
+ // -----------------------------------------------------------------------
+ // preExtFailOnError | java.lang.Boolean (RW)
+ // -----------------------------------------------------------------------
+ // postExtFailOnError | java.lang.Boolean (RW)
+ // -----------------------------------------------------------------------
+ // preExtSkipErrorCallback | java.lang.Boolean (RW)
+ // -----------------------------------------------------------------------
+ // postExtSkipErrorCallback | java.lang.Boolean (RW)
+ // -----------------------------------------------------------------------
+ // graph | com.thinkaurelius.titan.core.TitanGraph (RW)
+ // -----------------------------------------------------------------------
+ // objectFromResponse | Object
+ // -----------------------------------------------------------------------
+ // precheckAddedList | java.util.HashMap
+ // -----------------------------------------------------------------------
+ // precheckResponseMessages | org.openecomp.aai.extensions.AAIResponseMessages
+ // =======================================================================
+
+ private String message;
+ private ArrayList<String> templateVars;
+ private Exception preExtException;
+ private Exception postExtException;
+ private Method preExtErrorCallback;
+ private Method postExtErrorCallback;
+ private HttpServletRequest servletRequest;
+ private HttpHeaders httpHeaders;
+ private String objectFromRequestType;
+ private Object objectFromRequest;
+ private boolean preExtFailOnError = true;
+ private boolean postExtFailOnError = true;
+ private boolean preExtSkipErrorCallback = true;
+ private boolean postExtSkipErrorCallback = true;
+ private String fromAppId;
+ private String transId;
+ private LogLine logline;
+ private AAILogger aaiLogger;
+ private TitanTransaction graph;
+ private Object objectFromResponse;
+ private HashMap<String, Object> lookupHashMap;
+ private HashMap<String, ArrayList<String>> precheckAddedList;
+ private AAIResponseMessages precheckResponseMessages;
+ private HashMap<String, Object> topology;
+ private HashMap<String, TitanVertex> vertexCache;
+ private String baseObject;
+ private String namespace;
+ private String fullResourceName;
+ private String topObjectFullResourceName;
+ private String uri;
+ private String notificationUri;
+ private String apiVersion;
+ private long startTime;
+ private long checkpointTime;
+ private DynamicJAXBContext jaxbContext;
+ private String objectFromResponseType;
+ private String eventAction;
+ private AncestryItems ancestry;
+ private TransactionalGraphEngine dbEngine;
+ private Loader loader;
+ private UriInfo uriInfo;
+
+ /**
+ * Sets the message.
+ *
+ * @param _message the new message
+ */
+ public void setMessage(String _message) {
+ this.message = _message;
+ }
+
+ /**
+ * Sets the template vars.
+ *
+ * @param _templateVars the new template vars
+ */
+ public void setTemplateVars(ArrayList<String> _templateVars) {
+ this.templateVars = _templateVars;
+ }
+
+ /**
+ * Sets the pre ext exception.
+ *
+ * @param _exception the new pre ext exception
+ */
+ public void setPreExtException(Exception _exception) {
+ this.preExtException = _exception;
+ }
+
+ /**
+ * Sets the pre ext error callback.
+ *
+ * @param _errorCallback the new pre ext error callback
+ */
+ public void setPreExtErrorCallback(Method _errorCallback) {
+ this.preExtErrorCallback = _errorCallback;
+ }
+
+ /**
+ * Sets the post ext exception.
+ *
+ * @param _exception the new post ext exception
+ */
+ public void setPostExtException(Exception _exception) {
+ this.postExtException = _exception;
+ }
+
+ /**
+ * Sets the post ext error callback.
+ *
+ * @param _errorCallback the new post ext error callback
+ */
+ public void setPostExtErrorCallback(Method _errorCallback) {
+ this.postExtErrorCallback = _errorCallback;
+ }
+
+ /**
+ * Sets the servlet request.
+ *
+ * @param _httpServletRequest the new servlet request
+ */
+ public void setServletRequest(HttpServletRequest _httpServletRequest) {
+ this.servletRequest = _httpServletRequest;
+ }
+
+ /**
+ * Sets the http headers.
+ *
+ * @param _httpHeaders the new http headers
+ */
+ public void setHttpHeaders(HttpHeaders _httpHeaders) {
+ this.httpHeaders = _httpHeaders;
+ }
+
+ /**
+ * Sets the object from request type.
+ *
+ * @param _objectFromRequestType the new object from request type
+ */
+ public void setObjectFromRequestType(String _objectFromRequestType) {
+ this.objectFromRequestType = _objectFromRequestType;
+ }
+
+ /**
+ * Sets the object from request.
+ *
+ * @param _objectFromRequest the new object from request
+ */
+ public void setObjectFromRequest(Object _objectFromRequest) {
+ this.objectFromRequest = _objectFromRequest;
+ }
+
+ /**
+ * Sets the object from response type.
+ *
+ * @param resourceClassName the new object from response type
+ */
+ public void setObjectFromResponseType(String resourceClassName) {
+ // TODO Auto-generated method stub
+ this.objectFromResponseType = resourceClassName;
+ }
+
+ /**
+ * Gets the object from response type.
+ *
+ * @return the object from response type
+ */
+ public String getObjectFromResponseType() {
+ // TODO Auto-generated method stub
+ return this.objectFromResponseType;
+ }
+
+ /**
+ * Sets the pre ext fail on error.
+ *
+ * @param _failOnError the new pre ext fail on error
+ */
+ public void setPreExtFailOnError(boolean _failOnError) {
+ this.preExtFailOnError = _failOnError;
+ }
+
+ /**
+ * Sets the post ext fail on error.
+ *
+ * @param _failOnError the new post ext fail on error
+ */
+ public void setPostExtFailOnError(boolean _failOnError) {
+ this.postExtFailOnError = _failOnError;
+ }
+
+ /**
+ * Gets the message.
+ *
+ * @return the message
+ */
+ public String getMessage() {
+ return this.message;
+ }
+
+ /**
+ * Gets the template vars.
+ *
+ * @return the template vars
+ */
+ public ArrayList<String> getTemplateVars() {
+ if (this.templateVars == null) {
+ this.templateVars = new ArrayList<String>();
+ }
+ return this.templateVars;
+ }
+
+ /**
+ * Gets the pre ext exception.
+ *
+ * @return the pre ext exception
+ */
+ public Exception getPreExtException() {
+ return this.preExtException;
+ }
+
+ /**
+ * Gets the pre ext error callback.
+ *
+ * @return the pre ext error callback
+ */
+ public Method getPreExtErrorCallback() {
+ return this.preExtErrorCallback;
+ }
+
+ /**
+ * Gets the post ext exception.
+ *
+ * @return the post ext exception
+ */
+ public Exception getPostExtException() {
+ return this.postExtException;
+ }
+
+ /**
+ * Gets the post ext error callback.
+ *
+ * @return the post ext error callback
+ */
+ public Method getPostExtErrorCallback() {
+ return this.postExtErrorCallback;
+ }
+
+ /**
+ * Gets the http servlet request.
+ *
+ * @return the http servlet request
+ */
+ public HttpServletRequest getHttpServletRequest() {
+ return this.servletRequest;
+ }
+
+ /**
+ * Gets the http headers.
+ *
+ * @return the http headers
+ */
+ public HttpHeaders getHttpHeaders() {
+ return this.httpHeaders;
+ }
+
+ /**
+ * Gets the object from request type.
+ *
+ * @return the object from request type
+ */
+ public String getObjectFromRequestType() {
+ return this.objectFromRequestType;
+ }
+
+ /**
+ * Gets the object from request.
+ *
+ * @return the object from request
+ */
+ public Object getObjectFromRequest() {
+ return this.objectFromRequest;
+ }
+
+ /**
+ * Gets the pre ext fail on error.
+ *
+ * @return the pre ext fail on error
+ */
+ public boolean getPreExtFailOnError() {
+ return this.preExtFailOnError;
+ }
+
+ /**
+ * Gets the post ext fail on error.
+ *
+ * @return the post ext fail on error
+ */
+ public boolean getPostExtFailOnError() {
+ return this.postExtFailOnError;
+ }
+
+ /**
+ * Gets the from app id.
+ *
+ * @return the from app id
+ */
+ public String getFromAppId() {
+ return this.fromAppId;
+ }
+
+ /**
+ * Sets the from app id.
+ *
+ * @param fromAppId the new from app id
+ */
+ public void setFromAppId(String fromAppId) {
+ this.fromAppId = fromAppId;
+ }
+
+ /**
+ * Gets the trans id.
+ *
+ * @return the trans id
+ */
+ public String getTransId() {
+ return this.transId;
+ }
+
+ /**
+ * Sets the trans id.
+ *
+ * @param transId the new trans id
+ */
+ public void setTransId(String transId) {
+ this.transId = transId;
+ }
+
+ /**
+ * Gets the logline.
+ *
+ * @return the logline
+ */
+ public LogLine getLogline() {
+ if (logline == null) {
+ logline = new LogLine();
+ }
+ return logline;
+ }
+
+ /**
+ * Sets the logline.
+ *
+ * @param logline the new logline
+ */
+ public void setLogline(LogLine logline) {
+ this.logline = logline;
+
+ }
+
+ /**
+ * Gets the aai logger.
+ *
+ * @return the aai logger
+ */
+ public AAILogger getAaiLogger() {
+ if (aaiLogger == null) {
+ aaiLogger = new AAILogger(AAIExtensionMap.class.getName());
+ }
+ return aaiLogger;
+ }
+
+ /**
+ * Sets the aai logger.
+ *
+ * @param aaiLogger the new aai logger
+ */
+ public void setAaiLogger(AAILogger aaiLogger) {
+ this.aaiLogger = aaiLogger;
+ }
+
+ /**
+ * Gets the pre ext skip error callback.
+ *
+ * @return the pre ext skip error callback
+ */
+ public boolean getPreExtSkipErrorCallback() {
+ return preExtSkipErrorCallback;
+ }
+
+ /**
+ * Sets the pre ext skip error callback.
+ *
+ * @param preExtSkipErrorCallback the new pre ext skip error callback
+ */
+ public void setPreExtSkipErrorCallback(boolean preExtSkipErrorCallback) {
+ this.preExtSkipErrorCallback = preExtSkipErrorCallback;
+ }
+
+ /**
+ * Gets the post ext skip error callback.
+ *
+ * @return the post ext skip error callback
+ */
+ public boolean getPostExtSkipErrorCallback() {
+ return postExtSkipErrorCallback;
+ }
+
+ /**
+ * Sets the post ext skip error callback.
+ *
+ * @param postExtSkipErrorCallback the new post ext skip error callback
+ */
+ public void setPostExtSkipErrorCallback(boolean postExtSkipErrorCallback) {
+ this.postExtSkipErrorCallback = postExtSkipErrorCallback;
+ }
+
+ /**
+ * Gets the graph.
+ *
+ * @return the graph
+ */
+ public TitanTransaction getGraph() {
+ return graph;
+ }
+
+ /**
+ * Sets the graph.
+ *
+ * @param graph the new graph
+ */
+ public void setGraph(TitanTransaction graph) {
+ this.graph = graph;
+ }
+
+ /**
+ * Gets the object from response.
+ *
+ * @return the object from response
+ */
+ public Object getObjectFromResponse() {
+ return objectFromResponse;
+ }
+
+ /**
+ * Sets the object from response.
+ *
+ * @param objectFromResponse the new object from response
+ */
+ public void setObjectFromResponse(Object objectFromResponse) {
+ this.objectFromResponse = objectFromResponse;
+ }
+
+ /**
+ * Gets the lookup hash map.
+ *
+ * @return the lookup hash map
+ */
+ public HashMap<String, Object> getLookupHashMap() {
+ if (this.lookupHashMap == null) {
+ this.lookupHashMap = new HashMap<String, Object>();
+ }
+ return this.lookupHashMap;
+ }
+
+ /**
+ * Sets the lookup hash map.
+ *
+ * @param lookupHashMap the lookup hash map
+ */
+ public void setLookupHashMap(HashMap<String, Object> lookupHashMap) {
+ this.lookupHashMap = lookupHashMap;
+ }
+
+ /**
+ * Gets the precheck added list.
+ *
+ * @return the precheck added list
+ */
+ public HashMap<String, ArrayList<String>> getPrecheckAddedList() {
+ if (this.precheckAddedList == null) {
+ this.precheckAddedList = new HashMap<String, ArrayList<String>>();
+ }
+ return precheckAddedList;
+ }
+
+ /**
+ * Sets the precheck added list.
+ *
+ * @param precheckAddedList the precheck added list
+ */
+ public void setPrecheckAddedList(HashMap<String, ArrayList<String>> precheckAddedList) {
+ this.precheckAddedList = precheckAddedList;
+ }
+
+ /**
+ * Gets the precheck response messages.
+ *
+ * @return the precheck response messages
+ */
+ public AAIResponseMessages getPrecheckResponseMessages() {
+ if (this.precheckResponseMessages == null) {
+ this.precheckResponseMessages = new AAIResponseMessages();
+ }
+ return precheckResponseMessages;
+ }
+
+ /**
+ * Sets the precheck response messages.
+ *
+ * @param precheckResponseData the new precheck response messages
+ */
+ public void setPrecheckResponseMessages(AAIResponseMessages precheckResponseData) {
+ this.precheckResponseMessages = precheckResponseData;
+ }
+
+ /**
+ * Gets the topology.
+ *
+ * @return the topology
+ */
+ public HashMap<String, Object> getTopology() {
+ if (this.topology == null) {
+ this.topology = new HashMap<String, Object>();
+ }
+ return topology;
+ }
+
+ /**
+ * Gets the vertex cache.
+ *
+ * @return the vertex cache
+ */
+ public HashMap<String, TitanVertex> getVertexCache() {
+ if (this.vertexCache == null) {
+ this.vertexCache = new HashMap<String, TitanVertex>();
+ }
+ return vertexCache;
+ }
+
+ /**
+ * Gets the base object.
+ *
+ * @return the base object
+ */
+ public String getBaseObject() {
+ return baseObject;
+ }
+
+ /**
+ * Sets the base object.
+ *
+ * @param baseObject the new base object
+ */
+ public void setBaseObject(String baseObject) {
+ this.baseObject = baseObject;
+ }
+
+ /**
+ * Gets the namespace.
+ *
+ * @return the namespace
+ */
+ public String getNamespace() {
+ return namespace;
+ }
+
+ /**
+ * Sets the namespace.
+ *
+ * @param namespace the new namespace
+ */
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ /**
+ * Gets the full resource name.
+ *
+ * @return the full resource name
+ */
+ public String getFullResourceName() {
+ return fullResourceName;
+ }
+
+ /**
+ * Sets the full resource name.
+ *
+ * @param fullResourceName the new full resource name
+ */
+ public void setFullResourceName(String fullResourceName) {
+ this.fullResourceName = fullResourceName;
+ }
+
+ /**
+ * Gets the top object full resource name.
+ *
+ * @return the top object full resource name
+ */
+ public String getTopObjectFullResourceName() {
+ return topObjectFullResourceName;
+ }
+
+ /**
+ * Sets the top object full resource name.
+ *
+ * @param topObjectFullResourceName the new top object full resource name
+ */
+ public void setTopObjectFullResourceName(String topObjectFullResourceName) {
+ this.topObjectFullResourceName = topObjectFullResourceName;
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @return the uri
+ */
+ public String getUri() {
+ return uri;
+ }
+
+ /**
+ * Sets the uri.
+ *
+ * @param uri the new uri
+ */
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Gets the api version.
+ *
+ * @return the api version
+ */
+ public String getApiVersion() {
+ return apiVersion;
+ }
+
+ /**
+ * Sets the api version.
+ *
+ * @param apiVersion the new api version
+ */
+ public void setApiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ }
+
+ /**
+ * Sets the notification uri.
+ *
+ * @param uri the new notification uri
+ */
+ public void setNotificationUri(String uri) {
+ this.notificationUri = uri;
+
+ }
+
+ /**
+ * Gets the notification uri.
+ *
+ * @return the notification uri
+ */
+ public String getNotificationUri() {
+ return this.notificationUri;
+
+ }
+
+ /**
+ * Gets the start time.
+ *
+ * @return the start time
+ */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /**
+ * Sets the start time.
+ *
+ * @param startTime the new start time
+ */
+ public void setStartTime(long startTime) {
+ this.startTime = startTime;
+ }
+
+ /**
+ * Gets the checkpoint time.
+ *
+ * @return the checkpoint time
+ */
+ public long getCheckpointTime() {
+ return checkpointTime;
+ }
+
+ /**
+ * Sets the checkpoint time.
+ *
+ * @param checkpointTime the new checkpoint time
+ */
+ public void setCheckpointTime(long checkpointTime) {
+ this.checkpointTime = checkpointTime;
+ }
+
+ /**
+ * Gets the jaxb context.
+ *
+ * @return the jaxb context
+ */
+ public DynamicJAXBContext getJaxbContext() {
+ return jaxbContext;
+ }
+
+ /**
+ * Sets the jaxb context.
+ *
+ * @param jaxbContext the new jaxb context
+ */
+ public void setJaxbContext(DynamicJAXBContext jaxbContext) {
+ this.jaxbContext = jaxbContext;
+ }
+
+ /**
+ * Sets the event action.
+ *
+ * @param eventAction the new event action
+ */
+ public void setEventAction(String eventAction) {
+ this.eventAction = eventAction;
+ }
+
+ /**
+ * Gets the event action.
+ *
+ * @return the event action
+ */
+ public String getEventAction() {
+ return this.eventAction;
+ }
+
+ /**
+ * Sets the ancestry.
+ *
+ * @param ancestry the new ancestry
+ */
+ public void setAncestry(AncestryItems ancestry) {
+ this.ancestry = ancestry;
+ }
+
+ /**
+ * Gets the ancestry.
+ *
+ * @return the ancestry
+ */
+ public AncestryItems getAncestry() {
+ return this.ancestry;
+ }
+
+ /**
+ * Gets the transactional graph engine.
+ *
+ * @return the transactional graph engine
+ */
+ public TransactionalGraphEngine getTransactionalGraphEngine() {
+ return this.dbEngine;
+
+ }
+
+ /**
+ * Sets the transactional graph engine.
+ *
+ * @param dbEngine the new transactional graph engine
+ */
+ public void setTransactionalGraphEngine(TransactionalGraphEngine dbEngine) {
+ this.dbEngine = dbEngine;
+
+ }
+
+ /**
+ * Gets the loader.
+ *
+ * @return the loader
+ */
+ public Loader getLoader() {
+ return loader;
+ }
+
+ /**
+ * Sets the loader.
+ *
+ * @param loader the new loader
+ */
+ public void setLoader(Loader loader) {
+ this.loader = loader;
+ }
+
+ /**
+ * Gets the uri info.
+ *
+ * @return the uri info
+ */
+ public UriInfo getUriInfo() {
+ return uriInfo;
+ }
+
+ /**
+ * Sets the uri info.
+ *
+ * @param uriInfo the new uri info
+ */
+ public void setUriInfo(UriInfo uriInfo) {
+ this.uriInfo = uriInfo;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/extensions/ExtensionController.java b/ajsc-aai/src/main/java/org/openecomp/aai/extensions/ExtensionController.java
new file mode 100644
index 0000000..4bcd307
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/extensions/ExtensionController.java
@@ -0,0 +1,168 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.extensions;
+
+import java.lang.reflect.Method;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+
+public class ExtensionController {
+
+ /**
+ * Run extension.
+ *
+ * @param apiVersion the api version
+ * @param namespace the namespace
+ * @param resourceName the resource name
+ * @param methodName the method name
+ * @param aaiExtMap the aai ext map
+ * @param isPreExtension the is pre extension
+ * @throws AAIException the AAI exception
+ */
+ public void runExtension(String apiVersion, String namespace,
+ String resourceName, String methodName, AAIExtensionMap aaiExtMap,
+ boolean isPreExtension) throws AAIException {
+ String fromAppId = aaiExtMap.getFromAppId();
+ String transId = aaiExtMap.getTransId();
+ String extensionClassName = "org.openecomp.aai.extensions."
+ + apiVersion.toLowerCase() + "." + namespace + "."
+ + resourceName + "Extension";
+ String defaultErrorCallback = resourceName + "ExtensionErrorCallback";
+ LogLine eLogline = new LogLine();
+ AAILogger aaiLogger = aaiExtMap.getAaiLogger();
+
+ String configOption = "aai.extensions." + apiVersion.toLowerCase()
+ + "." + namespace.toLowerCase() + "."
+ + resourceName.toLowerCase() + ".enabled";
+
+ try {
+ String extensionEnabled = AAIConfig.get(configOption, "true");
+ if (extensionEnabled.equalsIgnoreCase("false")) {
+ return;
+ }
+ Class<?> clazz = Class.forName(extensionClassName);
+
+ Method extension = clazz.getMethod(methodName,
+ new Class[] { AAIExtensionMap.class });
+ if (extension != null) {
+
+ eLogline.init("runExtension", transId, fromAppId, methodName);
+
+ Object ret = extension.invoke(clazz.newInstance(), aaiExtMap);
+ // reset
+ if (ret instanceof Integer) {
+ //aaiLogger.debug(logline, methodName + "Returned "
+ // + (int) ret + " " + aaiExtMap.getMessage());
+
+ Exception e = null;
+ if (isPreExtension == true) {
+ e = aaiExtMap.getPreExtException();
+ } else {
+ e = aaiExtMap.getPostExtException();
+ }
+
+ boolean failOnError = true;
+ if (isPreExtension == true) {
+ failOnError = aaiExtMap.getPreExtFailOnError();
+ } else {
+ failOnError = aaiExtMap.getPostExtFailOnError();
+ }
+
+ if (e != null) {
+ boolean handleException = true;
+ if (isPreExtension == true) {
+ if (aaiExtMap.getPreExtSkipErrorCallback() == true) {
+ handleException = false;
+ }
+ } else {
+ if (aaiExtMap.getPostExtSkipErrorCallback() == true) {
+ handleException = false;
+ }
+ }
+ if (handleException == true) {
+ Method errorCallback = null;
+ if (isPreExtension == true) {
+ errorCallback = aaiExtMap
+ .getPreExtErrorCallback();
+ } else {
+ errorCallback = aaiExtMap
+ .getPostExtErrorCallback();
+ }
+
+ if (errorCallback != null) {
+ //aaiLogger.debug(logline,
+ //"Calling custom error callback: "
+ // + errorCallback.getName());
+ errorCallback.invoke(clazz.newInstance(),
+ aaiExtMap);
+ } else {
+ Method defaultErrorCallbackExtension = clazz
+ .getMethod(
+ defaultErrorCallback,
+ new Class[] { AAIExtensionMap.class });
+ //aaiLogger.debug(
+ //logline,
+ //"Calling default error callback: "
+ // + defaultErrorCallbackExtension
+ // .getName());
+ defaultErrorCallbackExtension.invoke(
+ clazz.newInstance(), aaiExtMap);
+ }
+ }
+ }
+
+ if (failOnError == true && e != null) {
+ throw e;
+ } else if (failOnError == false && e != null) { // in this
+ // case, we
+ // just note
+ // the error
+ // without
+ // stopping
+ eLogline.add(methodName + " Message",
+ aaiExtMap.getMessage());
+ aaiLogger.info(eLogline, true, "0");
+ } else {
+ aaiLogger.info(eLogline, true, "0");
+ }
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ // do nothing, this is normal
+ //aaiLogger.debug(logline, "Extension class not found in "
+ //+ extensionClassName + ", skipping " + methodName + ".");
+ } catch (NoSuchMethodException e) {
+ // The extension class might exist but there is not a matching
+ // method in the extension class
+ //aaiLogger.debug(logline, methodName + " not found in " + extensionClassName +
+ //". This is likely normal, this message is for devs to debug extensions.");
+ } catch (AAIException e) {
+ aaiLogger.info(eLogline, false, e.getErrorObject().getErrorCodeString());
+ throw e;
+ } catch (Exception e) {
+ aaiLogger.info(eLogline, false, "AAI_5105");
+ throw new AAIException("AAI_5105", e);
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/ConvertXmlToJsonMoxyOxm.java b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/ConvertXmlToJsonMoxyOxm.java
new file mode 100644
index 0000000..c745d62
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/ConvertXmlToJsonMoxyOxm.java
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ingestModel;
+
+import java.io.File;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.JAXBMarshaller;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+/**
+ * The Class ConvertXmlToJsonMoxyOxm.
+ */
+public class ConvertXmlToJsonMoxyOxm
+{
+
+ AAILogger aaiLogger = new AAILogger(ConvertXmlToJsonMoxyOxm.class.getName());
+
+ LogLine logline = new LogLine();
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws Exception the exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ String _apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String fileName = null;
+ String dynamicType = null;
+ if (args.length > 0) {
+ if (args[0] != null) {
+ _apiVersion = args[0];
+ }
+ if (args[1] != null) {
+ fileName = args[1];
+ }
+ if (args[2] != null) {
+ dynamicType = args[2];
+ }
+ }
+
+ if (fileName == null) {
+ System.err.println("You must specify a fileName");
+ System.exit(0);
+ }
+ if (dynamicType == null) {
+ System.err.println("You must specify a dynamic Type");
+ System.exit(0);
+ }
+
+ ArrayList<String> apiVersions = new ArrayList<String>();
+ apiVersions.add(_apiVersion);
+ final IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.init(apiVersions, false);
+
+ DynamicJAXBContext jaxbContext = IngestModelMoxyOxm.aaiResourceContainer.get(_apiVersion).getJaxbContext();
+
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicType).getClass();
+
+ DynamicEntity meObject = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(new File(fileName)), resultClass).getValue();
+
+ // put it out as JSON
+
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, true);
+
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(meObject, writer);
+
+ System.out.println(writer.toString());
+
+ System.exit(0);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/CreateWidgetModels.java b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/CreateWidgetModels.java
new file mode 100644
index 0000000..62b325f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/CreateWidgetModels.java
@@ -0,0 +1,164 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ingestModel;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.JAXBMarshaller;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.google.common.base.CaseFormat;
+
+/**
+ * The Class CreateWidgetModels.
+ */
+public class CreateWidgetModels
+{
+
+ AAILogger aaiLogger = new AAILogger(CreateWidgetModels.class.getName());
+
+ LogLine logline = new LogLine();
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws Exception the exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ String _apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ String widgetJsonDir = null;
+ String modelVersion = null;
+ if (args.length > 0) {
+ if (args[0] != null) {
+ _apiVersion = args[0];
+ }
+ if (args[1] != null) {
+ widgetJsonDir = args[1];
+ }
+ if (args[2] != null) {
+ modelVersion = args[2];
+ }
+ }
+
+ if (widgetJsonDir == null) {
+ System.err.println("You must specify a directory for widgetModelJson");
+ System.exit(0);
+ }
+ if (modelVersion == null) {
+ System.err.println("You must specify a modelVersion");
+ System.exit(0);
+ }
+
+ ArrayList<String> apiVersions = new ArrayList<String>();
+ apiVersions.add(_apiVersion);
+ final IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.init(apiVersions, false);
+
+ AAIResources aaiResources = IngestModelMoxyOxm.aaiResourceContainer.get(_apiVersion);
+
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ DynamicEntity meObject = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + _apiVersion + ".Model");
+
+ // iterate the collection of resources
+
+ ArrayList<String> processedWidgets = new ArrayList<String>();
+ for (Map.Entry<String, AAIResource> aaiResEnt : aaiResources.getAaiResources().entrySet()) {
+ AAIResource aaiRes = aaiResEnt.getValue();
+
+ if (aaiRes.getResourceType().equals("node")) {
+ String resource = aaiRes.getSimpleName();
+
+ if (processedWidgets.contains(resource)) {
+ continue;
+ }
+ processedWidgets.add(resource);
+
+ String widgetName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, resource);
+ String filePathString = widgetJsonDir + "/" + widgetName + "-" + modelVersion + ".json";
+ File f = new File(filePathString);
+
+ String filePathString2 = widgetJsonDir + "/../widget-model-json-old/" + widgetName + "-" + modelVersion + ".json";
+ File f2 = new File(filePathString2);
+
+ if(!f.exists() && !f.isDirectory()) {
+
+ if (f2.exists()) {
+ System.out.println("Using old file for " + resource + ".");
+
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ Class<? extends DynamicEntity> resultClass = meObject.getClass();
+ meObject = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(f2), resultClass).getValue();
+ // override, some of them are wrong
+ meObject.set("modelVersion", modelVersion);
+ } else {
+
+ System.out.println("Making new file for " + resource + ".");
+ meObject.set("modelId", UUID.randomUUID().toString());
+ meObject.set("modelNameVersionId", UUID.randomUUID().toString());
+ meObject.set("modelVersion", modelVersion);
+ meObject.set("modelType", "widget");
+ meObject.set("modelName", widgetName);
+ }
+ // put it out as JSON
+
+ JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+ marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, true);
+
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ marshaller.setProperty("eclipselink.json.include-root", false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(meObject, writer);
+ PrintWriter out = new PrintWriter(f);
+ out.println(writer.toString());
+ out.close();
+
+ } else {
+ System.out.println("File already exists for " + resource + ". Skipping.");
+ }
+ }
+ }
+ System.exit(0);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/DbMaps.java b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/DbMaps.java
new file mode 100644
index 0000000..c872f38
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/DbMaps.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ingestModel;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * The Class DbMaps.
+ */
+public class DbMaps {
+
+ // from oxm file
+ public Multimap<String, String> NodeAltKey1Props = ArrayListMultimap.create();
+
+ public Multimap<String, String> NodeDependencies = ArrayListMultimap.create();
+
+ public Multimap<String, String> NodeNameProps = ArrayListMultimap.create();
+
+ public Multimap<String, String> NodeMapIndexedProps = ArrayListMultimap.create();
+
+ public Multimap<String, String> NodeMapUniqueProps = ArrayListMultimap.create();
+
+ public Map<Integer, String> EdgeInfoMap = new LinkedHashMap<Integer, String>();
+
+ public Map<String, String> ReservedPropNames = new HashMap<String, String>();
+
+ // from AAIResources
+ public Multimap<String, String> NodeProps = ArrayListMultimap.create();
+
+ public Multimap<String, String> NodeKeyProps = ArrayListMultimap.create();
+
+ public Map<String, String> NodePlural = new HashMap<String, String>();
+
+ public Map<String, String> NodeNamespace = new HashMap<String, String>();
+
+ public Map<String, String> PropertyVersionInfoMap = new HashMap<String, String>();
+
+ public Map<String, String> NodeVersionInfoMap = new HashMap<String, String>();
+
+ public Map<String, String> PropertyDataTypeMap = new HashMap<String, String>();
+
+ }
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelListener.java b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelListener.java
new file mode 100644
index 0000000..4f9c4fb
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelListener.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ingestModel;
+
+import java.util.ArrayList;
+import java.util.UUID;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+
+/**
+ * The listener interface for receiving ingestModel events.
+ * The class that is interested in processing a ingestModel
+ * event implements this interface, and the object created
+ * with that class is registered with a component using the
+ * component's <code>addIngestModelListener<code> method. When
+ * the ingestModel event occurs, that object's appropriate
+ * method is invoked.
+ *
+ * @see IngestModelEvent
+ */
+public class IngestModelListener implements ServletContextListener {
+
+ AAILogger aaiLogger = new AAILogger("org.openecomp.aai.ingestModel.IngestModelListener");
+ LogLine logline = new LogLine();
+
+/**
+ * Destroys context.
+ *
+ * @param arg0 the ServletContextEvent
+ */
+//@Override
+ public void contextDestroyed(ServletContextEvent arg0) {
+ IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.cleanup();
+ System.out.println("AAI Auth Listener contextDestroyed() complete.");
+ }
+
+//Run this before web application is started
+ /**
+ * Initializaes the context.
+ *
+ * @param arg0 the ServletContextEvent
+ */
+//@Override
+ public void contextInitialized(ServletContextEvent arg0) {
+
+ logline.init("aaigen", UUID.randomUUID().toString(), "AAI-INIT", "AAI Ingest Model initialization");
+
+ System.out.println("IngestModel starts initialization...");
+ try {
+ ArrayList<String> apiVersions = new ArrayList<String>();
+ apiVersions.add("v8");
+ IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.init(apiVersions);
+ logline.add("apiVersions", apiVersions.toString());
+ aaiLogger.info(logline, true, "0");
+ } catch (Exception e) {
+ aaiLogger.error(new AAIException("AAI_3000").getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, "AAI_3000");
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelMoxyOxm.java b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelMoxyOxm.java
new file mode 100644
index 0000000..8db094e
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelMoxyOxm.java
@@ -0,0 +1,988 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.ingestModel;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.UUID;
+import java.util.Vector;
+
+import org.eclipse.persistence.descriptors.ClassDescriptor;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.dynamic.DynamicTypeImpl;
+import org.eclipse.persistence.internal.helper.DatabaseField;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.eclipse.persistence.oxm.XMLField;
+import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
+import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResourceKey;
+import org.openecomp.aai.domain.model.AAIResourceKeys;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.FileWatcher;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.Multimap;
+import com.google.common.base.Splitter;
+
+/**
+ * The Class IngestModelMoxyOxm.
+ */
+public class IngestModelMoxyOxm
+{
+
+ AAILogger aaiLogger = new AAILogger(IngestModelMoxyOxm.class.getName());
+ LogLine logline = new LogLine();
+
+ public static HashMap<String, AAIResources> aaiResourceContainer;
+
+ public static HashMap<String, DbMaps> dbMapsContainer;
+
+ private static HashMap<String, Timer> timers = new HashMap<String,Timer>();
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws Exception the exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ String _apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+
+ if (args.length > 0) {
+ if (args[0] != null) {
+ _apiVersion = args[0];
+ }
+ }
+ ArrayList<String> apiVersions = new ArrayList<String>();
+ apiVersions.add(_apiVersion);
+ final IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.init(apiVersions, false);
+
+ ArrayList<String> endpoints = new ArrayList<String>();
+
+ for (Map.Entry<String, AAIResources> ent: aaiResourceContainer.entrySet()) {
+
+ AAIResources aaiResources = ent.getValue();
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+ for (Map.Entry<String, AAIResource> aaiResEnt : aaiResources.getAaiResources().entrySet()) {
+ AAIResource aaiRes = aaiResEnt.getValue();
+
+ String uri = aaiRes.getUri();
+ if (uri != null) {
+ endpoints.add(uri);
+ DynamicType dt = jaxbContext.getDynamicType(aaiRes.getResourceClassName());
+ if (dt.containsProperty("relationshipList")) {
+ endpoints.add(uri + "/relationship-list/relationship");
+ }
+ }
+ }
+ Collections.sort(endpoints);
+ for (String endpoint : endpoints) {
+ if (!endpoint.contains("/aai-internal/")) {
+ System.out.println(endpoint);
+ }
+ }
+ }
+
+ System.exit(0);
+ }
+
+ /**
+ * Inits the.
+ *
+ * @param apiVersions the api versions
+ * @throws Exception the exception
+ */
+ public synchronized void init(ArrayList<String> apiVersions) throws Exception {
+ final IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+ m.init(apiVersions, true);
+ }
+
+ /**
+ * Inits the.
+ *
+ * @param apiVersions the api versions
+ * @param setTimer the set timer
+ * @throws Exception the exception
+ */
+ public synchronized void init(ArrayList<String> apiVersions, Boolean setTimer) throws Exception {
+
+ aaiResourceContainer = new HashMap<String, AAIResources>();
+ dbMapsContainer = new HashMap<String, DbMaps>();
+
+ final IngestModelMoxyOxm m = new IngestModelMoxyOxm();
+
+ for (String apiVersion : apiVersions) {
+
+ String relationshipUtils = "org.openecomp.aai.dbmap.RelationshipUtils";
+ final String thisRelationshipUtils = relationshipUtils;
+
+ final String thisApiVersion = apiVersion;
+ final String schemaFile = AAIConstants.AAI_HOME_ETC_OXM + "aai_oxm_" + apiVersion + ".xml";
+
+ m.loadSchema(apiVersion, schemaFile, relationshipUtils);
+
+ if (!setTimer) continue;
+
+ TimerTask task = null;
+ task = new FileWatcher ( new File(schemaFile)) {
+ protected void onChange( File file ) {
+ m.loadSchema(thisApiVersion, schemaFile, thisRelationshipUtils);
+ }
+ };
+
+ if (!timers.containsKey(apiVersion)) {
+ Timer timer = new Timer();
+ timer.schedule( task , new Date(), 10000 );
+ timers.put(apiVersion, timer);
+
+ }
+ }
+ if (apiVersions.contains(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP))) {
+ //System.out.println("---> Loading PropertyVersionInfoMap for all versions in dbMapsContainer");
+ m.createPropertyAndNodeVersionInfoMapFromDbMaps();
+
+ //System.out.println("************** Checking the dbMaps generated");
+ //m.checkDbMaps();
+
+ //System.out.println("---> Attaching dbMaps to AAIResources");
+
+ for (Map.Entry<String, AAIResources> ent: aaiResourceContainer.entrySet()) {
+ String apiVersion = ent.getKey();
+ AAIResources aaiResources = ent.getValue();
+
+ DbMaps dbMap = dbMapsContainer.get(apiVersion);
+
+ for (Map.Entry<String, AAIResource> aaiResEnt : aaiResources.getAaiResources().entrySet()) {
+ AAIResource aaiRes = aaiResEnt.getValue();
+ aaiRes.setPropertyDataTypeMap(dbMap.PropertyDataTypeMap);
+ aaiRes.setNodeKeyProps(dbMap.NodeKeyProps);
+ aaiRes.setNodeNameProps(dbMap.NodeNameProps);
+ aaiRes.setNodeMapIndexedProps(dbMap.NodeMapIndexedProps);
+ }
+ }
+ }
+ }
+
+ /**
+ * Load schema.
+ *
+ * @param apiVersion the api version
+ * @param schemaFile the schema file
+ * @param relationshipUtils the relationship utils
+ * @return the dynamic JAXB context
+ */
+ private DynamicJAXBContext loadSchema(String apiVersion,
+ String schemaFile,
+ String relationshipUtils) {
+
+ AAIResources aaiResources = new AAIResources();
+ DbMaps dbMaps = new DbMaps();
+ DynamicJAXBContext jaxbContext = null;
+ logline.init("aaigen", UUID.randomUUID().toString(), "AAI-INIT", "loadOXMschema");
+
+ try {
+
+ InputStream iStream = new FileInputStream(new File(schemaFile));
+
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, iStream);
+
+ jaxbContext =
+ DynamicJAXBContextFactory.createContextFromOXM(IngestModelMoxyOxm.class.getClassLoader(), properties);
+
+ aaiResources.setJaxbContext(jaxbContext);
+ String rootClassName = "inventory.aai.openecomp.org." + apiVersion + ".Inventory";
+
+ if ("v2".equals(apiVersion)) {
+ rootClassName = "inventory.aai.openecomp.org.Inventory";
+ }
+
+ DynamicTypeImpl t = (DynamicTypeImpl)jaxbContext.getDynamicType(rootClassName);
+
+ logline.add("loadingSchemaVersion", apiVersion);
+ lookAtDynamicResource("Inventory",
+ "inventory.aai.openecomp.org." + apiVersion,
+ jaxbContext,
+ t,
+ 1, "", "", apiVersion, "/" + apiVersion, false, aaiResources, dbMaps, relationshipUtils);
+ aaiLogger.info(logline, true, "0");
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ aaiLogger.error(new AAIException("AAI_3000").getErrorObject(), logline, e);
+ }
+
+ System.out.println("---> Loading " + apiVersion + " in aaiResourceContainer");
+ aaiResourceContainer.put(apiVersion, aaiResources);
+
+ createDbMapsfromAAIResources(aaiResources, dbMaps);
+
+ System.out.println("---> Loading " + apiVersion + " in dbMapsContainer");
+ dbMapsContainer.put(apiVersion, dbMaps);
+
+ return jaxbContext;
+ }
+
+ /**
+ * Cleanup.
+ */
+ public void cleanup() {
+ aaiResourceContainer.clear();
+ dbMapsContainer.clear();
+ }
+
+ /**
+ * Look at dynamic resource.
+ *
+ * @param resource the resource
+ * @param pojoBase the pojo base
+ * @param jaxbContext the jaxb context
+ * @param t the t
+ * @param depth the depth
+ * @param parent the parent
+ * @param namespace the namespace
+ * @param apiVersion the api version
+ * @param url the url
+ * @param container the container
+ * @param aaiResources the aai resources
+ * @param dbMaps the db maps
+ * @param relationshipUtils the relationship utils
+ * @throws ClassNotFoundException the class not found exception
+ * @throws NoSuchFieldException the no such field exception
+ * @throws SecurityException the security exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ private void lookAtDynamicResource(String resource,
+ String pojoBase,
+ DynamicJAXBContext jaxbContext,
+ DynamicTypeImpl t,
+ int depth,
+ String parent,
+ String namespace,
+ String apiVersion,
+ String url,
+ boolean container,
+ AAIResources aaiResources,
+ DbMaps dbMaps,
+ String relationshipUtils
+ )
+ throws ClassNotFoundException, NoSuchFieldException, SecurityException, IOException {
+
+ String className = pojoBase + "." + CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL, resource);
+
+ AAIResource parentResource = aaiResources.getAaiResources().get(parent);
+
+ AAIResources siblings = null;
+
+ if (parentResource == null) {
+ String fullName = "/" + resource;
+ AAIResource aaiRes = new AAIResource();
+ aaiRes.setFullName(fullName);
+ aaiRes.setSimpleName(resource);
+ aaiRes.setResourceType("container");
+ aaiRes.setResourceClassName(className);
+ aaiRes.setApiVersion(apiVersion);
+
+ aaiResources.getAaiResources().put(fullName, aaiRes);
+ parentResource = aaiRes;
+ }
+
+ if (depth >= 50) return;
+
+ siblings = parentResource.getChildren();
+
+ if (depth == 2) {
+ namespace = resource;
+ }
+ if (depth >= 50) {
+ return;
+ }
+
+ /* if ("Actions".equals(namespace) || "Search".equals(namespace)) {
+ return;
+ }*/
+
+ ClassDescriptor cd = t.getDescriptor();
+
+ createDbMapsfromOXM(cd.getProperties(), resource, dbMaps);
+
+
+
+ Vector<DatabaseMapping> dm = cd.getMappings();
+
+ for (DatabaseMapping dmInst : dm) {
+ String dmName = dmInst.getAttributeName();
+
+ ClassDescriptor cd2 = dmInst.getReferenceDescriptor();
+ if (cd2 != null) {
+
+ String newClassName = cd2.getJavaClassName();
+ //
+ if (newClassName.contains("RelationshipList")) {
+ continue;
+ }
+
+ DynamicTypeImpl newDt = (DynamicTypeImpl)jaxbContext.getDynamicType(newClassName);
+
+ if (dmInst instanceof XMLCompositeCollectionMapping) {
+ String simpleName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, dmName);
+ // System.out.println(spaces + "+ List of A&AI Object named " + simpleName);
+
+ String hypName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, simpleName);
+
+ String fullName = parent + "/" + simpleName;
+
+ //Class<?> newClazz = Class.forName(newClassName);
+ AAIResource aaiRes = new AAIResource();
+
+ if ("cvlan-tag-entry".equals(hypName)) {
+ }
+
+ ClassDescriptor cd3 = newDt.getDescriptor();
+
+ boolean allowDirectWrite = true;
+ if (cd3.getProperties().containsKey("allowDirectWrite")) {
+ if (cd3.getProperties().get("allowDirectWrite").equals("false")) {
+ allowDirectWrite = false;
+ }
+ }
+
+
+ boolean allowDirectRead = true;
+ if (cd3.getProperties().containsKey("allowDirectRead")) {
+ if (cd3.getProperties().get("allowDirectRead").equals("false")) {
+ allowDirectRead = false;
+ }
+ }
+
+ List<DatabaseField> dbfList = cd3.getPrimaryKeyFields();
+ ArrayList<String> keyFields = new ArrayList<String>();
+
+ if (dbfList != null) {
+ for (DatabaseField dbf : dbfList) {
+ String name = dbf.getName();
+ name = name.substring(0, name.indexOf('/'));
+ keyFields.add(name);
+ }
+ }
+ Vector<DatabaseMapping> dm2 = cd3.getMappings();
+ for (DatabaseMapping dmInst2 : dm2) {
+ String dmName2= CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmInst2.getAttributeName());
+ DatabaseField xf2 = dmInst2.getField();
+ if (dmInst2.getProperties().containsKey("autoGenerateUuid")) {
+ if (dmInst2.getProperties().get("autoGenerateUuid").equals("true")) {
+ aaiRes.getAutoGenUuidFields().add(dmName2);
+ }
+ }
+ if (xf2 instanceof XMLField) {
+ XMLField x = (XMLField)xf2;
+ if (x != null) {
+ if (x.isRequired()) {
+ aaiRes.getRequiredFields().add(dmName2);
+ }
+ }
+
+ }
+ try {
+ Class<?> xf2Clazz = xf2.getType();
+ if (xf2Clazz.getSimpleName().equals("String")) {
+ if (dmInst2 instanceof XMLCompositeDirectCollectionMapping) {
+ aaiRes.getStringListFields().add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmName2));
+ } else {
+ aaiRes.getStringFields().add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmName2));
+ }
+ } else if (xf2Clazz.getSimpleName().toLowerCase().contains("long")) {
+ aaiRes.getLongFields().add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmName2));
+ } else if (xf2Clazz.getSimpleName().toLowerCase().contains("int")) {
+ aaiRes.getIntFields().add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmName2));
+ } else if (xf2Clazz.getSimpleName().toLowerCase().contains("short")) {
+ aaiRes.getShortFields().add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmName2));
+ } else if (xf2Clazz.getSimpleName().toLowerCase().contains("boolean")) {
+ aaiRes.getBooleanFields().add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmName2));
+ }
+ } catch (Exception e) { // this xf2.getType() throws null pointer when I try to get the type and it doesn't have one
+ ;
+ }
+ }
+
+ // get the key(s) from DbRules
+ String uriKey = "";
+ LinkedHashMap<String, ArrayList<String>> itemKeyList = new LinkedHashMap<String, ArrayList<String>>();
+
+ aaiRes.setApiVersion(apiVersion);
+ itemKeyList.put(hypName, new ArrayList<String>());
+ for (String thisKey : keyFields) {
+ String pathParamName = hypName + "-" + thisKey;
+
+ AAIResourceKey aaiResKey = new AAIResourceKey();
+ aaiResKey.setKeyName(thisKey);
+ aaiResKey.setDnCamKeyName(CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, pathParamName));
+ aaiResKey.setPathParamName(pathParamName);
+
+ for (DatabaseMapping dmInst2 : dm2) {
+ String dmName2= CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,dmInst2.getAttributeName());
+ if (dmName2.equals(thisKey)){
+ DatabaseField xf2 = dmInst2.getField();
+ aaiResKey.setKeyType(xf2.getType().getSimpleName());
+ break;
+ }
+ }
+
+ aaiRes.getAaiResourceKeys().getAaiResourceKey().add(aaiResKey);
+
+ if (siblings != null) {
+ siblings.getAaiResources().put(fullName, aaiRes);
+ }
+
+ uriKey += "/{" + pathParamName + "}";
+ }
+
+ String newUri = url + "/" + hypName + uriKey;
+
+
+ if ("v2".equals(apiVersion)) {
+ aaiRes.setResourceClassName("inventory.aai.openecomp.org." + simpleName);
+ } else {
+ aaiRes.setResourceClassName("inventory.aai.openecomp.org." + apiVersion + "." + simpleName);
+ }
+
+ aaiRes.setAllowDirectWrite(allowDirectWrite);
+ aaiRes.setAllowDirectRead(allowDirectRead);
+ aaiRes.setNamespace(namespace);
+ aaiRes.setSimpleName(simpleName);
+
+ if (!aaiResources.getResourceLookup().containsKey(simpleName)) {
+ aaiResources.getResourceLookup().put(simpleName, aaiRes);
+ }
+
+ aaiRes.setFullName(fullName);
+ aaiRes.setUri(newUri);
+ aaiRes.setResourceType("node");
+ if ("v2".equals(apiVersion)) {
+ aaiRes.setRelationshipListClass("inventory.aai.openecomp.org.RelationshipList");
+ } else {
+ aaiRes.setRelationshipListClass("inventory.aai.openecomp.org." + apiVersion + ".RelationshipList");
+ }
+ aaiRes.setRelationshipUtils(relationshipUtils);
+
+ if (parentResource != null) {
+ aaiRes.setParent(parentResource);
+ } else {
+ aaiRes.setParent(aaiRes);
+ }
+
+ aaiResources.getAaiResources().put(fullName, aaiRes);
+
+ if (siblings != null) {
+ siblings.getAaiResources().put(fullName, aaiRes);
+ }
+// AAIResource ancestor = parentResource;
+//
+// boolean recursiveEntity = false;
+// while (ancestor != null) {
+//
+// if (ancestor.getSimpleName().equals(aaiRes.getSimpleName())) {
+// recursiveEntity = true;
+// // attach it to the container that contains the resource above this one with the same name
+// if (ancestor.getParent() != null && ancestor.getParent().getResourceType().equals("container")) {
+// AAIResource recurseHere = ancestor.getParent();
+// aaiRes.setRecurseToResource(recurseHere);
+// }
+// break;
+// }
+// ancestor = ancestor.getParent();
+//
+// }
+// if (recursiveEntity == false) {
+ lookAtDynamicResource(cd2.getJavaClass().getSimpleName(),
+ pojoBase,
+ jaxbContext,
+ newDt,
+ (depth + 1), fullName, namespace, apiVersion, newUri, false, aaiResources, dbMaps,
+ relationshipUtils);
+// }
+ } else {
+ String simpleName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, dmName);
+ String fullName = parent + "/" + simpleName;
+ // System.out.println(spaces + "+ Container of A&AI Object named " + simpleName);
+
+ AAIResource aaiRes = new AAIResource();
+ if (parentResource != null) {
+ aaiRes.setParent(parentResource);
+ } else {
+ aaiRes.setParent(aaiRes);
+ }
+ aaiRes.setAllowDirectWrite(true);
+ aaiRes.setAllowDirectRead(true);
+ aaiRes.setFullName(fullName);
+ aaiRes.setSimpleName(simpleName);
+ if (!aaiResources.getResourceLookup().containsKey(simpleName)) {
+ aaiResources.getResourceLookup().put(simpleName, aaiRes);
+ }
+ aaiRes.setResourceType("container");
+
+ if ("v2".equals(apiVersion)) {
+ aaiRes.setResourceClassName("inventory.aai.openecomp.org." + simpleName);
+ aaiRes.setRelationshipListClass("inventory.aai.openecomp.org.RelationshipList");
+ } else {
+ aaiRes.setResourceClassName("inventory.aai.openecomp.org." + apiVersion + "." + simpleName);
+ aaiRes.setRelationshipListClass("inventory.aai.openecomp.org." + apiVersion + ".RelationshipList");
+ }
+ aaiRes.setApiVersion(apiVersion);
+
+ aaiResources.getAaiResources().put(fullName, aaiRes);
+ aaiRes.setRelationshipUtils(relationshipUtils);
+
+ String hypName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, simpleName);
+
+ if (siblings != null) {
+ siblings.getAaiResources().put(fullName, aaiRes);
+ }
+
+ lookAtDynamicResource(cd2.getJavaClass().getSimpleName(),
+ pojoBase,
+ jaxbContext,
+ (DynamicTypeImpl)jaxbContext.getDynamicType(newClassName),
+ (depth + 1), fullName, namespace, apiVersion, url + "/" + hypName, false, aaiResources, dbMaps,
+ relationshipUtils);
+
+
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates the db mapsfrom OXM.
+ *
+ * @param propMap the prop map
+ * @param resource the resource
+ * @param dbMaps the db maps
+ */
+ private void createDbMapsfromOXM(Map<?, ?> propMap, String resource, DbMaps dbMaps) {
+ String nodeType = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, resource);
+ if ("cvlan-tag-entry".equals(nodeType)) {
+ nodeType = "cvlan-tag";
+ }
+
+ // if we have nodes dependent on multiple nodes we might revisit the node again - skip then
+ if (propMap.size() > 1 && !dbMaps.NodeMapIndexedProps.containsKey(nodeType)) {
+
+ if (propMap.containsKey("nameProps"))
+ dbMaps.NodeNameProps.putAll(nodeType,
+ (Iterable<String>) fromCommaSeparatedString(propMap.get("nameProps").toString()));
+
+ if (propMap.containsKey("indexedProps"))
+ dbMaps.NodeMapIndexedProps.putAll(nodeType,
+ (Iterable<String>) fromCommaSeparatedString(propMap.get("indexedProps").toString()));
+
+ if (propMap.containsKey("dependentOn"))
+ dbMaps.NodeDependencies.putAll(nodeType,
+ (Iterable<String>) fromCommaSeparatedString(propMap.get("dependentOn").toString()));
+
+ if (propMap.containsKey("alternateKeys1"))
+ dbMaps.NodeAltKey1Props.putAll(nodeType,
+ (Iterable<String>) fromCommaSeparatedString(propMap.get("alternateKeys1").toString()));
+
+ if (propMap.containsKey("uniqueProps"))
+ dbMaps.NodeMapUniqueProps.putAll(nodeType,
+ (Iterable<String>) fromCommaSeparatedString(propMap.get("uniqueProps").toString()));
+
+ // build EdgeInfoMap
+ if (propMap.containsKey("edgeInfo")) {
+ int i = 0;
+ Iterable<String> edgeInfoIterable = (Iterable<String>) fromCommaSeparatedString(propMap.get("edgeInfo").toString());
+ Iterator<String> edgeInfoIterator = edgeInfoIterable.iterator();
+ while(edgeInfoIterator.hasNext()) {
+ String propName = edgeInfoIterator.next();
+ dbMaps.EdgeInfoMap.put(i++, propName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates the db mapsfrom AAI resources.
+ *
+ * @param aaiResources the aai resources
+ * @param dbMaps the db maps
+ */
+ private void createDbMapsfromAAIResources(AAIResources aaiResources, DbMaps dbMaps) {
+
+ for (String resource: aaiResources.getAaiResources().keySet()) {
+
+ AAIResource aaiResource = aaiResources.getAaiResources().get(resource);
+ String nodeType = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,aaiResource.getSimpleName());
+
+ if (nodeType.equals("cvlan-tag-entry"))
+ nodeType = "cvlan-tag";
+
+ // Build NodeNamespace
+ if (aaiResource.getNamespace() != null && !aaiResource.getNamespace().equalsIgnoreCase("search"))
+ // oamNetworks is also defined under the search namespace - do not want that namespace
+ dbMaps.NodeNamespace.put(nodeType, CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiResource.getNamespace()));
+
+ // only process one nodetype once
+ if (dbMaps.NodeProps.containsKey(nodeType))
+ continue;
+
+ // Build NodePlural
+ if (aaiResource.getPluralName() != null && !aaiResource.getPluralName().equals(aaiResource.getNamespace()))
+ // dont want resources which are namespaces themselves in map
+ dbMaps.NodePlural.put(nodeType, CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiResource.getPluralName()));
+
+ // Build NodeProps
+ dbMaps.NodeProps.putAll(nodeType, aaiResource.getAllFields());
+
+ // build ReservedNames
+ if (nodeType.equalsIgnoreCase("reserved-prop-names")) {
+ for (String propName: aaiResource.getAllFields()) {
+ dbMaps.ReservedPropNames.put(propName, "");
+ }
+ }
+
+ // Build NodekeyProps
+ AAIResourceKeys aaiResKeys = aaiResource.getAaiResourceKeys();
+ List<String> keyList = new ArrayList<String>();
+ for (AAIResourceKey rk : aaiResKeys.getAaiResourceKey()) {
+ String keyProp = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,rk.getKeyName());
+ if (!keyList.contains(keyProp))
+ keyList.add(keyProp);
+ }
+ dbMaps.NodeKeyProps.putAll(nodeType, (Iterable<String>)keyList);
+
+ // Build PropertyDataTypeMap
+ for (String propName: aaiResource.getBooleanFields()) {
+ if (nodeType.equalsIgnoreCase("edge-prop-names")) // these properties are in mixed format in DB
+ propName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, propName);
+ if (propName.equals("sVCINFRA")) propName = "SVC-INFRA";
+ if (propName.equals("sVCINFRAREV")) propName = "SVC-INFRA-REV";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName))
+ dbMaps.PropertyDataTypeMap.put(propName, "Boolean");
+ else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("Boolean"))
+ System.out.println(propName + "defined with mis-matched types in oxm file");
+ }
+ for (String propName: aaiResource.getShortFields()) {
+ if (nodeType.equalsIgnoreCase("edge-prop-names")) // these properties are in mixed format in DB
+ propName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, propName);
+ if (propName.equals("sVCINFRA")) propName = "SVC-INFRA";
+ if (propName.equals("sVCINFRAREV")) propName = "SVC-INFRA-REV";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName))
+ dbMaps.PropertyDataTypeMap.put(propName, "Integer");
+ else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("Integer"))
+ System.out.println(propName + "defined with mis-matched types in oxm file");
+ }
+ for (String propName: aaiResource.getLongFields()) {
+ if (nodeType.equalsIgnoreCase("edge-prop-names")) // these properties are in mixed format in DB
+ propName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, propName);
+ if (propName.equals("sVCINFRA")) propName = "SVC-INFRA";
+ if (propName.equals("sVCINFRAREV")) propName = "SVC-INFRA-REV";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName)) {
+ if (propName.contains("-ts"))
+ dbMaps.PropertyDataTypeMap.put(propName, "Long");
+ else
+ dbMaps.PropertyDataTypeMap.put(propName, "Integer");
+ } else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("Integer"))
+ System.out.println(propName + "defined with mis-matched types in oxm file");
+ }
+ for (String propName: aaiResource.getIntFields()) {
+ if (nodeType.equalsIgnoreCase("edge-prop-names")) // these properties are in mixed format in DB
+ propName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, propName);
+ if (propName.equals("sVCINFRA")) propName = "SVC-INFRA";
+ if (propName.equals("sVCINFRAREV")) propName = "SVC-INFRA-REV";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName))
+ dbMaps.PropertyDataTypeMap.put(propName, "Integer");
+ else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("Integer"))
+ System.out.println(propName + "defined with mis-matched types in oxm file");
+ }
+ for (String propName: aaiResource.getStringFields()) {
+ if (nodeType.equalsIgnoreCase("edge-prop-names")) // these properties are in mixed format in DB
+ propName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, propName);
+ if (propName.equals("sVCINFRA")) propName = "SVC-INFRA";
+ if (propName.equals("sVCINFRAREV")) propName = "SVC-INFRA-REV";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName))
+ dbMaps.PropertyDataTypeMap.put(propName, "String");
+ else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("String"))
+ System.out.println(propName + "defined with mis-matched types in oxm file");
+ }
+ for (String propName: aaiResource.getStringListFields()) {
+ if (nodeType.equalsIgnoreCase("edge-prop-names")) // these properties are in mixed format in DB
+ propName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, propName);
+ if (propName.equals("sVCINFRA")) propName = "SVC-INFRA";
+ if (propName.equals("sVCINFRAREV")) propName = "SVC-INFRA-REV";
+ if (!dbMaps.PropertyDataTypeMap.containsKey(propName))
+ dbMaps.PropertyDataTypeMap.put(propName, "Set<String>");
+ else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("Set<String>"))
+ System.out.println(propName + "defined with mis-matched types in oxm file");
+ }
+ }
+
+ }
+
+
+ /**
+ * Creates the property and node version info map from db maps.
+ */
+ private void createPropertyAndNodeVersionInfoMapFromDbMaps() {
+ DbMaps dbMaps = null;
+ String previousApiVersion = null;
+
+ ArrayList<String> apiVersionsList = (ArrayList<String>) asSortedList(dbMapsContainer.keySet());
+
+ for (String apiVersion : apiVersionsList) {
+ System.out.println("apiVersion=" + apiVersion);
+ dbMaps = dbMapsContainer.get(apiVersion);
+
+ if (previousApiVersion != null) { // when running more than one version
+ dbMaps.PropertyVersionInfoMap.putAll(dbMapsContainer.get(previousApiVersion).PropertyVersionInfoMap);
+ dbMaps.NodeVersionInfoMap.putAll(dbMapsContainer.get(previousApiVersion).NodeVersionInfoMap);
+ }
+
+ Iterator<String> nodeTypeIterator = dbMaps.NodeProps.keySet().iterator();
+ while( nodeTypeIterator.hasNext() ){
+ String nType = nodeTypeIterator.next();
+ if (!dbMaps.NodeVersionInfoMap.containsKey(nType)) {
+ dbMaps.NodeVersionInfoMap.put(nType, apiVersion);
+ }
+ Collection <String> nodePropsForType = dbMaps.NodeProps.get(nType);
+ Iterator <String> propIter = nodePropsForType.iterator();
+ while( propIter.hasNext() ){
+ String propName = propIter.next();
+ String infoKey = nType + "|" + propName;
+ if( ! dbMaps.PropertyVersionInfoMap.containsKey(infoKey) ){
+ // We haven't seen this one yet -- add it in.
+ dbMaps.PropertyVersionInfoMap.put(infoKey, apiVersion);
+ }
+ }
+ }
+ dbMapsContainer.put(apiVersion, dbMaps);
+ previousApiVersion = apiVersion;
+ }
+ }
+
+ /**
+ * As sorted list.
+ *
+ * @param <T> the generic type
+ * @param c the c
+ * @return the list
+ */
+ private <T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) {
+ List<T> list = new ArrayList<T>(c);
+ java.util.Collections.sort(list);
+ return list;
+ }
+
+ /**
+ * Check db maps.
+ *
+ * @throws AAIException the AAI exception
+ */
+ private void checkDbMaps() throws AAIException {
+
+ DbMaps dbMaps = null;
+ //for (String apiVersion : asSortedList(dbMapsContainer.keySet())) {
+ String apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ System.out.println("apiVersion=" + apiVersion);
+ dbMaps = dbMapsContainer.get(apiVersion);
+
+ System.out.println("NodeNameProps " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeNameProps));
+ System.out.println("NodeMapIndexedProps " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeMapIndexedProps));
+ System.out.println("NodeDependencies " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeDependencies));
+ System.out.println("NodeAltKey1Props " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeAltKey1Props));
+ System.out.println("NodeProps " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeProps));
+ System.out.println("NodePlural " + apiVersion + "=" + prettyPrintMap(dbMaps.NodePlural));
+ System.out.println("NodeNamespace " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeNamespace));
+ System.out.println("NodeKeyProps " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeKeyProps));
+ System.out.println("NodeMapUniqueProps " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeMapUniqueProps));
+ System.out.println("PropertyDataTypeMap " + apiVersion + "=" + prettyPrintMap(dbMaps.PropertyDataTypeMap));
+ System.out.println("PropertyVersionInfoMap " + apiVersion + "=" + prettyPrintMap(dbMaps.PropertyVersionInfoMap));
+ System.out.println("NodeVersionInfoMap " + apiVersion + "=" + prettyPrintMap(dbMaps.NodeVersionInfoMap));
+ System.out.println("EdgeInfoMap " + apiVersion + "=" + prettyPrintMap(dbMaps.EdgeInfoMap));
+ System.out.println("ReservedPropNames " + apiVersion + "=" + prettyPrintMap(dbMaps.ReservedPropNames));
+
+ /* for (String key:dbMaps.NodeNameProps.keySet()) {
+ if (!DbRules.NodeNameProps.containsKey(key))
+ System.out.println("extra " + key + " in NodeNameProps");
+ }
+
+ for (String key:DbRules.NodeNameProps.keySet()) {
+ if (!dbMaps.NodeNameProps.containsKey(key))
+ System.out.println("missing " + key + " in NodeNameProps");
+ }
+
+ for (String key:dbMaps.NodeMapIndexedProps.keySet()) {
+ if (!DbRules.NodeMapIndexedProps.containsKey(key))
+ System.out.println("extra " + key + " in NodeMapIndexedProps");
+ }
+
+ for (String key:DbRules.NodeMapIndexedProps.keySet()) {
+ if (!dbMaps.NodeMapIndexedProps.containsKey(key))
+ System.out.println("missing " + key + " in NodeMapIndexedProps");
+ }
+
+ for (String key:dbMaps.NodeDependencies.keySet()) {
+ if (!DbRules.NodeDependencies.containsKey(key))
+ System.out.println("extra " + key + " in NodeDependencies");
+ }
+
+ for (String key:DbRules.NodeDependencies.keySet()) {
+ if (!dbMaps.NodeDependencies.containsKey(key))
+ System.out.println("missing " + key + " in NodeAltKey1Props");
+ }
+
+ for (String key:dbMaps.NodeAltKey1Props.keySet()) {
+ if (!DbRules.NodeAltKey1Props.containsKey(key))
+ System.out.println("extra " + key + " in NodeAltKey1Props");
+ }
+
+ for (String key:DbRules.NodeAltKey1Props.keySet()) {
+ if (!dbMaps.NodeAltKey1Props.containsKey(key))
+ System.out.println("missing " + key + " in NodeAltKey1Props");
+ }
+
+ for (String key:dbMaps.NodeProps.keySet()) {
+ if (!DbRules.NodeProps.containsKey(key))
+ System.out.println("extra " + key + " in NodeProps");
+ }
+
+ for (String key:DbRules.NodeProps.keySet()) {
+ if (!dbMaps.NodeProps.containsKey(key))
+ System.out.println("missing " + key + " in NodeProps");
+ }
+
+ for (String key:dbMaps.NodeKeyProps.keySet()) {
+ if (!DbRules.NodeKeyProps.containsKey(key))
+ System.out.println("extra " + key + " in NodeKeyProps");
+ }
+
+ for (String key:DbRules.NodeKeyProps.keySet()) {
+ if (!dbMaps.NodeKeyProps.containsKey(key))
+ System.out.println("missing " + key + " in NodeKeyProps");
+ }
+
+ for (String key:dbMaps.PropertyDataTypeMap.keySet()) {
+ if (!DbRules.PropertyDataTypeMap.containsKey(key))
+ System.out.println("extra " + key + " in PropertyDataTypeMap");
+ else if (!dbMaps.PropertyDataTypeMap.get(key).equals(DbRules.PropertyDataTypeMap.get(key)))
+ System.out.println("mis-matched type in PropertyDataTypeMap for: " + key);
+ }
+
+ for (String key:DbRules.PropertyDataTypeMap.keySet()) {
+ if (!dbMaps.PropertyDataTypeMap.containsKey(key))
+ System.out.println("missing " + key + " in PropertyDataTypeMap");
+ }
+
+ for (String key:dbMaps.PropertyVersionInfoMap.keySet()) {
+ if (!key.equals("aai-unique-key")) {
+ if (!DbRules.PropertyVersionInfoMap.containsKey(key))
+ System.out.println("extra " + key + " in PropertyVersionInfoMap");
+ else if (!dbMaps.PropertyVersionInfoMap.get(key).equals(DbRules.PropertyVersionInfoMap.get(key)))
+ System.out.println("mis-matched type in PropertyVersionInfoMap for: " + key);
+ }
+ }
+
+ for (String key:DbRules.PropertyVersionInfoMap.keySet()) {
+ if (!key.equals("aai-unique-key")) {
+ if (!dbMaps.PropertyVersionInfoMap.containsKey(key))
+ System.out.println("missing " + key + " in PropertyVersionInfoMap");
+ }
+ }
+ */
+ //}
+ }
+
+ /**
+ * From comma separated string.
+ *
+ * @param string the string
+ * @return the iterable
+ */
+ public Iterable<String> fromCommaSeparatedString( String string ) {
+ Iterable<String> split = Splitter.on( "," ).omitEmptyStrings().trimResults().split( string );
+ return split;
+ }
+
+ /**
+ * Pretty print map.
+ *
+ * @param map the map
+ * @return the string
+ */
+ public String prettyPrintMap(Multimap<String, String> map) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('\n');
+ for (String key:map.keySet()) {
+ sb.append('\t');
+ sb.append(key);
+ sb.append('=').append('"');
+ sb.append(map.get(key));
+ sb.append('"');
+ sb.append('\n');
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Pretty print map.
+ *
+ * @param map the map
+ * @return the string
+ */
+ public String prettyPrintMap(Map<?, String> map) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('\n');
+ for (Object key:map.keySet()) {
+ sb.append('\t');
+ sb.append(key);
+ sb.append('=').append('"');
+ sb.append(map.get(key));
+ sb.append('"');
+ sb.append('\n');
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java b/ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java
new file mode 100644
index 0000000..b0e1742
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java
@@ -0,0 +1,302 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.interceptors;
+
+import java.io.InputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.interceptor.LoggingMessage;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor;
+import org.apache.cxf.message.Message;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.util.EchoResponse;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.HbaseSaltPrefixer;
+
+public class AAILogJAXRSInInterceptor extends JAXRSInInterceptor {
+
+ protected final String COMPONENT = "aairest";
+ protected final String CAMEL_REQUEST ="CamelHttpUrl";
+ private static final Pattern uuidPattern = Pattern.compile("^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$");
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleMessage(Message message) {
+ boolean go = false;
+ AAILogger aaiLogger = new AAILogger(AAILogJAXRSInInterceptor.class.getName());
+ LogLine logline = new LogLine();
+ LogLine auditLogline = new LogLine();
+ String uri = null;
+ String query = null;
+ try {
+
+ uri = (String)message.get(CAMEL_REQUEST);
+ if (uri != null) {
+ query = (String)message.get(Message.QUERY_STRING);
+ }
+
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true") &&
+ AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
+ go = true;
+ message.getExchange().put("AAI_LOGGING_HBASE_ENABLED", 1);
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGREQUEST).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_HBASE_LOGREQUEST", 1);
+ }
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGRESPONSE).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_HBASE_LOGRESPONSE", 1);
+ }
+ }
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_ENABLED).equalsIgnoreCase("true") ) {
+ go = true;
+ message.getExchange().put("AAI_LOGGING_TRACE_ENABLED", 1);
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGREQUEST).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_TRACE_LOGREQUEST", 1);
+ }
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGRESPONSE).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_TRACE_LOGRESPONSE", 1);
+ }
+ }
+ } catch (AAIException e1) {
+ logline.add("Property", AAIConstants.AAI_LOGGING_TRACE_ENABLED);
+ logline.add("Property", AAIConstants.AAI_LOGGING_HBASE_ENABLED);
+ aaiLogger.error(e1.getErrorObject(), logline);
+ }
+
+ if (uri.contains(EchoResponse.echoPath)) {
+ // if it's a health check, we don't want to log ANYTHING if it's a lightweight one
+ if (query == null) {
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
+ message.getExchange().remove("AAI_LOGGING_HBASE_ENABLED");
+ }
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+ message.getExchange().remove("AAI_LOGGING_TRACE_ENABLED");
+ }
+ go = false;
+ }
+ }
+ else if (uri.contains("/translog/")) {
+ // if it's a translog query, we don't want to log the responses
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
+ message.getExchange().remove("AAI_LOGGING_HBASE_LOGRESPONSE");
+ }
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
+ message.getExchange().remove("AAI_LOGGING_TRACE_LOGRESPONSE");
+ }
+ }
+
+ if (go == false) { // there's nothing to do
+ return;
+ }
+
+ // DONE: get a TXID based on hostname, time (YYYYMMDDHHMMSSMILLIS, and LoggingMessage.nextId(); 20150326145301-1
+ String now = genDate(aaiLogger, logline);
+
+ message.getExchange().put("AAI_RQST_TM", now);
+
+ String id = (String)message.getExchange().get(LoggingMessage.ID_KEY);
+
+ String fullId = null;
+ try {
+ if (id == null) {
+ id = LoggingMessage.nextId();
+ }
+ fullId = AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" + now + "-" + id;
+ fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
+ message.getExchange().put(LoggingMessage.ID_KEY, fullId);
+ } catch (AAIException e1) {
+ aaiLogger.debug(logline, "config problem", e1);
+ }
+ if (fullId == null) {
+ fullId = now + "-" + id;
+ fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
+ }
+ message.put(LoggingMessage.ID_KEY, fullId);
+ final LoggingMessage buffer = new LoggingMessage("Message", fullId);
+
+ Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
+ if (responseCode != null) {
+ buffer.getResponseCode().append(responseCode);
+ }
+
+ String encoding = (String)message.get(Message.ENCODING);
+
+ if (encoding != null) {
+ buffer.getEncoding().append(encoding);
+ }
+ String httpMethod = (String)message.get(Message.HTTP_REQUEST_METHOD);
+ if (httpMethod != null) {
+ buffer.getHttpMethod().append(httpMethod);
+ }
+
+ String ct = (String)message.get(Message.CONTENT_TYPE);
+ if (ct != null) {
+ if ("*/*".equals(ct)) {
+ message.put(Message.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ ct = MediaType.APPLICATION_JSON;
+ }
+ buffer.getContentType().append(ct);
+
+ }
+ Object headers = message.get(Message.PROTOCOL_HEADERS);
+ if (headers != null) {
+ buffer.getHeader().append(headers);
+
+ Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+ String transId = "";
+ String fromAppId = null;
+ List<String> xt = headersList.get("X-TransactionId");
+ String newTransId = transId;
+ boolean missingTransId = false;
+ boolean replacedTransId = false;
+ String logMsg = null;
+ if (xt != null) {
+ for (String transIdValue : xt) {
+ transId = transIdValue;
+ }
+ Matcher matcher = uuidPattern.matcher(transId);
+ if (!matcher.find()) {
+ replacedTransId = true;
+ // check if there's a colon, and check the first group?
+ if (transId.contains(":")) {
+ String[] uuidParts = transId.split(":");
+ Matcher matcher2 = uuidPattern.matcher(uuidParts[0]);
+ if (matcher2.find()) {
+ newTransId = uuidParts[0];
+ } else {
+ // punt, we tried to find it, it has a colon but no UUID-1
+ newTransId = UUID.randomUUID().toString();
+ }
+ } else {
+ newTransId = UUID.randomUUID().toString();
+ }
+ }
+ } else {
+ newTransId = UUID.randomUUID().toString();
+ missingTransId = true;
+ }
+
+ if (missingTransId || replacedTransId) {
+ List<String> txList = new ArrayList<String>();
+ txList.add(newTransId);
+ headersList.put("X-TransactionId", txList);
+ if (missingTransId) {
+ logMsg = "Missing requestID. Assigned " + newTransId;
+ } else if (replacedTransId) {
+ logMsg = "Replaced invalid requestID of " + transId + " Assigned " + newTransId;
+ }
+ }
+
+
+ List<String> fa = headersList.get("X-FromAppId");
+ if (fa != null) {
+ for (String fromAppIdValue : fa) {
+ fromAppId = fromAppIdValue;
+ }
+ }
+
+ List<String> contentType = headersList.get("Content-Type");
+ if (contentType == null) {
+ ct = (String)message.get(Message.CONTENT_TYPE);
+ headersList.put(Message.CONTENT_TYPE, Collections.singletonList(ct));
+ }
+ logline.init(COMPONENT, newTransId, fromAppId, "interceptIn");
+ auditLogline.init(COMPONENT, newTransId, fromAppId, "REST " + httpMethod + " "
+ + ((query != null)? uri+"?"+query : uri));
+ if (logMsg != null) {
+ logline.add(logMsg, true);
+ }
+ logline.add("HbaseTxId", fullId);
+ aaiLogger.info(logline, true, "0");
+ }
+
+
+ if (uri != null) {
+ buffer.getAddress().append(uri);
+ if (query != null) {
+ buffer.getAddress().append("?").append(query);
+ }
+ }
+
+ InputStream is = message.getContent(InputStream.class);
+ if (is != null) {
+ try {
+ String currentPayload = IOUtils.toString(is, "UTF-8");
+ IOUtils.closeQuietly(is);
+ buffer.getPayload().append(currentPayload);
+ is = IOUtils.toInputStream(currentPayload, "UTF-8");
+ message.setContent(InputStream.class, is);
+ IOUtils.closeQuietly(is);
+ } catch (Exception e) {
+ // It's ok to not have request input content
+ // throw new Fault(e);
+ }
+ }
+
+ // this will be saved in the message exchange, and can be pulled out later...
+ message.getExchange().put(fullId + "_REQUEST", buffer.toString());
+ message.getExchange().put("AUDIT_LOGLINE", auditLogline);
+
+ }
+
+ /**
+ * Gen date.
+ *
+ * @param aaiLogger the aai logger
+ * @param logline the logline
+ * @return the string
+ */
+ protected String genDate(AAILogger aaiLogger, LogLine logline) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (AAIException ex) {
+ logline.add("Property", AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT);
+ aaiLogger.error(ex.getErrorObject(), logline);
+ } finally {
+ if (formatter == null) {
+ formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ }
+ }
+
+ return formatter.format(date);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java b/ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java
new file mode 100644
index 0000000..b2afc37
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java
@@ -0,0 +1,647 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.interceptors;
+
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.JMSException;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.LoggingMessage;
+import org.apache.cxf.io.CacheAndWriteOutputStream;
+import org.apache.cxf.io.CachedOutputStream;
+import org.apache.cxf.io.CachedOutputStreamCallback;
+import org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor;
+import org.apache.cxf.message.Message;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HConnection;
+import org.apache.hadoop.hbase.client.HConnectionManager;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.util.Bytes;
+//import org.apache.log4j.MDC;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dmaap.AAIDmaapEventJMSProducer;
+import org.openecomp.aai.domain.notificationEvent.NotificationEvent;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.PojoUtils;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+
+// right after the request is complete, there may be content
+public class AAILogJAXRSOutInterceptor extends JAXRSOutInterceptor {
+
+ protected final String COMPONENT = "aairest";
+ protected final String CAMEL_REQUEST = "CamelHttpUrl";
+
+ private HConnection hConnection = null;
+ private org.apache.hadoop.conf.Configuration config = null;
+
+ @Autowired
+ private ApplicationContext appContext;
+ private AAIDmaapEventJMSProducer springJmsProducer;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleMessage(Message message) {
+
+ AAILogger aaiLogger = new AAILogger(AAILogJAXRSOutInterceptor.class.getName());
+ LogLine logline = new LogLine();
+
+ String fullId = (String) message.getExchange().get(LoggingMessage.ID_KEY);
+
+ Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>) message.get(Message.PROTOCOL_HEADERS));
+ if (headers == null) {
+ headers = new HashMap<String, List<String>>();
+ }
+
+ headers.put("X-AAI-TXID", Collections.singletonList(fullId));
+ message.put(Message.PROTOCOL_HEADERS, headers);
+
+ Message outMessage = message.getExchange().getOutMessage();
+ final OutputStream os = outMessage.getContent(OutputStream.class);
+ if (os == null) {
+ return;
+ }
+
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED") && hConnection == null) {
+ try {
+ config = HBaseConfiguration.create();
+
+ if (config == null) {
+ aaiLogger.debug(logline, "AAITxnLog: Default Constructor: can't create HBase configuration");
+ return;
+ }
+
+ config.set(AAIConstants.ZOOKEEPER_ZNODE_PARENT,
+ AAIConfig.get(AAIConstants.HBASE_ZOOKEEPER_ZNODE_PARENT));
+ config.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM,
+ AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM));
+ config.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT,
+ AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT));
+
+ hConnection = HConnectionManager.createConnection(config);
+ } catch (Exception e) {
+ aaiLogger.debug(logline, "Cannot establish connection to hbase", e);
+ return;
+ }
+ }
+
+// if (this.springJmsProducer == null) {
+// this.springJmsProducer = (AAIDmaapEventJMSProducer) this.appContext.getBean("messageProducer");
+// }
+ // we only want to register the callback if there is good reason for it.
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")
+ || message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+
+ // FINEGRAINaaiLogger.debug(logline, "Registering callback for
+ // logging");
+
+ final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os);
+ message.setContent(OutputStream.class, newOut);
+ newOut.registerCallback(new LoggingCallback(message, os));
+ }
+
+ }
+
+ class LoggingCallback implements CachedOutputStreamCallback {
+
+ private final Message message;
+ private final OutputStream origStream;
+
+ public LoggingCallback(final Message msg, final OutputStream os) {
+ this.message = msg;
+ this.origStream = os;
+ }
+
+ public void onFlush(CachedOutputStream cos) {
+
+ }
+
+ public void onClose(CachedOutputStream cos) {
+ // LoggingMessage buffer = setupBuffer(message);
+ //
+ // String formattedMessage = formatLoggingMessage(buffer);
+ AAILogger aaiLogger = new AAILogger(AAILogJAXRSOutInterceptor.class.getName());
+ AAILogger auditLogger = new AAILogger("org.openecomp.aai.AUDITLOGGER");
+ LogLine logline = new LogLine();
+
+ if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")
+ && !message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+ // FINEGRAINaaiLogger.debug(logline, "Skipping the callback
+ // interceptor, logging disabled");
+ return;
+ }
+
+ // this function gets all the stuff that's closest to the wire and
+ // actually
+ // logs to hbase
+
+ String fullId = (String) message.getExchange().get(LoggingMessage.ID_KEY);
+
+ Message inMessage = message.getExchange().getInMessage();
+ String transId = null;
+ String fromAppId = null;
+
+ Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS));
+ if (headersList != null) {
+ List<String> xt = headersList.get("X-TransactionId");
+ if (xt != null) {
+ for (String transIdValue : xt) {
+ transId = transIdValue;
+ }
+ }
+ List<String> fa = headersList.get("X-FromAppId");
+ if (fa != null) {
+ for (String fromAppIdValue : fa) {
+ fromAppId = fromAppIdValue;
+ }
+ }
+ }
+
+ logline.init(COMPONENT, transId, fromAppId, "interceptOut");
+ // FINEGRAINaaiLogger.debug(logline, "Logging callback hbase
+ // transactionId: " + fullId);
+ String httpMethod = (String) inMessage.get(Message.HTTP_REQUEST_METHOD);
+
+ String uri = (String) inMessage.get(CAMEL_REQUEST);
+ String fullUri = uri;
+ if (uri != null) {
+ String query = (String) message.get(Message.QUERY_STRING);
+ if (query != null) {
+ fullUri = uri + "?" + query;
+ }
+ }
+
+ String request = (String) message.getExchange().get(fullId + "_REQUEST");
+
+ Message outMessage = message.getExchange().getOutMessage();
+
+ final LoggingMessage buffer = new LoggingMessage("OUTMessage", fullId);
+
+ // should we check this, and make sure it's not an error?
+ Integer responseCode = (Integer) outMessage.get(Message.RESPONSE_CODE);
+ if (responseCode == null) {
+ responseCode = 200; // this should never happen, but just in
+ // case we don't get one
+ }
+ buffer.getResponseCode().append(responseCode);
+
+ String encoding = (String) outMessage.get(Message.ENCODING);
+
+ if (encoding != null) {
+ buffer.getEncoding().append(encoding);
+ }
+
+ String ct = (String) outMessage.get(Message.CONTENT_TYPE);
+ if (ct != null) {
+ buffer.getContentType().append(ct);
+ }
+
+ Object headers = outMessage.get(Message.PROTOCOL_HEADERS);
+ if (headers != null) {
+ buffer.getHeader().append(headers);
+ }
+
+ Boolean ss = false;
+ if (responseCode >= 200 && responseCode <= 299) {
+ ss = true;
+ }
+ String response = buffer.toString();
+
+ // this should have been set by the in interceptor
+ String rqstTm = (String) message.getExchange().get("AAI_RQST_TM");
+
+ // just in case it wasn't, we'll put this here. not great, but it'll
+ // have a val.
+ if (rqstTm == null) {
+ rqstTm = genDate(aaiLogger, logline);
+ }
+
+ String respTm = genDate(aaiLogger, logline);
+
+ // TODO: make sure these aren't null, maybe make that primitive Int
+ // an object type
+ // TODO: pretty print json. maybe i should tak
+ // final String fromAppId =
+ // (String)message.getExchange().get("LOG_TX_fromAppId");
+ // final String httpMethod =
+ // (String)message.getExchange().get("LOG_TX_httpMethod");
+ // final String transId =
+ // (String)message.getExchange().get("LOG_TX_transId");
+ // final String fullUri =
+ // (String)message.getExchange().get("LOG_TX_fullUri");
+ // final String rqstTm =
+ // (String)message.getExchange().get("LOG_TX_rqstTm");
+ // final String respTm =
+ // (String)message.getExchange().get("LOG_TX_respTm");
+ // final String request =
+ // (String)message.getExchange().get("LOG_TX_request");
+ // final int responseCode =
+ // (int)message.getExchange().get("LOG_TX_responseCode");
+ // final String response =
+ // (String)message.getExchange().get("LOG_TX_response");
+ // final String fullId =
+ // (String)message.getExchange().get("LOG_TX_fullId");
+
+ try {
+ String actualRequest = request;
+ StringBuilder builder = new StringBuilder();
+ cos.writeCacheTo(builder, 100000);
+ // here comes my xml:
+ String payload = builder.toString();
+
+ String actualResponse = response;
+ if (payload == null) {
+ // FINEGRAINaaiLogger.debug(logline,
+ // "AAILogJAXRSOutInterceptor: no payload");
+ } else {
+ actualResponse = response + payload;
+ }
+
+ // we only log to AAI log if it's eanbled in the config props
+ // file
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+
+ // FINEGRAINaaiLogger.debug(logline, "Trace is on, going to
+ // log to aai log");
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGREQUEST")) {
+
+ // strip newlines from request
+ String traceRequest = actualRequest;
+ traceRequest = traceRequest.replace("\n", " ");
+ traceRequest = traceRequest.replace("\r", "");
+ traceRequest = traceRequest.replace("\t", "");
+ aaiLogger.debug(logline, traceRequest);
+ }
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
+ // strip newlines from response
+ String traceResponse = actualResponse;
+ traceResponse = traceResponse.replace("\n", " ");
+ traceResponse = traceResponse.replace("\r", "");
+ traceResponse = traceResponse.replace("\t", "");
+
+ aaiLogger.debug(logline, traceResponse);
+ }
+ }
+
+ // we only log to HBASE if it's enabled in the config props file
+ // TODO: pretty print XML/JSON. we might need to get the payload
+ // and envelope seperately
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
+ if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGREQUEST")) {
+ actualRequest = "loggingDisabled";
+ }
+ if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
+ actualResponse = "loggingDisabled";
+ }
+
+ // only log notification event on success
+ NotificationEvent ne = new NotificationEvent();
+ boolean hasNotificationEvent = false;
+ boolean notificationEventIsDynamic = false;
+ DynamicJAXBContext notificationJaxbContext = null;
+ DynamicEntity notificationEventEntity = null;
+
+ if (responseCode >= 200 && responseCode <= 299) {
+ if (message.getExchange().containsKey("NOTIFICATION_EVENT")) {
+ hasNotificationEvent = true;
+
+ if (message.getExchange().containsKey("NOTIFICATION_EVENT_TYPE")) {
+ String notificationEventType = (String) message.getExchange()
+ .get("NOTIFICATION_EVENT_TYPE");
+ if (notificationEventType.equals("dynamic")) {
+ notificationJaxbContext = (DynamicJAXBContext) message.getExchange()
+ .get("NOTIFICATION_JAXB_CONTEXT");
+ notificationEventIsDynamic = true;
+ notificationEventEntity = (DynamicEntity) message.getExchange()
+ .get("NOTIFICATION_EVENT");
+ }
+ } else {
+ ne = (NotificationEvent) message.getExchange().get("NOTIFICATION_EVENT");
+ }
+ }
+ }
+
+ logline.add("action", httpMethod);
+ logline.add("urlin", fullUri);
+ logline.add("HbTransId", fullId);
+
+ if (notificationEventIsDynamic) {
+ logTransaction(fromAppId, transId, fullId, httpMethod, fullUri, rqstTm, respTm, actualRequest,
+ actualResponse, responseCode, hasNotificationEvent, notificationEventEntity,
+ notificationJaxbContext);
+ } else {
+ logTransaction(fromAppId, transId, fullId, httpMethod, fullUri, rqstTm, respTm, actualRequest,
+ actualResponse, responseCode, hasNotificationEvent, ne);
+ }
+ }
+ } catch (Exception ex) {
+ // ignore
+ }
+
+ message.setContent(OutputStream.class, origStream);
+ aaiLogger.info(logline, true, "0");
+
+ if (message.getExchange().containsKey("AUDIT_LOGLINE")) {
+ LogLine auditLogline = (LogLine) message.getExchange().get("AUDIT_LOGLINE");
+ if (MDC.get("ERROR_CODE") != null)
+ auditLogline.setEc(MDC.get("ERROR_CODE"));
+ if (MDC.get("ERROR_TEXT") != null)
+ auditLogline.setEt(MDC.get("ERROR_TEXT"));
+ auditLogline.add("HTTP Response Code", responseCode.toString());
+ auditLogline.finish(ss);
+ auditLogger.audit(auditLogline);
+ }
+ }
+ }
+
+ protected String genDate(AAILogger aaiLogger, LogLine logline) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (AAIException ex) {
+ logline.add("Property", AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT);
+ aaiLogger.error(ex.getErrorObject(), logline);
+ } finally {
+ if (formatter == null) {
+ formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ }
+ }
+ return formatter.format(date);
+ }
+
+ /**
+ * Log transaction.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param tId the t id
+ * @param action the action
+ * @param input the input
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param request the request
+ * @param response the response
+ * @param status the status
+ * @param hasNotificationEvent the has notification event
+ * @param ne the ne
+ */
+ /* ---------------- Log Transaction into HBase (for Apache CXF Interceptors) --------------------- */
+ public void logTransaction(String fromAppId, String transId, String tId, String action, String input, String rqstTm,
+ String respTm, String request, String response, int status, boolean hasNotificationEvent,
+ NotificationEvent ne) throws JMSException {
+ String hbtid = putTransaction(tId, String.valueOf(status), rqstTm, respTm, fromAppId + ":" + transId, input,
+ action, request, response, hasNotificationEvent, ne);
+ }
+
+ /**
+ * Log transaction.
+ *
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @param tId the t id
+ * @param action the action
+ * @param input the input
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param request the request
+ * @param response the response
+ * @param status the status
+ * @param hasNotificationEvent the has notification event
+ * @param ne the ne
+ * @param notificationJaxbContext the notification jaxb context
+ */
+ /* ---------------- Log Transaction into HBase (for Apache CXF Interceptors) --------------------- */
+ public void logTransaction(String fromAppId, String transId, String tId, String action, String input, String rqstTm,
+ String respTm, String request, String response, int status, boolean hasNotificationEvent, DynamicEntity ne,
+ DynamicJAXBContext notificationJaxbContext) throws JMSException {
+ String hbtid = putTransaction(tId, String.valueOf(status), rqstTm, respTm, fromAppId + ":" + transId, input,
+ action, request, response, hasNotificationEvent, ne, notificationJaxbContext);
+ }
+
+ /**
+ * Put transaction.
+ *
+ * @param tid the tid
+ * @param status the status
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param srcId the src id
+ * @param rsrcId the rsrc id
+ * @param rsrcType the rsrc type
+ * @param rqstBuf the rqst buf
+ * @param respBuf the resp buf
+ * @param hasNotificationEvent the has notification event
+ * @param ne the ne
+ * @return the string
+ */
+ public String putTransaction(String tid, String status, String rqstTm, String respTm, String srcId, String rsrcId,
+ String rsrcType, String rqstBuf, String respBuf, boolean hasNotificationEvent, NotificationEvent ne) {
+ AAILogger aaiLogger = new AAILogger(AAILogJAXRSOutInterceptor.class.getName());
+ LogLine logline = new LogLine();
+ String tm = null;
+ String fromAppId = srcId.substring(0, srcId.indexOf(':'));
+ String transId = srcId.substring(srcId.indexOf(':') + 1);
+
+ logline.init(COMPONENT, transId, fromAppId, "putTransaction");
+ // FINEGRAINaaiLogger.debug(logline, "In put: storing hbase config
+ // file...");
+ Exception ex = null;
+
+ if (tid == null || "".equals(tid)) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (Exception e) {
+ formatter = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS");
+ }
+ tm = formatter.format(date);
+ tid = tm + "-";
+ }
+ // String htid = tid + rsrcType; // orig
+ // String htid = tid + srcId; //final version?
+ String htid = tid;// + srcId + "_" + rsrcType; // use this one for now
+ // FINEGRAINaaiLogger.debug(logline, "In put...: htid="+htid);
+ // FINEGRAINaaiLogger.debug(logline, "tid: " + tid + ", srcId: " + srcId
+ // + " rsrcType: " + rsrcType);
+
+ if (rqstTm == null || "".equals(rqstTm)) {
+ rqstTm = tm;
+ }
+
+ if (respTm == null || "".equals(respTm)) {
+ respTm = tm;
+ }
+
+ try {
+ HTableInterface table = hConnection.getTable(AAIConfig.get(AAIConstants.HBASE_TABLE_NAME));
+
+ Put p = new Put(Bytes.toBytes(htid));
+
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("tid"), Bytes.toBytes(tid));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("status"), Bytes.toBytes(status));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("rqstDate"), Bytes.toBytes(rqstTm));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("respDate"), Bytes.toBytes(respTm));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("sourceId"), Bytes.toBytes(srcId));
+
+ p.add(Bytes.toBytes("resource"), Bytes.toBytes("resourceId"), Bytes.toBytes(rsrcId));
+ p.add(Bytes.toBytes("resource"), Bytes.toBytes("resourceType"), Bytes.toBytes(rsrcType));
+
+ p.add(Bytes.toBytes("payload"), Bytes.toBytes("rqstBuf"), Bytes.toBytes(rqstBuf));
+ p.add(Bytes.toBytes("payload"), Bytes.toBytes("respBuf"), Bytes.toBytes(respBuf));
+
+ /*
+ * Once you've adorned your Put instance with all the updates you
+ * want to make, to commit it do the following
+ */
+ table.put(p);
+ table.flushCommits();
+ table.close();
+
+ return htid;
+ } catch (Exception e) {
+ aaiLogger.debug(logline, "AAITxnLog: put: Exception=", e);
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_4000", "Exception updating HBase:"), logline, e);
+ return htid;
+ } finally {
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else
+ aaiLogger.info(logline, false, "AAI_4000");
+ }
+ }
+
+ /**
+ * Put transaction.
+ *
+ * @param tid the tid
+ * @param status the status
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param srcId the src id
+ * @param rsrcId the rsrc id
+ * @param rsrcType the rsrc type
+ * @param rqstBuf the rqst buf
+ * @param respBuf the resp buf
+ * @param hasNotificationEvent the has notification event
+ * @param ne the ne
+ * @param notificationJaxbContext the notification jaxb context
+ * @return the string
+ */
+ public String putTransaction(String tid, String status, String rqstTm, String respTm, String srcId, String rsrcId,
+ String rsrcType, String rqstBuf, String respBuf, boolean hasNotificationEvent, DynamicEntity ne,
+ DynamicJAXBContext notificationJaxbContext) {
+ AAILogger aaiLogger = new AAILogger("AAILogJAXRSOutInterceptor");
+ LogLine logline = new LogLine();
+ String tm = null;
+ String fromAppId = srcId.substring(0, srcId.indexOf(':'));
+ String transId = srcId.substring(srcId.indexOf(':') + 1);
+
+ logline.init(COMPONENT, transId, fromAppId, "putTransaction");
+ Exception ex = null;
+
+ // FINEGRAINaaiLogger.debug(logline, "In put: storing hbase config
+ // file...");
+
+ if (tid == null || "".equals(tid)) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (Exception e) {
+ formatter = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS");
+ }
+ tm = formatter.format(date);
+ tid = tm + "-";
+ }
+ // String htid = tid + rsrcType; // orig
+ // String htid = tid + srcId; //final version?
+ String htid = tid;// + srcId + "_" + rsrcType; // use this one for now
+ // FINEGRAINaaiLogger.debug(logline, "In put...: htid="+htid);
+ // FINEGRAINaaiLogger.debug(logline, "tid: " + tid + ", srcId: " + srcId
+ // + " rsrcType: " + rsrcType);
+
+ if (rqstTm == null || "".equals(rqstTm)) {
+ rqstTm = tm;
+ }
+
+ if (respTm == null || "".equals(respTm)) {
+ respTm = tm;
+ }
+
+ try {
+ HTableInterface table = hConnection.getTable(AAIConfig.get(AAIConstants.HBASE_TABLE_NAME));
+
+ Put p = new Put(Bytes.toBytes(htid));
+
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("tid"), Bytes.toBytes(tid));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("status"), Bytes.toBytes(status));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("rqstDate"), Bytes.toBytes(rqstTm));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("respDate"), Bytes.toBytes(respTm));
+ p.add(Bytes.toBytes("transaction"), Bytes.toBytes("sourceId"), Bytes.toBytes(srcId));
+
+ p.add(Bytes.toBytes("resource"), Bytes.toBytes("resourceId"), Bytes.toBytes(rsrcId));
+ p.add(Bytes.toBytes("resource"), Bytes.toBytes("resourceType"), Bytes.toBytes(rsrcType));
+
+ p.add(Bytes.toBytes("payload"), Bytes.toBytes("rqstBuf"), Bytes.toBytes(rqstBuf));
+ p.add(Bytes.toBytes("payload"), Bytes.toBytes("respBuf"), Bytes.toBytes(respBuf));
+
+ /*
+ * Once you've adorned your Put instance with all the updates you
+ * want to make, to commit it do the following
+ */
+ table.put(p);
+ table.flushCommits();
+ table.close();
+
+ return htid;
+ } catch (Exception e) {
+ ex = e;
+ aaiLogger.debug(logline, "AAITxnLog: put: Exception=", e);
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_4000", "Exception updating HBase:"), logline, e);
+ return htid;
+ } finally {
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else
+ aaiLogger.info(logline, false, "AAI_4000");
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Introspector.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Introspector.java
new file mode 100644
index 0000000..6042ee8
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Introspector.java
@@ -0,0 +1,459 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.persistence.exceptions.DynamicException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.MediaType;
+import org.openecomp.aai.workarounds.NamingExceptions;
+
+import com.google.common.base.CaseFormat;
+
+public abstract class Introspector implements Cloneable {
+
+ protected String className;
+ protected AAILogger aaiLogger;
+ protected String uriChain = "";
+ protected final LogLineBuilder llBuilder;
+ protected Loader loader;
+ protected final NamingExceptions namingException = NamingExceptions.getInstance();
+
+ protected Introspector(Object obj, LogLineBuilder llBuilder) {
+ this.llBuilder = llBuilder;
+ }
+ public abstract boolean hasProperty(String name);
+
+ protected String convertPropertyName (String name) {
+ return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, name);
+ }
+
+ protected abstract Object get(String name);
+ protected abstract void set(String name, Object value);
+ /**
+ *
+ * @param name the property name you'd like to retrieve the value for
+ * @return the value of the property
+ */
+ public Object getValue(String name) {
+ String convertedName = convertPropertyName(name);
+ Object result = null;
+
+ if (this.hasProperty(name)) {
+ result = this.get(convertedName);
+ } else {
+ /* property not found - slightly ambiguous */
+ return null;
+ }
+
+ Class<?> clazz = this.getClass(name);
+ if (this.isListType(name) && result == null) {
+ try {
+ this.set(convertedName, clazz.newInstance());
+ result = this.get(convertedName);
+ } catch (DynamicException | InstantiationException | IllegalAccessException e) {
+
+ }
+ }
+
+ return result;
+ }
+ /**
+ *
+ * @param name the property name you'd like to set the value of
+ * @param obj the value to be set
+ * @return
+ */
+ public void setValue(String name, Object obj) throws IllegalArgumentException {
+ Object box = obj;
+ Class<?> nameClass = this.getClass(name);
+ if (nameClass == null) {
+ throw new IllegalArgumentException("property: " + name + " does not exist on " + this.getDbName());
+ }
+ if (obj != null) {
+
+ try {
+ if (!obj.getClass().getName().equals(nameClass.getName())) {
+ if (obj.getClass().getName().equals("java.lang.String")) {
+ box = nameClass.getConstructor(String.class).newInstance(obj);
+ } else if (!this.isListType(name)){
+ box = obj.toString();
+ }
+ }
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+ AAIException ex = new AAIException("AAI_4017", e);
+ LogLine line = llBuilder.build(className, "set value");
+ line.add(name, obj.toString());
+ aaiLogger.error(ex.getErrorObject(), line, e);
+
+ }
+ }
+
+
+ name = convertPropertyName(name);
+ this.set(name, box);
+ }
+ /**
+ *
+ * @return a list of all the properties available on the object
+ */
+ public abstract List<String> getProperties();
+ /**
+ *
+ * @return a list of the required properties on the object
+ */
+ public abstract List<String> getRequiredProperties();
+ /**
+ *
+ * @return a list of the properties that can be used to query the object in the db
+ */
+ public abstract List<String> getKeys();
+ /**
+ *
+ * @return a list of the all key properties for this object
+ */
+ public List<String> getAllKeys() {
+ List<String> keys = this.getKeys();
+ String altKeys = this.getMetadata("alternateKeys1");
+ if (altKeys != null) {
+ String[] altKeysArray = altKeys.split(",");
+ for (String altKey : altKeysArray) {
+ keys.add(altKey);
+ }
+ }
+
+ return keys;
+ }
+
+ public List<String> getIndexedProperties() {
+ List<String> keys = this.getKeys();
+ String altKeys = this.getMetadata("indexedProps");
+ if (altKeys != null) {
+ String[] altKeysArray = altKeys.split(",");
+ for (String altKey : altKeysArray) {
+ keys.add(altKey);
+ }
+ }
+
+ return keys;
+ }
+ /**
+ *
+ * @param name
+ * @return the string name of the java class of the named property
+ */
+ public String getType(String name) {
+ Class<?> resultClass = this.getClass(name);
+ String result = "";
+
+ if (resultClass != null) {
+ result = resultClass.getName();
+ if (result.equals("java.util.ArrayList")) {
+ result = "java.util.List";
+ }
+ }
+
+ return result;
+ }
+ /**
+ * This will returned the generic parameterized type of the underlying
+ * object if it exists
+ * @param name
+ * @return the generic type of the java class of the underlying object
+ */
+ public String getGenericType(String name) {
+ Class<?> resultClass = this.getGenericTypeClass(name);
+ String result = "";
+
+ if (resultClass != null) {
+ result = resultClass.getName();
+ }
+
+ return result;
+ }
+ /**
+ *
+ * @return the string name of the java class of the underlying object
+ */
+ public abstract String getJavaClassName();
+
+ /**
+ *
+ * @param name the property name
+ * @return the Class object
+ */
+ public abstract Class<?> getClass(String name);
+
+ public abstract Class<?> getGenericTypeClass(String name);
+
+ /**
+ *
+ * @param name the property name
+ * @return a new instance of the underlying type of this property
+ */
+ public Object newInstanceOfProperty(String name) {
+ String type = this.getType(name);
+ return loader.objectFromName(type);
+ }
+
+ public Object newInstanceOfNestedProperty(String name) {
+ String type = this.getGenericType(name);
+ return loader.objectFromName(type);
+ }
+
+
+ public Introspector newIntrospectorInstanceOfProperty(String name) {
+
+ Introspector result = IntrospectorFactory.newInstance(this.getModelType(), this.newInstanceOfProperty(name), llBuilder);
+
+ return result;
+
+ }
+
+ public Introspector newIntrospectorInstanceOfNestedProperty(String name) {
+
+ Introspector result = IntrospectorFactory.newInstance(this.getModelType(), this.newInstanceOfNestedProperty(name), llBuilder);
+
+ return result;
+
+ }
+ /**
+ * Is this type not a Java String or primitive
+ * @param name
+ * @return
+ */
+ public boolean isComplexType(String name) {
+ String result = this.getType(name);
+
+ if (result.contains("aai")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isComplexGenericType(String name) {
+ String result = this.getGenericType(name);
+
+ if (result.contains("aai")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isSimpleType(String name) {
+ return !(this.isComplexType(name) || this.isListType(name));
+ }
+
+ public boolean isSimpleGenericType(String name) {
+ return !this.isComplexGenericType(name);
+ }
+
+ public boolean isListType(String name) {
+ String result = this.getType(name);
+
+ if (result.contains("java.util.List")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isContainer() {
+ List<String> props = this.getProperties();
+ boolean result = false;
+ if (props.size() == 1 && this.isListType(props.get(0))) {
+ result = true;
+ }
+
+ return result;
+ }
+
+ public abstract String getChildName();
+ public String getChildDBName() {
+ String result = this.getChildName();
+
+ result = namingException.getDBName(result);
+ return result;
+ }
+ public abstract String getName();
+
+ public String getDbName() {
+ String lowerHyphen = this.getName();
+
+ lowerHyphen = namingException.getDBName(lowerHyphen);
+
+ return lowerHyphen;
+ }
+
+ public abstract ModelType getModelType();
+
+ public boolean hasChild(Introspector child) {
+ boolean result = false;
+ //check all inheriting types for this child
+ if ("true".equals(this.getMetadata("abstract"))) {
+ String[] inheritors = this.getMetadata("inheritors").split(",");
+ for (String inheritor : inheritors) {
+ Introspector temp = this.loader.introspectorFromName(inheritor);
+ result = temp.hasProperty(child.getName());
+ if (result) {
+ break;
+ }
+ }
+ } else {
+ result = this.hasProperty(child.getName());
+ }
+ return result;
+ }
+
+ public void setURIChain(String uri) {
+ this.uriChain = uri;
+ }
+ public abstract String getObjectId() throws UnsupportedEncodingException;
+
+ public String getURI() throws UnsupportedEncodingException {
+ //String result = this.uriChain;
+ String result = "";
+ String namespace = this.getMetadata("namespace");
+ String container = this.getMetadata("container");
+ if (this.isContainer()) {
+ result += "/" + this.getName();
+ } else {
+
+ if (container != null) {
+ result += "/" + container;
+ }
+ result += "/" + this.getDbName() + "/" + this.findKey();
+
+ if (namespace != null && !namespace.equals("")) {
+ result = "/" + namespace + result;
+ }
+ }
+
+
+ return result;
+ }
+
+ public String getGenericURI() {
+ String result = "";
+ if (this.isContainer()) {
+ result += "/" + this.getName();
+ } else {
+ result += "/" + this.getDbName();
+ for (String key : this.getKeys()) {
+ result += "/{" + this.getDbName() + "-" + key + "}";
+ }
+ }
+
+ return result;
+ }
+
+ public String getFullGenericURI() {
+ String result = "";
+ String namespace = this.getMetadata("namespace");
+ String container = this.getMetadata("container");
+ if (this.isContainer()) {
+ result += "/" + this.getName();
+ } else {
+
+
+ if (container != null) {
+ result += "/" + container;
+ }
+ result += "/" + this.getDbName();
+
+ for (String key : this.getKeys()) {
+ result += "/{" + this.getDbName() + "-" + key + "}";
+ }
+ if (namespace != null && !namespace.equals("")) {
+ result = "/" + namespace + result;
+ }
+
+ }
+
+ return result;
+ }
+
+ public abstract String preProcessKey(String key);
+
+ protected abstract String findKey() throws UnsupportedEncodingException;
+
+ public abstract String marshal(MarshallerProperties properties);
+
+ public abstract Object clone();
+
+ public abstract Object getUnderlyingObject();
+
+ public String marshal(boolean formatted) {
+ MarshallerProperties properties =
+ new MarshallerProperties.Builder(MediaType.APPLICATION_JSON_TYPE).formatted(formatted).build();
+
+ return marshal(properties);
+ }
+ public String makeSingular(String word) {
+
+ String result = word;
+ result = result.replaceAll("(?:([ho])es|s)$", "");
+
+ if (result.equals("ClassesOfService")) {
+ result = "ClassOfService";
+ } else if (result.equals("CvlanTag")) {
+ result = "CvlanTagEntry";
+ } else if (result.equals("Metadata")) {
+ result = "Metadatum";
+ }
+ return result;
+ }
+
+ protected String makePlural(String word) {
+ String result = word;
+
+ if (result.equals("cvlan-tag-entry")) {
+ return "cvlan-tags";
+ } else if (result.equals("class-of-service")) {
+ return "classes-of-service";
+ } else if (result.equals("metadatum")) {
+ return "metadata";
+ }
+ result = result.replaceAll("([a-z])$", "$1s");
+ result = result.replaceAll("([hox])s$", "$1es");
+ /*
+ if (result.equals("classes-of-services")) {
+ result = "classes-of-service";
+ }*/
+
+ return result;
+ }
+
+ public abstract String getMetadata(String metadataName);
+ public abstract Map<String, String> getPropertyMetadata(String prop);
+
+ public abstract Version getVersion();
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorFactory.java
new file mode 100644
index 0000000..cdf9269
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorFactory.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import org.openecomp.aai.logging.LogLineBuilder;
+
+public class IntrospectorFactory {
+
+ /**
+ * New instance.
+ *
+ * @param type the type
+ * @param o the o
+ * @param llBuilder the ll builder
+ * @return the introspector
+ */
+ public static Introspector newInstance(ModelType type, Object o, LogLineBuilder llBuilder) {
+
+ if (type.equals(ModelType.MOXY)) {
+ return new MoxyStrategy(o, llBuilder);
+ } else if (type.equals(ModelType.POJO)) {
+ return new PojoStrategy(o, llBuilder);
+ } else if (type.equals(ModelType.JSON)) {
+ return new JSONStrategy(o, llBuilder);
+ } else {
+ throw new IllegalArgumentException("Unknown class type: " + type);
+ }
+
+ }
+
+ /**
+ * New instance.
+ *
+ * @param type the type
+ * @param o the o
+ * @param namedType the named type
+ * @param llBuilder the ll builder
+ * @return the introspector
+ */
+ public static Introspector newInstance(ModelType type, Object o, String namedType, LogLineBuilder llBuilder) {
+
+ if (type.equals(ModelType.JSON)) {
+ return new JSONStrategy(o, namedType, llBuilder);
+ } else {
+ throw new IllegalArgumentException("Unknown class type: " + type);
+ }
+
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorWalker.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorWalker.java
new file mode 100644
index 0000000..6dd06ea
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorWalker.java
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.openecomp.aai.logging.LogLineBuilder;
+
+public class IntrospectorWalker {
+
+ private Introspector obj;
+ private Wanderer w = null;
+ private Set<String> blacklist = null;
+ private boolean preventCycles = false;
+ private final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new introspector walker.
+ *
+ * @param w the w
+ * @param llBuilder the ll builder
+ */
+ public IntrospectorWalker(Wanderer w, LogLineBuilder llBuilder) {
+ this.llBuilder = llBuilder;
+ this.w = w;
+ this.blacklist = new HashSet<>();
+ }
+
+ /**
+ * Sets the blacklist.
+ *
+ * @param list the new blacklist
+ */
+ public void setBlacklist(List<String> list) {
+ blacklist.addAll(list);
+ }
+
+ /**
+ * Prevent cycles.
+ *
+ * @param prevent the prevent
+ */
+ public void preventCycles(boolean prevent) {
+ this.preventCycles = prevent;
+ }
+
+ /**
+ * Walk.
+ *
+ * @param obj the obj
+ */
+ public void walk(Introspector obj) {
+ walk(obj, null);
+ }
+
+ /**
+ * Walk.
+ *
+ * @param obj the obj
+ * @param parent the parent
+ */
+ private void walk(Introspector obj, Introspector parent) {
+ if (preventCycles) {
+ blacklist.add(obj.getName()); //so we don't recurse while walking its children
+ }
+ List<String> props = obj.getProperties();
+ w.processComplexObj(obj);
+ props.removeAll(blacklist);
+ if (!obj.isContainer()) {
+ parent = obj;
+ }
+ for (String prop : props) {
+
+ if (obj.isSimpleType(prop)) {
+
+ w.processPrimitive(prop, obj);
+ } else if (obj.isListType(prop)) {
+
+ List list = (List)obj.getValue(prop);
+ boolean isComplexType = obj.isComplexGenericType(prop);
+ if (isComplexType) {
+ Introspector child = obj.newIntrospectorInstanceOfNestedProperty(prop);
+ w.modifyComplexList(list, parent, child);
+ for (Object item : list) {
+ child = IntrospectorFactory.newInstance(obj.getModelType(), item, llBuilder);
+ walk(child, parent);
+ }
+ } else {
+ w.processPrimitiveList(prop, obj);
+ }
+ if (list.size() == 0) {
+ if (isComplexType) {
+ Introspector child = obj.newIntrospectorInstanceOfNestedProperty(prop);
+ int size = w.createComplexListSize(parent, child);
+ for (int i = 0; i < size; i++) {
+ child = obj.newIntrospectorInstanceOfNestedProperty(prop);
+ walk(child, parent);
+ list.add(child.getUnderlyingObject());
+ }
+
+ obj.setValue(prop, list);
+ } else if (!isComplexType){
+ w.processPrimitiveList(prop, obj);
+ }
+ }
+
+ } else if (obj.isComplexType(prop)) {
+ Introspector child = null;
+ if (obj.getValue(prop) != null) {
+ child = IntrospectorFactory.newInstance(obj.getModelType(), obj.getValue(prop), llBuilder);
+ } else {
+ if (w.createComplexObjIfNull()) {
+ child = obj.newIntrospectorInstanceOfProperty(prop);
+ obj.setValue(prop, child.getUnderlyingObject());
+ }
+ }
+ if (child != null) {
+ walk(child, obj);
+ }
+ }
+
+ }
+ if (preventCycles) {
+ blacklist.remove(obj.getName()); //so we can see it down another path that isn't in danger of recursing over it
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/JSONStrategy.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/JSONStrategy.java
new file mode 100644
index 0000000..6cde063
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/JSONStrategy.java
@@ -0,0 +1,363 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.json.simple.JSONObject;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+public class JSONStrategy extends Introspector {
+
+ private JSONObject json = null;
+ private String namedType = "";
+ protected JSONStrategy(Object o, LogLineBuilder llBuilder) {
+ super(o, llBuilder);
+ json = (JSONObject)o;
+ //Assumes you provide a wrapper
+ Set<String> keySet = json.keySet();
+ if (keySet.size() == 1) {
+ namedType = keySet.iterator().next();
+ json = (JSONObject)json.get(namedType);
+ } else {
+ throw new IllegalArgumentException("This object has no named type.");
+ }
+
+
+ }
+
+ protected JSONStrategy(Object o, String namedType, LogLineBuilder llBuilder) {
+ super(o, llBuilder);
+ json = (JSONObject)o;
+ this.namedType = namedType;
+
+ }
+
+ @Override
+ public boolean hasProperty(String name) {
+ //TODO
+ return true;
+ }
+ @Override
+ public Object getValue(String name) {
+ Object result = "";
+ result = json.get(name);
+
+ return result;
+ }
+
+ @Override
+ public void setValue(String name, Object obj) {
+ json.put(name, obj);
+
+ }
+ @Override
+ public Object getUnderlyingObject() {
+ return this.json;
+ }
+
+ @Override
+ public List<String> getProperties() {
+ Set<String> set = json.keySet();
+ List<String> result = new ArrayList<>();
+ result.addAll(set);
+ return result;
+ }
+
+ @Override
+ public List<String> getRequiredProperties() {
+ //unknowable
+
+ return this.getProperties();
+ }
+
+ @Override
+ public List<String> getKeys() {
+ //unknowable
+ return this.getProperties();
+ }
+
+ @Override
+ public List<String> getAllKeys() {
+ //unknowable
+ return this.getProperties();
+ }
+
+ @Override
+ public String getType(String name) {
+ String result = "";
+ Class<?> resultClass = this.getClass(name);
+ if (resultClass != null) {
+ result = resultClass.getName();
+ }
+
+ if (result.equals("org.json.simple.JSONArray")) {
+ result = "java.util.List";
+ }
+
+ return result;
+ }
+
+ @Override
+ public String getGenericType(String name) {
+ String result = "";
+ Class<?> resultClass = this.getGenericTypeClass(name);
+ if (resultClass != null) {
+ result = resultClass.getName();
+ }
+ return result;
+ }
+
+ @Override
+ public String getJavaClassName() {
+ return json.getClass().getName();
+ }
+
+ @Override
+ public Class<?> getClass(String name) {
+ Class<?> result = null;
+ result = json.get(name).getClass();
+
+ return result;
+ }
+
+ @Override
+ public Class<?> getGenericTypeClass(String name) {
+ Object resultObject = null;
+ Class<?> resultClass = null;
+ resultObject = this.getValue(name);
+ if (resultObject.getClass().getName().equals("org.json.simple.JSONArray")) {
+ resultClass = ((List)resultObject).get(0).getClass();
+ }
+
+ return resultClass;
+ }
+
+ @Override
+ public Object newInstanceOfProperty(String name) {
+ try {
+ return this.getClass(name).newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public Object newInstanceOfNestedProperty(String name) {
+ try {
+ return this.getGenericTypeClass(name).newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isComplexType(String name) {
+ String result = this.getType(name);
+
+ if (result.contains("JSONObject")) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ @Override
+ public boolean isComplexGenericType(String name) {
+ String result = this.getGenericType(name);
+
+ if (result.contains("JSONObject")) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ @Override
+ public boolean isListType(String name) {
+ String result = this.getType(name);
+
+ if (result.contains("java.util.List")) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ @Override
+ public boolean isContainer() {
+ List<String> props = this.getProperties();
+ boolean result = false;
+ if (props.size() == 1 && this.isListType(props.get(0))) {
+ result = true;
+ }
+
+ return result;
+ }
+ @Override
+ protected String findKey() {
+ return "";
+ }
+
+ @Override
+ public String getName() {
+ return this.namedType;
+ }
+
+ @Override
+ public String getDbName() {
+ return this.getName();
+ }
+
+ @Override
+ public String getURI() {
+
+ // use a UUID for now
+ return UUID.randomUUID().toString();
+ }
+
+ @Override
+ public String getGenericURI() {
+
+ //there is none defined for this
+ return "";
+ }
+
+ @Override
+ public String preProcessKey (String key) {
+
+ // don't do anything with it
+ return key;
+
+ }
+
+ @Override
+ public String marshal(MarshallerProperties properties) {
+ //TODO
+ return null;
+ }
+
+ @Override
+ public Object clone() {
+ //TODO
+ return null;
+ }
+
+ /*@Override
+ public String findEdgeName(String parent, String child) {
+
+ // Always has for now
+ return "has";
+
+ }*/
+
+ @Override
+ public ModelType getModelType() {
+ return ModelType.JSON;
+ }
+
+ @Override
+ public List<String> getIndexedProperties() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getChildName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean hasChild(Introspector child) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isSimpleType(String name) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isSimpleGenericType(String name) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Map<String, String> getPropertyMetadata(String prop) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getMetadata(String metadataName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getChildDBName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getFullGenericURI() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Object get(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected void set(String name, Object value) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getObjectId() throws UnsupportedEncodingException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Version getVersion() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Loader.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Loader.java
new file mode 100644
index 0000000..6296aae
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Loader.java
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.MediaType;
+
+public abstract class Loader {
+
+ private final Version version;
+ private final ModelType modelType;
+ protected final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new loader.
+ *
+ * @param version the version
+ * @param modelType the model type
+ * @param llBuilder the ll builder
+ */
+ public Loader (Version version, ModelType modelType, LogLineBuilder llBuilder) {
+ this.version = version;
+ this.modelType = modelType;
+ this.llBuilder = llBuilder;
+ }
+
+ /**
+ * Process.
+ *
+ * @param version the version
+ */
+ protected abstract void process(Version version);
+
+ /**
+ * Object from name.
+ *
+ * @param name the name
+ * @return the object
+ */
+ public abstract Object objectFromName(String name);
+
+ /**
+ * Introspector from name.
+ *
+ * @param name the name
+ * @return the introspector
+ */
+ public abstract Introspector introspectorFromName(String name);
+
+ /**
+ * Unmarshal.
+ *
+ * @param type the type
+ * @param json the json
+ * @param mediaType the media type
+ * @return the introspector
+ */
+ public abstract Introspector unmarshal(String type, String json, MediaType mediaType);
+
+ /**
+ * Unmarshal.
+ *
+ * @param type the type
+ * @param json the json
+ * @return the introspector
+ */
+ public Introspector unmarshal(String type, String json) {
+ return unmarshal(type, json, MediaType.APPLICATION_JSON_TYPE);
+ }
+
+
+ /**
+ * Gets the model type.
+ *
+ * @return the model type
+ */
+ public ModelType getModelType() {
+ return this.modelType;
+ }
+
+ /**
+ * Gets the version.
+ *
+ * @return the version
+ */
+ public Version getVersion() {
+ return this.version;
+ }
+
+ /**
+ * Gets the log line builder.
+ *
+ * @return the log line builder
+ */
+ public LogLineBuilder getLogLineBuilder() {
+ return this.llBuilder;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/LoaderFactory.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/LoaderFactory.java
new file mode 100644
index 0000000..90af154
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/LoaderFactory.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import org.openecomp.aai.logging.LogLineBuilder;
+
+public class LoaderFactory {
+
+ /**
+ * Creates a new Loader object.
+ *
+ * @param type the type
+ * @param version the version
+ * @param llBuilder the ll builder
+ * @return the loader
+ */
+ public static Loader createLoaderForVersion(ModelType type, Version version, LogLineBuilder llBuilder) {
+
+ if (type.equals(ModelType.MOXY)) {
+ return new MoxyLoader(version, llBuilder);
+ } else if (type.equals(ModelType.POJO)) {
+ return new PojoLoader(version, llBuilder);
+ }
+
+ return null;
+
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MarshallerProperties.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MarshallerProperties.java
new file mode 100644
index 0000000..5932e69
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MarshallerProperties.java
@@ -0,0 +1,139 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import org.openecomp.aai.rest.MediaType;
+
+public class MarshallerProperties {
+
+ private final MediaType type;
+ private final boolean includeRoot;
+ private final boolean wrapperAsArrayName;
+ private final boolean formatted;
+
+ /**
+ * Instantiates a new marshaller properties.
+ *
+ * @param builder the builder
+ */
+ private MarshallerProperties(Builder builder) {
+
+ this.type = builder.type;
+ this.includeRoot = builder.includeRoot;
+ this.wrapperAsArrayName = builder.wrapperAsArrayName;
+ this.formatted = builder.formatted;
+ }
+
+ /**
+ * Gets the media type.
+ *
+ * @return the media type
+ */
+ public MediaType getMediaType() {
+ return this.type;
+ }
+
+ /**
+ * Gets the include root.
+ *
+ * @return the include root
+ */
+ public boolean getIncludeRoot() {
+ return this.includeRoot;
+ }
+
+ /**
+ * Gets the wrapper as array name.
+ *
+ * @return the wrapper as array name
+ */
+ public boolean getWrapperAsArrayName() {
+ return this.wrapperAsArrayName;
+ }
+
+ /**
+ * Gets the formatted.
+ *
+ * @return the formatted
+ */
+ public boolean getFormatted() {
+ return this.formatted;
+ }
+
+ public static class Builder {
+
+ private final MediaType type;
+ private boolean includeRoot = false;
+ private boolean wrapperAsArrayName = true;
+ private boolean formatted = false;
+
+ /**
+ * Instantiates a new builder.
+ *
+ * @param type the type
+ */
+ public Builder(MediaType type) {
+ this.type = type;
+ }
+
+ /**
+ * Include root.
+ *
+ * @param includeRoot the include root
+ * @return the builder
+ */
+ public Builder includeRoot (boolean includeRoot) {
+ this.includeRoot = includeRoot;
+ return this;
+ }
+
+ /**
+ * Wrapper as array name.
+ *
+ * @param wrapperAsArrayName the wrapper as array name
+ * @return the builder
+ */
+ public Builder wrapperAsArrayName (boolean wrapperAsArrayName) {
+ this.wrapperAsArrayName = wrapperAsArrayName;
+ return this;
+ }
+
+ /**
+ * Formatted.
+ *
+ * @param formatted the formatted
+ * @return the builder
+ */
+ public Builder formatted (boolean formatted) {
+ this.formatted = formatted;
+ return this;
+ }
+
+ /**
+ * Builds the properties.
+ *
+ * @return the marshaller properties
+ */
+ public MarshallerProperties build() {
+ return new MarshallerProperties(this);
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelInjestor.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelInjestor.java
new file mode 100644
index 0000000..768090d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelInjestor.java
@@ -0,0 +1,171 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBException;
+
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
+import org.openecomp.aai.util.AAIConstants;
+
+public class ModelInjestor {
+
+ private Map<Version, DynamicJAXBContext> versionContextMap = new HashMap<>();
+
+
+ /**
+ * Instantiates a new model injestor.
+ */
+ private ModelInjestor() {
+ try {
+ injestModels();
+ } catch (FileNotFoundException | JAXBException e) {
+ System.exit(1);
+ }
+ }
+
+ private static class Helper {
+ private static final ModelInjestor INSTANCE = new ModelInjestor();
+ }
+
+ /**
+ * Gets the single instance of ModelInjestor.
+ *
+ * @return single instance of ModelInjestor
+ */
+ public synchronized static ModelInjestor getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ /**
+ * Injest models.
+ *
+ * @throws FileNotFoundException the file not found exception
+ * @throws JAXBException the JAXB exception
+ */
+ private void injestModels() throws FileNotFoundException, JAXBException {
+
+ for (Version version : Version.values()) {
+ this.injestModel(version);
+ }
+ }
+
+ /**
+ * Injest model.
+ *
+ * @param version the version
+ * @throws JAXBException the JAXB exception
+ * @throws FileNotFoundException the file not found exception
+ */
+ private void injestModel (Version version) throws JAXBException, FileNotFoundException {
+ String fileName = AAIConstants.AAI_HOME_ETC_OXM + "aai_oxm_" + version.toString() + ".xml";
+ InputStream iStream = new FileInputStream(new File(fileName));
+ Map<String, Object> properties = new HashMap<String, Object>();
+ properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, iStream);
+ final DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(this.getClass().getClassLoader(), properties);
+ versionContextMap.put(version, jaxbContext);
+
+ }
+
+ /**
+ * Gets the version from class name.
+ *
+ * @param classname the classname
+ * @return the version from class name
+ */
+ public Version getVersionFromClassName (String classname) {
+ Pattern p = Pattern.compile("\\.(v\\d+)\\.");
+ Matcher m = p.matcher(classname);
+ String version = "v2";
+ if (m.find()) {
+ version = m.group(1);
+ }
+
+ return Version.valueOf(version);
+ }
+
+ /**
+ * Gets the context for URI.
+ *
+ * @param uri the uri
+ * @return the context for URI
+ */
+ public DynamicJAXBContext getContextForURI(String uri) {
+ DynamicJAXBContext result = null;
+ Pattern p = Pattern.compile("(v\\d+)\\/");
+ Matcher m = p.matcher(uri);
+ Version version = null;
+ if (m.find()) {
+ version = Version.valueOf(m.group(1));
+ result = versionContextMap.get(version);
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets the context for version.
+ *
+ * @param version the version
+ * @return the context for version
+ */
+ public DynamicJAXBContext getContextForVersion(Version version) {
+ DynamicJAXBContext result = null;
+
+ result = versionContextMap.get(version);
+
+
+ return result;
+ }
+
+ /**
+ * Gets the dynamic type for class name.
+ *
+ * @param classname the classname
+ * @return the dynamic type for class name
+ */
+ public DynamicType getDynamicTypeForClassName(String classname) {
+ DynamicType result = null;
+ DynamicJAXBContext context = null;
+
+ Version version = this.getVersionFromClassName(classname);
+
+ context = versionContextMap.get(version);
+
+ if (context != null) {
+ result = context.getDynamicType(classname);
+ }
+
+ return result;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelType.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelType.java
new file mode 100644
index 0000000..132b754
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelType.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+public enum ModelType {
+ MOXY, POJO, JSON
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyLoader.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyLoader.java
new file mode 100644
index 0000000..37d66ee
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyLoader.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.StringReader;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToRelationshipObject;
+import org.openecomp.aai.rest.MediaType;
+import org.openecomp.aai.workarounds.NamingExceptions;
+
+import com.google.common.base.CaseFormat;
+
+public class MoxyLoader extends Loader {
+
+ private DynamicJAXBContext jaxbContext = null;
+ private Unmarshaller unmarshaller = null;
+ private final String className = MoxyLoader.class.getSimpleName();
+ private AAILogger aaiLogger = new AAILogger(MoxyLoader.class.getName());
+
+ /**
+ * Instantiates a new moxy loader.
+ *
+ * @param version the version
+ * @param llBuilder the ll builder
+ */
+ protected MoxyLoader(Version version, LogLineBuilder llBuilder) {
+ super(version, ModelType.MOXY, llBuilder);
+ process(version);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Introspector introspectorFromName(String name) {
+
+ Introspector result = null;
+ Object temp = this.objectFromName(name);
+ if (temp != null) {
+ result = IntrospectorFactory.newInstance(ModelType.MOXY, temp, llBuilder);
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object objectFromName(String name) {
+ String upperCamel = "";
+
+ NamingExceptions exceptions = NamingExceptions.getInstance();
+ name = exceptions.getObjectName(name);
+ //Contains any uppercase, then assume it's upper camel
+ if (name.matches(".*[A-Z].*")) {
+ upperCamel = name;
+ } else {
+ upperCamel = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
+ }
+
+ Object result = null;
+ try {
+ result = jaxbContext.newDynamicEntity(upperCamel);
+ } catch (IllegalArgumentException e) {
+ //entity does not exist
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void process(Version version) {
+ ModelInjestor injestor = ModelInjestor.getInstance();
+ jaxbContext = injestor.getContextForVersion(version);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Introspector unmarshal(String type, String json, MediaType mediaType) {
+
+ DynamicEntity entity = null;
+ Introspector result = null;
+ Object clazz = this.objectFromName(type);
+ try {
+ unmarshaller = jaxbContext.createUnmarshaller();
+ if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ }
+
+ entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(json)), clazz.getClass()).getValue();
+ result = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ } catch (JAXBException e) {
+ AAIException ex = new AAIException("AAI_4007", e);
+ aaiLogger.error(ex.getErrorObject(), llBuilder.build(className, "could not unmarshal"), e);
+ }
+ return result;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyStrategy.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyStrategy.java
new file mode 100644
index 0000000..ce0d0ec
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyStrategy.java
@@ -0,0 +1,355 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.descriptors.ClassDescriptor;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.exceptions.DynamicException;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.eclipse.persistence.mappings.DatabaseMapping;
+import org.eclipse.persistence.oxm.XMLField;
+import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
+import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.MediaType;
+import org.openecomp.aai.workarounds.NamingExceptions;
+import org.springframework.web.util.UriUtils;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+
+public class MoxyStrategy extends Introspector {
+
+ private DynamicEntity internalObject = null;
+ private DynamicType internalType = null;
+ private DynamicJAXBContext jaxbContext = null;
+ private ClassDescriptor cd = null;
+ private Marshaller marshaller = null;
+ private Unmarshaller unmarshaller = null;
+ private Version version = null;
+
+ protected MoxyStrategy(Object obj, LogLineBuilder llBuilder) {
+ super(obj, llBuilder);
+ /* must look up the correct jaxbcontext for this object */
+ className = MoxyStrategy.class.getSimpleName();
+ aaiLogger = new AAILogger(MoxyStrategy.class.getName());
+ internalObject = (DynamicEntity)obj;
+ ModelInjestor injestor = ModelInjestor.getInstance();
+ version = injestor.getVersionFromClassName(internalObject.getClass().getName());
+ jaxbContext = injestor.getContextForVersion(version);
+ super.loader = LoaderFactory.createLoaderForVersion(getModelType(), version, llBuilder);
+ String simpleName = internalObject.getClass().getName();
+ internalType = jaxbContext.getDynamicType(simpleName);
+ cd = internalType.getDescriptor();
+ try {
+ marshaller = jaxbContext.createMarshaller();
+ unmarshaller = jaxbContext.createUnmarshaller();
+ } catch (JAXBException e) {
+
+ }
+
+ }
+
+ @Override
+ public boolean hasProperty(String name) {
+ String convertedName = convertPropertyName(name);
+
+ return internalType.containsProperty(convertedName);
+ }
+
+ @Override
+ public Object get(String name) {
+ return internalObject.get(name);
+ }
+
+ @Override
+ public void set(String name, Object obj) throws IllegalArgumentException {
+
+ internalObject.set(name, obj);
+ }
+
+ @Override
+ public List<String> getProperties() {
+ List<String> result = new ArrayList<>();
+ for (String s : internalType.getPropertiesNames()) {
+ result.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, s));
+
+ }
+ return result;
+ }
+
+ @Override
+ public List<String> getRequiredProperties() {
+ List<String> result = new ArrayList<>();
+ for (DatabaseMapping dm : cd.getMappings()) {
+ if (dm.getField() instanceof XMLField) {
+ XMLField x = (XMLField)dm.getField();
+ if (x != null) {
+ if (x.isRequired()) {
+ result.add(this.removeXPathDescriptor(x.getName()));
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List<String> getKeys() {
+ List<String> result = new ArrayList<>();
+
+ for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) {
+ result.add(this.removeXPathDescriptor(name));
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, String> getPropertyMetadata(String prop) {
+ String propName = this.convertPropertyName(prop);
+ DatabaseMapping mapping = cd.getMappingForAttributeName(propName);
+ Map<String, String> result = null;
+ if (mapping != null) {
+ result = mapping.getProperties();
+ }
+
+ return result;
+ }
+
+ @Override
+ public String getJavaClassName() {
+ return internalObject.getClass().getName();
+ }
+
+
+
+ @Override
+ public Class<?> getClass(String name) {
+ name = convertPropertyName(name);
+ Class<?> resultClass = null;
+ try {
+ if (internalType.getPropertyType(name) == null) {
+ if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
+ resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
+
+ } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
+ resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
+ } else {
+ ClassDescriptor referenceDiscriptor = cd.getMappingForAttributeName(name).getReferenceDescriptor();
+ if (referenceDiscriptor != null) {
+ resultClass = referenceDiscriptor.getJavaClass();
+ } else {
+ resultClass = Object.class;
+ }
+ }
+ } else {
+ resultClass = internalType.getPropertyType(name);
+ }
+ } catch (DynamicException e) {
+ //property doesn't exist
+ }
+ return resultClass;
+ }
+
+ @Override
+ public Class<?> getGenericTypeClass(String name) {
+ name = convertPropertyName(name);
+ Class<?> resultClass = null;
+ if (internalType.getPropertyType(name) == null) {
+ if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
+ resultClass = cd.getMappingForAttributeName(name).getFields().get(0).getType();
+
+ } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
+ resultClass = cd.getMappingForAttributeName(name).getReferenceDescriptor().getJavaClass();
+ }
+ }
+
+ return resultClass;
+ }
+
+ @Override
+ public Object getUnderlyingObject() {
+ return this.internalObject;
+ }
+
+ @Override
+ public String getChildName() {
+
+ String className = internalObject.getClass().getSimpleName();
+ String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
+
+ if (this.isContainer()) {
+ lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().get(0)).getSimpleName());
+ }
+
+ return lowerHyphen;
+ }
+
+ @Override
+ public String getName() {
+ String className = internalObject.getClass().getSimpleName();
+ String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
+ /*
+ if (this.isContainer()) {
+ lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().get(0)).getSimpleName());
+ }*/
+
+
+ return lowerHyphen;
+ }
+
+ @Override
+ public String getObjectId() throws UnsupportedEncodingException {
+ String result = "";
+ String container = this.getMetadata("container");
+ if (this.isContainer()) {
+ result += "/" + this.getName();
+ } else {
+
+ if (container != null) {
+ result += "/" + container;
+ }
+ result += "/" + this.getDbName() + "/" + this.findKey();
+
+ }
+
+ return result;
+ }
+
+ @Override
+ protected String findKey() throws UnsupportedEncodingException {
+ List<String> keys = null;
+ keys = this.getKeys();
+ List<String> results = new ArrayList<>();
+ for (String key : keys) {
+ if (this.getType(key).toLowerCase().contains("long")) {
+ key = ((Long)this.getValue(key)).toString();
+ } else {
+ key = (String)this.getValue(key);
+ }
+ key = UriUtils.encodePath(key, "UTF-8");
+
+ results.add(key);
+ }
+
+ return Joiner.on("/").join(results);
+ }
+
+ @Override
+ public String preProcessKey (String key) {
+ String result = "";
+ //String trimmedRestURI = restURI.replaceAll("/[\\w\\-]+?/[\\w\\-]+?$", "");
+ String[] split = key.split("/");
+ int i = 0;
+ for (i = split.length-1; i >= 0; i--) {
+
+ if (jaxbContext.getDynamicType(split[i]) != null) {
+ break;
+
+ }
+
+ }
+ result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
+
+ return result;
+
+ }
+
+ @Override
+ public String marshal(MarshallerProperties properties) {
+ StringWriter result = new StringWriter();
+ try {
+ if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, properties.getIncludeRoot());
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
+ }
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
+ marshaller.marshal(this.internalObject, result);
+ } catch (JAXBException e) {
+ //e.printStackTrace();
+ }
+
+ return result.toString();
+ }
+
+ @Override
+ public Object clone() {
+ Object result = null;
+ try {
+ unmarshaller = jaxbContext.createUnmarshaller();
+
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+
+ result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
+ } catch (JAXBException e) {
+ // TODO Auto-generated catch block
+ //e.printStackTrace();
+ }
+ result = IntrospectorFactory.newInstance(getModelType(), result, llBuilder);
+ return result;
+ }
+ @Override
+ public ModelType getModelType() {
+ return ModelType.MOXY;
+ }
+
+ private String removeXPathDescriptor(String name) {
+
+ return name.replaceAll("/text\\(\\)", "");
+ }
+
+ @Override
+ public String getMetadata(String name) {
+ String result = "";
+
+ result = (String)cd.getProperty(name);
+
+ return result;
+ }
+
+ @Override
+ public Version getVersion() {
+
+ return this.version;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoInjestor.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoInjestor.java
new file mode 100644
index 0000000..f2a61db
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoInjestor.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.openecomp.aai.db.AAIProperties;
+
+public class PojoInjestor {
+
+ private String POJO_CLASSPATH = "org.openecomp.aai.domain.yang";
+
+ public PojoInjestor() {
+ }
+
+ public JAXBContext getContextForVersion(Version v) {
+ JAXBContext context = null;
+ try {
+ if (!v.equals(AAIProperties.LATEST)) {
+ POJO_CLASSPATH += "." + v;
+ }
+ context = JAXBContext.newInstance(POJO_CLASSPATH);
+ } catch (JAXBException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return context;
+ }
+ public Version getVersion (String classname) {
+ Pattern p = Pattern.compile("\\.(v\\d+)\\.");
+ Matcher m = p.matcher(classname);
+ String version = "";
+ if (m.find()) {
+ version = m.group(1);
+ }
+
+ return Version.valueOf(version);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoLoader.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoLoader.java
new file mode 100644
index 0000000..91e88a1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoLoader.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.StringReader;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.MediaType;
+import org.openecomp.aai.workarounds.NamingExceptions;
+
+import com.google.common.base.CaseFormat;
+
+public class PojoLoader extends Loader {
+
+ protected JAXBContext context;
+ private Unmarshaller unmarshaller = null;
+ private String POJO_CLASSPATH = "org.openecomp.aai.domain.yang";
+ private final String className = PojoLoader.class.getSimpleName();
+ private AAILogger aaiLogger = new AAILogger(PojoLoader.class.getName());
+ protected PojoLoader(Version version, LogLineBuilder llBuilder) {
+ super(version, ModelType.POJO, llBuilder);
+ try {
+ if (!version.equals(AAIProperties.LATEST)) {
+ POJO_CLASSPATH += "." + version;
+ }
+ context = JAXBContext.newInstance(POJO_CLASSPATH);
+ } catch (JAXBException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+
+ }
+
+ @Override
+ public Introspector introspectorFromName(String name) {
+ Introspector result = null;
+ Object temp = this.objectFromName(name);
+ if (temp != null) {
+ result = IntrospectorFactory.newInstance(ModelType.POJO, temp, llBuilder);
+ }
+ return result;
+ }
+
+ @Override
+ public Object objectFromName(String name) {
+ String upperCamel = "";
+
+ NamingExceptions exceptions = NamingExceptions.getInstance();
+ name = exceptions.getObjectName(name);
+ //Contains any uppercase, then assume it's upper camel
+ if (name.matches(".*[A-Z].*")) {
+ upperCamel = name;
+ } else {
+ upperCamel = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
+ }
+
+ Object result = null;
+ try {
+ if (!upperCamel.contains(POJO_CLASSPATH)) {
+ upperCamel = POJO_CLASSPATH + "." + upperCamel;
+ }
+ result = Class.forName(upperCamel).newInstance();
+ } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+ //entity does not exist
+ }
+ return result;
+ }
+
+ @Override
+ protected void process(Version version) {
+
+
+ }
+
+ @Override
+ public Introspector unmarshal(String type, String json, MediaType mediaType) {
+ Introspector result = null;
+ Object obj = null;
+ Object clazz = this.objectFromName(type);
+ try {
+ unmarshaller = context.createUnmarshaller();
+ if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ }
+
+ obj = unmarshaller.unmarshal(new StreamSource(new StringReader(json)), clazz.getClass()).getValue();
+ result = IntrospectorFactory.newInstance(ModelType.POJO, obj, llBuilder);
+ } catch (JAXBException e) {
+ AAIException ex = new AAIException("AAI_4007", e);
+ aaiLogger.error(ex.getErrorObject(), llBuilder.build(className, "could not unmarshal"), e);
+ }
+ return result;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoStrategy.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoStrategy.java
new file mode 100644
index 0000000..49ad6d4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoStrategy.java
@@ -0,0 +1,383 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.MediaType;
+import org.openecomp.aai.annotations.Metadata;
+
+import com.att.aft.dme2.internal.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Multimap;
+
+public class PojoStrategy extends Introspector {
+
+ private Object internalObject = null;
+ private PojoInjestor injestor = null;
+ private Multimap<String, String> keyProps = null;
+ private Multimap<String, String> requiredProps = null;
+ private Multimap<String, String> altKeyProps = null;
+ private Metadata classLevelMetadata = null;
+ private Version version;
+ private JAXBContext jaxbContext;
+ private Marshaller marshaller;
+ private Unmarshaller unmarshaller;
+ protected PojoStrategy(Object obj, LogLineBuilder llBuilder) {
+ super(obj, llBuilder);
+ className = PojoStrategy.class.getSimpleName();
+ aaiLogger = new AAILogger(PojoStrategy.class.getName());
+ this.internalObject = obj;
+ injestor = new PojoInjestor();
+ classLevelMetadata = obj.getClass().getAnnotation(Metadata.class);
+
+ version = injestor.getVersion(obj.getClass().getName());
+ jaxbContext = injestor.getContextForVersion(version);
+ super.loader = LoaderFactory.createLoaderForVersion(getModelType(), version, llBuilder);
+ try {
+ marshaller = jaxbContext.createMarshaller();
+ unmarshaller = jaxbContext.createUnmarshaller();
+ } catch (JAXBException e) {
+
+ }
+
+ }
+
+ private String covertFieldToOutputFormat(String propName) {
+ return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName);
+ }
+
+ @Override
+ public boolean hasProperty(String name) {
+ //TODO
+ return true;
+ }
+
+ @Override
+ /**
+ * Gets the value of the property via reflection
+ */
+ public Object get(String name) {
+ String getMethodName = "get" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name);
+ try {
+ return this.internalObject.getClass().getDeclaredMethod(getMethodName).invoke(this.internalObject);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void set(String name, Object value) {
+ String setMethodName = "set" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name);
+ try {
+ this.internalObject.getClass().getDeclaredMethod(setMethodName, value.getClass()).invoke(this.internalObject, value);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
+ AAIException ex = new AAIException("AAI_4017", e);
+ LogLine line = llBuilder.build(className, "set value");
+ line.add(name, value.toString());
+ aaiLogger.error(ex.getErrorObject(), line, e);
+ }
+ }
+
+ @Override
+ public List<String> getProperties() {
+ Field[] fields = this.internalObject.getClass().getDeclaredFields();
+ List<String> result = new ArrayList<>();
+
+ for (Field field : fields) {
+ if (!field.getName().equals("any")) {
+ result.add(covertFieldToOutputFormat(field.getName()));
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List<String> getRequiredProperties() {
+ Field[] fields = this.internalObject.getClass().getDeclaredFields();
+ List<String> result = new ArrayList<>();
+
+ for (Field field : fields) {
+ if (!field.getName().equals("any")) {
+ XmlElement annotation = field.getAnnotation(XmlElement.class);
+ if (annotation != null) {
+ if (annotation.required()) {
+ result.add(covertFieldToOutputFormat(field.getName()));
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List<String> getKeys() {
+ Field[] fields = this.internalObject.getClass().getDeclaredFields();
+ List<String> result = new ArrayList<>();
+
+ for (Field field : fields) {
+ if (!field.getName().equals("any")) {
+ Metadata annotation = field.getAnnotation(Metadata.class);
+ if (annotation != null) {
+ if (annotation.isKey()) {
+ result.add(covertFieldToOutputFormat(field.getName()));
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List<String> getAllKeys() {
+ List<String> keys = this.getKeys();
+ String altKeys = classLevelMetadata.alternateKeys1();
+ if (altKeys != null) {
+ String[] altKeysArray = altKeys.split(",");
+ for (String altKey : altKeysArray) {
+ keys.add(altKey);
+ }
+ }
+
+ return keys;
+
+ }
+
+ public Class<?> getClass(String name) {
+
+ Field field = null;
+ try {
+ field = this.internalObject.getClass().getDeclaredField(CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, name));
+ } catch (NoSuchFieldException | SecurityException e) {
+
+ return null;
+ }
+
+ return field.getType();
+ }
+
+ public Class<?> getGenericTypeClass(String name) {
+
+ try {
+ String getMethodName = "get" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
+ Method method = internalObject.getClass().getDeclaredMethod(getMethodName);
+ Type t = method.getGenericReturnType();
+ if(t instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType)t;
+ return ((Class)pt.getActualTypeArguments()[0]);
+ } else {
+ return null;
+ }
+
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String getJavaClassName() {
+ return internalObject.getClass().getName();
+ }
+
+ @Override
+ public Object getUnderlyingObject() {
+ return this.internalObject;
+ }
+
+ @Override
+ public String getName() {
+ String className = internalObject.getClass().getSimpleName();
+
+ return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
+ }
+
+ @Override
+ protected String findKey() {
+ List<String> keys = null;
+ keys = this.getKeys();
+ List<String> results = new ArrayList<>();
+ for (String key : keys) {
+ if (this.getType(key).toLowerCase().contains("long")) {
+ key = ((Long)this.getValue(key)).toString();
+ } else {
+ key = (String)this.getValue(key);
+ }
+ results.add(key);
+ }
+
+ return Joiner.on("/").join(results);
+ }
+
+ @Override
+ public String marshal(MarshallerProperties properties) {
+ StringWriter result = new StringWriter();
+ try {
+ if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, properties.getIncludeRoot());
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
+ }
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
+ marshaller.marshal(this.internalObject, result);
+ } catch (JAXBException e) {
+ //e.printStackTrace();
+ }
+
+ return result.toString();
+ }
+
+ @Override
+ public Object clone() {
+ Object result = null;
+ try {
+ unmarshaller = jaxbContext.createUnmarshaller();
+
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+
+ result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
+ } catch (JAXBException e) {
+ // TODO Auto-generated catch block
+ //e.printStackTrace();
+ }
+ result = IntrospectorFactory.newInstance(getModelType(), result, llBuilder);
+ return result;
+ }
+
+ @Override
+ public String preProcessKey (String key) {
+ String result = "";
+ //String trimmedRestURI = restURI.replaceAll("/[\\w\\-]+?/[\\w\\-]+?$", "");
+ String[] split = key.split("/");
+ int i = 0;
+ for (i = split.length-1; i >= 0; i--) {
+
+ if (keyProps.containsKey(split[i])) {
+ break;
+
+ }
+
+ }
+ result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
+
+ return result;
+
+ }
+
+ @Override
+ public ModelType getModelType() {
+ return ModelType.POJO;
+ }
+
+ @Override
+ public String getChildName() {
+ String className = internalObject.getClass().getSimpleName();
+ String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
+
+ if (this.isContainer()) {
+ lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().get(0)).getSimpleName());
+ }
+
+ return lowerHyphen;
+ }
+
+ @Override
+ public Map<String, String> getPropertyMetadata(String prop) {
+ Field f;
+ Map<String, String> result = new HashMap<>();
+ try {
+ f = internalObject.getClass().getField(prop);
+ Metadata m = f.getAnnotation(Metadata.class);
+ if (m != null) {
+ Field[] fields = m.getClass().getFields();
+ String fieldName = "";
+ for (Field field : fields) {
+ fieldName = field.getName();
+ if (fieldName.equals("isAbstract")) {
+ fieldName = "abstract";
+ } else if (fieldName.equals("extendsFrom")) {
+ fieldName = "extends";
+ }
+ result.put(fieldName, (String)field.get(m));
+ }
+ }
+ } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ }
+
+ return result;
+ }
+
+ @Override
+ public String getObjectId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getMetadata(String metadataName) {
+ String value = null;
+ if ("abstract".equals(metadataName)) {
+ metadataName = "isAbstract";
+ } else if ("extends".equals(metadataName)) {
+ metadataName = "extendsFrom";
+ }
+
+ try {
+ value = (String)this.classLevelMetadata.getClass().getField(metadataName).get(classLevelMetadata);
+ } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
+ //TODO
+ }
+
+ return value;
+ }
+
+ @Override
+ public Version getVersion() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Version.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Version.java
new file mode 100644
index 0000000..d1e71c1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Version.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+public enum Version {
+ v8;
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Wanderer.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Wanderer.java
new file mode 100644
index 0000000..16399be
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/Wanderer.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection;
+
+import java.util.List;
+
+public interface Wanderer {
+
+ /**
+ * Process primitive.
+ *
+ * @param propName the prop name
+ * @param obj the obj
+ */
+ public void processPrimitive(String propName, Introspector obj);
+
+ /**
+ * Process primitive list.
+ *
+ * @param propName the prop name
+ * @param obj the obj
+ */
+ public void processPrimitiveList(String propName, Introspector obj);
+
+ /**
+ * Process complex obj.
+ *
+ * @param obj the obj
+ */
+ public void processComplexObj(Introspector obj);
+
+ /**
+ * Modify complex list.
+ *
+ * @param list the list
+ * @param parent the parent
+ * @param child the child
+ */
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child);
+
+ /**
+ * Creates the complex obj if null.
+ *
+ * @return true, if successful
+ */
+ public boolean createComplexObjIfNull();
+
+ /**
+ * Creates the complex list size.
+ *
+ * @param parent the parent
+ * @param child the child
+ * @return the int
+ */
+ public int createComplexListSize(Introspector parent, Introspector child);
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java
new file mode 100644
index 0000000..7283f1a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java
@@ -0,0 +1,167 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.generator;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorWalker;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.Wanderer;
+
+public class CreateExample implements Wanderer {
+
+ private Random rand = new Random();
+ private final long range = 100000000L;
+ private Loader loader = null;
+ private Introspector result = null;
+ private String objectName = null;
+ private List<String> blacklist = null;
+
+ /**
+ * Instantiates a new creates the example.
+ *
+ * @param loader the loader
+ * @param objectName the object name
+ */
+ public CreateExample(Loader loader, String objectName) {
+
+ this.loader = loader;
+ this.objectName = objectName;
+ this.blacklist = new ArrayList<>();
+
+ }
+
+ /**
+ * Gets the example object.
+ *
+ * @return the example object
+ */
+ public Introspector getExampleObject() {
+ result = loader.introspectorFromName(objectName);
+ blacklist = new ArrayList<>();
+ blacklist.add("any");
+ blacklist.add("relationship-list");
+ if (!result.isContainer()) {
+ blacklist.add("resource-version");
+ }
+ IntrospectorWalker walker = new IntrospectorWalker(this, loader.getLogLineBuilder());
+
+ walker.preventCycles(true);
+ walker.setBlacklist(blacklist);
+ walker.walk(result);
+ //this.getExampleObject(result);
+
+ return result;
+ }
+
+ /**
+ * Gets the value.
+ *
+ * @param property the property
+ * @param type the type
+ * @param suffix the suffix
+ * @return the value
+ */
+ private Object getValue(String property, String type, String suffix) {
+ long randLong = (long)(rand.nextDouble()*range);
+ Integer randInt = rand.nextInt(100000);
+ Integer randShrt = rand.nextInt(20000);
+ short randShort = randShrt.shortValue();
+
+ Object newObj = null;
+ if (type.contains("java.lang.String")) {
+ newObj = "example-" + property + "-val-" + randInt + suffix;
+ } else if ( type.toLowerCase().equals("long") ||type.contains("java.lang.Long")) {
+ newObj = randLong;
+ } else if(type.toLowerCase().equals("boolean") || type.contains("java.lang.Boolean")){
+ newObj = Boolean.TRUE;
+ } else if ( type.toLowerCase().equals("int") || type.contains("java.lang.Integer")){
+ newObj = randInt;
+ } else if ( type.toLowerCase().equals("short") || type.contains("java.lang.Short")){
+ newObj = randShort;
+ }
+
+ return newObj;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitive(String propName, Introspector obj) {
+ String propType = obj.getType(propName);
+
+ Object val = this.getValue(propName, propType, "");
+ obj.setValue(propName, val);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitiveList(String propName, Introspector obj) {
+ int listSize = 2;
+ String propType = "";
+ List<Object> list = new ArrayList<>();
+ for (int i = 0; i < listSize; i++) {
+ propType = obj.getGenericType(propName);
+ Object val = this.getValue(propName, propType, "-" + (i + 1));
+ list.add(val);
+ }
+ obj.setValue(propName, list);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processComplexObj(Introspector obj) {
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean createComplexObjIfNull() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int createComplexListSize(Introspector parent, Introspector child) {
+ return 1;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/CreateUUID.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/CreateUUID.java
new file mode 100644
index 0000000..366c854
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/CreateUUID.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+import java.util.Map;
+import java.util.UUID;
+
+import org.openecomp.aai.introspection.Introspector;
+
+public class CreateUUID implements IssueResolver {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean resolveIssue(Issue issue) {
+
+ Introspector obj = issue.getIntrospector();
+ if (issue.getError().equals(Error.MISSING_KEY_PROP)) {
+ Map<String, String> metadata = obj.getPropertyMetadata(issue.getPropName());
+ if (metadata.containsKey("autoGenerateUuid") && metadata.get("autoGenerateUuid").equals("true")) {
+ obj.setValue(issue.getPropName(), UUID.randomUUID().toString());
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/DefaultFields.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/DefaultFields.java
new file mode 100644
index 0000000..05c78b6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/DefaultFields.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+import java.util.Map;
+import java.util.UUID;
+
+import org.openecomp.aai.introspection.Introspector;
+
+public class DefaultFields implements IssueResolver {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean resolveIssue(Issue issue) {
+
+ Introspector obj = issue.getIntrospector();
+ if (issue.getError().equals(Error.MISSING_REQUIRED_PROP)) {
+ Map<String, String> metadata = obj.getPropertyMetadata(issue.getPropName());
+ if (metadata.containsKey("defaultValue")) {
+ obj.setValue(issue.getPropName(), metadata.get("defaultValue"));
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Error.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Error.java
new file mode 100644
index 0000000..044820f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Error.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+public enum Error {
+ MISSING_REQUIRED_PROP, MISSING_KEY_PROP
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/InjectKeysFromURI.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/InjectKeysFromURI.java
new file mode 100644
index 0000000..2c12f82
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/InjectKeysFromURI.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+import java.net.URI;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToObject;
+
+public class InjectKeysFromURI implements IssueResolver {
+
+ private URI uri = null;
+ private Loader loader = null;
+
+ /**
+ * Instantiates a new inject keys from URI.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ */
+ public InjectKeysFromURI(Loader loader, URI uri) {
+ this.loader = loader;
+ this.uri = uri;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean resolveIssue(Issue issue) {
+ boolean result = false;
+ Introspector obj = issue.getIntrospector();
+ if (issue.getError().equals(Error.MISSING_KEY_PROP)) {
+ try {
+ URIToObject toObject = new URIToObject(loader, uri);
+ Introspector minimumObj = toObject.getEntity();
+ if (toObject.getEntityName().equals(obj.getDbName())) {
+ obj.setValue(issue.getPropName(), minimumObj.getValue(issue.getPropName()));
+ result = true;
+ }
+ } catch (Exception e) {
+ //log something probably
+ result = false;
+ }
+ }
+
+ return result;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IntrospectorValidator.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IntrospectorValidator.java
new file mode 100644
index 0000000..89771df
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IntrospectorValidator.java
@@ -0,0 +1,278 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorWalker;
+import org.openecomp.aai.introspection.Wanderer;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+public class IntrospectorValidator implements Wanderer {
+
+
+ private List<Issue> issues = null;
+ private List<IssueResolver> issueResolvers = null;
+ private boolean validateRequired = true;
+ private final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new introspector validator.
+ *
+ * @param builder the builder
+ */
+ private IntrospectorValidator(IntrospectorValidator.Builder builder) {
+ this.llBuilder = builder.getLogLineBuilder();
+ this.validateRequired = builder.getValidateRequired();
+ this.issueResolvers = builder.getResolvers();
+ issues = new ArrayList<>();
+ }
+
+ /**
+ * Validate.
+ *
+ * @param obj the obj
+ * @return true, if successful
+ */
+ public boolean validate(Introspector obj) {
+ IntrospectorWalker walker = new IntrospectorWalker(this, llBuilder);
+ walker.walk(obj);
+
+ for (Issue m : issues) {
+ if (!m.getSeverity().equals(Severity.WARNING)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets the issues.
+ *
+ * @return the issues
+ */
+ public List<Issue> getIssues() {
+ return this.issues;
+ }
+
+ /**
+ * Sets the issue resolvers.
+ *
+ * @param resolvers the new issue resolvers
+ */
+ public void setIssueResolvers(List<IssueResolver> resolvers) {
+ issueResolvers = new ArrayList<>();
+ for (IssueResolver resolver : resolvers) {
+ issueResolvers.add(resolver);
+ }
+ }
+
+ /**
+ * Resolve issues.
+ *
+ * @return true, if successful
+ */
+ public boolean resolveIssues() {
+ boolean result = true;
+ for (Issue issue : issues) {
+ for (IssueResolver resolver : issueResolvers) {
+ if (resolver.resolveIssue(issue)) {
+ issue.setResolved(true);
+ }
+ }
+ if (!issue.isResolved()) {
+ result = false;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processComplexObj(Introspector obj) {
+ List<String> requiredProps = obj.getRequiredProperties();
+ List<String> keys = obj.getKeys();
+
+ requiredProps.removeAll(keys);
+ if (validateRequired) {
+ for (String prop : requiredProps) {
+ Object value = obj.getValue(prop);
+ if (value == null) {
+ Issue message =
+ this.buildMessage(Severity.CRITICAL, Error.MISSING_REQUIRED_PROP, "Missing required property: " + prop);
+ message.setIntrospector(obj);
+ message.setPropName(prop);
+ issues.add(message);
+ }
+ }
+ }
+ for (String prop : keys) {
+ Object value = obj.getValue(prop);
+ if (value == null) {
+ Issue message =
+ this.buildMessage(Severity.CRITICAL, Error.MISSING_KEY_PROP, "Missing key property: " + prop);
+ message.setIntrospector(obj);
+ message.setPropName(prop);
+ issues.add(message);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitive(String propName, Introspector obj) {
+ //NO OP
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitiveList(String propName, Introspector obj) {
+ //NO OP
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child) {
+ //NO OP
+ }
+
+
+ /**
+ * Builds the message.
+ *
+ * @param severity the severity
+ * @param error the error
+ * @param detail the detail
+ * @return the issue
+ */
+ private Issue buildMessage(Severity severity, Error error, String detail) {
+ Issue message = new Issue();
+ message.setSeverity(severity);
+ message.setError(error);
+ message.setDetail(detail);
+
+ return message;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean createComplexObjIfNull() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int createComplexListSize(Introspector parent, Introspector child) {
+ return 0;
+ }
+
+ public static class Builder {
+
+ private boolean validateRequired = true;
+ private List<IssueResolver> issueResolvers = null;
+ private final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new builder.
+ *
+ * @param llBuilder the ll builder
+ */
+ public Builder(LogLineBuilder llBuilder) {
+ this.llBuilder = llBuilder;
+ issueResolvers = new ArrayList<IssueResolver>();
+ }
+
+ /**
+ * Validate required.
+ *
+ * @param validateRequired the validate required
+ * @return the builder
+ */
+ public Builder validateRequired(boolean validateRequired) {
+ this.validateRequired = validateRequired;
+ return this;
+ }
+
+ /**
+ * Adds the resolver.
+ *
+ * @param resolver the resolver
+ * @return the builder
+ */
+ public Builder addResolver(IssueResolver resolver) {
+ issueResolvers.add(resolver);
+ return this;
+ }
+
+ /**
+ * Builds the.
+ *
+ * @return the introspector validator
+ */
+ public IntrospectorValidator build() {
+ return new IntrospectorValidator(this);
+ }
+
+ /**
+ * Gets the validate required.
+ *
+ * @return the validate required
+ */
+ public boolean getValidateRequired() {
+ return this.validateRequired;
+ }
+
+ /**
+ * Gets the resolvers.
+ *
+ * @return the resolvers
+ */
+ public List<IssueResolver> getResolvers() {
+ return this.issueResolvers;
+ }
+
+ /**
+ * Gets the log line builder.
+ *
+ * @return the log line builder
+ */
+ public LogLineBuilder getLogLineBuilder() {
+ return this.llBuilder;
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Issue.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Issue.java
new file mode 100644
index 0000000..2aa9761
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Issue.java
@@ -0,0 +1,144 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+import org.openecomp.aai.introspection.Introspector;
+
+public class Issue {
+
+ private Severity severity;
+ private Error error;
+ private String detail;
+ private Introspector obj;
+ private String propName;
+ private boolean resolved = false;
+
+ /**
+ * Sets the severity.
+ *
+ * @param severity the new severity
+ */
+ public void setSeverity(Severity severity) {
+
+ this.severity = severity;
+ }
+
+ /**
+ * Sets the error.
+ *
+ * @param error the new error
+ */
+ public void setError(Error error) {
+ this.error = error;
+ }
+
+ /**
+ * Sets the detail.
+ *
+ * @param detail the new detail
+ */
+ public void setDetail(String detail) {
+ this.detail = detail;
+ }
+
+ /**
+ * Gets the severity.
+ *
+ * @return the severity
+ */
+ public Object getSeverity() {
+ return this.severity;
+ }
+
+ /**
+ * Sets the introspector.
+ *
+ * @param obj the new introspector
+ */
+ public void setIntrospector(Introspector obj) {
+ this.obj = obj;
+ }
+
+ /**
+ * Gets the introspector.
+ *
+ * @return the introspector
+ */
+ public Introspector getIntrospector() {
+ return this.obj;
+ }
+
+ /**
+ * Gets the detail.
+ *
+ * @return the detail
+ */
+ public String getDetail() {
+ return this.detail;
+ }
+
+ /**
+ * Gets the error.
+ *
+ * @return the error
+ */
+ public Error getError() {
+ return this.error;
+ }
+
+ /**
+ * Sets the prop name.
+ *
+ * @param prop the new prop name
+ */
+ public void setPropName(String prop) {
+ this.propName= prop;
+ }
+
+ /**
+ * Gets the prop name.
+ *
+ * @return the prop name
+ */
+ public String getPropName() {
+ return this.propName;
+ }
+
+ /**
+ * Checks if is resolved.
+ *
+ * @return true, if is resolved
+ */
+ public boolean isResolved() {
+ return resolved;
+ }
+
+ /**
+ * Sets the resolved.
+ *
+ * @param resolved the new resolved
+ */
+ public void setResolved(boolean resolved) {
+ this.resolved = resolved;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IssueResolver.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IssueResolver.java
new file mode 100644
index 0000000..e62e9b7
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IssueResolver.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+public interface IssueResolver {
+
+
+ /**
+ * Resolve issue.
+ *
+ * @param issue the issue
+ * @return true, if successful
+ */
+ public boolean resolveIssue(Issue issue);
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Severity.java b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Severity.java
new file mode 100644
index 0000000..1450179
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Severity.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.introspection.tools;
+
+public enum Severity {
+ WARNING,
+ ERROR,
+ CRITICAL
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/logging/AAILogger.java b/ajsc-aai/src/main/java/org/openecomp/aai/logging/AAILogger.java
new file mode 100644
index 0000000..2a87d16
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/logging/AAILogger.java
@@ -0,0 +1,492 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.logging;
+
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.slf4j.MDC;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * This class provides Logger methods for the AAI application
+ */
+@SuppressWarnings("rawtypes")
+public class AAILogger {
+
+ public EELFLogger logger;
+
+ // private boolean mdcInitialized = false;
+
+ /**
+ * Instantiates a new AAI logger.
+ *
+ * @param name the name
+ */
+ public AAILogger(String name) {
+ // if ( !mdcInitialized ) { address problem where host/ip not in most
+ // logfile entries
+ MDC.put("ERROR_CODE", "");
+ MDC.put("ERROR_TEXT", "");
+ if (MDC.get("hostaddress") == null) {
+ mdcSetUp();
+ // mdcInitialized = true;
+ }
+ this.logger = EELFManager.getInstance().getLogger(name);
+ }
+
+ /**
+ * Instantiates a new AAI logger.
+ *
+ * @param clazz the clazz
+ */
+ public AAILogger(Class clazz) {
+ this(clazz.getSimpleName());
+ }
+
+ /**
+ * Mdc set up.
+ */
+ private void mdcSetUp() {
+ InetAddress ip;
+ String hostname;
+
+ MDC.put("hostname", "");
+ MDC.put("hostaddress", "");
+
+ try {
+ ip = InetAddress.getLocalHost();
+ if (ip != null) {
+ hostname = ip.getCanonicalHostName();
+ if (hostname != null)
+ MDC.put("hostname", hostname);
+ MDC.put("hostaddress", ip.getHostAddress());
+ }
+ // System.out.println("MDC setup " + MDC.get("hostname"));
+ } catch (UnknownHostException e) {
+
+ e.printStackTrace();
+
+ }
+ }
+
+ /**
+ * Method isInfoEnabled.
+ *
+ * @return boolean
+ */
+ public boolean isInfoEnabled() {
+ return logger.isInfoEnabled();
+ }
+
+ /**
+ * Method isDebugEnabled.
+ *
+ * @return boolean
+ */
+ public boolean isDebugEnabled() {
+ return logger.isDebugEnabled();
+ }
+
+ /**
+ * Method debug.
+ *
+ * @param logline
+ * LogLine
+ * @param text
+ * String
+ */
+ public void debug(LogLine logline, String text) {
+ if (isDebugEnabled()) {
+ logline.setLevel("DEBUG");
+ logline.setUserContributed(text);
+ String msg = logline.getLine(false).replaceAll("\\n", "^");// make it
+ // more
+ // readable
+ // by
+ // replacing
+ // newlines
+ logger.debug(msg);
+ }
+ }
+
+ /**
+ * Method debug.
+ *
+ * @param logline
+ * LogLine
+ * @param text
+ * String
+ * @param t
+ * Throwable
+ */
+ public void debug(LogLine logline, String text, Throwable t) {
+ if (isDebugEnabled()) {
+ logline.setLevel("DEBUG");
+ logline.add("db", text);
+ String msg = logline.getLine(false).replaceAll("\\n", "^");// make it
+ // more
+ // readable
+ // by
+ // replacing
+ // newlines
+ logger.debug(msg, t);
+
+ Throwable nestedT = getNestedThrowable(t);
+ if (nestedT != null) {
+ logger.debug(logline + "More info on previous error: ", nestedT);
+ }
+ }
+ }
+
+ /**
+ * Method audit.
+ *
+ * @param logline
+ * LogLine
+ */
+ public void audit(LogLine logline) {
+ if (isInfoEnabled()) {
+ logline.setLevel("INFO");
+ String msg = logline.getLine(true);
+ logger.info(msg);
+ }
+ }
+
+ /**
+ * Method info.
+ *
+ * @param logline
+ * LogLine
+ * @param success
+ * Boolean true or false
+ * @param errorCode
+ * "0" for success=true and a valid "AAI_*" error code from error.properties for success=false
+ * ex. aaiLogger.info(logline, false, "AAI_7402", e);
+ * aaiLogger.info(logline, true, "0");
+ * aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString(), e);
+ */
+ public void info(LogLine logline, Boolean success, String errorCode) {
+ info(logline, success, errorCode, null);
+ }
+
+ /**
+ * Method info.
+ *
+ * @param logline
+ * LogLine
+ * @param success
+ * Boolean true or false
+ * @param errorCode
+ * "0" for success=true and a valid "AAI_*" error code from error.properties for success=false
+ * ex. aaiLogger.info(logline, false, "AAI_7402", e);
+ * aaiLogger.info(logline, true, "0");
+ * aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString(), e);
+ * @param t
+ * Throwable
+ */
+ public void info(LogLine logline, Boolean success, String errorCode, Throwable t) {
+ if (isInfoEnabled()) {
+ logline.setLevel("INFO");
+ if (errorCode.equals("0")) {
+ logline.setEc(errorCode);
+ //Set Response Description to "Success" if error code is 0.
+ if (success){
+ logline.setEt("Success");
+ }
+ }
+ else {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject(errorCode);
+ logline.setEc(errorObject.getErrorCodeString());
+ logline.setEt(errorObject.getErrorText());
+ }
+
+ if (t != null) {
+ Throwable nestedT = getNestedThrowable(t);
+ if (nestedT != null) {
+ logline.add("info", nestedT.getStackTrace().toString());
+ }
+ }
+ String msg = logline.finish(success);
+ logger.info(msg);
+ }
+ }
+
+ /**
+ * Method error.
+ *
+ * @param errorObject
+ * ErrorObject
+ * @param logline
+ * LogLine
+ */
+ @Deprecated
+ public void error(ErrorObject errorObject, LogLine logline) {
+ error(errorObject, logline, null);
+ }
+
+ /**
+ * Method error.
+ *
+ * @param errorObject
+ * ErrorObject
+ * @param logline
+ * LogLine
+ * @param t
+ * Throwable
+ */
+ public void error(ErrorObject errorObject, LogLine logline, Throwable t) {
+
+ String errorSeverity = errorObject.getSeverity();
+ if (errorSeverity.equalsIgnoreCase("WARN"))
+ logline.setLevel("WARN");
+ else if (errorSeverity.equalsIgnoreCase("ERROR"))
+ logline.setLevel("ERROR");
+ else if (errorSeverity.equalsIgnoreCase("FATAL"))
+ logline.setLevel("FATAL");
+
+ String errorMessage = errorObject.getErrorText() + ":"
+ + errorObject.getRESTErrorCode() + ":" + errorObject.getHTTPResponseCode();
+ if (errorObject.getDetails() != null)
+ errorMessage += ":" + errorObject.getDetails();
+ errorMessage = errorMessage.replaceAll("\\n", "^");
+ MDC.put("ERROR_CODE", errorObject.getErrorCodeString());
+ MDC.put("ERROR_TEXT", errorMessage);
+ try {
+ if (t != null)
+ errorMessage += ":" + getStackTop(t);
+ } catch (AAIException e) {
+ errorMessage += ": unable to get stack trace, " + e.getMessage() + ":" + e.getErrorObject().getErrorText();
+ }
+ errorMessage = errorMessage.replaceAll("\\n", "^");
+
+ logline.setEc(errorObject.getErrorCodeString());
+ logline.setEt(errorMessage);
+
+ //Set status code correctly
+ logline.setSs("ERROR");
+
+
+ if (errorSeverity.equalsIgnoreCase("WARN"))
+ warn(logline.getLine(false));
+ else if (errorSeverity.equalsIgnoreCase("ERROR"))
+ error(logline.getLine(false));
+ else if (errorSeverity.equalsIgnoreCase("FATAL"))
+ fatal(logline.getLine(false));
+ // logNestedException(Level.DEBUG, errorMessage, t);
+ }
+
+ /**
+ * Method warn.
+ *
+ * @param logline
+ * String
+ */
+ private void warn(String logline) {
+ logger.warn(logline);
+ }
+
+ /**
+ * Method error.
+ *
+ * @param logline
+ * String
+ */
+ private void error(String logline) {
+ logger.error(logline);
+ }
+
+ /**
+ * Method fatal.
+ *
+ * @param logline
+ * String
+ */
+ private void fatal(String logline) {
+ logger.error(logline);
+ }
+
+ // /**
+ // * Method logNestedException.
+ // *
+ // * @param level
+ // * Level
+ // * @param logline
+ // * String
+ // * @param t
+ // * Throwable
+ // */
+ // private void logNestedException(Level level, String logline, Throwable t)
+ // {
+ // if (null == t) {
+ // return;
+ // }
+ //
+ // try {
+ // Class tC = t.getClass();
+ // Method[] mA = tC.getMethods();
+ // Method nextThrowableMethod = null;
+ //
+ // for (int i = 0; i < mA.length; i++) {
+ // if (("getCause".equals(mA[i].getName())) ||
+ // "getRootCause".equals(mA[i].getName())
+ // || "getNextException".equals(mA[i].getName()) ||
+ // "getException".equals(mA[i].getName())) {
+ // // check param types
+ // Class[] params = mA[i].getParameterTypes();
+ //
+ // if ((null == params) || (0 == params.length)) {
+ // // just found the getter for the nested throwable
+ // nextThrowableMethod = mA[i];
+ //
+ // break; // no need to search further
+ // }
+ // }
+ // }
+ //
+ // if (null != nextThrowableMethod) {
+ // // get the nested throwable and log it
+ // Throwable nextT = (Throwable) nextThrowableMethod.invoke(t, new
+ // Object[0]);
+ //
+ // if (null != nextT) {
+ // this.logger.log(AAICLASS, level, logline + "More info on previous error:
+ // ", nextT);
+ // }
+ // }
+ // } catch (Exception e) {
+ // // do nothing
+ // }
+ // }
+
+ /**
+ * This method returns the nested throwable of the given throwable.
+ *
+ * @param t Throwable
+ * @return the nested throwable
+ */
+ private Throwable getNestedThrowable(Throwable t) {
+ if (null == t) {
+ return null;
+ }
+
+ try {
+ Class tC = t.getClass();
+ Method[] mA = tC.getMethods();
+ Method nextThrowableMethod = null;
+
+ for (int i = 0; i < mA.length; i++) {
+ if (("getCause".equals(mA[i].getName())) || "getRootCause".equals(mA[i].getName())
+ || "getNextException".equals(mA[i].getName()) || "getException".equals(mA[i].getName())) {
+ // check param types
+ Class[] params = mA[i].getParameterTypes();
+
+ if ((null == params) || (0 == params.length)) {
+ // just found the getter for the nested throwable
+ nextThrowableMethod = mA[i];
+
+ break; // no need to search further
+ }
+ }
+ }
+
+ if (null != nextThrowableMethod) {
+ // get the nested throwable and log it
+ return (Throwable) nextThrowableMethod.invoke(t, new Object[0]);
+
+ }
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the stack top.
+ *
+ * @param e the e
+ * @return the stack top
+ * @throws NumberFormatException the number format exception
+ * @throws AAIException the AAI exception
+ */
+ public String getStackTop(Throwable e) throws NumberFormatException, AAIException {
+ StringBuffer stackMessage = new StringBuffer();
+ int maxStackTraceEntries = Integer.valueOf(AAIConfig.get(AAIConstants.LOGGING_MAX_STACK_TRACE_ENTRIES));
+ if (e != null) {
+ Throwable rootCause = ExceptionUtils.getRootCause(e);
+ if (rootCause != null) {
+ stackMessage.append("root cause=" + ExceptionUtils.getRootCause(e));
+ StackTraceElement[] elements = rootCause.getStackTrace();
+ int i = 0;
+ for (StackTraceElement element : elements) {
+ if (i < maxStackTraceEntries) {
+ stackMessage.append(" ClassName- ");
+ stackMessage.append(element.getClassName());
+ stackMessage.append(" :LineNumber- ");
+ stackMessage.append(element.getLineNumber());
+ stackMessage.append(" :MethodName- ");
+ stackMessage.append(element.getMethodName());
+ }
+ i++;
+ }
+ } else if (e.getCause() != null) {
+ stackMessage.append("cause=" + e.getCause());
+ StackTraceElement[] elements = e.getCause().getStackTrace();
+ int i = 0;
+ for (StackTraceElement element : elements) {
+ if (i < maxStackTraceEntries) {
+ stackMessage.append(" ClassName- ");
+ stackMessage.append(element.getClassName());
+ stackMessage.append(" :LineNumber- ");
+ stackMessage.append(element.getLineNumber());
+ stackMessage.append(" :MethodName- ");
+ stackMessage.append(element.getMethodName());
+ }
+ i++;
+ }
+ } else if (e.getStackTrace() != null) {
+ stackMessage.append("ex=" + e.toString());
+ StackTraceElement[] elements = e.getStackTrace();
+ int i = 0;
+ for (StackTraceElement element : elements) {
+ if (i < maxStackTraceEntries) {
+ stackMessage.append(" ClassName- ");
+ stackMessage.append(element.getClassName());
+ stackMessage.append(" :LineNumber- ");
+ stackMessage.append(element.getLineNumber());
+ stackMessage.append(" :MethodName- ");
+ stackMessage.append(element.getMethodName());
+ }
+ i++;
+ }
+ }
+ }
+ return stackMessage.toString();
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorLogHelper.java b/ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorLogHelper.java
new file mode 100644
index 0000000..baa9f5f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorLogHelper.java
@@ -0,0 +1,587 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.logging;
+
+import java.io.FileInputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.MapperUtil;
+
+/**
+ *
+ * This classes loads the application error properties file
+ * and provides a method that returns an ErrorObject
+ *
+ */
+
+public class ErrorLogHelper {
+
+ private static AAILogger aaiLogger = new AAILogger(ErrorLogHelper.class.getName());
+ private static Properties props = new Properties();
+ private static boolean isLoaded = false;
+ public static String errorPropertiesPath = null;
+
+ /**
+ * Sets the error props path.
+ *
+ * @param errorPropsPath the new error props path
+ */
+ public static void setErrorPropsPath(String errorPropsPath) {
+ if(errorPropertiesPath == null || errorPropertiesPath.length() == 0){
+ errorPropertiesPath = errorPropsPath;
+ }
+ }
+
+ /**
+ * Load properties.
+ *
+ * @throws Exception the exception
+ */
+ public static void loadProperties() throws Exception{
+ LogLine logline = new LogLine();
+ logline.init("aaigen", UUID.randomUUID().toString(), "AAI-INIT", "loading error properties");
+ if (!isLoaded) {
+
+ if(errorPropertiesPath == null ) {
+ errorPropertiesPath = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "error.properties"; // set default if not configured
+ }
+ logline.add("file", errorPropertiesPath);
+ String filepath = errorPropertiesPath;
+
+ if(filepath.startsWith("error")) {
+ props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(filepath));
+ } else {
+ FileInputStream fis = new FileInputStream(filepath);
+ props.load(fis);
+ fis.close();
+ }
+ isLoaded = true;
+ aaiLogger.info(logline, true, "0");
+
+ }
+ }
+
+ /**
+ * Gets the error object.
+ *
+ * @param key the key
+ * @return the error object
+ */
+ /* method that returns an error object for a key (error code) based
+ * on the error.properties file
+ * @param key - of the form "AAI_nnnn" that has an entry in the error.properties file
+ * @return ErrorObject
+ */
+ public static ErrorObject getErrorObject(String key){
+ return getErrorObject(key, null);
+ }
+
+ /**
+ * Gets the error object.
+ *
+ * @param key the key
+ * @param details the details
+ * @return the error object
+ */
+ /* method that returns an error object for a key (error code) based
+ * on the error.properties file
+ * @param key - of the form "AAI_nnnn" that has an entry in the error.properties file
+ * @param details - set the details of the errorObject to this
+ * @return ErrorObject
+ */
+ public static ErrorObject getErrorObject(String key, String details){
+ ErrorObject errorObject = new ErrorObject();
+ try {
+ if (!isLoaded) {
+ // The properties were not successfully loaded, try again
+ loadProperties();
+ }
+ if ((null != key) && (0 != key.trim().length())) {
+
+ String value = "";
+ value = (String) props.get(key);
+ if ((null == value) || (0 == value.trim().length())) {
+ throw new Exception("getErrorObject():Value is null for key: " + key);
+ } else {
+
+ String errorProperties[] = value.split(":");
+
+ errorObject.setDisposition(errorProperties[0].trim());
+ errorObject.setCategory(errorProperties[1].trim());
+ errorObject.setSeverity(errorProperties[2].trim());
+ errorObject.setErrorCode(errorProperties[3].trim());
+ errorObject.setHTTPResponseCode(errorProperties[4].trim());
+ if (errorProperties.length != 7) {
+ throw new Exception("error.properties line for "+key+" is improperly formatted");
+ } else {
+ errorObject.setRESTErrorCode(errorProperties[5].trim());
+ errorObject.setErrorText(errorProperties[6].trim());
+ }
+ errorObject.setDetails(details);
+ }
+ } else {
+ throw new Exception("getErrorObject():Key is null");
+ }
+
+ } catch (Exception e) {
+ errorObject.setDisposition("5");
+ errorObject.setCategory("4");
+ errorObject.setSeverity("FATAL");
+ errorObject.setErrorCode("4004");
+ errorObject.setHTTPResponseCode(Status.INTERNAL_SERVER_ERROR); // 500
+ errorObject.setRESTErrorCode("3002");
+ if ( e.getCause() != null && e.getCause().getMessage() != null)
+ errorObject.setErrorText("Error reading/parsing the error properties file trying to get error object for " + key + ":" + e.getMessage() + ":" + e.getCause().getMessage());
+ else
+ errorObject.setErrorText("Error reading/parsing the error properties file trying to get error object for " + key + ":" + e.getMessage());
+ }
+ return errorObject;
+ }
+
+ /**
+ * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error.
+ * The AAIRESTException may contain a different ErrorObject than that created with the REST error key.
+ * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
+ * If no error object is embedded in the AAIException, one will be created using the error object from the AAIException.
+ * @param are must have a restError value whose numeric value must match what should be returned in the REST API
+ * @param variables optional list of variables to flesh out text in error string
+ * @param logline LogLine
+ * @return appropriately formatted JSON response per the REST API spec.
+ * @deprecated
+ */
+ public static String getRESTAPIErrorResponse(AAIException are, ArrayList<String> variables, LogLine logline) {
+ List<MediaType> acceptHeaders = new ArrayList<MediaType>();
+ acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
+
+ return getRESTAPIErrorResponse(acceptHeaders, are, variables, logline);
+ }
+
+ /**
+ * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error.
+ * The AAIRESTException may contain a different ErrorObject than that created with the REST error key.
+ * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
+ * If no error object is embedded in the AAIException, one will be created using the error object from the AAIException.
+ *
+ * @param acceptHeadersOrig the accept headers orig
+ * @param are must have a restError value whose numeric value must match what should be returned in the REST API
+ * @param variables optional list of variables to flesh out text in error string
+ * @param logline LogLine
+ * @return appropriately formatted JSON response per the REST API spec.
+ */
+ public static String getRESTAPIErrorResponse(List<MediaType> acceptHeadersOrig, AAIException are, ArrayList<String> variables, LogLine logline) {;
+
+
+ StringBuilder text = new StringBuilder();
+ String response = null;
+
+ List<MediaType> acceptHeaders = new ArrayList<MediaType>();
+ // we might have an exception but no accept header, so we'll set default to JSON
+ boolean foundValidAcceptHeader = false;
+ for (MediaType mt : acceptHeadersOrig) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt) ||
+ MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
+ acceptHeaders.add(mt);
+ foundValidAcceptHeader = true;
+ }
+ }
+ if (foundValidAcceptHeader == false) {
+ // override the exception, client needs to set an appropriate Accept header
+ are = new AAIException("AAI_4014");
+ acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ ErrorObject eo = are.getErrorObject();
+
+ int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
+ ErrorObject restErrorObject = ErrorLogHelper.getErrorObject("AAI_"+restErrorCode);
+ if (restErrorObject == null) {
+ restErrorObject = eo;
+ }
+ text.append(restErrorObject.getErrorText());
+
+
+
+ // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
+ // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
+ // error, are ordered based on the error string.
+ int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
+ text.append(" (msg=%").append(localDataIndex+1).append(") (ec=%").append(localDataIndex+2).append(")");
+
+ if (variables == null)
+ {
+ variables = new ArrayList<String>();
+ }
+
+ if (variables.size() < localDataIndex) {
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_4011", "data missing for rest error"), logline, null);
+ while (variables.size() < localDataIndex) {
+ variables.add("null");
+ }
+ }
+
+ // This will put the error code and error text into the right positions
+ if (eo.getDetails() == null || eo.getDetails().length() == 0) {
+ variables.add(localDataIndex++, eo.getErrorText());
+ }
+ else {
+ variables.add(localDataIndex++, eo.getErrorText() + ":" + eo.getDetails());
+ }
+ variables.add(localDataIndex, eo.getErrorCodeString());
+
+ for (MediaType mediaType : acceptHeaders) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) {
+ JAXBContext context = null;
+ try {
+ if(eo.getCategory().equals("1")) {
+
+ context = JAXBContext.newInstance(org.openecomp.aai.domain.restPolicyException.Fault.class);
+ Marshaller m = context.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+
+ org.openecomp.aai.domain.restPolicyException.ObjectFactory factory = new org.openecomp.aai.domain.restPolicyException.ObjectFactory();
+ org.openecomp.aai.domain.restPolicyException.Fault fault = factory.createFault();
+ org.openecomp.aai.domain.restPolicyException.Fault.RequestError requestError = factory.createFaultRequestError();
+ org.openecomp.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException = factory.createFaultRequestErrorPolicyException();
+ org.openecomp.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables = factory.createFaultRequestErrorPolicyExceptionVariables();
+
+ policyException.setMessageId("POL" + eo.getRESTErrorCode());
+ policyException.setText(text.toString());
+ for (int i=0;i<variables.size();i++)
+ {
+ polvariables.getVariable().add(variables.get(i));
+ }
+ policyException.setVariables(polvariables);
+ requestError.setPolicyException(policyException);
+ fault.setRequestError(requestError);
+
+ StringWriter sw = new StringWriter();
+ m.marshal(fault, sw);
+
+ response = sw.toString();
+
+ } else {
+
+ context = JAXBContext.newInstance(org.openecomp.aai.domain.restServiceException.Fault.class);
+ Marshaller m = context.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+
+ org.openecomp.aai.domain.restServiceException.ObjectFactory factory = new org.openecomp.aai.domain.restServiceException.ObjectFactory();
+ org.openecomp.aai.domain.restServiceException.Fault fault = factory.createFault();
+ org.openecomp.aai.domain.restServiceException.Fault.RequestError requestError = factory.createFaultRequestError();
+ org.openecomp.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException = factory.createFaultRequestErrorServiceException();
+ org.openecomp.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables = factory.createFaultRequestErrorServiceExceptionVariables();
+ serviceException.setMessageId("SVC" + eo.getRESTErrorCode());
+ serviceException.setText(text.toString());
+ for (int i=0;i<variables.size();i++)
+ {
+ svcvariables.getVariable().add(variables.get(i));
+ }
+ serviceException.setVariables(svcvariables);
+ requestError.setServiceException(serviceException);
+ fault.setRequestError(requestError);
+
+ StringWriter sw = new StringWriter();
+ m.marshal(fault, sw);
+
+ response = sw.toString();
+
+ }
+ } catch (Exception ex) {
+ restErrorObject.setDetails("We were unable to create a rest exception to return on an API because of a parsing error");
+ aaiLogger.error(restErrorObject, logline, ex);
+ }
+ }
+ else {
+ try {
+ if(eo.getCategory().equals("1")) {
+ org.openecomp.aai.domain.restPolicyException.RESTResponse restresp = new org.openecomp.aai.domain.restPolicyException.RESTResponse();
+ org.openecomp.aai.domain.restPolicyException.RequestError reqerr = new org.openecomp.aai.domain.restPolicyException.RequestError();
+ org.openecomp.aai.domain.restPolicyException.PolicyException polexc = new org.openecomp.aai.domain.restPolicyException.PolicyException();
+ polexc.setMessageId("POL" + eo.getRESTErrorCode());
+ polexc.setText(text.toString());
+ polexc.setVariables(variables);
+ reqerr.setPolicyException(polexc);
+ restresp.setRequestError(reqerr);
+ response = (MapperUtil.writeAsJSONString((Object) restresp));
+
+ } else {
+ org.openecomp.aai.domain.restServiceException.RESTResponse restresp = new org.openecomp.aai.domain.restServiceException.RESTResponse();
+ org.openecomp.aai.domain.restServiceException.RequestError reqerr = new org.openecomp.aai.domain.restServiceException.RequestError();
+ org.openecomp.aai.domain.restServiceException.ServiceException svcexc = new org.openecomp.aai.domain.restServiceException.ServiceException();
+ svcexc.setMessageId("SVC" + eo.getRESTErrorCode());
+ svcexc.setText(text.toString());
+ svcexc.setVariables(variables);
+ reqerr.setServiceException(svcexc);
+ restresp.setRequestError(reqerr);
+ response = (MapperUtil.writeAsJSONString((Object) restresp));
+ }
+ } catch (AAIException ex) {
+ restErrorObject.setDetails("We were unable to create a rest exception to return on an API because of a parsing error");
+ aaiLogger.error(restErrorObject, logline, ex);
+ }
+ }
+ }
+
+
+ return response;
+ }
+
+ /**
+ * Gets the RESTAPI error response with logging.
+ *
+ * @param acceptHeadersOrig the accept headers orig
+ * @param are the are
+ * @param variables the variables
+ * @param logline the logline
+ * @return the RESTAPI error response with logging
+ */
+ public static String getRESTAPIErrorResponseWithLogging(List<MediaType> acceptHeadersOrig, AAIException are, ArrayList<String> variables, LogLine logline) {;
+ String response = ErrorLogHelper.getRESTAPIErrorResponse(acceptHeadersOrig, are, variables, logline);
+
+ aaiLogger.error(are.getErrorObject(), logline, are);
+ aaiLogger.info(logline, false, are.getErrorObject().getErrorCodeString());
+
+ return response;
+
+ }
+
+ /**
+ * Gets the RESTAPI info response.
+ *
+ * @param acceptHeaders the accept headers
+ * @param areList the are list
+ * @param logline the logline
+ * @return the RESTAPI info response
+ */
+ public static Object getRESTAPIInfoResponse(List<MediaType> acceptHeaders, HashMap<AAIException,ArrayList<String>> areList, LogLine logline) {
+
+ Object respObj = null;
+
+ org.openecomp.aai.domain.restResponseInfo.ObjectFactory factory = new org.openecomp.aai.domain.restResponseInfo.ObjectFactory();
+ org.openecomp.aai.domain.restResponseInfo.Info info = factory.createInfo();
+ org.openecomp.aai.domain.restResponseInfo.Info.ResponseMessages responseMessages = factory.createInfoResponseMessages();
+ Iterator<Map.Entry<AAIException, ArrayList<String>>> it = areList.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<AAIException,ArrayList<String>> pair = (Map.Entry<AAIException, ArrayList<String>>)it.next();
+ AAIException are = pair.getKey();
+ ArrayList<String> variables = pair.getValue();
+ //System.out.println(pair.getKey() + " = " + pair.getValue());
+
+ StringBuilder text = new StringBuilder();
+
+ ErrorObject eo = are.getErrorObject();
+
+ int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
+ ErrorObject restErrorObject = ErrorLogHelper.getErrorObject("AAI_"+String.format("%04d", restErrorCode));
+ if (restErrorObject == null) {
+ restErrorObject = eo;
+ }
+ text.append(restErrorObject.getErrorText());
+
+ // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
+ // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
+ // error, are ordered based on the error string.
+ int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
+ text.append(" (msg=%").append(localDataIndex+1).append(") (rc=%").append(localDataIndex+2).append(")");
+
+ if (variables == null)
+ {
+ variables = new ArrayList<String>();
+ }
+
+ if (variables.size() < localDataIndex) {
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_4011", "data missing for rest error"), logline, null);
+ while (variables.size() < localDataIndex) {
+ variables.add("null");
+ }
+ }
+
+ // This will put the error code and error text into the right positions
+ if (eo.getDetails() == null) {
+ variables.add(localDataIndex++, eo.getErrorText());
+ }
+ else {
+ variables.add(localDataIndex++, eo.getErrorText() + ":" + eo.getDetails());
+ }
+ variables.add(localDataIndex, eo.getErrorCodeString());
+
+ try {
+ org.openecomp.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage responseMessage = factory.createInfoResponseMessagesResponseMessage();
+ org.openecomp.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage.Variables infovariables = factory.createInfoResponseMessagesResponseMessageVariables();
+
+ responseMessage.setMessageId("INF" + eo.getRESTErrorCode());
+ responseMessage.setText(text.toString());
+ for (int i=0;i<variables.size();i++)
+ {
+ infovariables.getVariable().add(variables.get(i));
+ }
+
+ responseMessage.setVariables(infovariables);
+ responseMessages.getResponseMessage().add(responseMessage);
+
+ } catch (Exception ex) {
+ restErrorObject.setDetails("We were unable to create a rest exception to return on an API because of a parsing error");
+ aaiLogger.error(restErrorObject, logline, ex);
+ }
+ }
+
+ info.setResponseMessages(responseMessages);
+ respObj = (Object) info;
+
+ return respObj;
+ }
+
+
+ /**
+ * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error.
+ * The AAIRESTException may contain a different ErrorObject than that created with the REST error key.
+ * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
+ * If no error object is embedded in the AAIException, one will be created using the error object from the AAIException.
+ * @param are must have a restError value whose numeric value must match what should be returned in the REST API
+ * @param variables optional list of variables to flesh out text in error string
+ * @param logline LogLine
+ * @return appropriately formatted JSON response per the REST API spec.
+ */
+ public static String getRESTAPIPolicyErrorResponseXML(AAIException are, ArrayList<String> variables, LogLine logline) {
+
+ StringBuilder text = new StringBuilder();
+ String response = null;
+ JAXBContext context = null;
+
+
+
+ ErrorObject eo = are.getErrorObject();
+
+ int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
+ ErrorObject restErrorObject = ErrorLogHelper.getErrorObject("AAI_"+restErrorCode);
+ if (restErrorObject == null) {
+ restErrorObject = eo;
+ }
+ text.append(restErrorObject.getErrorText());
+
+ // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
+ // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
+ // error, are ordered based on the error string.
+ int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
+ text.append(" (msg=%").append(localDataIndex+1).append(") (ec=%").append(localDataIndex+2).append(")");
+
+ if (variables == null)
+ {
+ variables = new ArrayList<String>();
+ }
+
+ if (variables.size() < localDataIndex) {
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_4011", "data missing for rest error"), logline, null);
+ while (variables.size() < localDataIndex) {
+ variables.add("null");
+ }
+ }
+
+ // This will put the error code and error text into the right positions
+ if (eo.getDetails() == null) {
+ variables.add(localDataIndex++, eo.getErrorText());
+ }
+ else {
+ variables.add(localDataIndex++, eo.getErrorText() + ":" + eo.getDetails());
+ }
+ variables.add(localDataIndex, eo.getErrorCodeString());
+
+ try {
+ if(eo.getCategory().equals("1")) {
+
+ context = JAXBContext.newInstance(org.openecomp.aai.domain.restPolicyException.Fault.class);
+ Marshaller m = context.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+
+ org.openecomp.aai.domain.restPolicyException.ObjectFactory factory = new org.openecomp.aai.domain.restPolicyException.ObjectFactory();
+ org.openecomp.aai.domain.restPolicyException.Fault fault = factory.createFault();
+ org.openecomp.aai.domain.restPolicyException.Fault.RequestError requestError = factory.createFaultRequestError();
+ org.openecomp.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException = factory.createFaultRequestErrorPolicyException();
+ org.openecomp.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables = factory.createFaultRequestErrorPolicyExceptionVariables();
+
+ policyException.setMessageId("POL" + eo.getRESTErrorCode());
+ policyException.setText(text.toString());
+ for (int i=0;i<variables.size();i++)
+ {
+ polvariables.getVariable().add(variables.get(i));
+ }
+ policyException.setVariables(polvariables);
+ requestError.setPolicyException(policyException);
+ fault.setRequestError(requestError);
+
+ StringWriter sw = new StringWriter();
+ m.marshal(fault, sw);
+
+ response = sw.toString();
+
+ } else {
+
+ context = JAXBContext.newInstance(org.openecomp.aai.domain.restServiceException.Fault.class);
+ Marshaller m = context.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+
+ org.openecomp.aai.domain.restServiceException.ObjectFactory factory = new org.openecomp.aai.domain.restServiceException.ObjectFactory();
+ org.openecomp.aai.domain.restServiceException.Fault fault = factory.createFault();
+ org.openecomp.aai.domain.restServiceException.Fault.RequestError requestError = factory.createFaultRequestError();
+ org.openecomp.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException = factory.createFaultRequestErrorServiceException();
+ org.openecomp.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables = factory.createFaultRequestErrorServiceExceptionVariables();
+ serviceException.setMessageId("POL" + eo.getRESTErrorCode());
+ serviceException.setText(text.toString());
+ for (int i=0;i<variables.size();i++)
+ {
+ svcvariables.getVariable().add(variables.get(i));
+ }
+ serviceException.setVariables(svcvariables);
+ requestError.setServiceException(serviceException);
+ fault.setRequestError(requestError);
+
+ StringWriter sw = new StringWriter();
+ m.marshal(fault, sw);
+
+ response = sw.toString();
+
+ }
+ } catch (Exception ex) {
+ restErrorObject.setDetails("We were unable to create a rest exception to return on an API because of a parsing error");
+ aaiLogger.error(restErrorObject, logline, ex);
+ }
+ return response;
+ }
+ }
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorObject.java
new file mode 100644
index 0000000..88274dd
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorObject.java
@@ -0,0 +1,328 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.logging;
+
+import javax.ws.rs.core.Response.Status;
+
+/**
+ *
+ * Contains the definition of all error message fields to be mapped from the Error
+ * properties file
+ *
+ */
+public class ErrorObject {
+
+ private String disposition;
+ private String category;
+ private String severity;
+ private Status httpResponseCode = Status.INTERNAL_SERVER_ERROR; // default
+ private String restErrorCode = "3002";
+ private String errorCode;
+ private String errorText;
+ private String details;
+
+ public static final ErrorObject DefaultErrorObject = ErrorLogHelper.getErrorObject("AAI_4000", "TBD Error Processing");
+
+ /**
+ * Instantiates a new error object.
+ */
+ public ErrorObject() {
+ super();
+ }
+
+ /**
+ * Creates an error object with the default HTTP Error Code (Status.INTERNAL_SERVER_ERROR)
+ *
+ * @param disposition the disposition
+ * @param category the category
+ * @param severity the severity
+ * @param httpResponseCode the http response code
+ * @param restErrorCode the rest error code
+ * @param errorCode the error code
+ * @param errorText the error text
+ */
+ public ErrorObject(String disposition, String category, String severity, Integer httpResponseCode, String restErrorCode, String errorCode, String errorText) {
+ super();
+ this.setDisposition(disposition);
+ this.setCategory(category);
+ this.severity = severity;
+ this.setHTTPResponseCode(httpResponseCode);
+ this.setRESTErrorCode(restErrorCode);
+ this.setErrorCode(errorCode);
+ this.setErrorText(errorText);
+ }
+
+ // OLD STARTS HERE
+
+ /**
+ * Instantiates a new error object.
+ *
+ * @param severity the severity
+ * @param errorCode the error code
+ * @param errorText the error text
+ * @param disposition the disposition
+ * @param category the category
+ */
+ public ErrorObject(String severity, String errorCode, String errorText, String disposition, String category) {
+ this(severity, Status.INTERNAL_SERVER_ERROR, errorCode, errorText, disposition, category);
+ }
+
+ /**
+ * Instantiates a new error object.
+ *
+ * @param severity the severity
+ * @param httpResponseCode the http response code
+ * @param errorCode the error code
+ * @param errorText the error text
+ * @param disposition the disposition
+ * @param category the category
+ */
+ public ErrorObject(String severity, Integer httpResponseCode, String errorCode, String errorText, String disposition, String category) {
+ super();
+ this.severity = severity;
+ this.setHTTPResponseCode(httpResponseCode);
+ this.setErrorCode(errorCode);
+ this.setErrorText(errorText);
+ this.setDisposition(disposition);
+ this.setCategory(category);
+ }
+
+ /**
+ * Instantiates a new error object.
+ *
+ * @param severity the severity
+ * @param httpResponseCode the http response code
+ * @param errorCode the error code
+ * @param errorText the error text
+ * @param disposition the disposition
+ * @param category the category
+ */
+ public ErrorObject(String severity, Status httpResponseCode, String errorCode, String errorText, String disposition, String category) {
+ super();
+ this.severity = severity;
+ this.setHTTPResponseCode(httpResponseCode);
+ this.setErrorCode(errorCode);
+ this.setErrorText(errorText);
+ this.setDisposition(disposition);
+ this.setCategory(category);
+ }
+
+ /**
+ * Gets the disposition.
+ *
+ * @return the disposition
+ */
+ public String getDisposition() {
+ return disposition;
+ }
+
+ /**
+ * Sets the disposition.
+ *
+ * @param disposition the new disposition
+ */
+ public void setDisposition(String disposition) {
+ this.disposition = disposition;
+ }
+
+ /**
+ * Gets the category.
+ *
+ * @return the category
+ */
+ public String getCategory() {
+ return category;
+ }
+
+ /**
+ * Sets the category.
+ *
+ * @param category the new category
+ */
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ /**
+ * Gets the severity.
+ *
+ * @return the severity
+ */
+ public String getSeverity() {
+ return severity;
+ }
+
+ /**
+ * Sets the severity.
+ *
+ * @param severity the new severity
+ */
+ public void setSeverity(String severity) {
+ this.severity = severity;
+ }
+
+ /**
+ * Gets the error code.
+ *
+ * @return the error code
+ */
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * Sets the error code.
+ *
+ * @param errorCode the new error code
+ */
+ public void setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Gets the HTTP response code.
+ *
+ * @return the HTTP response code
+ */
+ public Status getHTTPResponseCode() {
+ return httpResponseCode;
+ }
+
+ /**
+ * Sets the HTTP response code.
+ *
+ * @param httpResponseCode the new HTTP response code
+ */
+ public void setHTTPResponseCode(Integer httpResponseCode) {
+ this.httpResponseCode = Status.fromStatusCode(httpResponseCode);
+ if (this.httpResponseCode == null) {
+ throw new IllegalArgumentException("setHTTPResponseCode was passed an invalid Integer value, fix error.properties or your code "+httpResponseCode);
+ }
+ }
+
+ /**
+ * Sets the HTTP response code.
+ *
+ * @param httpResponseCode the new HTTP response code
+ */
+ public void setHTTPResponseCode(String httpResponseCode) {
+ this.httpResponseCode = Status.fromStatusCode(Integer.valueOf(httpResponseCode));
+ if (this.httpResponseCode == null) {
+ throw new IllegalArgumentException("setHTTPResponseCode was passed an invalid String value, fix error.properties or your code "+httpResponseCode);
+ }
+ }
+
+ /**
+ * Sets the REST error code.
+ *
+ * @param restErrorCode the new REST error code
+ */
+ public void setRESTErrorCode(String restErrorCode) {
+ this.restErrorCode = restErrorCode;
+ }
+
+ /**
+ * Gets the REST error code.
+ *
+ * @return the REST error code
+ */
+ public String getRESTErrorCode() {
+ return this.restErrorCode;
+ }
+
+ /**
+ * Sets the HTTP response code.
+ *
+ * @param httpResponseCode the new HTTP response code
+ */
+ public void setHTTPResponseCode(Status httpResponseCode) {
+ this.httpResponseCode = httpResponseCode;
+ if (this.httpResponseCode == null) {
+ throw new IllegalArgumentException("setHTTPResponseCode was passed an invalid String value, fix error.properties or your code "+httpResponseCode);
+ }
+ }
+
+ /**
+ * Gets the error text.
+ *
+ * @return the error text
+ */
+ public String getErrorText() {
+ return errorText;
+ }
+
+ /**
+ * Sets the error text.
+ *
+ * @param errorText the new error text
+ */
+ public void setErrorText(String errorText) {
+ this.errorText = errorText;
+ }
+
+ /**
+ * Gets the details.
+ *
+ * @return the details
+ */
+ public String getDetails() {
+ return details;
+ }
+
+ /**
+ * Sets the details.
+ *
+ * @param details the new details
+ */
+ public void setDetails(String details) {
+ this.details = details == null ? "" : details;
+ }
+
+ /**
+ * Gets the error code string.
+ *
+ * @return the error code string
+ */
+ // Get the X.Y.Z representation of the error code
+ public String getErrorCodeString() {
+ String prefix = null;
+ switch (disposition) {
+ default:
+ prefix = "";
+ break;
+ case "5":
+ prefix = "ERR.";
+ break;
+ }
+ return prefix + disposition + "." + category + "." + errorCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return "ErrorObject [errorCode="+ errorCode + ", errorText=" + errorText
+ + ", restErrorCode=" + restErrorCode + ", httpResponseCode="+ httpResponseCode
+ + ", severity=" + severity + ", disposition=" + disposition + ", category=" + category +"]";
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLine.java b/ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLine.java
new file mode 100644
index 0000000..50149e6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLine.java
@@ -0,0 +1,488 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.logging;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.slf4j.MDC;
+/**
+ * This class is used to help standardize how log lines are written and provide profiling info.
+ *
+ * Note that the name-value pairs are assembled in the order they are inserted.. Init sets up the tr, fr and co values
+ * so that they can be used consistently via start() for debug and error logs. finish() adds the ss and tt so they
+ * can be provided for each INFO record.
+ */
+
+public class LogLine {
+
+ private long startTime = 0;
+ private long endTime = 0;
+
+ private String co = ""; // component
+ private String tr = ""; // transId
+ private String ll = ""; // log level
+
+ private String fr = ""; // fromAppId
+ private String to = ""; // toAppId
+ private String me = ""; // operation
+
+ private String tt = ""; // time taken
+ private String ss = ""; // success
+ private String ec = "0"; // error code
+ private String et = ""; // error text
+
+
+ private String userContributed = "";
+
+ /**
+ * Initialize the start time and identify the component, transactionId and fromAppId
+ * which are mandatory to log on each line.
+ *
+ * @param component identifies the subsystem or component of the application
+ * @param transId identifies the unique transaction id for the request being processed
+ * @param fromAppId identifies the application that is making the request
+ * @param operation the operation
+ */
+
+
+
+ public void init(String component, String transId, String fromAppId, String operation){
+
+ init(component, transId, fromAppId, "AAI", operation);
+ }
+
+ /**
+ * Inits the logline.
+ *
+ * @param component the component
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param toAppId the to app id
+ * @param operation the operation
+ */
+ public void init(String component, String transId, String fromAppId, String toAppId, String operation){
+
+ this.setUserContributed("");
+ startTime = System.currentTimeMillis();
+ this.setCo(component);
+ this.setTr(transId);
+ this.setFr(fromAppId);
+ this.setTo(toAppId);
+ this.setMe(operation);
+ }
+
+ /**
+ * Overrides the value from init().
+ */
+ public void startTimer() {
+ startTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Adds the.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ public void add(String name, String value) {
+ String uc = getUserContributed();
+ if (value != null) {
+ uc += ":" + name + "=" + value.replaceAll("\\|", "^").trim();
+ } else {
+ uc += ":" + name + "=" + value;
+ }
+ setUserContributed(uc);
+ }
+
+ /**
+ * Adds the.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ public void add(String name, int value) {
+ String uc = getUserContributed();
+ uc += ":" + name + "=" + Integer.toString(value);
+ setUserContributed(uc);
+ }
+
+ /**
+ * Adds the.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ public void add(String name, long value) {
+ String uc = getUserContributed();
+ uc += ":" + name + "=" + Long.toString(value);
+ setUserContributed(uc);
+ }
+
+ /**
+ * Adds the.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ public void add(String name, double value) {
+ String uc = getUserContributed();
+ uc += ":" + name + "=" + Double.toString(value);
+ setUserContributed(uc);
+ }
+
+ /**
+ * Adds the.
+ *
+ * @param name the name
+ * @param value the value
+ */
+ public void add(String name, boolean value) {
+ String uc = getUserContributed();
+ uc += ":" + name + "=" + Boolean.toString(value);
+ setUserContributed(uc);
+ }
+
+ /**
+ * Return the log line based on what we have so far.
+ *
+ * @param audit the audit
+ * @return the line
+ */
+ protected String getLine(boolean audit) {
+
+ // MDC is setup when AAILogger is setup
+ String hostName = (String)MDC.get("hostname")== null ? "" : (String)MDC.get("hostname");
+ String hostAddress = (String)MDC.get("hostaddress") == null ? "" : (String)MDC.get("hostaddress");
+ //String className = (String)MDC.get("classname") == null ? "" : (String)MDC.get("classname");
+ String className = "";
+
+ Exception ex = new Exception();
+ StackTraceElement[] stackTraceArray = ex.getStackTrace();
+
+ //Find the class in the stack trace that calls the AAILogger.
+ for (int i =0; i < stackTraceArray.length; i++ ){
+ String fullClassName = stackTraceArray[i].getClassName();
+ if (fullClassName.contains("AAILogger")){
+ int aaiLoggerIndex = i;
+ String nextClassInStackTrace = stackTraceArray[i+1].getClassName();
+ if (nextClassInStackTrace.contains("AAILogger")){
+ fullClassName = stackTraceArray[i+2].getClassName();
+ } else {
+ fullClassName = nextClassInStackTrace;
+ }
+ className = fullClassName.substring(fullClassName.lastIndexOf('.') + 1 );
+ break;
+ }
+ }
+
+// if (ex.getStackTrace().length > 3) { // 3rd in stack shd be aaiLogger so we need the 4th
+// String fullClassName = ex.getStackTrace()[3].getClassName();
+// if (!fullClassName.contains("aai"))
+// fullClassName = ex.getStackTrace()[2].getClassName();
+// className = fullClassName.substring(fullClassName.lastIndexOf('.') + 1 );
+// }
+
+ // this will format it
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ Date startDate = new Date(startTime);
+ String startTimeStr = dateFormat.format(startDate);
+
+ Date endDate = new Date(endTime);
+ String endTimeStr = dateFormat.format(endDate);
+
+ String timeTaken = this.getTt();
+
+ if (!ll.equals("INFO")) //if this is debug or error, use the now time
+ {
+ // "endtime" will now be equal to when the log is written (nowtime )
+ long nowTime = System.currentTimeMillis();
+ timeTaken = String.valueOf(nowTime - startTime); //tt is "time taken" or "elapsed time"
+ Date nowDate = new Date (nowTime);
+ endTimeStr = dateFormat.format(nowDate);
+
+ }
+
+
+ return startTimeStr + // start timestamp
+ "|" + endTimeStr + // end timestamp
+ "|" + this.getTr() + // RequestId => transId
+ "|" + // serviceInstanceId => NA
+ "|" + // threadId => NA
+ "|" + // physical server name => NA
+ "|" + this.getMe() + // serviceName method => operation
+ "|" + this.getFr() + // partnerName from => fromAppId
+ (audit ? "" :"|" + this.getTo()) + // TargetEntity => toAppID
+ (audit ? "" :"|") + //TargetServiceName => NA
+ "|" + this.getSs() + //StatusCode/success => NA
+ "|" + this.getEc() + //Response Code, is our error code => NA
+ "|" + this.getEt() + // Response Description, is our error text => NA
+ "|" + // instanceUUID => NA
+ "|" + this.getLevel() + // category => loglevel
+ "|" + // severity => NA
+ "|" + hostAddress + // Server IP address => hostAddress
+ "|" + timeTaken + // Timer => tt
+ "|" + hostName + // Server => hostName
+ "|" + // IP Address => NA
+ "|" + className + // className => className
+ "|" + //Unused => NA
+ "|" + //ProcessKey => NA
+ (audit ? "": "|") + //TargetVirtualEntity => NA
+ "|" + //CustomField1 => NA
+ "|" + //CustomField2 => NA
+ "|" + //CustomField3 => NA
+ "|" + //CustomField4 => NA
+ "|co=" + this.getCo() + // DetailMessage component => component
+ ":" + this.getUserContributed() + "|";
+
+
+ }
+
+
+ /**
+ * Return the finished log line, including success and elapsed time.
+ * This should be called at the end for INFO logs
+ *
+ * @param success the success
+ * @return the string
+ */
+ public String finish(boolean success) {
+ endTime = System.currentTimeMillis();
+ setSs((success ? "COMPLETE" : "ERROR"));
+ setTt(String.valueOf(endTime - startTime)); // tt is "time taken" or "elapsed time"
+ return getLine(false);
+ }
+
+ /**
+ * Gets the co.
+ *
+ * @return the co
+ */
+ private String getCo() {
+ return co;
+ }
+
+ /**
+ * Sets the co.
+ *
+ * @param co the new co
+ */
+ private void setCo(String co) {
+ this.co = co;
+ }
+
+ /**
+ * Gets the tr.
+ *
+ * @return the tr
+ */
+ private String getTr() {
+ return tr;
+ }
+
+ /**
+ * Sets the tr.
+ *
+ * @param tr the new tr
+ */
+ private void setTr(String tr) {
+ this.tr = tr;
+ }
+
+ /**
+ * Gets the level.
+ *
+ * @return the level
+ */
+ private String getLevel() {
+ return ll;
+ }
+
+ /**
+ * Sets the level.
+ *
+ * @param ll the new level
+ */
+ public void setLevel(String ll) {
+ this.ll = ll;
+ }
+
+ /**
+ * Gets the fr.
+ *
+ * @return the fr
+ */
+ private String getFr() {
+ return fr;
+ }
+
+ /**
+ * Sets the fr.
+ *
+ * @param fr the new fr
+ */
+ private void setFr(String fr) {
+ this.fr = fr;
+ }
+
+ /**
+ * Gets the to.
+ *
+ * @return the to
+ */
+ private String getTo() {
+ return to;
+ }
+
+ /**
+ * Sets the to.
+ *
+ * @param to the new to
+ */
+ private void setTo(String to) {
+ this.to = to;
+ }
+
+ /**
+ * Gets the me.
+ *
+ * @return the me
+ */
+ private String getMe() {
+ return me;
+ }
+
+ /**
+ * Sets the me.
+ *
+ * @param me the new me
+ */
+ private void setMe(String me) {
+ this.me = me;
+ }
+
+ /**
+ * Gets the tt.
+ *
+ * @return the tt
+ */
+ private String getTt() {
+ return tt;
+ }
+
+ /**
+ * Sets the tt.
+ *
+ * @param tt the new tt
+ */
+ private void setTt(String tt) {
+ this.tt = tt;
+ }
+
+ /**
+ * Gets the ss.
+ *
+ * @return the ss
+ */
+ private String getSs() {
+ return ss;
+ }
+
+ /**
+ * Sets the ss.
+ *
+ * @param ss the new ss
+ */
+ protected void setSs(String ss) {
+ this.ss = ss;
+ }
+
+ /**
+ * Sets the ss.
+ *
+ * @param ss the new ss
+ */
+ public void setSs(Boolean ss) {
+ if (ss)
+ this.ss = "y";
+ else
+ this.ss = "n";
+ }
+
+ /**
+ * Gets the ec.
+ *
+ * @return the ec
+ */
+ public String getEc() {
+ return ec;
+ }
+
+ /**
+ * Sets the ec.
+ *
+ * @param ec the new ec
+ */
+ public void setEc(String ec) {
+ this.ec = ec;
+ }
+
+ /**
+ * Gets the et.
+ *
+ * @return the et
+ */
+ public String getEt() {
+ return et;
+ }
+
+ /**
+ * Sets the et.
+ *
+ * @param et the new et
+ */
+ public void setEt(String et) {
+ this.et = et;
+ }
+
+
+ /**
+ * Gets the user contributed.
+ *
+ * @return the user contributed
+ */
+ private String getUserContributed() {
+ return userContributed;
+ }
+
+ /**
+ * Sets the user contributed.
+ *
+ * @param userContributed the new user contributed
+ */
+ protected void setUserContributed(String userContributed) {
+ this.userContributed = userContributed;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLineBuilder.java b/ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLineBuilder.java
new file mode 100644
index 0000000..dff4cce
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLineBuilder.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.logging;
+
+import java.util.UUID;
+
+public class LogLineBuilder {
+
+ private String component;
+ private final String transId;
+ private final String fromAppId;
+ private String operation;
+
+ /**
+ * Instantiates a new log line builder.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ */
+ public LogLineBuilder(String transId, String fromAppId) {
+ this.transId = transId;
+ this.fromAppId = fromAppId;
+ }
+
+ /**
+ * Instantiates a new log line builder.
+ */
+ public LogLineBuilder() {
+ this.transId = UUID.randomUUID().toString();
+ this.fromAppId = "AAI";
+ }
+
+ /**
+ * Builds the.
+ *
+ * @param component the component
+ * @param operation the operation
+ * @return the log line
+ */
+ public LogLine build(String component, String operation) {
+ LogLine line = new LogLine();
+ line.init(component, transId, fromAppId, operation);
+ return line;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/LegacyQueryParser.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/LegacyQueryParser.java
new file mode 100644
index 0000000..e943cd9
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/LegacyQueryParser.java
@@ -0,0 +1,163 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.Parsable;
+import org.openecomp.aai.parsers.uri.URIParser;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+/**
+ * The Class LegacyQueryParser.
+ */
+public class LegacyQueryParser extends QueryParser implements Parsable {
+
+ private Introspector previous = null;
+
+ /**
+ * Instantiates a new legacy query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ * @param uri the uri
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public LegacyQueryParser(Loader loader, QueryBuilder queryBuilder, URI uri) throws UnsupportedEncodingException, AAIException {
+ super(loader, queryBuilder, uri);
+ URIParser parser = new URIParser(loader, uri);
+ parser.parse(this);
+ }
+
+ /**
+ * Instantiates a new legacy query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ * @param uri the uri
+ * @param queryParams the query params
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public LegacyQueryParser(Loader loader, QueryBuilder queryBuilder, URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException {
+ super(loader, queryBuilder, uri);
+ URIParser parser = new URIParser(loader, uri, queryParams);
+ parser.parse(this);
+ }
+
+ /**
+ * Instantiates a new legacy query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ */
+ public LegacyQueryParser(Loader loader, QueryBuilder queryBuilder) {
+ super(loader, queryBuilder);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processObject(Introspector obj, Map<String, String> uriKeys) {
+ if (previous != null) {
+ this.parentResourceType = previous.getDbName();
+ queryBuilder.createEdgeTraversal(previous, obj);
+ }
+ for (String key : uriKeys.keySet()) {
+ obj.setValue(key, uriKeys.get(key));
+ //TODO probably need to check that these are actually indexed
+ queryBuilder.getVerticesByIndexedProperty(key, obj.getValue(key));
+ }
+ if (previous == null) {
+ queryBuilder.createContainerQuery(obj);
+ }
+ previous = obj;
+ this.resultResource = obj.getDbName();
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processContainer(Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) throws AAIException {
+ if (isFinalContainer) {
+ if (previous != null) {
+ this.parentResourceType = previous.getDbName();
+ queryBuilder.createEdgeTraversal(previous, obj);
+ }
+
+ queryBuilder.createContainerQuery(obj);
+
+ if (!uriKeys.isEmpty()) {
+ if (previous == null) {
+ queryBuilder.formBoundary();
+ }
+ Introspector child = obj.newIntrospectorInstanceOfNestedProperty(obj.getChildName());
+ for (String key : uriKeys.keySet()) {
+ try {
+ child.setValue(key, uriKeys.get(key));
+ } catch (IllegalArgumentException e) {
+ throw new AAIException("AAI_3000", e);
+ }
+ //TODO probably need to check that these are actually indexed
+ queryBuilder.getVerticesByIndexedProperty(key, child.getValue(key));
+ }
+ }
+
+ this.resultResource = obj.getChildDBName();
+ this.containerResource = obj.getName();
+ }
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processNamespace(Introspector obj) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String getCloudRegionTransform() {
+ return "add";
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public boolean useOriginalLoader() {
+ return false;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParser.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParser.java
new file mode 100644
index 0000000..813eb7f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParser.java
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.net.URI;
+
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+/**
+ * The Class QueryParser.
+ */
+public abstract class QueryParser {
+
+ protected Loader loader = null;
+
+ protected QueryBuilder queryBuilder = null;
+
+ protected QueryBuilder parentQueryBuilder = null;
+
+ protected URI uri = null;
+
+ protected String resultResource = "";
+
+ protected String parentResourceType = "";
+
+ protected String containerResource = "";
+
+ protected final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ * @param uri the uri
+ */
+ protected QueryParser(Loader loader, QueryBuilder queryBuilder, URI uri) {
+ this.uri = uri;
+ this.queryBuilder = queryBuilder;
+ this.loader = loader;
+ this.llBuilder = loader.getLogLineBuilder();
+ //this.init(loader, queryBuilder, uri);
+ }
+
+ /**
+ * Instantiates a new query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ */
+ protected QueryParser(Loader loader, QueryBuilder queryBuilder) {
+ this.queryBuilder = queryBuilder;
+ this.loader = loader;
+ this.llBuilder = loader.getLogLineBuilder();
+
+ }
+
+ /**
+ * Gets the container type.
+ *
+ * @return the container type
+ */
+ public String getContainerType() {
+
+ return this.containerResource;
+ }
+
+ /**
+ * Gets the parent result type.
+ *
+ * @return the parent result type
+ */
+ public String getParentResultType() {
+ return this.parentResourceType;
+ }
+
+ /**
+ * Gets the result type.
+ *
+ * @return the result type
+ */
+ public String getResultType() {
+ return this.resultResource;
+ }
+
+ /**
+ * Gets the query builder.
+ *
+ * @return the query builder
+ */
+ public QueryBuilder getQueryBuilder() {
+ return this.queryBuilder;
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @return the uri
+ */
+ public URI getUri() {
+ return this.uri;
+ }
+
+ /**
+ * Gets the parent query builder.
+ *
+ * @return the parent query builder
+ */
+ public QueryBuilder getParentQueryBuilder() {
+ if (this.parentQueryBuilder != null) {
+ return this.parentQueryBuilder;
+ } else {
+ return this.queryBuilder;
+ }
+ }
+
+ /**
+ * Checks if is dependent.
+ *
+ * @return true, if is dependent
+ */
+ public boolean isDependent() {
+ return !this.queryBuilder.getQuery().toString().equals(this.queryBuilder.getParentQuery().toString());
+ }
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParserStrategy.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParserStrategy.java
new file mode 100644
index 0000000..601f474
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParserStrategy.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+/**
+ * The Class QueryParserStrategy.
+ */
+public abstract class QueryParserStrategy {
+
+ protected Loader loader = null;
+
+ protected QueryBuilder builder = null;
+
+ /**
+ * Instantiates a new query parser strategy.
+ *
+ * @param loader the loader
+ * @param builder the builder
+ */
+ public QueryParserStrategy(Loader loader, QueryBuilder builder) {
+
+ this.loader = loader;
+ this.builder = builder;
+ }
+
+ /**
+ * Builds the URI parser.
+ *
+ * @param uri the uri
+ * @return the query parser
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public abstract QueryParser buildURIParser(URI uri) throws UnsupportedEncodingException, AAIException;
+
+ /**
+ * Builds the URI parser.
+ *
+ * @param uri the uri
+ * @param queryParams the query params
+ * @return the query parser
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public abstract QueryParser buildURIParser(URI uri,MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
+
+ /**
+ * Builds the relationship parser.
+ *
+ * @param obj the obj
+ * @return the query parser
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public abstract QueryParser buildRelationshipParser(Introspector obj) throws UnsupportedEncodingException, AAIException;
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/RelationshipQueryParser.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/RelationshipQueryParser.java
new file mode 100644
index 0000000..55b97d9
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/RelationshipQueryParser.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.relationship.RelationshipToURI;
+import org.openecomp.aai.parsers.uri.URIParser;
+import org.openecomp.aai.query.builder.QueryBuilder;
+import org.openecomp.aai.serialization.db.EdgeRules;
+
+import com.google.common.base.CaseFormat;
+
+/**
+ * The Class RelationshipQueryParser.
+ */
+public class RelationshipQueryParser extends LegacyQueryParser {
+
+ private Introspector relationship = null;
+
+ private ModelType modelType = null;
+
+ private EdgeRules edgeRules = null;
+
+ /**
+ * Instantiates a new relationship query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ * @param obj the obj
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public RelationshipQueryParser(Loader loader, QueryBuilder queryBuilder, Introspector obj) throws UnsupportedEncodingException, AAIException {
+ super(loader, queryBuilder);
+ this.relationship = obj;
+ this.modelType = obj.getModelType();
+ this.edgeRules = EdgeRules.getInstance();
+ RelationshipToURI rToUri = new RelationshipToURI(loader, obj);
+ this.uri = rToUri.getUri();
+ URIParser parser = new URIParser(loader, uri);
+ parser.parse(this);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/TraversalStrategy.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/TraversalStrategy.java
new file mode 100644
index 0000000..36dee24
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/TraversalStrategy.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+/**
+ * The Class TraversalStrategy.
+ */
+public class TraversalStrategy extends QueryParserStrategy {
+
+
+ /**
+ * Instantiates a new traversal strategy.
+ *
+ * @param loader the loader
+ * @param builder the builder
+ */
+ public TraversalStrategy(Loader loader, QueryBuilder builder) {
+ super(loader, builder);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser buildURIParser(URI uri) throws UnsupportedEncodingException, AAIException {
+ return new LegacyQueryParser(loader, builder, uri);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser buildRelationshipParser(Introspector obj) throws UnsupportedEncodingException, AAIException {
+ return new RelationshipQueryParser(loader, builder, obj);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser buildURIParser(URI uri, MultivaluedMap<String, String> queryParams)
+ throws UnsupportedEncodingException, AAIException {
+ return new LegacyQueryParser(loader, builder, uri, queryParams);
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryParser.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryParser.java
new file mode 100644
index 0000000..ee5df7f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryParser.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.relationship.RelationshipToURI;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+/**
+ * The Class UniqueRelationshipQueryParser.
+ */
+public class UniqueRelationshipQueryParser extends UniqueURIQueryParser {
+
+
+ /**
+ * Instantiates a new unique relationship query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ * @param obj the obj
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ */
+ public UniqueRelationshipQueryParser(Loader loader, QueryBuilder queryBuilder, Introspector obj) throws UnsupportedEncodingException, IllegalArgumentException, AAIException {
+ super(loader, queryBuilder);
+ RelationshipToURI rToUri = new RelationshipToURI(loader, obj);
+ UniqueURIQueryParser parser = new UniqueURIQueryParser(loader, queryBuilder, rToUri.getUri());
+ this.containerResource = parser.getContainerType();
+ this.resultResource = parser.getResultType();
+ this.queryBuilder = parser.getQueryBuilder();
+ this.parentQueryBuilder = parser.getParentQueryBuilder();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueStrategy.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueStrategy.java
new file mode 100644
index 0000000..75163c6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueStrategy.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+/**
+ * The Class UniqueStrategy.
+ */
+public class UniqueStrategy extends QueryParserStrategy {
+
+
+
+ /**
+ * Instantiates a new unique strategy.
+ *
+ * @param loader the loader
+ * @param builder the builder
+ */
+ public UniqueStrategy(Loader loader, QueryBuilder builder) {
+ super(loader, builder);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser buildURIParser(URI uri) throws UnsupportedEncodingException, IllegalArgumentException, AAIException {
+ return new UniqueURIQueryParser(loader, builder, uri);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser buildRelationshipParser(Introspector obj) throws UnsupportedEncodingException, AAIException {
+ return new UniqueRelationshipQueryParser(loader, builder, obj);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser buildURIParser(URI uri, MultivaluedMap<String, String> queryParams)
+ throws UnsupportedEncodingException, AAIException {
+ return new LegacyQueryParser(loader, builder, uri, queryParams);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueURIQueryParser.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueURIQueryParser.java
new file mode 100644
index 0000000..6237e05
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueURIQueryParser.java
@@ -0,0 +1,169 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.Map;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.parsers.uri.Parsable;
+import org.openecomp.aai.parsers.uri.URIParser;
+import org.openecomp.aai.parsers.uri.URIToDBKey;
+import org.openecomp.aai.query.builder.QueryBuilder;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+/**
+ * The Class UniqueURIQueryParser.
+ */
+public class UniqueURIQueryParser extends QueryParser implements Parsable {
+
+
+ private URIToDBKey dbKeyParser = null;
+
+ private Introspector previous = null;
+
+ private boolean endsInContainer = false;
+
+ private Introspector finalContainer = null;
+
+ private String parentName = "";
+
+ /**
+ * Instantiates a new unique URI query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ * @param uri the uri
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ */
+ public UniqueURIQueryParser(Loader loader, QueryBuilder queryBuilder, URI uri) throws UnsupportedEncodingException, IllegalArgumentException, AAIException {
+ super(loader, queryBuilder, uri);
+ URIParser parser = new URIParser(loader, uri);
+ parser.parse(this);
+
+ if (!endsInContainer) {
+ this.dbKeyParser = new URIToDBKey(loader, uri);
+ String dbKey = (String)dbKeyParser.getResult();
+ queryBuilder.getVerticesByIndexedProperty("aai-unique-key", dbKey);
+ queryBuilder.formBoundary();
+
+ if (!(parentName.equals("") || parentName.equals(this.resultResource))) {
+ URI parentUri = UriBuilder.fromPath(uri.getRawPath().substring(0, uri.getRawPath().indexOf(containerResource))).build();
+ this.dbKeyParser = new URIToDBKey(loader, parentUri);
+ this.parentQueryBuilder = queryBuilder.newInstance().getVerticesByIndexedProperty("aai-unique-key", (String)dbKeyParser.getResult());
+ this.parentResourceType = parentName;
+ }
+ this.containerResource = "";
+ } else {
+ URI parentUri = UriBuilder.fromPath(uri.getRawPath().substring(0, uri.getRawPath().indexOf(this.finalContainer.getDbName()))).build();
+ this.dbKeyParser = new URIToDBKey(loader, parentUri);
+ String dbKey = (String)dbKeyParser.getResult();
+ this.parentResourceType = parentName;
+
+ if (!dbKey.equals("")) {
+ queryBuilder.getVerticesByIndexedProperty("aai-unique-key", dbKey);
+ queryBuilder.formBoundary();
+ queryBuilder.createEdgeTraversal(previous, finalContainer);
+
+ }
+
+ queryBuilder.createContainerQuery(finalContainer);
+
+
+ }
+ }
+
+
+ /**
+ * Instantiates a new unique URI query parser.
+ *
+ * @param loader the loader
+ * @param queryBuilder the query builder
+ */
+ public UniqueURIQueryParser(Loader loader, QueryBuilder queryBuilder) {
+ super(loader, queryBuilder);
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processObject(Introspector obj, Map<String, String> uriKeys) {
+ this.resultResource = obj.getDbName();
+ if (previous != null) {
+ this.parentName = previous.getDbName();
+ }
+ this.previous = obj;
+
+
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processContainer(Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) {
+ this.containerResource = obj.getName();
+ if (previous != null) {
+ this.parentName = previous.getDbName();
+ }
+ if (isFinalContainer) {
+ this.endsInContainer = true;
+ this.resultResource = obj.getChildDBName();
+
+ this.finalContainer = obj;
+ }
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processNamespace(Introspector obj) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String getCloudRegionTransform() {
+ return "add";
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public boolean useOriginalLoader() {
+ return false;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/relationship/RelationshipToURI.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/relationship/RelationshipToURI.java
new file mode 100644
index 0000000..d23d055
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/relationship/RelationshipToURI.java
@@ -0,0 +1,217 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.relationship;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.EdgeRules;
+import org.openecomp.aai.workarounds.LegacyURLTransformer;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+/**
+ * The Class RelationshipToURI.
+ */
+public class RelationshipToURI {
+
+ private final String className = RelationshipToURI.class.getSimpleName();
+
+ private AAILogger aaiLogger = new AAILogger(RelationshipToURI.class.getName());
+
+ private Introspector relationship = null;
+
+ private Loader loader = null;
+
+ private ModelType modelType = null;
+
+ private EdgeRules edgeRules = null;
+
+ private URI uri = null;
+
+ private LegacyURLTransformer urlTransform = null;
+
+ /**
+ * Instantiates a new relationship to URI.
+ *
+ * @param loader the loader
+ * @param relationship the relationship
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public RelationshipToURI(Loader loader, Introspector relationship) throws UnsupportedEncodingException, AAIException {
+ this.relationship = relationship;
+ this.modelType = relationship.getModelType();
+ this.edgeRules = EdgeRules.getInstance();
+ this.loader = loader;
+ this.urlTransform = LegacyURLTransformer.getInstance();
+
+ this.parse();
+
+ }
+
+ /**
+ * Parses the.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ protected void parse() throws UnsupportedEncodingException, AAIException {
+ String relatedLink = (String)relationship.getValue("related-link");
+ StringBuilder uriBuilder = new StringBuilder();
+ if (relatedLink != null) {
+ try {
+ URL url = new URL (relatedLink);
+ String path = url.toString();
+ uriBuilder.append(url.getPath());
+ } catch (MalformedURLException e) {
+ AAIException ex = new AAIException("AAI_3009", e);
+ aaiLogger.error(ex.getErrorObject(), loader.getLogLineBuilder().build(className, "could not parse url"), e);
+
+ }
+ }
+ if (uriBuilder.length() == 0) {
+ List<Object> data = (List<Object>)relationship.getValue("relationship-data");
+ Introspector wrapper = null;
+ String key = "";
+ String value = "";
+ String objectType = "";
+ String propertyName = "";
+ String[] split = null;
+ HashMap<String, Introspector> map = new HashMap<>();
+ for (Object datum : data) {
+ wrapper = IntrospectorFactory.newInstance(modelType, datum, loader.getLogLineBuilder());
+ key = (String)wrapper.getValue("relationship-key");
+ value = (String)wrapper.getValue("relationship-value");
+ split = key.split("\\.");
+ if (split == null || split.length != 2) {
+ throw new AAIException("AAI_3000", "incorrect format for key must be of the form {node-type}.{property-name}");
+ }
+ //check node name ok
+ //check prop name ok
+ objectType = split[0];
+ propertyName = split[1];
+ Introspector wrappedObj = loader.introspectorFromName(objectType);
+ if (wrappedObj == null) {
+ throw new AAIException("AAI_3000", "invalid object name: " + objectType);
+ }
+ if (!wrappedObj.hasProperty(propertyName)) {
+ throw new AAIException("AAI_3000", "invalid property name: " + propertyName);
+ }
+ if (map.containsKey(objectType)) {
+ wrappedObj = map.get(objectType);
+ } else {
+ map.put(objectType, wrappedObj);
+ }
+ wrappedObj.setValue(propertyName, value);
+
+ }
+ String startType = (String)relationship.getValue("related-to");
+ List<String> nodeTypes = new ArrayList<>();
+ nodeTypes.addAll(map.keySet());
+
+ String displacedType = "";
+ for (int i = 0; i < nodeTypes.size(); i++) {
+ if (nodeTypes.get(i).equals(startType)) {
+ displacedType = nodeTypes.set(nodeTypes.size() - 1, startType);
+ nodeTypes.set(i, displacedType);
+ break;
+ }
+ }
+ sortRelationships(nodeTypes, startType, 1);
+
+ for (String type : nodeTypes) {
+ uriBuilder.append(map.get(type).getURI());
+ }
+ }
+
+ this.uri = UriBuilder.fromPath(uriBuilder.toString()).build();
+
+ }
+
+ /**
+ * Sort relationships.
+ *
+ * @param data the data
+ * @param startType the start type
+ * @param i the i
+ * @return true, if successful
+ */
+ private boolean sortRelationships(List<String> data, String startType, int i) {
+
+ if (i == data.size()) {
+ return true;
+ }
+ int j = 0;
+ String objectType = "";
+ String displacedObject = null;
+ EdgeRule rule = null;
+ String label = "";
+ Direction direction = null;
+ for (j = (data.size() - i) - 1; j >= 0; j--) {
+ objectType = data.get(j);
+ try {
+ rule = edgeRules.getEdgeRule(objectType, startType);
+ label = rule.getLabel();
+ direction = rule.getDirection();
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ }
+ if (!label.equals("") && (direction != null && direction.equals(Direction.OUT))) {
+ displacedObject = data.set((data.size() - i) - 1, data.get(j));
+ data.set(j, displacedObject);
+ if (sortRelationships(data, objectType, i+1)) {
+ return true;
+ } else {
+
+ }
+ }
+ }
+
+
+ return false;
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @return the uri
+ */
+ public URI getUri() {
+ return uri;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/Parsable.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/Parsable.java
new file mode 100644
index 0000000..0e80a74
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/Parsable.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import java.util.Map;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+
+/**
+ * The Interface Parsable.
+ */
+public interface Parsable {
+
+ /**
+ * Process object.
+ *
+ * @param obj the obj
+ * @param uriKeys the uri keys
+ */
+ public void processObject(Introspector obj, Map<String, String> uriKeys);
+
+ /**
+ * Process container.
+ *
+ * @param obj the obj
+ * @param uriKeys the uri keys
+ * @param isFinalContainer the is final container
+ * @throws AAIException the AAI exception
+ */
+ public void processContainer(Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) throws AAIException;
+
+ /**
+ * Process namespace.
+ *
+ * @param obj the obj
+ */
+ public void processNamespace(Introspector obj);
+
+ /**
+ * Gets the cloud region transform.
+ *
+ * @return the cloud region transform
+ */
+ public String getCloudRegionTransform();
+
+ /**
+ * Use original loader.
+ *
+ * @return true, if successful
+ */
+ public boolean useOriginalLoader();
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIParser.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIParser.java
new file mode 100644
index 0000000..3725344
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIParser.java
@@ -0,0 +1,272 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.util.AAIConfig;
+import org.springframework.web.util.UriUtils;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+/**
+ * The Class URIParser.
+ */
+public class URIParser {
+
+ private final String className = URIParser.class.getSimpleName();
+
+ private AAILogger aaiLogger = new AAILogger(URIParser.class.getName());
+
+ protected URI uri = null;
+
+ protected Loader loader = null;
+
+ protected Loader originalLoader = null;
+
+ private URI originalURI = null;
+
+ private MultivaluedMap<String, String> queryParams = null;
+
+ private final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new URI parser.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ */
+ public URIParser(Loader loader, URI uri) {
+ this.llBuilder = loader.getLogLineBuilder();
+ this.uri = uri;
+ /*Pattern p = Pattern.compile("(v\\d+)\\/");
+ Matcher m = p.matcher(uri);
+ Version version = null;
+ if (m.find()) {
+ version = Version.valueOf(m.group(1));
+ }
+ this.version = version;*/
+ String currentVersion = "v7";
+ this.originalLoader = loader;
+ try {
+ currentVersion = AAIConfig.get("aai.default.api.version");
+ } catch (AAIException e) {
+ aaiLogger.error(e.getErrorObject(), llBuilder.build(className, "read property file"), e);
+
+ }
+ this.loader = loader;
+ }
+
+ /**
+ * Instantiates a new URI parser.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ * @param queryParams the query params
+ */
+ public URIParser(Loader loader, URI uri, MultivaluedMap<String, String> queryParams) {
+ this(loader, uri);
+ this.queryParams = queryParams;
+ }
+
+ public Loader getLoader() {
+
+ return this.loader;
+
+ }
+
+ /**
+ * Gets the original URI.
+ *
+ * @return the original URI
+ */
+ public URI getOriginalURI() {
+ return this.originalURI;
+ }
+
+ /**
+ * Parses the.
+ *
+ * @param p the p
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public void parse(Parsable p) throws UnsupportedEncodingException, AAIException {
+ try {
+ uri = this.trimURI(uri);
+// uri = handleCloudRegion(p.getCloudRegionTransform(), uri);
+ if (p.useOriginalLoader()) {
+ this.loader = this.originalLoader;
+ }
+ this.originalURI = UriBuilder.fromPath(uri.getRawPath()).build();
+ String[] parts = uri.getRawPath().split("/");
+ Introspector validNamespaces = loader.introspectorFromName("inventory");
+ List<String> keys = null;
+ String part = "";
+ Introspector previousObj = null;
+
+ for (int i = 0; i < parts.length;) {
+ part = parts[i];
+ Introspector introspector = null;
+ introspector = loader.introspectorFromName(part);
+ if (introspector != null) {
+
+ //previous has current as property
+ if (previousObj != null && !previousObj.hasChild(introspector)) {
+ throw new AAIException("AAI_3001", uri + " not a valid path. " + part + " not valid");
+ } else if (previousObj == null) {
+ String abstractType = introspector.getMetadata("abstract");
+ if (abstractType == null) {
+ abstractType = "";
+ }
+ //first time through, make sure it starts from a namespace
+ //ignore abstract types
+ if (!abstractType.equals("true") && !validNamespaces.hasChild(introspector)) {
+ throw new AAIException("AAI_3000", uri + " not a valid path. It does not start from a valid namespace");
+ }
+ }
+
+ keys = introspector.getKeys();
+ if (keys.size() > 0) {
+ Map<String, String> uriKeys = new LinkedHashMap<>();
+ i++;
+ if (i == parts.length && queryParams != null) {
+ Set<String> queryKeys = queryParams.keySet();
+ for (String key : queryKeys) {
+ queryParams.get(key);
+ for (String value : queryParams.get(key)) {
+ value = UriUtils.decode(value, "UTF-8");
+
+ uriKeys.put(key, value);
+
+ }
+ }
+ } else {
+ for (String key : keys) {
+ part = UriUtils.decode(parts[i], "UTF-8");
+
+ uriKeys.put(key, part);
+
+ //skip this for further processing
+ i++;
+ }
+ }
+
+ p.processObject(introspector, uriKeys);
+
+ } else if (introspector.isContainer()) {
+ boolean isFinalContainer = i == parts.length-1;
+ Map<String, String> uriKeys = new LinkedHashMap<>();
+
+ if (isFinalContainer && queryParams != null) {
+ Set<String> queryKeys = queryParams.keySet();
+ for (String key : queryKeys) {
+ queryParams.get(key);
+ for (String value : queryParams.get(key)) {
+ value = UriUtils.decode(value, "UTF-8");
+
+ uriKeys.put(key, value);
+
+ }
+ }
+ }
+ p.processContainer(introspector, uriKeys, isFinalContainer);
+
+ i++;
+ } else {
+ p.processNamespace(introspector);
+ //namespace case
+ i++;
+ }
+ previousObj = introspector;
+ } else {
+ //invalid item found should log
+ //original said bad path
+ throw new AAIException("AAI_3001", "invalid item found in path: " + part);
+ }
+ }
+ } catch (AAIException e) {
+ throw new AAIException("AAI_" + e.getErrorObject().getErrorCode(), e.getErrorObject().getDetails());
+
+ } catch (Exception e) {
+
+ throw new AAIException("AAI_3001", e);
+
+ }
+ }
+
+ //public abstract Object getResult();
+
+ /**
+ * Handle cloud region.
+ *
+ * @param action the action
+ * @param uri the uri
+ * @return the uri
+ */
+// protected URI handleCloudRegion(String action, URI uri) {
+//
+// if (action.equals("add")) {
+// return this.cloudRegionWorkaround.addToUri(uri);
+// } else if (action.equals("remove")) {
+// return this.cloudRegionWorkaround.removeFromUri(uri);
+// } else {
+// return uri;
+// }
+// }
+
+ /**
+ * Trim URI.
+ *
+ * @param uri the uri
+ * @return the uri
+ */
+ protected URI trimURI(URI uri) {
+
+ String result = uri.getRawPath();
+ if (result.startsWith("/")) {
+ result = result.substring(1, result.length());
+ }
+
+ if (result.endsWith("/")) {
+ result = result.substring(0, result.length() - 1);
+ }
+
+ result = result.replaceFirst("aai/v\\d+/", "");
+ URI uriResult = UriBuilder.fromPath(result).build();
+ return uriResult;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToDBKey.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToDBKey.java
new file mode 100644
index 0000000..6ad3827
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToDBKey.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+
+import com.google.common.base.Joiner;
+
+/**
+ * Creates a Unique database key from a URI
+ *
+ * The key is of the form node-type/key(s).
+ */
+public class URIToDBKey implements Parsable {
+
+
+ private List<String> dbKeys = new ArrayList<>();
+
+ /**
+ * Instantiates a new URI to DB key.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public URIToDBKey(Loader loader, URI uri) throws IllegalArgumentException, AAIException, UnsupportedEncodingException {
+
+ URIParser parser = new URIParser(loader, uri);
+ parser.parse(this);
+ }
+ /*
+ public URIToDBKey(Version version, String uri) throws IllegalArgumentException {
+
+ super(version, uri);
+ try {
+ context = ModelInjestor.getInstance().getContextForVersion(version);
+ if (context == null) {
+ throw new IllegalArgumentException("could not find a context for version: " + version);
+ }
+ this.parse();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("uri not valid against our model: " + uri);
+ }
+ }*/
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processObject (Introspector obj, Map<String, String> uriKeys) {
+
+ dbKeys.add(obj.getDbName());
+
+ for (String key : uriKeys.keySet()) {
+ dbKeys.add(uriKeys.get(key).toString());
+ }
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processContainer (Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processNamespace(Introspector obj) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String getCloudRegionTransform() {
+ return "add";
+ }
+
+ /**
+ * Gets the result.
+ *
+ * @return the result
+ */
+ public Object getResult() {
+ return Joiner.on("/").join(this.dbKeys);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public boolean useOriginalLoader() {
+ return false;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToExtensionInformation.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToExtensionInformation.java
new file mode 100644
index 0000000..e6c5e4a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToExtensionInformation.java
@@ -0,0 +1,170 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.HttpMethod;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+
+/**
+ * The Class URIToExtensionInformation.
+ */
+public class URIToExtensionInformation implements Parsable {
+
+ private String namespace = "";
+
+ private String methodName = "";
+
+ private String topObject = "";
+
+ private List<String> pieces = null;
+
+ /**
+ * Instantiates a new URI to extension information.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public URIToExtensionInformation(Loader loader, URI uri) throws IllegalArgumentException, AAIException, UnsupportedEncodingException {
+ pieces = new ArrayList<>();
+ URIParser parser = new URIParser(loader, uri);
+ parser.parse(this);
+
+ this.methodName = Joiner.on("").join(this.pieces);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processObject(Introspector obj, Map<String, String> uriKeys) {
+ String upperCamel = toUpperCamel(obj.getDbName());
+ if (topObject.equals("")) {
+ topObject = upperCamel;
+ }
+ pieces.add(upperCamel);
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processContainer(Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) {
+ pieces.add(toUpperCamel(obj.getName()));
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processNamespace(Introspector obj) {
+ this.namespace = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, obj.getDbName());
+ pieces.add(toUpperCamel(obj.getDbName()));
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String getCloudRegionTransform() {
+ return "remove";
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public boolean useOriginalLoader() {
+ return true;
+ }
+
+ /**
+ * Gets the namespace.
+ *
+ * @return the namespace
+ */
+ public String getNamespace() {
+ return this.namespace;
+ }
+
+ /**
+ * Gets the top object.
+ *
+ * @return the top object
+ */
+ public String getTopObject() {
+ return this.topObject;
+ }
+
+ /**
+ * Gets the method name.
+ *
+ * @param httpMethod the http method
+ * @param isPreprocess the is preprocess
+ * @return the method name
+ */
+ public String getMethodName(HttpMethod httpMethod, boolean isPreprocess) {
+ String result = "Dynamic";
+ if (httpMethod.equals(HttpMethod.PUT)) {
+ result += "Add";
+ } else if (httpMethod.equals(HttpMethod.DELETE)) {
+ result += "Del";
+ } else {
+ throw new IllegalArgumentException("http method not supported: " + httpMethod);
+ }
+ result += this.methodName;
+
+ if (isPreprocess) {
+ result += "PreProc";
+ } else {
+ result += "PostProc";
+ }
+ return result;
+ }
+
+ /**
+ * To upper camel.
+ *
+ * @param name the name
+ * @return the string
+ */
+ private String toUpperCamel(String name) {
+ String result = "";
+ result = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
+ return result;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToObject.java
new file mode 100644
index 0000000..3c5c9da
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToObject.java
@@ -0,0 +1,224 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.Version;
+
+/**
+ * Given a URI this class returns an object, or series of nested objects
+ * with their keys populated based off the values in the URI.
+ *
+ * It populates the keys in the order they are listed in the model.
+ *
+
+ *
+ */
+public class URIToObject implements Parsable {
+
+
+ private Introspector topEntity = null;
+
+ private String topEntityName = null;
+
+ private String entityName = null;
+
+ private Introspector entity = null;
+
+ private Introspector previous = null;
+
+ private List<Object> parentList = null;
+
+ private Version version = null;
+ private Loader loader = null;
+ private final HashMap<String, Introspector> relatedObjects;
+
+ /**
+ * Instantiates a new URI to object.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public URIToObject(Loader loader, URI uri) throws IllegalArgumentException, AAIException, UnsupportedEncodingException {
+
+ URIParser parser = new URIParser(loader, uri);
+ this.relatedObjects = new HashMap<>();
+
+ parser.parse(this);
+ this.loader = parser.getLoader();
+ this.version = loader.getVersion();
+ }
+ public URIToObject(Loader loader, URI uri, HashMap<String, Introspector> relatedObjects) throws IllegalArgumentException, AAIException, UnsupportedEncodingException {
+
+ URIParser parser = new URIParser(loader, uri);
+ this.relatedObjects = relatedObjects;
+
+ parser.parse(this);
+ this.loader = parser.getLoader();
+ this.version = loader.getVersion();
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processObject(Introspector obj, Map<String, String> uriKeys) {
+
+ if (this.entityName == null) {
+ this.topEntityName = obj.getDbName();
+ this.topEntity = obj;
+ }
+ this.entityName = obj.getDbName();
+ this.entity = obj;
+ this.parentList = (List<Object>)this.previous.getValue(obj.getName());
+ this.parentList.add(entity.getUnderlyingObject());
+
+ for (String key : uriKeys.keySet()) {
+ entity.setValue(key, uriKeys.get(key));
+ }
+ try {
+ if (relatedObjects.containsKey(entity.getObjectId())) {
+ Introspector relatedObject = relatedObjects.get(entity.getObjectId());
+ String nameProp = relatedObject.getMetadata("nameProps");
+ if (nameProp == null) {
+ nameProp = "";
+ }
+ if (nameProp != null && !nameProp.equals("")) {
+ String[] nameProps = nameProp.split(",");
+ for (String prop : nameProps) {
+ entity.setValue(prop, relatedObject.getValue(prop));
+ }
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ }
+ this.previous = entity;
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processContainer(Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) {
+
+ this.previous = obj;
+
+ if (this.entity != null) {
+ this.entity.setValue(obj.getName(), obj.getUnderlyingObject());
+ }
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processNamespace(Introspector obj) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String getCloudRegionTransform() {
+ return "add";
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public boolean useOriginalLoader() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * Gets the top entity.
+ *
+ * @return the top entity
+ */
+ public Introspector getTopEntity() {
+ return this.topEntity;
+ }
+
+ /**
+ * Gets the entity.
+ *
+ * @return the entity
+ */
+ public Introspector getEntity() {
+ return this.entity;
+ }
+
+ /**
+ * Gets the parent list.
+ *
+ * @return the parent list
+ */
+ public List<Object> getParentList() {
+ return this.parentList;
+ }
+
+ /**
+ * Gets the entity name.
+ *
+ * @return the entity name
+ */
+ public String getEntityName() {
+ return this.entityName;
+ }
+
+ /**
+ * Gets the top entity name.
+ *
+ * @return the top entity name
+ */
+ public String getTopEntityName() {
+ return this.topEntityName;
+ }
+
+ /**
+ * Gets the object version.
+ *
+ * @return the object version
+ */
+ public Version getObjectVersion() {
+ return this.loader.getVersion();
+ }
+ public Loader getLoader() {
+ return this.loader;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToRelationshipObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToRelationshipObject.java
new file mode 100644
index 0000000..89372ae
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToRelationshipObject.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.LegacyMoxyConsumer;
+import org.openecomp.aai.util.AAIApiServerURLBase;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.workarounds.LegacyURLTransformer;
+import org.openecomp.aai.workarounds.NamingExceptions;
+
+/**
+ * Given a URI a Relationship Object is returned.
+ *
+ * The relationship-data objects are created from the keys in the model.
+ * The keys are processed in the order they appear in the model.
+
+ *
+ */
+public class URIToRelationshipObject implements Parsable {
+
+ private final String className = URIToRelationshipObject.class.getSimpleName();
+
+ private AAILogger aaiLogger = new AAILogger(URIToRelationshipObject.class.getName());
+
+ private Introspector result = null;
+
+ private DynamicJAXBContext context = null;
+
+ private NamingExceptions exceptions = null;
+
+ private LegacyURLTransformer urlTransformer = null;
+
+ private Version originalVersion = null;
+
+ private Introspector relationship = null;
+
+ private Loader loader = null;
+
+ /**
+ * Instantiates a new URI to relationship object.
+ *
+ * @param loader the loader
+ * @param uri the uri
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ public URIToRelationshipObject(Loader loader, URI uri) throws IllegalArgumentException, AAIException, UnsupportedEncodingException, MalformedURLException {
+
+ this.loader = loader;
+ exceptions = NamingExceptions.getInstance();
+ urlTransformer = LegacyURLTransformer.getInstance();
+ originalVersion = loader.getVersion();
+ relationship = loader.introspectorFromName("relationship");
+ URIParser parser = new URIParser(loader, uri);
+ parser.parse(this);
+ URI originalUri = parser.getOriginalURI();
+ String baseURL = "";
+ try {
+ baseURL = AAIApiServerURLBase.get(originalVersion);
+ } catch (AAIException e) {
+
+ aaiLogger.error(e.getErrorObject(), loader.getLogLineBuilder().build(className, "read property file"), e);
+
+ }
+ URL relatedLink = new URL(baseURL + originalVersion + "/" + originalUri);
+ relationship.setValue("related-link", relatedLink + "/");
+
+
+ result = relationship;
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String getCloudRegionTransform(){
+ return "remove";
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processObject(Introspector obj, Map<String, String> uriKeys) {
+
+
+ for (String key : uriKeys.keySet()) {
+
+ Introspector data = loader.introspectorFromName("relationship-data");
+ data.setValue("relationship-key", obj.getDbName() + "." + key);
+ data.setValue("relationship-value", uriKeys.get(key));
+
+ ((List<Object>)relationship.getValue("relationship-data")).add(data.getUnderlyingObject());
+
+ }
+ relationship.setValue("related-to", obj.getDbName());
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processContainer(Introspector obj, Map<String, String> uriKeys, boolean isFinalContainer) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void processNamespace(Introspector obj) {
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public boolean useOriginalLoader() {
+ return true;
+ }
+
+ /**
+ * Gets the result.
+ *
+ * @return the result
+ */
+ public Introspector getResult() {
+ return this.result;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GraphTraversalBuilder.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GraphTraversalBuilder.java
new file mode 100644
index 0000000..8f85ffb
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GraphTraversalBuilder.java
@@ -0,0 +1,275 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+
+import java.nio.channels.Pipe;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.EdgeRules;
+
+/**
+ * The Class GraphTraversalBuilder.
+ */
+public abstract class GraphTraversalBuilder extends QueryBuilder {
+
+ private GraphTraversal<Vertex, Vertex> traversal = null;
+
+ private EdgeRules edgeRules = EdgeRules.getInstance();
+
+ private int parentStepIndex = 0;
+
+ private int stepIndex = 0;
+
+ /**
+ * Instantiates a new graph traversal builder.
+ *
+ * @param loader the loader
+ */
+ public GraphTraversalBuilder(Loader loader) {
+ super(loader);
+
+ traversal = __.start();
+
+ }
+
+ /**
+ * Instantiates a new graph traversal builder.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public GraphTraversalBuilder(Loader loader, Vertex start) {
+ super(loader, start);
+
+ traversal = __.__(start);
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getVerticesByIndexedProperty(String key, Object value) {
+
+ return this.getVerticesByProperty(key, value);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getVerticesByProperty(String key, Object value) {
+
+ //this is because the index is registered as an Integer
+ if (value != null && value.getClass().equals(Long.class)) {
+ traversal.has(key,new Integer(value.toString()));
+ } else {
+ traversal.has(key, value);
+ }
+ stepIndex++;
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getChildVerticesFromParent(String parentKey, String parentValue, String childType) {
+ traversal.has(parentKey, parentValue).has(AAIProperties.NODE_TYPE, childType);
+ stepIndex++;
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getTypedVerticesByMap(String type, LinkedHashMap<String, String> map) {
+
+ for (String key : map.keySet()) {
+ traversal.has(key, map.get(key));
+ stepIndex++;
+ }
+ traversal.has(AAIProperties.NODE_TYPE, type);
+ stepIndex++;
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createDBQuery(Introspector obj) {
+ this.createKeyQuery(obj);
+ this.createContainerQuery(obj);
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createKeyQuery(Introspector obj) {
+ List<String> keys = obj.getKeys();
+ Object val = null;
+ for (String key : keys) {
+ val = obj.getValue(key);
+ //this is because the index is registered as an Integer
+ if (val != null && val.getClass().equals(Long.class)) {
+ traversal.has(key,new Integer(val.toString()));
+ } else {
+ traversal.has(key, val);
+ }
+ stepIndex++;
+ }
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+
+ public QueryBuilder createContainerQuery(Introspector obj) {
+ String type = obj.getChildDBName();
+ String abstractType = obj.getMetadata("abstract");
+ if (abstractType != null) {
+ String[] inheritors = obj.getMetadata("inheritors").split(",");
+ Traversal<Vertex, Vertex>[] traversals = new Traversal[inheritors.length];
+ for (int i = 0; i < inheritors.length; i++) {
+ traversals[i] = __.has(AAIProperties.NODE_TYPE, inheritors[i]);
+ }
+ traversal.or(traversals);
+ } else {
+ traversal.has(AAIProperties.NODE_TYPE, type);
+ }
+ stepIndex++;
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createEdgeTraversal(Introspector parent, Introspector child) {
+ String parentName = parent.getDbName();
+ String childName = child.getDbName();
+ if (parent.isContainer()) {
+ parentName = parent.getChildDBName();
+ }
+ if (child.isContainer()) {
+ childName = child.getChildDBName();
+ }
+ this.edgeQuery(parentName, childName);
+ return this;
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createEdgeTraversal(Vertex parent, Introspector child) {
+
+ String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ this.edgeQuery(nodeType, child.getDbName());
+ return this;
+
+ }
+
+ /**
+ * Edge query.
+ *
+ * @param outType the out type
+ * @param inType the in type
+ */
+ private void edgeQuery(String outType, String inType) {
+ formBoundary();
+ EdgeRule rule;
+ String label = "";
+ try {
+ rule = edgeRules.getEdgeRule(outType, inType);
+ label = rule.getLabel();
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ }
+ traversal = traversal.out(label);
+ stepIndex++;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Object getQuery() {
+ return this.traversal;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Object getParentQuery() {
+ if (parentStepIndex == 0) {
+ parentStepIndex = stepIndex;
+ }
+ GraphTraversal<Vertex, Vertex> clone = this.traversal.asAdmin().clone();
+ GraphTraversal.Admin<Vertex, Vertex> cloneAdmin = clone.asAdmin();
+ List<Step> steps = cloneAdmin.getSteps();
+
+ //add two for the garbage identity pipes
+ for (int i = steps.size()-1; i >= parentStepIndex; i--) {
+ cloneAdmin.removeStep(i);
+ }
+
+ return cloneAdmin;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void formBoundary() {
+ parentStepIndex = stepIndex;
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Vertex getStart() {
+ return this.start;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineBuilder.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineBuilder.java
new file mode 100644
index 0000000..ec3dc47
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineBuilder.java
@@ -0,0 +1,215 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+/*
+package org.openecomp.aai.query.builder;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.EdgeRules;
+
+public abstract class GremlinPipelineBuilder extends QueryBuilder {
+
+ private GremlinPipeline pipeline = null;
+ private EdgeRules edgeRules = EdgeRules.getInstance();
+ private int parentStepIndex = 0;
+ private int stepIndex = 0;
+
+ public GremlinPipelineBuilder(Loader loader) {
+ super(loader);
+
+ pipeline = new GremlinPipeline(new IdentityPipe()).V();
+
+ }
+
+ public GremlinPipelineBuilder(Loader loader, Vertex start) {
+ super(loader, start);
+
+ pipeline = new GremlinPipeline(start);
+
+ }
+
+ @Override
+ public QueryBuilder getVerticesByIndexedProperty(String key, Object value) {
+
+ return this.getVerticesByProperty(key, value);
+ }
+
+ @Override
+ public QueryBuilder getVerticesByProperty(String key, Object value) {
+
+ //this is because the index is registered as an Integer
+ if (value != null && value.getClass().equals(Long.class)) {
+ pipeline.has(key,new Integer(value.toString()));
+ } else {
+ pipeline.has(key, value);
+ }
+ stepIndex++;
+ return this;
+ }
+
+ @Override
+ public QueryBuilder getChildVerticesFromParent(String parentKey, String parentValue, String childType) {
+ pipeline.has(parentKey, parentValue).has(AAIProperties.NODE_TYPE, childType);
+ stepIndex++;
+ return this;
+ }
+
+ @Override
+ public QueryBuilder getTypedVerticesByMap(String type, LinkedHashMap<String, String> map) {
+
+ for (String key : map.keySet()) {
+ pipeline.has(key, map.get(key));
+ stepIndex++;
+ }
+ pipeline.has(AAIProperties.NODE_TYPE, type);
+ stepIndex++;
+ return this;
+ }
+
+ @Override
+ public QueryBuilder createDBQuery(Introspector obj) {
+ this.createKeyQuery(obj);
+ this.createContainerQuery(obj);
+ return this;
+ }
+
+ @Override
+ public QueryBuilder createKeyQuery(Introspector obj) {
+ List<String> keys = obj.getKeys();
+ Object val = null;
+ for (String key : keys) {
+ val = obj.getValue(key);
+ //this is because the index is registered as an Integer
+ if (val != null && val.getClass().equals(Long.class)) {
+ pipeline.has(key,new Integer(val.toString()));
+ } else {
+ pipeline.has(key, val);
+ }
+ stepIndex++;
+ }
+ return this;
+ }
+
+ @Override
+
+ public QueryBuilder createContainerQuery(Introspector obj) {
+ String type = obj.getChildDBName();
+ String abstractType = obj.getMetadata("abstract");
+ if (abstractType != null) {
+ String[] inheritors = obj.getMetadata("inheritors").split(",");
+ GremlinPipeline[] pipes = new GremlinPipeline[inheritors.length];
+ for (int i = 0; i < inheritors.length; i++) {
+ pipes[i] = new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, inheritors[i]);
+ }
+ pipeline.or(pipes);
+ } else {
+ pipeline.has(AAIProperties.NODE_TYPE, type);
+ }
+ stepIndex++;
+ return this;
+ }
+
+ @Override
+ public QueryBuilder createEdgeTraversal(Introspector parent, Introspector child) {
+ String parentName = parent.getDbName();
+ String childName = child.getDbName();
+ String isAbstractType = parent.getMetadata("abstract");
+ if ("true".equals(isAbstractType)) {
+ formBoundary();
+ pipeline.outE().has("isParent", true).inV();
+ } else {
+ if (parent.isContainer()) {
+ parentName = parent.getChildDBName();
+ }
+ if (child.isContainer()) {
+ childName = child.getChildDBName();
+ }
+ this.edgeQuery(parentName, childName);
+ }
+ return this;
+
+ }
+
+ @Override
+ public QueryBuilder createEdgeTraversal(Vertex parent, Introspector child) {
+
+ String nodeType = parent.getProperty(AAIProperties.NODE_TYPE);
+ this.edgeQuery(nodeType, child.getDbName());
+ return this;
+
+ }
+
+ private void edgeQuery(String outType, String inType) {
+ formBoundary();
+ EdgeRule rule;
+ String label = "";
+ try {
+ rule = edgeRules.getEdgeRule(outType, inType);
+ label = rule.getLabel();
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ }
+ pipeline = pipeline.out(label);
+ stepIndex++;
+ }
+
+ @Override
+ public Object getQuery() {
+ return this.pipeline;
+ }
+
+ @Override
+ public Object getParentQuery() {
+ GremlinPipeline parent = new GremlinPipeline();
+ if (parentStepIndex == 0) {
+ parentStepIndex = stepIndex;
+ }
+ List<Pipe> pipes = this.pipeline.getPipes();
+ //add two for the garbage identity pipes
+ for (int i = 0; i < parentStepIndex + 2; i++) {
+ parent.add(pipes.get(i));
+ }
+
+ return parent;
+ }
+
+ @Override
+ public void formBoundary() {
+ parentStepIndex = stepIndex;
+ }
+
+
+ @Override
+ public Vertex getStart() {
+ return this.start;
+ }
+
+}
+*/
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineTraversal.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineTraversal.java
new file mode 100644
index 0000000..6048542
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineTraversal.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+/*
+package org.openecomp.aai.query.builder;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.query.TraversalStrategy;
+
+public class GremlinPipelineTraversal extends GremlinPipelineBuilder {
+
+ public GremlinPipelineTraversal(Loader loader) {
+ super(loader);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ public GremlinPipelineTraversal(Loader loader, Vertex start) {
+ super(loader, start);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ @Override
+ public QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri);
+ }
+
+ @Override
+ public QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException {
+ return factory.buildRelationshipParser(relationship);
+ }
+
+ @Override
+ public QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams)
+ throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri, queryParams);
+ }
+
+ @Override
+ public QueryBuilder newInstance(Vertex start) {
+ return new GremlinPipelineTraversal(loader, start);
+ }
+
+ @Override
+ public QueryBuilder newInstance() {
+ return new GremlinPipelineTraversal(loader);
+ }
+
+}
+*/
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinQueryBuilder.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinQueryBuilder.java
new file mode 100644
index 0000000..c80c92c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinQueryBuilder.java
@@ -0,0 +1,273 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.EdgeRules;
+
+import com.google.common.base.Joiner;
+
+/**
+ * The Class GremlinQueryBuilder.
+ */
+public abstract class GremlinQueryBuilder extends QueryBuilder {
+
+ private EdgeRules edgeRules = EdgeRules.getInstance();
+
+ private List<String> list = null;
+
+ private int parentStepIndex = 0;
+
+ private int stepIndex = 0;
+
+ /**
+ * Instantiates a new gremlin query builder.
+ *
+ * @param loader the loader
+ */
+ public GremlinQueryBuilder(Loader loader) {
+ super(loader);
+ list = new ArrayList<String>();
+ }
+
+ /**
+ * Instantiates a new gremlin query builder.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public GremlinQueryBuilder(Loader loader, Vertex start) {
+ super(loader, start);
+ list = new ArrayList<String>();
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createDBQuery(Introspector obj) {
+ this.createKeyQuery(obj);
+ this.createContainerQuery(obj);
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getVerticesByIndexedProperty(String key, Object value) {
+ return this.getVerticesByProperty(key, value);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getVerticesByProperty(String key, Object value) {
+
+ String term = "";
+ if (value != null && !value.getClass().getName().equals("java.lang.String")) {
+ term = value.toString();
+ } else {
+ term = "'" + value + "'";
+ }
+ list.add(".has('" + key + "', " + term + ")");
+ stepIndex++;
+ return this;
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getChildVerticesFromParent(String parentKey, String parentValue, String childType) {
+ /*
+ String query = ".has('aai-node-type', '" + childType + "')";
+
+ return this.processGremlinQuery(parentKey, parentValue, query);
+ */
+ //TODO
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder getTypedVerticesByMap(String type, LinkedHashMap<String, String> map) {
+
+ for (String key : map.keySet()) {
+ list.add(".has('" + key + "', '" + map.get(key) + "')");
+ stepIndex++;
+ }
+ list.add(".has('aai-node-type', '" + type + "')");
+ stepIndex++;
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createKeyQuery(Introspector obj) {
+ List<String> keys = obj.getKeys();
+
+ for (String key : keys) {
+
+ this.getVerticesByProperty(key, obj.getValue(key));
+
+ }
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createEdgeTraversal(Introspector parent, Introspector child) {
+ String parentName = parent.getDbName();
+ String childName = child.getDbName();
+ if (parent.isContainer()) {
+ parentName = parent.getChildDBName();
+ }
+ if (child.isContainer()) {
+ childName = child.getChildDBName();
+ }
+ this.edgeQuery(parentName, childName);
+ return this;
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createEdgeTraversal(Vertex parent, Introspector child) {
+ String nodeType = parent.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ this.edgeQuery(nodeType, child.getDbName());
+
+ return this;
+
+ }
+
+ /**
+ * Edge query.
+ *
+ * @param outType the out type
+ * @param inType the in type
+ */
+ private void edgeQuery(String outType, String inType) {
+ formBoundary();
+ EdgeRule rule;
+ String label = "";
+ try {
+ rule = edgeRules.getEdgeRule(outType, inType);
+ label = rule.getLabel();
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ }
+ list.add(".out('" +
+ label + "')");
+ stepIndex++;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder createContainerQuery(Introspector obj) {
+ String type = obj.getChildDBName();
+ String abstractType = obj.getMetadata("abstract");
+ if (abstractType != null) {
+ String command = ".or(";
+ List<String> ors = new ArrayList<>();
+ String[] inheritors = obj.getMetadata("inheritors").split(",");
+ for (int i = 0; i < inheritors.length; i++) {
+ ors.add("_().has('aai-node-type', '" + inheritors[i] + "')");
+ }
+ command += Joiner.on(",").join(ors);
+ command += ")";
+ list.add(command);
+ } else {
+ list.add(".has('aai-node-type', '" + type + "')");
+ }
+ stepIndex++;
+
+ return this;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Object getParentQuery() {
+ StringBuilder sb = new StringBuilder();
+ if (parentStepIndex == 0) {
+ parentStepIndex = stepIndex;
+ }
+ for (int i = 0; i < parentStepIndex; i++) {
+ sb.append(this.list.get(i));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Object getQuery() {
+ StringBuilder sb = new StringBuilder();
+
+ for (String piece : this.list) {
+ sb.append(piece);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public void formBoundary() {
+ parentStepIndex = stepIndex;
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Vertex getStart() {
+ return this.start;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinTraversal.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinTraversal.java
new file mode 100644
index 0000000..5d89cde
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinTraversal.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.query.TraversalStrategy;
+
+/**
+ * The Class GremlinTraversal.
+ */
+public class GremlinTraversal extends GremlinQueryBuilder {
+
+ /**
+ * Instantiates a new gremlin traversal.
+ *
+ * @param loader the loader
+ */
+ public GremlinTraversal(Loader loader) {
+ super(loader);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ /**
+ * Instantiates a new gremlin traversal.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public GremlinTraversal(Loader loader, Vertex start) {
+ super(loader, start);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException {
+ return factory.buildRelationshipParser(relationship);
+ }
+
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams)
+ throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri, queryParams);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder newInstance(Vertex start) {
+ return new GremlinTraversal(loader, start);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder newInstance() {
+ return new GremlinTraversal(loader);
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinUnique.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinUnique.java
new file mode 100644
index 0000000..cd1eaad
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinUnique.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.query.UniqueStrategy;
+
+/**
+ * The Class GremlinUnique.
+ */
+public class GremlinUnique extends GremlinQueryBuilder {
+
+ /**
+ * Instantiates a new gremlin unique.
+ *
+ * @param loader the loader
+ */
+ public GremlinUnique(Loader loader) {
+ super(loader);
+ this.factory = new UniqueStrategy(this.loader, this);
+ }
+
+ /**
+ * Instantiates a new gremlin unique.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public GremlinUnique(Loader loader, Vertex start) {
+ super(loader, start);
+ this.factory = new UniqueStrategy(this.loader, this);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException {
+ return factory.buildRelationshipParser(relationship);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams)
+ throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri, queryParams);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder newInstance() {
+ return new GremlinUnique(loader);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder newInstance(Vertex start) {
+ return new GremlinUnique(loader, start);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/QueryBuilder.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/QueryBuilder.java
new file mode 100644
index 0000000..8dc1c41
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/QueryBuilder.java
@@ -0,0 +1,221 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.LinkedHashMap;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.query.QueryParserStrategy;
+
+/**
+ * The Class QueryBuilder.
+ */
+public abstract class QueryBuilder {
+
+ protected QueryParserStrategy factory = null;
+
+ protected Loader loader = null;
+
+ protected boolean optimize = false;
+
+ protected Vertex start = null;
+
+ /**
+ * Instantiates a new query builder.
+ *
+ * @param loader the loader
+ */
+ public QueryBuilder(Loader loader) {
+ this.loader = loader;
+ }
+
+ /**
+ * Instantiates a new query builder.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public QueryBuilder(Loader loader, Vertex start) {
+ this.loader = loader;
+ this.start = start;
+ }
+
+ /**
+ * Gets the vertices by indexed property.
+ *
+ * @param key the key
+ * @param value the value
+ * @return the vertices by indexed property
+ */
+ public abstract QueryBuilder getVerticesByIndexedProperty(String key, Object value);
+
+ /**
+ * Gets the vertices by property.
+ *
+ * @param key the key
+ * @param value the value
+ * @return the vertices by property
+ */
+ public abstract QueryBuilder getVerticesByProperty(String key, Object value);
+
+ /**
+ * Gets the child vertices from parent.
+ *
+ * @param parentKey the parent key
+ * @param parentValue the parent value
+ * @param childType the child type
+ * @return the child vertices from parent
+ */
+ public abstract QueryBuilder getChildVerticesFromParent(String parentKey, String parentValue, String childType);
+
+ /**
+ * Gets the typed vertices by map.
+ *
+ * @param type the type
+ * @param map the map
+ * @return the typed vertices by map
+ */
+ public abstract QueryBuilder getTypedVerticesByMap(String type, LinkedHashMap<String, String> map);
+
+ /**
+ * Creates the DB query.
+ *
+ * @param obj the obj
+ * @return the query builder
+ */
+ public abstract QueryBuilder createDBQuery(Introspector obj);
+
+ /**
+ * Creates the key query.
+ *
+ * @param obj the obj
+ * @return the query builder
+ */
+ public abstract QueryBuilder createKeyQuery(Introspector obj);
+
+ /**
+ * Creates the container query.
+ *
+ * @param obj the obj
+ * @return the query builder
+ */
+ public abstract QueryBuilder createContainerQuery(Introspector obj);
+
+ /**
+ * Creates the edge traversal.
+ *
+ * @param parent the parent
+ * @param child the child
+ * @return the query builder
+ */
+ public abstract QueryBuilder createEdgeTraversal(Introspector parent, Introspector child);
+
+ /**
+ * Creates the edge traversal.
+ *
+ * @param parent the parent
+ * @param child the child
+ * @return the query builder
+ */
+ public abstract QueryBuilder createEdgeTraversal(Vertex parent, Introspector child);
+
+ /**
+ * Creates the query from URI.
+ *
+ * @param uri the uri
+ * @return the query parser
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public abstract QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException;
+
+ /**
+ * Creates the query from URI.
+ *
+ * @param uri the uri
+ * @param queryParams the query params
+ * @return the query parser
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public abstract QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams) throws UnsupportedEncodingException, AAIException;
+
+ /**
+ * Creates the query from relationship.
+ *
+ * @param relationship the relationship
+ * @return the query parser
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public abstract QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException;
+
+ /**
+ * Gets the parent query.
+ *
+ * @return the parent query
+ */
+ public abstract Object getParentQuery();
+
+ /**
+ * Gets the query.
+ *
+ * @return the query
+ */
+ public abstract Object getQuery();
+
+ /**
+ * Form boundary.
+ */
+ public abstract void formBoundary();
+
+ /**
+ * New instance.
+ *
+ * @param start the start
+ * @return the query builder
+ */
+ public abstract QueryBuilder newInstance(Vertex start);
+
+ /**
+ * New instance.
+ *
+ * @return the query builder
+ */
+ public abstract QueryBuilder newInstance();
+
+ /**
+ * Gets the start.
+ *
+ * @return the start
+ */
+ public abstract Vertex getStart();
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/TraversalQuery.java b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/TraversalQuery.java
new file mode 100644
index 0000000..fba752e
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/query/builder/TraversalQuery.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.query.builder;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.query.TraversalStrategy;
+
+/**
+ * The Class TraversalQuery.
+ */
+public class TraversalQuery extends GraphTraversalBuilder {
+
+ /**
+ * Instantiates a new traversal query.
+ *
+ * @param loader the loader
+ */
+ public TraversalQuery(Loader loader) {
+ super(loader);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ /**
+ * Instantiates a new traversal query.
+ *
+ * @param loader the loader
+ * @param start the start
+ */
+ public TraversalQuery(Loader loader, Vertex start) {
+ super(loader, start);
+ this.factory = new TraversalStrategy(this.loader, this);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromURI(URI uri) throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromRelationship(Introspector relationship) throws UnsupportedEncodingException, AAIException {
+ return factory.buildRelationshipParser(relationship);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryParser createQueryFromURI(URI uri, MultivaluedMap<String, String> queryParams)
+ throws UnsupportedEncodingException, AAIException {
+ return factory.buildURIParser(uri, queryParams);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder newInstance(Vertex start) {
+ return new TraversalQuery(loader, start);
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public QueryBuilder newInstance() {
+ return new TraversalQuery(loader);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java
new file mode 100644
index 0000000..3d19f87
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java
@@ -0,0 +1,412 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.PUT;
+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.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.javatuples.Pair;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.rest.db.DBRequest;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.rest.util.ValidateEncoding;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+/**
+ * The Class BulkAddConsumer.
+ */
+/*
+ * The purpose of this endpoint is to allow a client to add
+ * multiple objects with one request. It may take
+ * one or more transaction objects containing one or more
+ * objects to add.
+ * The transactions are independent of each other -
+ * if one fails, its effects are rolled back, but the others' aren't.
+ * Within a single transaction, if adding one object fails, all the others'
+ * changes are rolled back.
+ */
+@Path("{version: v[8]}/bulkadd")
+public class BulkAddConsumer extends RESTAPI {
+
+ /** The introspector factory type. */
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+
+ /** The query style. */
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ /**
+ * Bulk add.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON})
+ @Produces({ MediaType.APPLICATION_JSON})
+ public Response bulkAdd(String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req){
+
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.PUT.toString());
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ Version version = Version.valueOf(versionParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+
+
+ Response response = null;
+
+ /* A Response will be generated for each object in each transaction.
+ * To keep track of what came from where to give organized feedback to the client,
+ * we keep responses from a given transaction together in one list (hence all being a list of lists)
+ * and pair each response with its matching URI (which will be null if there wasn't one).
+ */
+ List<List<Pair<URI, Response>>> allResponses = new ArrayList<List<Pair<URI, Response>>>();
+
+ try {
+ //TODO add auth check when this endpoint added to that auth properties files
+
+ Loader loader = httpEntry.getLoader();
+ TransactionalGraphEngine dbEngine = httpEntry.getDbEngine();
+
+ JsonArray transactions = getTransactions(content);
+
+ for (int i = 0; i < transactions.size(); i++){
+ TitanTransaction g = dbEngine.getGraph().newTransaction();
+ URI thisUri = null;
+ List<Pair<URI, Introspector>> tuples = new ArrayList<Pair<URI, Introspector>>();
+ try {
+ JsonElement transObj = transactions.get(i);
+ if (!(transObj instanceof JsonObject)) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+ JsonObject transaction = transObj.getAsJsonObject();
+
+ fillObjectTuplesFromTransaction(tuples, transaction, loader, dbEngine, outputMediaType);
+ if (tuples.size() == 0) {
+ //case where user sends a validly formatted transactions object but
+ //which has no actual things in it for A&AI to do anything with
+ //assuming we should count this as a user error
+ throw new AAIException("AAI_6118", "payload had no objects to operate on");
+ }
+
+ List<DBRequest> requests = new ArrayList<>();
+ for (Pair<URI, Introspector> tuple : tuples){
+ thisUri = tuple.getValue0();
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(thisUri);
+ DBRequest request = new DBRequest(HttpMethod.PUT, thisUri, uriQuery, tuple.getValue1(), headers, info, transId);
+ requests.add(request);
+ }
+
+ Pair<Boolean, List<Pair<URI, Response>>> results = httpEntry.process(g, requests, sourceOfTruth);
+ List<Pair<URI, Response>> responses = results.getValue1();
+ allResponses.add(responses);
+ if (results.getValue0()) { //everything was processed without error
+ g.commit();
+ } else { //something failed
+ g.rollback();
+ }
+ } catch (Exception e) {
+ /* While httpEntry.process handles its exceptions, exceptions thrown in earlier helpers
+ * bubbles up to here. As we want to tie error messages to the URI of the object that caused
+ * them, we catch here, generate a Response, bundle it with that URI, and move on.
+ */
+ if (tuples.size() != 0) { //failed somewhere in the middle of tuple-filling
+ Pair<URI,Introspector> lastTuple = tuples.get(tuples.size()-1); //last one in there was the problem
+ if (lastTuple.getValue1() == null){
+ //failed out before thisUri could be set but after tuples started being filled
+ thisUri = lastTuple.getValue0();
+ }
+ } //else failed out on empty payload so tuples never filled (or failed out even earlier than tuple-filling)
+ addExceptionCaseFailureResponse(allResponses, e, i, thisUri, headers, info, HttpMethod.PUT, logline);
+ g.rollback();
+ continue; /* if an exception gets thrown within a transaction we want to keep going to
+ the next transaction, not break out of the whole request */
+ }
+ }
+
+ String returnPayload = generateResponsePayload(allResponses);
+
+ //unless a top level error gets thrown, we want to 201 bc the client wanted a "fire and forget" kind of setup
+ response = Response
+ .status(Status.OK)
+ .entity(returnPayload)
+ .build();
+ } catch (AAIException e) { //these catches needed for handling top level errors in payload parsing where the whole request must fail out
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e, logline);
+ } catch(JsonSyntaxException e) {
+ AAIException ex = new AAIException("AAI_6111");
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex, logline);
+ } catch (Exception e ) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex, logline);
+ }
+
+ return response;
+ }
+
+
+ /**
+ * Gets the transactions.
+ *
+ * @param content - input JSON payload string
+ * @return JsonArray - the array of transactions
+ * @throws AAIException the AAI exception
+ * @throws JsonSyntaxException Parses and breaks the single payload into an array of individual transaction
+ * bodies to be processed.
+ */
+ private JsonArray getTransactions(String content) throws AAIException, JsonSyntaxException {
+ JsonParser parser = new JsonParser();
+
+ JsonObject input = parser.parse(content).getAsJsonObject();
+
+ if (!(input.has("transactions"))) {
+ throw new AAIException("AAI_6118", "input payload does not follow bulk add interface - missing \"transactions\"");
+ }
+ JsonElement transactionsObj = input.get("transactions");
+
+ if (!(transactionsObj.isJsonArray())){
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+ JsonArray transactions = transactionsObj.getAsJsonArray();
+ if (transactions.size() == 0) {
+ //case where user sends a validly formatted transactions object but
+ //which has no actual things in it for A&AI to do anything with
+ //assuming we should count this as a user error
+ throw new AAIException("AAI_6118", "payload had no objects to operate on");
+ }
+ return transactions;
+ }
+
+ /**
+ * Fill object tuples from transaction.
+ *
+ * @param tuples the tuples
+ * @param transaction - JSON body containing the objects to be added
+ * each object must have a URI and an object body
+ * @param loader the loader
+ * @param dbEngine the db engine
+ * @param inputMediaType the input media type
+ * @return list of tuples containing each introspector-wrapped object and its given URI
+ * @throws AAIException the AAI exception
+ * @throws JsonSyntaxException the json syntax exception
+ * @throws UnsupportedEncodingException Walks through the given transaction and unmarshals each object in it, then bundles each
+ * with its URI.
+ */
+ private void fillObjectTuplesFromTransaction(List<Pair<URI, Introspector>> tuples, JsonObject transaction, Loader loader, TransactionalGraphEngine dbEngine, String inputMediaType) throws AAIException, JsonSyntaxException, UnsupportedEncodingException {
+
+ if (!(transaction.has("put"))){
+ throw new AAIException("AAI_6118", "input payload does not follow bulk add interface - missing \"put\"");
+ }
+
+ JsonElement transArrayObj = transaction.get("put"); //for right now only PUTS, later could be DELETEs or whatever too
+ if (!(transArrayObj.isJsonArray())) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+
+ JsonArray transArray = transArrayObj.getAsJsonArray(); //these contents are the items to be added
+ for (int i=0; i<transArray.size(); i++) {
+ Pair<URI, Introspector> tuple = Pair.with(null, null);
+
+ try {
+ JsonElement itemObj = transArray.get(i);
+ if (!(itemObj.isJsonObject())) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+
+ JsonObject item = itemObj.getAsJsonObject();
+ JsonElement itemURIfield = item.get("uri");
+ if (itemURIfield == null) {
+ throw new AAIException("AAI_6118", "must include object uri");
+ }
+ String uriStr = itemURIfield.getAsString();
+ URI uri = UriBuilder.fromPath(uriStr).build();
+
+ /* adding the uri as soon as we have one (valid or not) lets us
+ * keep any errors with their corresponding uris for client feedback
+ */
+ tuple = Pair.with(uri, null);
+
+ if (!ValidateEncoding.getInstance().validate(uri)) {
+ throw new AAIException("AAI_3008", "uri=" + uri.getPath());
+ }
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String objName = uriQuery.getResultType();
+
+ if (!(item.has("body"))){
+ throw new AAIException("AAI_6118", "input payload does not follow bulk add interface - missing \"body\"");
+ }
+ JsonElement bodyObj = item.get("body");
+ if (!(bodyObj.isJsonObject())) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+ Gson gson = new Gson();
+
+ String bodyStr = gson.toJson(bodyObj);
+
+ Introspector obj = loader.unmarshal(objName, bodyStr, org.openecomp.aai.rest.MediaType.getEnum(inputMediaType));
+ if (obj == null) {
+ throw new AAIException("AAI_3000", "object could not be unmarshalled:" + bodyStr);
+ }
+
+ this.validateIntrospector(obj, loader, uri, true);
+ tuple = Pair.with(uri, obj);
+ tuples.add(tuple);
+ } catch (AAIException e) {
+ // even if tuple doesn't have a uri or body, this way we keep all information associated with this error together
+ // even if both are null, that indicates how the input was messed up, so still useful to carry around like this
+ tuples.add(tuple);
+ throw e; //rethrow so the right response is generated on the level above
+ }
+ }
+ }
+
+ /**
+ * Generate response payload.
+ *
+ * @param allResponses - the list of the lists of responses from every action in every transaction requested
+ * @return A json string of similar format to the bulk add interface which for each response includes
+ * the original URI and a body with the status code of the response and the error message.
+ *
+ * Creates the payload for a single unified response from all responses generated
+ */
+ private String generateResponsePayload(List<List<Pair<URI,Response>>> allResponses){
+ JsonObject ret = new JsonObject();
+ JsonArray retArr = new JsonArray();
+
+ for(List<Pair<URI,Response>> responses : allResponses){
+ JsonObject tResp = new JsonObject();
+ JsonArray tArrResp = new JsonArray();
+
+ for (Pair<URI,Response> r : responses) {
+ JsonObject indPayload = new JsonObject();
+
+ URI origURI = r.getValue0();
+ if (origURI != null) {
+ indPayload.addProperty("uri", origURI.getPath());
+ } else {
+ indPayload.addProperty("uri", (String)null);
+ }
+
+ JsonObject body = new JsonObject();
+
+ int rStatus = r.getValue1().getStatus();
+ String rContents = null;
+
+ rContents = (String)r.getValue1().getEntity();
+
+ body.addProperty(new Integer(rStatus).toString(), rContents);
+ indPayload.add("body", body);
+
+ tArrResp.add(indPayload);
+ }
+
+ tResp.add("put", tArrResp);
+ retArr.add(tResp);
+ }
+ ret.add("transaction", retArr);
+ Gson gson = new GsonBuilder().serializeNulls().create();
+ String jsonStr = gson.toJson(ret);
+ return jsonStr;
+ }
+
+ /**
+ * Adds the exception case failure response.
+ *
+ * @param allResponses the all responses
+ * @param e the e
+ * @param index - index of which transaction was being processed when the exception was thrown
+ * @param thisUri the this uri
+ * @param headers the headers
+ * @param info the info
+ * @param templateAction the template action
+ * @param logline Generates a Response based on the given exception and adds it to the collection of responses for this request.
+ */
+ private void addExceptionCaseFailureResponse(List<List<Pair<URI, Response>>> allResponses, Exception e, int index, URI thisUri, HttpHeaders headers, UriInfo info, HttpMethod templateAction, LogLine logline){
+ AAIException ex = null;
+
+ if (!(e instanceof AAIException)){
+ ex = new AAIException("AAI_4000", e); //bc exception response generator needs AAIException
+ } else {
+ ex = (AAIException)e;
+ }
+
+ if (allResponses.size() != (index+1)) {
+ //index+1 bc if all transactions thus far have had a response list added
+ //the size will be one more than the current index (since those are offset by 1)
+
+ //this transaction doesn't have a response list yet, so create one
+ Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex, logline);
+ Pair<URI, Response> uriResp = Pair.with(thisUri, failResp);
+ List<Pair<URI, Response>> transRespList = new ArrayList<Pair<URI,Response>>();
+ transRespList.add(uriResp);
+ allResponses.add(transRespList);
+ } else {
+ //this transaction already has a response list, so add this failure response to it
+ Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex, logline);
+ Pair<URI, Response> uriResp = Pair.with(thisUri, failResp);
+ List<Pair<URI, Response>> tResps = allResponses.get(index);
+ tResps.add(uriResp);
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/CustomJacksonJaxBJsonProvider.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/CustomJacksonJaxBJsonProvider.java
new file mode 100644
index 0000000..c17ea96
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/CustomJacksonJaxBJsonProvider.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import javax.ws.rs.ext.Provider;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+
+/**
+ * The Class CustomJacksonJaxBJsonProvider.
+ */
+@Provider
+public class CustomJacksonJaxBJsonProvider extends JacksonJaxbJsonProvider {
+
+ private static ObjectMapper commonMapper = null;
+
+ /**
+ * Instantiates a new custom jackson jax B json provider.
+ */
+ public CustomJacksonJaxBJsonProvider() {
+ if (commonMapper == null) {
+ ObjectMapper mapper = new ObjectMapper();
+
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ mapper.configure(SerializationFeature.INDENT_OUTPUT, false);
+ mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
+
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
+
+ mapper.registerModule(new JaxbAnnotationModule());
+
+ commonMapper = mapper;
+ }
+ super.setMapper(commonMapper);
+ }
+
+ /**
+ * Gets the mapper.
+ *
+ * @return the mapper
+ */
+ public ObjectMapper getMapper() {
+ return commonMapper;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java
new file mode 100644
index 0000000..cab974f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+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.MediaType;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.introspection.generator.CreateExample;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * The Class ExampleConsumer.
+ */
+@Path("/{version: v[8]}/examples")
+public class ExampleConsumer extends RESTAPI {
+
+
+ /**
+ * Gets the example.
+ *
+ * @param versionParam the version param
+ * @param type the type
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the example
+ */
+ @GET
+ @Path("/{objectType: [^\\/]+}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response getExample(@PathParam("version")String versionParam, @PathParam("objectType")String type, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ Status status = Status.INTERNAL_SERVER_ERROR;
+ Response response = null;
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.PUT.toString());
+
+ try {
+ String mediaType = getMediaType(headers.getAcceptableMediaTypes());
+ org.openecomp.aai.rest.MediaType outputMediaType = org.openecomp.aai.rest.MediaType.getEnum(mediaType);
+
+ Version version = Version.valueOf(versionParam);
+ Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, version, llBuilder);
+
+ CreateExample example = new CreateExample(loader, type);
+
+ Introspector obj = example.getExampleObject();
+ String result = "";
+ if (obj != null) {
+ status = Status.OK;
+ MarshallerProperties properties =
+ new MarshallerProperties.Builder(outputMediaType).build();
+ result = obj.marshal(properties);
+ } else {
+
+ }
+ response = Response
+ .ok(obj)
+ .entity(result)
+ .status(status)
+ .type(outputMediaType.toString()).build();
+// } catch (AAIException e) {
+// //TODO check that the details here are sensible
+// response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e, logline);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex, logline);
+ }
+ return response;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java
new file mode 100644
index 0000000..1d9b411
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java
@@ -0,0 +1,132 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+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.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.sun.istack.SAXParseException2;
+
+/**
+ * The Class ExceptionHandler.
+ */
+@Provider
+public class ExceptionHandler implements ExceptionMapper<Exception> {
+
+ @Context
+ private HttpServletRequest request;
+
+ @Context
+ private HttpHeaders headers;
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Response toResponse(Exception exception) {
+
+ Response response = null;
+ ArrayList<String> templateVars = new ArrayList<String>();
+
+ LogLine logline = new LogLine();
+ //the general case is that cxf will give us a WebApplicationException
+ //with a linked exception
+ if (exception instanceof WebApplicationException) {
+ WebApplicationException e = (WebApplicationException) exception;
+ if (e.getCause() != null) {
+ if (e.getCause() instanceof SAXParseException2) {
+ templateVars.add("UnmarshalException");
+ AAIException ex = new AAIException("AAI_4007", exception);
+ response = Response
+ .status(400)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ }
+ }
+ } else if (exception instanceof JsonParseException) {
+ //jackson does it differently so we get the direct JsonParseException
+ templateVars.add("JsonParseException");
+ AAIException ex = new AAIException("AAI_4007", exception);
+ response = Response
+ .status(400)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } else if (exception instanceof JsonMappingException) {
+ //jackson does it differently so we get the direct JsonParseException
+ templateVars.add("JsonMappingException");
+ AAIException ex = new AAIException("AAI_4007", exception);
+ response = Response
+ .status(400)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ }
+
+ // it didn't get set above, we wrap a general fault here
+ if (response == null) {
+
+ Exception actual_e = exception;
+ if (exception instanceof WebApplicationException) {
+ WebApplicationException e = (WebApplicationException) exception;
+ response = e.getResponse();
+ } else {
+ templateVars.add(request.getMethod());
+ templateVars.add("unknown");
+ AAIException ex = new AAIException("AAI_4000", actual_e);
+ List<MediaType> mediaTypes = headers.getAcceptableMediaTypes();
+ int setError = 0;
+
+ for (MediaType mediaType : mediaTypes) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) {
+ response = Response
+ .status(400)
+ .type(MediaType.APPLICATION_XML_TYPE)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ setError = 1;
+ }
+ }
+ if (setError == 0) {
+ response = Response
+ .status(400)
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ }
+ }
+ }
+ return response;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/HttpMethod.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/HttpMethod.java
new file mode 100644
index 0000000..117d926
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/HttpMethod.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+/**
+ * The Enum HttpMethod.
+ */
+public enum HttpMethod {
+ PUT,
+ MERGE_PATCH,
+ DELETE,
+ PUT_EDGE,
+ DELETE_EDGE,
+ GET;
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java
new file mode 100644
index 0000000..6e31a0b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java
@@ -0,0 +1,593 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.GET;
+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.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.jaxrs.ext.PATCH;
+import org.javatuples.Pair;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.rest.db.DBRequest;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.rest.util.ValidateEncoding;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.openecomp.aai.workarounds.RemoveDME2QueryParams;
+
+import com.google.common.base.Joiner;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+
+/**
+ * The Class LegacyMoxyConsumer.
+ */
+@Path("{version: v[8]}")
+public class LegacyMoxyConsumer extends RESTAPI {
+
+ protected static AAILogger aaiLogger = new AAILogger(LegacyMoxyConsumer.class.getName());
+ protected static String authPolicyFunctionName = "REST";
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ /**
+ * Update.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Path("/{uri: .+}")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response update (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ MediaType mediaType = headers.getMediaType();
+
+ return this.handleWrites(Action.PUT, mediaType, HttpMethod.PUT, content, versionParam, uri, headers, info, req);
+ }
+
+ /**
+ * Update relationship.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Path("/{uri: .+}/relationship-list/relationship")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response updateRelationship (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+
+
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+
+ MediaType inputMediaType = headers.getMediaType();
+
+ Response response = null;
+ Loader loader = null;
+ TransactionalGraphEngine dbEngine = null;
+ TitanTransaction g = null;
+ boolean success = true;
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.PUT_EDGE.toString());
+
+ try {
+ this.validateRequest(uri, headers, req, Action.PUT, info, logline);
+ Version version = Version.valueOf(versionParam);
+ version = Version.valueOf(versionParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ loader = httpEntry.getLoader();
+ dbEngine = httpEntry.getDbEngine();
+
+ g = dbEngine.getGraph().newTransaction();
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+
+ Introspector wrappedEntity = loader.unmarshal("relationship", content, org.openecomp.aai.rest.MediaType.getEnum(this.getInputMediaType(inputMediaType)));
+
+ DBRequest request = new DBRequest(HttpMethod.PUT_EDGE, uriObject, uriQuery, wrappedEntity, headers, info, transId);
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(g, requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e, logline);
+ success = false;
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, aaiException, logline);
+ success = false;
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ aaiLogger.info(logline, true, "0");
+ } else {
+ g.rollback();
+ }
+ }
+
+ }
+
+ return response;
+ }
+
+ /**
+ * Patch.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PATCH
+ @Path("/{uri: .+}")
+ @Consumes({ "application/merge-patch+json" })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response patch (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ MediaType mediaType = MediaType.APPLICATION_JSON_TYPE;
+
+ return this.handleWrites(Action.PUT, mediaType, HttpMethod.MERGE_PATCH, content, versionParam, uri, headers, info, req);
+
+ }
+
+ /**
+ * Gets the legacy.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param depthParam the depth param
+ * @param cleanUp the clean up
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the legacy
+ */
+ @GET
+ @Path("/{uri: .+}")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response getLegacy (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("all") @QueryParam("depth") String depthParam, @DefaultValue("false") @QueryParam("cleanup") String cleanUp, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+
+ Response response = null;
+ TransactionalGraphEngine dbEngine = null;
+ TitanTransaction g = null;
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.GET.toString());
+
+ try {
+ this.validateRequest(uri, headers, req, Action.GET, info, logline);
+ Version version = Version.valueOf(versionParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ dbEngine = httpEntry.getDbEngine();
+
+
+ MultivaluedMap<String, String> params = info.getQueryParameters();
+
+ RemoveDME2QueryParams dme2Workaround = new RemoveDME2QueryParams();
+ //clear out all params not used for filtering
+ params.remove("depth");
+ params.remove("cleanup");
+ if (dme2Workaround.shouldRemoveQueryParams(params)) {
+ dme2Workaround.removeQueryParams(params);
+ }
+
+ uri = uri.split("\\?")[0];
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, params);
+ g = dbEngine.getGraph().newTransaction();
+
+ DBRequest request = new DBRequest(HttpMethod.GET, uriObject, uriQuery, null, headers, info, transId);
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(g, requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e, logline);
+ } catch (Exception e ) {
+ AAIException ex = new AAIException("AAI_4000", e);
+
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex, logline);
+ } finally {
+ if (g != null) {
+ if (cleanUp.equals("true")) {
+ g.commit();
+ } else {
+ g.rollback();
+ }
+ aaiLogger.info(logline, true, "0");
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * Delete.
+ *
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param resourceVersion the resource version
+ * @param req the req
+ * @return the response
+ */
+ @DELETE
+ @Path("/{uri: .+}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response delete (@PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @QueryParam("resource-version")String resourceVersion, @Context HttpServletRequest req) {
+
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+
+ TransactionalGraphEngine dbEngine = null;
+ Response response = Response.status(404)
+ .type(outputMediaType).build();
+
+ TitanTransaction g = null;
+ boolean success = true;
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.DELETE.toString());
+
+ try {
+
+ this.validateRequest(uri, headers, req, Action.DELETE, info, logline);
+ Version version = Version.valueOf(versionParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ dbEngine = httpEntry.getDbEngine();
+
+ g = dbEngine.getGraph().newTransaction();
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+
+ DBRequest request = new DBRequest(HttpMethod.DELETE, uriObject, uriQuery, null, headers, info, transId);
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(g, requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e, logline);
+ success = false;
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex, logline);
+ success = false;
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ aaiLogger.info(logline, true, "0");
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * This whole method does nothing because the body is being dropped while fielding the request.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @DELETE
+ @Path("/{uri: .+}/relationship-list/relationship")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response deleteRelationship (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ MediaType inputMediaType = headers.getMediaType();
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+
+ Loader loader = null;
+ TransactionalGraphEngine dbEngine = null;
+ Response response = Response.status(404)
+ .type(outputMediaType).build();
+
+ TitanTransaction g = null;
+ boolean success = true;
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.DELETE_EDGE.toString());
+
+ try {
+ this.validateRequest(uri, headers, req, Action.DELETE, info, logline);
+ Version version = Version.valueOf(versionParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ loader = httpEntry.getLoader();
+ dbEngine = httpEntry.getDbEngine();
+
+ g = dbEngine.getGraph().newTransaction();
+
+ if (content.equals("")) {
+ throw new AAIException("AAI_3102", "You must supply a relationship");
+ }
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+
+ Introspector wrappedEntity = loader.unmarshal("relationship", content, org.openecomp.aai.rest.MediaType.getEnum(this.getInputMediaType(inputMediaType)));
+
+ DBRequest request = new DBRequest(HttpMethod.DELETE_EDGE, uriObject, uriQuery, wrappedEntity, headers, info, transId);
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(g, requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e, logline);
+ success = false;
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex, logline);
+ success = false;
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ aaiLogger.info(logline, true, "0");
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * Validate request.
+ *
+ * @param uri the uri
+ * @param headers the headers
+ * @param req the req
+ * @param action the action
+ * @param info the info
+ * @param logline the logline
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private void validateRequest(String uri, HttpHeaders headers, HttpServletRequest req, Action action, UriInfo info,
+ LogLine logline) throws AAIException, UnsupportedEncodingException {
+ String namespace = "";
+ String[] splitUri = uri.split("/");
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ if (sourceOfTruth == null) {
+ throw new AAIException("AAI_4009");
+ }
+ if (transId == null) {
+ throw new AAIException("AAI_4010");
+ }
+
+
+ if (!ValidateEncoding.getInstance().validate(info)) {
+ throw new AAIException("AAI_3008", "uri=" + getPath(info));
+ }
+ if (splitUri.length > 0) {
+ namespace = splitUri[0];
+ }
+ }
+
+ /**
+ * Gets the path.
+ *
+ * @param info the info
+ * @return the path
+ */
+ private String getPath(UriInfo info) {
+ String path = info.getPath(false);
+ MultivaluedMap<String, String> map = info.getQueryParameters(false);
+ String params = "?";
+ List<String> parmList = new ArrayList<>();
+ for (String key : map.keySet()) {
+ for (String value : map.get(key)) {
+ parmList.add(key + "=" + value);
+ }
+ }
+ String queryParams = Joiner.on("&").join(parmList);
+ if (map.keySet().size() > 0) {
+ path += params + queryParams;
+ }
+
+ return path;
+
+ }
+
+ /**
+ * Handle writes.
+ *
+ * @param aaiAction the aai action
+ * @param mediaType the media type
+ * @param method the method
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ private Response handleWrites(Action aaiAction, MediaType mediaType, HttpMethod method, String content, String versionParam, String uri, HttpHeaders headers, UriInfo info, HttpServletRequest req) {
+
+
+ Response response = null;
+ TransactionalGraphEngine dbEngine = null;
+ Loader loader = null;
+ Version version = null;
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+
+ TitanTransaction g = null;
+
+ Boolean success = true;
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, method.toString());
+
+ try {
+
+ this.validateRequest(uri, headers, req, Action.PUT, info, logline);
+
+ version = Version.valueOf(versionParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ loader = httpEntry.getLoader();
+ dbEngine = httpEntry.getDbEngine();
+
+ g = dbEngine.getGraph().newTransaction();
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+ String objName = uriQuery.getResultType();
+ if (content.length() == 0 && mediaType.equals(MediaType.APPLICATION_JSON)) {
+ content = "{}";
+ }
+ Introspector obj = loader.unmarshal(objName, content, org.openecomp.aai.rest.MediaType.getEnum(this.getInputMediaType(mediaType)));
+ if (obj == null) {
+ throw new AAIException("AAI_3000", "object could not be unmarshalled:" + content);
+ }
+
+ boolean validateRequired = true;
+ if (method.equals(HttpMethod.MERGE_PATCH)) {
+ validateRequired = false;
+ }
+ this.validateIntrospector(obj, loader, uriObject, validateRequired);
+
+ DBRequest request = new DBRequest(method, uriObject, uriQuery, obj, headers, info, transId);
+ request.setRawContent(content);
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(g, requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, method, e, logline);
+ success = false;
+ } catch (Exception e ) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, method, ex, logline);
+ success = false;
+ } finally {
+ if (g != null) {
+ if (success) {
+ g.commit();
+ aaiLogger.info(logline, true, "0");
+ } else {
+ g.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * Gets the input media type.
+ *
+ * @param mediaType the media type
+ * @return the input media type
+ */
+ private String getInputMediaType(MediaType mediaType) {
+ String result = mediaType.getType() + "/" + mediaType.getSubtype();
+
+ return result;
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/MediaType.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/MediaType.java
new file mode 100644
index 0000000..15f72dd
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/MediaType.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+/**
+ * The Enum MediaType.
+ */
+public enum MediaType {
+ APPLICATION_JSON_TYPE("application/json"),
+ APPLICATION_XML_TYPE("application/xml");
+
+ private final String text;
+
+ /**
+ * Instantiates a new media type.
+ *
+ * @param text the text
+ */
+ private MediaType(final String text) {
+ this.text = text;
+ }
+
+ /**
+ * Gets the enum.
+ *
+ * @param value the value
+ * @return the enum
+ */
+ public static MediaType getEnum(String value) {
+
+ for(MediaType v : values()) {
+ if(v.toString().equalsIgnoreCase(value)) {
+ return v;
+ }
+ }
+
+ throw new IllegalArgumentException("bad value: " + value);
+
+ }
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return text;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/RESTAPI.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/RESTAPI.java
new file mode 100644
index 0000000..ce4cb9a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/RESTAPI.java
@@ -0,0 +1,391 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.tools.CreateUUID;
+import org.openecomp.aai.introspection.tools.DefaultFields;
+import org.openecomp.aai.introspection.tools.InjectKeysFromURI;
+import org.openecomp.aai.introspection.tools.IntrospectorValidator;
+import org.openecomp.aai.introspection.tools.Issue;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.AAITxnLog;
+
+import com.google.common.base.Joiner;
+
+
+/**
+ * Base class for AAI REST API classes.
+ * Provides method to validate header information
+ * TODO should authenticate caller and authorize them for the API they are calling
+ * TODO should store the transaction
+
+ *
+ */
+public class RESTAPI {
+
+ protected static AAILogger aaiLogger = new AAILogger(RESTAPI.class.getName());
+
+// protected LogLine logline = new LogLine();
+//
+// public String transId = null;
+// public String fromAppId = null;
+
+protected final String COMPONENT = "aairest";
+
+ /**
+ * The Enum Action.
+ */
+ public enum Action {
+ GET, PUT, POST, DELETE
+ };
+
+
+ public AAITxnLog txn = null;
+
+ /**
+ * Gets the from app id.
+ *
+ * @param headers the headers
+ * @param logline the logline
+ * @return the from app id
+ * @throws AAIException the AAI exception
+ */
+ protected String getFromAppId(HttpHeaders headers, LogLine logline) throws AAIException {
+ String fromAppId = null;
+ if (headers != null) {
+ List<String> fromAppIdHeader = headers.getRequestHeader("X-FromAppId");
+ if (fromAppIdHeader != null) {
+ for (String fromAppIdValue : fromAppIdHeader) {
+ fromAppId = fromAppIdValue;
+ }
+ }
+ }
+
+ if (fromAppId == null) {
+ throw new AAIException("AAI_4009");
+ }
+
+ return fromAppId;
+ }
+
+ /**
+ * Gets the trans id.
+ *
+ * @param headers the headers
+ * @param logline the logline
+ * @return the trans id
+ * @throws AAIException the AAI exception
+ */
+ protected String getTransId(HttpHeaders headers, LogLine logline) throws AAIException {
+ String transId = null;
+ if (headers != null) {
+ List<String> transIdHeader = headers.getRequestHeader("X-TransactionId");
+ if (transIdHeader != null) {
+ for (String transIdValue : transIdHeader) {
+ transId = transIdValue;
+ }
+ }
+ }
+
+ if (transId == null) {
+ throw new AAIException("AAI_4010");
+ }
+
+ return transId;
+ }
+
+
+ /**
+ * Gen date.
+ *
+ * @return the string
+ */
+ protected String genDate() {
+ LogLine logline = new LogLine();
+ return genDate(logline);
+ }
+
+ /**
+ * Gen date.
+ *
+ * @param logline the logline
+ * @return the string
+ */
+ protected String genDate(LogLine logline) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (AAIException ex) {
+ logline.add("Property", AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT);
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ } finally {
+ if (formatter == null) {
+ formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ }
+ }
+
+ return formatter.format(date);
+ }
+
+ /**
+ * Gets the media type.
+ *
+ * @param mediaTypeList the media type list
+ * @return the media type
+ */
+ protected String getMediaType(List <MediaType> mediaTypeList) {
+ String mediaType = MediaType.APPLICATION_JSON; // json is the default
+ for (MediaType mt : mediaTypeList) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
+ mediaType = MediaType.APPLICATION_XML;
+ }
+ }
+ return mediaType;
+ }
+
+ /**
+ * Gets the dynamic entity for request.
+ *
+ * @param jaxbContext the jaxb context
+ * @param aaiRes the aai res
+ * @param objectFromRequest the object from request
+ * @param aaiExtMap the aai ext map
+ * @return the dynamic entity for request
+ * @throws JAXBException the JAXB exception
+ */
+ protected DynamicEntity getDynamicEntityForRequest(DynamicJAXBContext jaxbContext,
+ AAIResource aaiRes,
+ String objectFromRequest,
+ AAIExtensionMap aaiExtMap) throws JAXBException {
+ DynamicEntity request = null;
+ if (objectFromRequest != null) {
+ JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ String dynamicClass = aaiRes.getResourceClassName();
+
+ if (aaiExtMap.getHttpServletRequest().getContentType() == null ||
+ aaiExtMap.getHttpServletRequest().getContentType().contains("application/json")) {
+ unmarshaller.setProperty("eclipselink.media-type", "application/json");
+ unmarshaller.setProperty("eclipselink.json.include-root", false);
+ }
+
+ Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+ StringReader reader = new StringReader(objectFromRequest);
+ request = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+ }
+ return request;
+ }
+
+ /**
+ * Log transaction.
+ *
+ * @param appId the app id
+ * @param tId the t id
+ * @param action the action
+ * @param input the input
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param request the request
+ * @param respBuf the resp buf
+ * @param status the status
+ */
+ public void logTransaction( String appId, String tId, String action,
+ String input, String rqstTm, String respTm, String request, String respBuf, String status) {
+ logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status), new LogLine());
+ }
+
+ /**
+ * Log transaction.
+ *
+ * @param appId the app id
+ * @param tId the t id
+ * @param action the action
+ * @param input the input
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param request the request
+ * @param response the response
+ * @param logline the logline
+ */
+ /* ---------------- Log Transaction into HBase --------------------- */
+ public void logTransaction( String appId, String tId, String action,
+ String input, String rqstTm, String respTm, String request, Response response, LogLine logline) {
+ String respBuf = "";
+ int status = 0;
+
+ if (response != null && response.getEntity() != null) {
+ respBuf = response.getEntity().toString();
+ status = response.getStatus();
+ }
+ logTransaction(appId, tId, action, input, rqstTm, respTm, request, respBuf, String.valueOf(status), logline);
+ }
+
+ /**
+ * Log transaction.
+ *
+ * @param appId the app id
+ * @param tId the t id
+ * @param action the action
+ * @param input the input
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param request the request
+ * @param respBuf the resp buf
+ * @param status the status
+ * @param logline the logline
+ */
+ public void logTransaction( String appId, String tId, String action,
+ String input, String rqstTm, String respTm, String request, String respBuf, String status, LogLine logline) {
+ try {
+ // we only run this way if we're not doing it in the CXF interceptor
+ if (!AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true")) {
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
+ txn = new AAITxnLog(tId, appId);
+ // tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf
+ String hbtid = txn.put(tId, status,
+ rqstTm, respTm, appId, input, action, request, respBuf);
+
+ logline.add("HbTransId",hbtid);
+ logline.add("action", action);
+ logline.add("urlin", input);
+ }
+
+ }
+ } catch (AAIException e) {
+ // i think we do nothing
+ }
+ }
+
+ /* ----------helpers for common consumer actions ----------- */
+
+ /**
+ * Sets the depth.
+ *
+ * @param depthParam the depth param
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ protected int setDepth(String depthParam) throws AAIException {
+ int depth = Integer.MAX_VALUE; //default
+ if (depthParam != null && depthParam.length() > 0 && !depthParam.equals("all")){
+ try {
+ depth = Integer.valueOf(depthParam);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4016");
+ }
+ }
+ return depth;
+ }
+
+ /**
+ * Consumer exception response generator.
+ *
+ * @param headers the headers
+ * @param info the info
+ * @param templateAction the template action
+ * @param e the e
+ * @param logline the logline
+ * @return the response
+ */
+ protected Response consumerExceptionResponseGenerator(HttpHeaders headers, UriInfo info, HttpMethod templateAction, AAIException e, LogLine logline) {
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(templateAction.toString()); //GET, PUT, etc
+ templateVars.add(info.getPath().toString());
+ templateVars.addAll(e.getTemplateVars());
+ return Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponseWithLogging(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ }
+
+ /**
+ * Validate introspector.
+ *
+ * @param obj the obj
+ * @param loader the loader
+ * @param uri the uri
+ * @param validateRequired the validate required
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ protected void validateIntrospector(Introspector obj, Loader loader, URI uri, boolean validateRequired) throws AAIException, UnsupportedEncodingException {
+
+ IntrospectorValidator validator = new IntrospectorValidator.Builder(loader.getLogLineBuilder()).
+ validateRequired(validateRequired).
+ addResolver(new CreateUUID()).
+ addResolver(new DefaultFields()).
+ addResolver(new InjectKeysFromURI(loader, uri)).
+ build();
+ boolean result = validator.validate(obj);
+ if (!result) {
+ result = validator.resolveIssues();
+ }
+ if (!result) {
+ List<String> messages = new ArrayList<>();
+ for (Issue issue : validator.getIssues()) {
+ messages.add(issue.getDetail());
+ }
+ String errors = Joiner.on(",").join(messages);
+ throw new AAIException("AAI_3000", errors);
+ }
+ //check that key in payload and key in request uri are the same
+ String objURI = obj.getURI();
+ //if requested object is a parent objURI will have a leading slash the input uri will lack
+ //this adds that leading slash for the comparison
+ String testURI = "/" + uri.getRawPath();
+ if (!testURI.endsWith(objURI)) {
+ throw new AAIException("AAI_3000", "uri and payload keys don't match");
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/RestProviders.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/RestProviders.java
new file mode 100644
index 0000000..aa5c517
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/RestProviders.java
@@ -0,0 +1,666 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+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.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResourceKey;
+import org.openecomp.aai.domain.model.AAIResourceKeys;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.exceptions.AAIExceptionWithInfo;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.springframework.web.util.UriUtils;
+
+import com.google.common.base.CaseFormat;
+
+/**
+ * The Class RestProviders.
+ */
+@Path("{parameter: v[8]}/service-design-and-creation")
+public class RestProviders extends RESTAPI {
+ protected static String authPolicyFunctionName = "REST";
+ protected static AAILogger aaiLogger = new AAILogger(RestProviders.class.getName());
+
+ /**
+ * Put provider.
+ *
+ * @param objectFromRequest the object from request
+ * @param uriInfo the uri info
+ * @param headers the headers
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path("/{subResources:.*}")
+ public Response putProvider (
+ String objectFromRequest,
+ @Context UriInfo uriInfo,
+ @Context HttpHeaders headers,
+ @Context HttpServletRequest req) {
+ AAIException ex = null;
+ Response response = null;
+ LogLine logline = new LogLine();
+ long startTime = System.currentTimeMillis();
+ ArrayList<String> templateVars = new ArrayList<String>();
+
+ try {
+
+ String fromAppId = getFromAppId(headers, logline);
+ String transId = getTransId(headers, logline);
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setAaiLogger(aaiLogger);
+ aaiExtMap.setLogline(new LogLine());
+
+ aaiExtMap.setStartTime(startTime);
+ aaiExtMap.setCheckpointTime(startTime);
+ HashMap<String, String> allKeys = new HashMap<String, String>();
+ LinkedHashMap<String, LinkedHashMap<String,Object>> keyList = new LinkedHashMap<String, LinkedHashMap<String,Object>>();
+
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+
+ logline.init(COMPONENT, transId, fromAppId, "parseUri");
+ parseUri(allKeys, keyList, uriInfo.getPath(false), aaiExtMap);
+ logline.init(COMPONENT, transId, fromAppId, "putProvider");
+
+ aaiExtMap.setTransId(transId);
+ aaiExtMap.setFromAppId(fromAppId);
+ org.openecomp.aai.dbmap.GraphHelpersMoxy graphHelpers = new org.openecomp.aai.dbmap.GraphHelpersMoxy();
+
+ String[] chunks = aaiExtMap.getFullResourceName().split("/");
+
+ String keyString = "";
+ String resName = "";
+ if (chunks.length > 0) {
+ resName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, chunks[(chunks.length-1)]);
+
+ HashMap<String,Object> thisResourceKeys = keyList.get(aaiExtMap.getFullResourceName());
+
+ for (Map.Entry<String,Object> ent : thisResourceKeys.entrySet()) {
+ keyString += ent.getKey() + "=" + ent.getValue() + " ";
+ }
+ }
+ logline.add("nodeType", resName);
+ logline.add("keyString", keyString);
+
+ if (keyList.containsKey(aaiExtMap.getFullResourceName() + "/RelationshipList")) {
+ templateVars.add("PUT " + resName + " relationship");
+ logline.add("putRel", "true");
+ templateVars.add(keyString);
+ response = graphHelpers.handleUpdateRel(objectFromRequest, keyList, allKeys, aaiExtMap);
+ } else {
+ templateVars.add("PUT " + resName);
+ templateVars.add(keyString);
+ response = graphHelpers.handlePut(objectFromRequest, keyList, allKeys, aaiExtMap);
+ }
+ } catch (AAIExceptionWithInfo e) {
+
+ ex = e;
+ templateVars.add(e.getInfo());
+ String hashString = e.getInfoHash().toString();
+ hashString = hashString.replace("{", "");
+ hashString = hashString.replace("}", "");
+ templateVars.add(hashString);
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper
+ .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+
+ } catch (AAIException e) {
+
+ if (templateVars.size() == 0) {
+ templateVars.add("PUT");
+ templateVars.add(uriInfo.getPath().toString());
+ }
+ // send error response
+ ex = e;
+ // e.printStackTrace();
+
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e,
+ templateVars, logline)).build();
+
+ } catch (Exception e) {
+
+ if (templateVars.size() == 0) {
+ templateVars.add("PUT");
+ templateVars.add(uriInfo.getPath().toString());
+ }
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ // e.printStackTrace();
+
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex,
+ templateVars, logline)).build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+
+/* long endDate = System.currentTimeMillis();
+ long diff = endDate - startTime;
+ System.out.println("PUT " + diff);*/
+
+ return response;
+ }
+
+ /**
+ * Delete provider.
+ *
+ * @param objectFromRequest the object from request
+ * @param uriInfo the uri info
+ * @param headers the headers
+ * @param req the req
+ * @param resourceVersion the resource version
+ * @return the response
+ */
+ @DELETE
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path("/{subResources:.*}")
+ public Response deleteProvider (
+ String objectFromRequest,
+ @Context UriInfo uriInfo,
+ @Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @QueryParam("resource-version") String resourceVersion) {
+ AAIException ex = null;
+ Response response = null;
+ LogLine logline = new LogLine();
+
+ long startTime = System.currentTimeMillis() ;
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+
+ String fromAppId = getFromAppId(headers, logline);
+ String transId = getTransId(headers, logline);
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setStartTime(startTime);
+ aaiExtMap.setCheckpointTime(startTime);
+ aaiExtMap.setAaiLogger(aaiLogger);
+ aaiExtMap.setLogline(new LogLine());
+ HashMap<String, String> allKeys = new HashMap<String, String>();
+ LinkedHashMap<String, LinkedHashMap<String,Object>> keyList = new LinkedHashMap<String, LinkedHashMap<String,Object>>();
+
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+
+ logline.init(COMPONENT, transId, fromAppId, "parseUri");
+ parseUri(allKeys, keyList, uriInfo.getPath(false), aaiExtMap);
+ logline.init(COMPONENT, transId, fromAppId, "deleteProvider");
+
+ String[] chunks = aaiExtMap.getFullResourceName().split("/");
+ String keyString = "";
+ String resName = "";
+ if (chunks.length > 0) {
+ resName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, chunks[(chunks.length-1)]);
+
+ HashMap<String,Object> thisResourceKeys = keyList.get(aaiExtMap.getFullResourceName());
+
+ for (Map.Entry<String,Object> ent : thisResourceKeys.entrySet()) {
+ keyString += ent.getKey() + "=" + ent.getValue() + " ";
+ }
+ }
+ logline.add("nodeType", resName);
+ logline.add("keyString", keyString);
+ aaiExtMap.setTransId(transId);
+ aaiExtMap.setFromAppId(fromAppId);
+
+ org.openecomp.aai.dbmap.GraphHelpersMoxy graphHelpers = new org.openecomp.aai.dbmap.GraphHelpersMoxy();
+ if (keyList.containsKey(aaiExtMap.getFullResourceName() + "/RelationshipList")) {
+ templateVars.add("DELETE " + resName + " relationship");
+ logline.add("delRel", "true");
+ templateVars.add(keyString);
+ response = graphHelpers.handleDeleteRel(objectFromRequest, keyList, allKeys, aaiExtMap);
+ } else {
+ templateVars.add("DELETE " + resName);
+ templateVars.add(keyString);
+ response = graphHelpers.handleDelete(keyList, allKeys, resourceVersion, aaiExtMap);
+ }
+ } catch (AAIExceptionWithInfo e) {
+
+ ex = e;
+ templateVars.add(e.getInfo());
+ String hashString = e.getInfoHash().toString();
+ hashString = hashString.replace("{", "");
+ hashString = hashString.replace("}", "");
+ templateVars.add(hashString);
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper
+ .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+
+ } catch (AAIException e) {
+ if (templateVars.size() == 0) {
+ templateVars.add("DELETE");
+ templateVars.add(uriInfo.getPath().toString());
+ }
+ // send error response
+ ex = e;
+
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e,
+ templateVars, logline)).build();
+ } catch (Exception e) {
+ if (templateVars.size() == 0) {
+ templateVars.add("DELETE");
+ templateVars.add(uriInfo.getPath().toString());
+ }
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex,
+ templateVars, logline)).build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+
+/* long endDate = System.currentTimeMillis();
+ long diff = endDate - startTime;
+ System.out.println("DELETE " + diff);*/
+
+ return response;
+ }
+
+ /**
+ * Gets the provider.
+ *
+ * @param uriInfo the uri info
+ * @param headers the headers
+ * @param req the req
+ * @param depthParam the depth param
+ * @return the provider
+ */
+ @GET
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path("/{subResources:.*}")
+ // TODO: include "depth" thing
+ public Response getProvider (
+ @Context UriInfo uriInfo,
+ @Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @QueryParam("depth") String depthParam) {
+ AAIException ex = null;
+ Response response = null;
+ LogLine logline = new LogLine();
+ long startTime = System.currentTimeMillis() ;
+ ArrayList<String> templateVars = new ArrayList<String>(2);
+ try {
+
+ int depth = -1;
+ if (depthParam != null && depthParam.length() > 0) {
+ if ("all".equals(depthParam)) {
+ depthParam = "-1";
+ }
+ try {
+ depth = Integer.valueOf(depthParam);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4016");
+ }
+ }
+
+ String fromAppId = getFromAppId(headers, logline);
+ String transId = getTransId(headers, logline);
+ String rqstTm = genDate();
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setAaiLogger(aaiLogger);
+ aaiExtMap.setLogline(new LogLine());
+ aaiExtMap.setStartTime(startTime);
+ aaiExtMap.setCheckpointTime(startTime);
+
+ HashMap<String, String> allKeys = new HashMap<String, String>();
+ LinkedHashMap<String, LinkedHashMap<String,Object>> keyList = new LinkedHashMap<String, LinkedHashMap<String,Object>>();
+
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+
+ logline.init(COMPONENT, transId, fromAppId, "parseUri");
+ AAIResource aaiRes = parseUri(allKeys, keyList, uriInfo.getPath(false), aaiExtMap);
+ logline.init(COMPONENT, transId, fromAppId, "getProvider");
+
+ String[] chunks = aaiExtMap.getFullResourceName().split("/");
+ String resName = "";
+ if (chunks.length > 0) {
+ resName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, chunks[(chunks.length-1)]);
+
+ }
+ templateVars.add("GET " + resName);
+
+ aaiExtMap.setTransId(transId);
+ aaiExtMap.setFromAppId(fromAppId);
+
+ org.openecomp.aai.dbmap.GraphHelpersMoxy graphHelpers = new org.openecomp.aai.dbmap.GraphHelpersMoxy();
+ logline.add("nodeType", aaiRes.getSimpleName());
+ if (aaiRes.getResourceType().equals("container")) {
+
+ if (keyList.containsKey(aaiRes.getFullName())) {
+ String exampleType = (String)keyList.get(aaiRes.getFullName()).get("container|example");
+
+ boolean singleton = false;
+ if (exampleType.equals("singletonExample")) {
+ templateVars.add("singletonExample");
+ logline.add("example", "singleton");
+ singleton = true;
+ } else {
+ logline.add("example", "full");
+ templateVars.add("example");
+ }
+ response = graphHelpers.handleExample(aaiRes, aaiExtMap, singleton, true);
+
+ } else {
+ logline.add("getAll", "true");
+ templateVars.add("all");
+ response = graphHelpers.handleGetAll(keyList, allKeys, depth, aaiExtMap);
+ }
+ } else {
+ // check if there's a key for this node Type in the lookupHashMap
+ String dnHypNodeType = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, aaiRes.getSimpleName());
+
+ if (!keyList.containsKey(aaiRes.getFullName())) {
+ MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
+ if (dnHypNodeType.equals("cvlan-tag-entry")) {
+ dnHypNodeType = "cvlan-tag";
+ }
+ Collection<String> indexedProps = aaiRes.getNodeMapIndexedProps().get(dnHypNodeType);
+
+ ArrayList<String> stringFields = aaiRes.getStringFields();
+ // get all the string props for this method
+
+ boolean hasIndexProp = false;
+
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+ String keyString = "";
+ for (Entry<String, List<String>> param : params.entrySet()) {
+
+ String paramName = param.getKey();
+ if (indexedProps.contains(paramName)) {
+ hasIndexProp = true;
+ }
+ List<String> paramVals = param.getValue();
+ for (String val : paramVals) {
+ if (stringFields.contains(paramName)) {
+ subKeyList.put(paramName, val);
+ keyString += paramName + "=" + val + " ";
+ }
+ if (aaiRes.getBooleanFields().contains(paramName)) {
+ subKeyList.put(paramName, Boolean.valueOf(val));
+ keyString += paramName + "=" + val + " ";
+ }
+ if (aaiRes.getLongFields().contains(paramName)) {
+ subKeyList.put(paramName, Long.valueOf(val));
+ keyString += paramName + "=" + val + " ";
+ }
+ }
+ }
+ keyString = keyString.trim();
+ templateVars.add(keyString);
+ logline.add("keyString", keyString);
+ keyList.put(aaiRes.getFullName(), subKeyList);
+ if (hasIndexProp == true) {
+
+ response = graphHelpers.handleGetByName(keyList, allKeys, depth, aaiExtMap);
+ } else {
+ AAIException e = new AAIException("AAI_4015");
+
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(
+ headers.getAcceptableMediaTypes(), e, templateVars,
+ logline)).build();
+ }
+ } else {
+
+ HashMap<String,Object> thisResourceKeys = keyList.get(aaiExtMap.getFullResourceName());
+ String keyString = "";
+ for (Map.Entry<String,Object> ent : thisResourceKeys.entrySet()) {
+ keyString += ent.getKey() + "=" + ent.getValue() + " ";
+ }
+ keyString = keyString.trim();
+ templateVars.add(keyString);
+ logline.add("keyString", keyString);
+ response = graphHelpers.handleGetSingleByKey(keyList, allKeys, depth, aaiExtMap);
+ }
+ }
+ } catch (AAIExceptionWithInfo e) {
+
+ ex = e;
+ templateVars.add(e.getInfo());
+ String hashString = e.getInfoHash().toString();
+ hashString = hashString.replace("{", "");
+ hashString = hashString.replace("}", "");
+ templateVars.add(hashString);
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode()).entity(ErrorLogHelper
+ .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+
+ } catch (AAIException e) {
+ if (templateVars.size() == 0) {
+ templateVars.add("GET");
+ templateVars.add(uriInfo.getPath().toString());
+ }
+ // send error response
+ ex = e;
+
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e,
+ templateVars, logline)).build();
+ } catch (Exception e) {
+ if (templateVars.size() == 0) {
+ templateVars.add("GET");
+ templateVars.add(uriInfo.getPath().toString());
+ }
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex,
+ templateVars, logline)).build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+
+/* long endDate = System.currentTimeMillis();
+ long diff = endDate - startTime;
+ System.out.println("DELETE " + diff);*/
+
+ return response;
+ }
+
+ /**
+ * Parses the uri.
+ *
+ * @param allKeys the all keys
+ * @param keyList the key list
+ * @param uriInfo the uri info
+ * @param aaiExtMap the aai ext map
+ * @return the AAI resource
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public AAIResource parseUri(HashMap<String, String> allKeys, LinkedHashMap<String,
+ LinkedHashMap<String,Object>> keyList, String uriInfo,
+ AAIExtensionMap aaiExtMap) throws UnsupportedEncodingException, AAIException {
+ // map back to the model
+
+ String[] ps = uriInfo.split("/");
+
+ String apiVersion = ps[0];
+ aaiExtMap.setApiVersion(apiVersion);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer.get(apiVersion);
+
+ String namespace = ps[1];
+
+ aaiExtMap.setNamespace(namespace);
+
+ // /vces/vce/{vnf-id}/port-groups/port-group/{port-group-id}/cvlan-tag-entry/cvlan-tag/{cvlan-tag}
+
+ // FullName -> /Vces/Vce/PortGroups/PortGroup/CvlanTagEntry/CvlanTag <-
+
+ String fullResourceName = "/" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, namespace);
+ AAIResources theseResources = new AAIResources();
+
+ StringBuffer thisUri = new StringBuffer();
+
+ // the URI config option in the props file has a trailing slash
+ thisUri.append("/" + namespace);
+
+ boolean firstNode = true;
+
+ AAIResource lastResource = null;
+
+ for (int i = 2; i < ps.length; i++) {
+
+ AAIResource aaiRes;
+ StringBuffer tmpResourceName = new StringBuffer();
+
+ String p = ps[i];
+ String seg =ps[i];
+
+ thisUri.append("/" + seg);
+
+ tmpResourceName.append(fullResourceName);
+
+ if (seg.equals("cvlan-tag")) {
+ seg = "cvlan-tag-entry";
+ }
+ tmpResourceName.append("/" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, seg));
+
+ String tmpResource = tmpResourceName.toString();
+
+ if (aaiResources.getAaiResources().containsKey(tmpResource)) {
+ aaiRes = aaiResources.getAaiResources().get(tmpResource);
+ lastResource = aaiRes;
+ theseResources.getAaiResources().put(tmpResource, aaiRes);
+ fullResourceName = tmpResource;
+ if ("node".equals(aaiRes.getResourceType())) {
+
+ if (firstNode == true) {
+ aaiExtMap.setTopObjectFullResourceName(fullResourceName);
+ firstNode = false;
+ }
+
+ // get the keys, which will be in order and the next path segment(s)
+ AAIResourceKeys keys = aaiRes.getAaiResourceKeys();
+
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+
+ // there might not be another path segment
+ if ( (i + 1) < ps.length) {
+
+ for (AAIResourceKey rk : keys.getAaiResourceKey()) {
+ String p1 = ps[++i];
+ String encodedKey = p1.toString();
+ thisUri.append("/" + encodedKey);
+ String decodedKey = UriUtils.decode(p1.toString(), "UTF-8");
+ subKeyList.put(rk.getKeyName(), decodedKey);
+ }
+ keyList.put(tmpResource, subKeyList);
+ // this is the key
+ allKeys.put(tmpResource, thisUri.toString());
+ }
+ } else { // examples sit directly under the container level, should probably be query params!!!
+ if ( (i + 1) < ps.length) {
+ String p1 = ps[i+1];
+ if (p1.toString().equals("example") || p1.toString().equals("singletonExample")) {
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+ subKeyList.put("container|example", p1.toString());
+ keyList.put(tmpResource, subKeyList);
+ }
+ }
+ }
+ } else {
+ if (p.equals("relationship-list")) {
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+ subKeyList.put("container|relationship", p.toString());
+ keyList.put(tmpResource, subKeyList);
+ } else if ( p.toString().length() > 0 && !p.toString().equals("example") && !p.toString().equals("singletonExample")
+ && !p.toString().equals("relationship") ) {
+ // this means the URL will break the model, so we bail
+ throw new AAIException("AAI_3001", "bad path");
+ }
+ }
+ }
+ aaiExtMap.setUri(AAIConfig.get("aai.global.callback.url") + apiVersion + thisUri.toString());
+ aaiExtMap.setNotificationUri(AAIConfig.get("aai.global.callback.url") + AAIConfig.get("aai.notification.current.version") + thisUri.toString());
+ aaiExtMap.setFullResourceName(fullResourceName);
+ return lastResource;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java
new file mode 100644
index 0000000..e8d1865
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Iterator;
+
+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.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.workarounds.LegacyURLTransformer;
+
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+/**
+ * The Class URLFromVertexIdConsumer.
+ */
+@Path("{version: v[8]}/generateurl")
+public class URLFromVertexIdConsumer extends RESTAPI {
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ private final String ID_ENDPOINT = "/id/{vertexid: \\d+}";
+
+ /**
+ * Generate url from vertex id.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param vertexid the vertexid
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @GET
+ @Path(ID_ENDPOINT)
+ @Produces({ MediaType.TEXT_PLAIN })
+ public Response generateUrlFromVertexId(String content, @PathParam("version")String versionParam, @PathParam("vertexid")long vertexid, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ Version version = Version.valueOf(versionParam);
+
+ StringBuilder result = new StringBuilder();
+
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.GET.toString());
+
+ Response response = null;
+ TitanTransaction g = null;
+ try {
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ TransactionalGraphEngine dbEngine = httpEntry.getDbEngine();
+
+ g = dbEngine.getGraph().newTransaction();
+
+ DBSerializer serializer = new DBSerializer(version, dbEngine, g, introspectorFactoryType, sourceOfTruth, llBuilder);
+
+ Iterator<Vertex> thisVertex = g.vertices(vertexid);
+
+ if (!thisVertex.hasNext()) {
+ throw new AAIException("AAI_6114", "no node at that vertex id");
+ }
+ URI uri = serializer.getURIForVertex(thisVertex.next());
+
+ result.append(uri.getRawPath());
+ result.insert(0, version);
+ result.insert(0, AAIConfig.get("aai.server.url.base"));
+ LegacyURLTransformer urlTransformer = LegacyURLTransformer.getInstance();
+ URL output = new URL(result.toString());
+
+ response = Response.ok().entity(result.toString()).status(Status.OK).type(MediaType.TEXT_PLAIN).build();
+ } catch (AAIException e) {
+ //TODO check that the details here are sensible
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e, logline);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex, logline);
+ } finally { //to close the titan transaction (I think)
+ if (g != null) {
+ g.rollback();
+ }
+ }
+ return response;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java
new file mode 100644
index 0000000..2f09220
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java
@@ -0,0 +1,144 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+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.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+/**
+ * The Class VertexIdConsumer.
+ */
+@Path("{version: v[8]}/resources")
+public class VertexIdConsumer extends RESTAPI {
+
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ private final String ID_ENDPOINT = "/id/{vertexid: \\d+}";
+
+ /**
+ * Gets the by vertex id.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param vertexid the vertexid
+ * @param depthParam the depth param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the by vertex id
+ */
+ @GET
+ @Path(ID_ENDPOINT)
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response getByVertexId(String content, @PathParam("version")String versionParam, @PathParam("vertexid")long vertexid, @DefaultValue("all") @QueryParam("depth") String depthParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+
+ Version version = Version.valueOf(versionParam);
+
+
+ LogLineBuilder llBuilder = new LogLineBuilder(transId, sourceOfTruth);
+ LogLine logline = llBuilder.build(COMPONENT, HttpMethod.GET.toString());
+
+ Status status = Status.NOT_FOUND;
+ String result = "";
+ Response response = null;
+ TitanTransaction g = null;
+ try {
+
+ int depth = setDepth(depthParam);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, llBuilder);
+ TransactionalGraphEngine dbEngine = httpEntry.getDbEngine();
+ Loader loader = httpEntry.getLoader();
+ g = dbEngine.getGraph().newTransaction();
+
+ DBSerializer serializer = new DBSerializer(version, dbEngine, g, introspectorFactoryType, sourceOfTruth, llBuilder);
+
+ Vertex thisVertex = null;
+ Iterator<Vertex> itr = g.vertices(vertexid);
+
+ if (!itr.hasNext()) {
+ throw new AAIException("AAI_6114", "no node at that vertex id");
+ }
+ thisVertex = itr.next();
+ String objName = thisVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ Introspector obj = loader.introspectorFromName(objName);
+ List<Vertex> vertexListWrapper= new ArrayList<Vertex>();
+ vertexListWrapper.add(thisVertex);
+ String cleanUp = "false";
+ obj = serializer.dbToObject(vertexListWrapper, obj, depth, cleanUp);
+ if (obj != null) {
+ status = Status.OK;
+ //this tells it to include the xml root in the marshalled object
+ MarshallerProperties marshprops = new MarshallerProperties.Builder(org.openecomp.aai.rest.MediaType.getEnum(outputMediaType))
+ .includeRoot(true)
+ .build();
+ result = obj.marshal(marshprops);
+ }
+ response = Response.ok().entity(result).status(status).type(outputMediaType).build();
+ } catch (AAIException e){
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e, logline);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex, logline);
+ } finally { //to close the titan transaction (I think)
+ if (g != null) {
+ g.rollback();
+ }
+ }
+ return response;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/actions/ActionsProvider.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/actions/ActionsProvider.java
new file mode 100644
index 0000000..e39ac94
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/actions/ActionsProvider.java
@@ -0,0 +1,275 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.actions;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+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.xml.bind.JAXBException;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dbmap.ActionsGraph;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.extensions.ExtensionController;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.RESTAPI;
+import org.openecomp.aai.util.AAIApiVersion;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+/**
+ * Implements the action subdomain in the REST API. All API calls must include
+ * X-FromAppId and X-TransactionId in the header.
+ *
+
+ *
+ */
+
+@Path("/{parameter: v8}/actions")
+public class ActionsProvider extends RESTAPI {
+
+ protected static AAILogger aaiLogger = new AAILogger(ActionsProvider.class.getName());
+ protected static String authPolicyFunctionName = "actions";
+
+ public static final String ACTIONS_UPDATE = "/update";
+
+ public static final String ACTIONS_NOTIFY = "/notify";
+
+ /**
+ * Update.
+ *
+ * @param objectFromRequest the object from request
+ * @param headers the headers
+ * @param req the req
+ * @return the response
+ */
+ /* ---------------- Start Property Update PUT --------------------- */
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path(ACTIONS_UPDATE)
+ public Response update(
+ String objectFromRequest,
+ @Context HttpHeaders headers,
+ @Context HttpServletRequest req) {
+ AAIException ex = null;
+ Response response = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ String rqstTm = genDate(logline);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+
+ logline.init(COMPONENT, transId, fromAppId, "update");
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+ aaiExtMap.setApiVersion(AAIApiVersion.get());
+
+ AAIResources aaiResources = IngestModelMoxyOxm.aaiResourceContainer.get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get("/Actions/Update");
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ DynamicEntity updateRequest = getDynamicEntityForRequest(jaxbContext, aaiRes, objectFromRequest, aaiExtMap);
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+ actionsGraph.propertyUpdate(fromAppId, transId, updateRequest, aaiExtMap);
+
+ response = Response
+ .status(Status.OK)
+ .build();
+
+ String respTm = genDate();
+ logTransaction(fromAppId, transId,
+ "PUTACTIONSUPDATE", req.getRequestURI(), rqstTm, respTm, "",
+ response, logline);
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("PUT Actions");
+ templateVars.add("update");
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("PUT Actions");
+ templateVars.add("update");
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex != null) {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ if (ex != null) {
+ return response;
+ }
+
+
+ return response;
+ }
+
+ /* ---------------- End Property Update PUT --------------------- */
+
+ /**
+ * Notify.
+ *
+ * @param objectFromRequest the object from request
+ * @param headers the headers
+ * @param req the req
+ * @return the response
+ */
+ /* ---------------- Start Notify PUT --------------------- */
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path(ACTIONS_NOTIFY)
+ public Response notify(
+ String objectFromRequest,
+ @Context HttpHeaders headers, @Context HttpServletRequest req) {
+ AAIException ex = null;
+ Response response = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+
+ logline.init(COMPONENT, transId, fromAppId, "notify");
+
+ // get the API version from the URL
+ String apiVersion = AAIApiVersion.get();
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+ aaiExtMap.setApiVersion(AAIApiVersion.get());
+
+ AAIResources aaiResources = IngestModelMoxyOxm.aaiResourceContainer.get(aaiExtMap.getApiVersion());
+ AAIResource aaiRes = aaiResources.getAaiResources().get("/Actions/Notify");
+ DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext();
+
+ DynamicEntity notifyRequest = getDynamicEntityForRequest(jaxbContext, aaiRes, objectFromRequest, aaiExtMap);
+
+ List<DynamicEntity> keyParams = notifyRequest.get("keyData");
+
+ String caller = null;
+ if (notifyRequest.get("keyData") != null) {
+ for (DynamicEntity keyDatum : keyParams) {
+ if (keyDatum.get("keyName") != null) {
+ if (keyDatum.get("keyName").equals("source")) {
+ caller = keyDatum.get("keyValue");
+ }
+ } else {
+ throw new AAIException("AAI_6103");
+ }
+ }
+ } else {
+ throw new AAIException("AAI_6103");
+ }
+
+
+// if (caller != null) {
+// String callerProp = "aai.extensions." + apiVersion + ".notify."
+// + caller.toLowerCase() + ".class";
+// String targetClass = AAIConfig.get(callerProp);
+//
+// aaiExtMap.setAaiLogger(aaiLogger);
+// aaiExtMap.setTransId(transId);
+// aaiExtMap.setFromAppId(fromAppId);
+// aaiExtMap.setObjectFromRequest(notifyRequest);
+// aaiExtMap.setObjectFromRequestType("Actions/Notify");
+//
+//// ExtensionController ext = new ExtensionController();
+//// ext.runExtension(apiVersion, "notify", targetClass, "processNotify", aaiExtMap, true);
+//
+// } else {
+// throw new AAIException("AAI_6103");
+// }
+
+ response = Response
+ .status(Status.OK)
+ .build();
+
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("PUT Actions");
+ templateVars.add("notify");
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("PUT Actions");
+ templateVars.add("notify");
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return response;
+ }
+ /* ---------------- End Notify PUT --------------------- */
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/db/DBRequest.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/db/DBRequest.java
new file mode 100644
index 0000000..524e21b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/db/DBRequest.java
@@ -0,0 +1,218 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.db;
+
+import java.net.URI;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.rest.HttpMethod;
+
+/**
+ * The Class DBRequest.
+ */
+public class DBRequest {
+
+ private QueryParser parser = null;
+
+ private Introspector introspector = null;
+
+ private HttpHeaders headers = null;
+
+ private String transactionId = null;
+
+ private UriInfo info = null;
+
+ private HttpMethod method = null;
+
+ private URI uri = null;
+
+ private String rawContent = null;
+
+ /**
+ * Instantiates a new DB request.
+ *
+ * @param method the method
+ * @param uri the uri
+ * @param parser the parser
+ * @param obj the obj
+ * @param headers the headers
+ * @param info the info
+ * @param transactionId the transaction id
+ */
+ public DBRequest(HttpMethod method, URI uri, QueryParser parser, Introspector obj, HttpHeaders headers, UriInfo info, String transactionId) {
+ this.method = method;
+ this.parser = parser;
+ this.introspector = obj;
+ this.headers = headers;
+ this.transactionId = transactionId;
+ this.info = info;
+ this.uri = uri;
+ }
+
+ /**
+ * Gets the headers.
+ *
+ * @return the headers
+ */
+ public HttpHeaders getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Sets the headers.
+ *
+ * @param headers the new headers
+ */
+ public void setHeaders(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
+ /**
+ * Gets the transaction id.
+ *
+ * @return the transaction id
+ */
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ /**
+ * Sets the transaction id.
+ *
+ * @param transactionId the new transaction id
+ */
+ public void setTransactionId(String transactionId) {
+ this.transactionId = transactionId;
+ }
+
+ /**
+ * Gets the info.
+ *
+ * @return the info
+ */
+ public UriInfo getInfo() {
+ return info;
+ }
+
+ /**
+ * Sets the info.
+ *
+ * @param info the new info
+ */
+ public void setInfo(UriInfo info) {
+ this.info = info;
+ }
+
+ /**
+ * Gets the parser.
+ *
+ * @return the parser
+ */
+ public QueryParser getParser() {
+ return parser;
+ }
+
+ /**
+ * Sets the parser.
+ *
+ * @param parser the new parser
+ */
+ public void setParser(QueryParser parser) {
+ this.parser = parser;
+ }
+
+ /**
+ * Gets the introspector.
+ *
+ * @return the introspector
+ */
+ public Introspector getIntrospector() {
+ return introspector;
+ }
+
+ /**
+ * Sets the introspector.
+ *
+ * @param introspector the new introspector
+ */
+ public void setIntrospector(Introspector introspector) {
+ this.introspector = introspector;
+ }
+
+ /**
+ * Gets the method.
+ *
+ * @return the method
+ */
+ public HttpMethod getMethod() {
+ return method;
+ }
+
+ /**
+ * Sets the method.
+ *
+ * @param method the new method
+ */
+ public void setMethod(HttpMethod method) {
+ this.method = method;
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @return the uri
+ */
+ public URI getUri() {
+ return uri;
+ }
+
+ /**
+ * Sets the uri.
+ *
+ * @param uri the new uri
+ */
+ public void setUri(URI uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Gets the raw content.
+ *
+ * @return the raw content
+ */
+ public String getRawContent() {
+ return rawContent;
+ }
+
+ /**
+ * Sets the raw content.
+ *
+ * @param rawContent the new raw content
+ */
+ public void setRawContent(String rawContent) {
+ this.rawContent = rawContent;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java
new file mode 100644
index 0000000..6c7f76b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java
@@ -0,0 +1,584 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.db;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.javatuples.Pair;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessage;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessageDatum;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.extensions.ExtensionController;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.uri.URIToExtensionInformation;
+import org.openecomp.aai.rest.HttpMethod;
+import org.openecomp.aai.rest.ueb.UEBNotification;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.fge.jsonpatch.JsonPatchException;
+import com.github.fge.jsonpatch.mergepatch.JsonMergePatch;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+/**
+ * The Class HttpEntry.
+ */
+public class HttpEntry {
+
+ private final ModelType introspectorFactoryType;
+
+ private final QueryStyle queryStyle;
+
+ private final Version version;
+
+ private final Loader loader;
+
+ private final TransactionalGraphEngine dbEngine;
+
+ private final LogLineBuilder llBuilder;
+
+ private boolean processSingle = true;
+
+ protected static AAILogger aaiLogger = new AAILogger(HttpEntry.class.getName());
+
+ /**
+ * Instantiates a new http entry.
+ *
+ * @param version the version
+ * @param modelType the model type
+ * @param queryStyle the query style
+ * @param llBuilder the ll builder
+ */
+ public HttpEntry(Version version, ModelType modelType, QueryStyle queryStyle, LogLineBuilder llBuilder) {
+ this.introspectorFactoryType = modelType;
+ this.queryStyle = queryStyle;
+ this.version = version;
+ this.llBuilder = llBuilder;
+ this.loader = LoaderFactory.createLoaderForVersion(introspectorFactoryType, version, llBuilder);
+ this.dbEngine = new TitanDBEngine(
+ queryStyle,
+ loader);
+
+
+ }
+
+ /**
+ * Gets the introspector factory type.
+ *
+ * @return the introspector factory type
+ */
+ public ModelType getIntrospectorFactoryType() {
+ return introspectorFactoryType;
+ }
+
+ /**
+ * Gets the query style.
+ *
+ * @return the query style
+ */
+ public QueryStyle getQueryStyle() {
+ return queryStyle;
+ }
+
+ /**
+ * Gets the version.
+ *
+ * @return the version
+ */
+ public Version getVersion() {
+ return version;
+ }
+
+ /**
+ * Gets the loader.
+ *
+ * @return the loader
+ */
+ public Loader getLoader() {
+ return loader;
+ }
+
+ /**
+ * Gets the db engine.
+ *
+ * @return the db engine
+ */
+ public TransactionalGraphEngine getDbEngine() {
+ return dbEngine;
+ }
+
+ /**
+ * Process.
+ *
+ * @param g the g
+ * @param requests the requests
+ * @param sourceOfTruth the source of truth
+ * @return the pair
+ * @throws AAIException the AAI exception
+ */
+ public Pair<Boolean, List<Pair<URI, Response>>> process (TitanTransaction g, List<DBRequest> requests, String sourceOfTruth) throws AAIException {
+ DBSerializer serializer = new DBSerializer(version, dbEngine, g, introspectorFactoryType, sourceOfTruth, llBuilder);
+ Response response = null;
+ Status status = Status.NOT_FOUND;
+ Introspector obj = null;
+ QueryParser query = null;
+ URI uri = null;
+ UEBNotification notification = new UEBNotification(loader);
+ int depth = Integer.MAX_VALUE;
+ List<Pair<URI,Response>> responses = new ArrayList<>();
+ MultivaluedMap<String, String> params = null;
+ HttpMethod method = null;
+ String uriTemp = "";
+ Boolean success = true;
+ for (DBRequest request : requests) {
+ try {
+ method = request.getMethod();
+ obj = request.getIntrospector();
+ query = request.getParser();
+ uriTemp = request.getUri().getRawPath().replaceFirst("^v\\d+/", "");
+ uri = UriBuilder.fromPath(uriTemp).build();
+ List<Vertex> vertices = dbEngine.getQueryEngine().executeQuery(g, query.getQueryBuilder());
+ boolean isNewVertex = false;
+ String outputMediaType = getMediaType(request.getHeaders().getAcceptableMediaTypes());
+ String result = null;
+ params = request.getInfo().getQueryParameters(false);
+ depth = setDepth(params.getFirst("depth"));
+ String cleanUp = params.getFirst("cleanup");
+ if (cleanUp == null) {
+ cleanUp = "false";
+ }
+ if (vertices.size() > 1 && processSingle && !method.equals(HttpMethod.GET)) {
+ if (method.equals(HttpMethod.DELETE)) {
+ throw new AAIException("AAI_6138");
+ } else {
+ throw new AAIException("AAI_6137");
+ }
+ }
+ if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.MERGE_PATCH)) {
+ String resourceVersion = (String)obj.getValue("resource-version");
+ if (vertices.size() == 1) {
+ serializer.verifyResourceVersion("update", query.getResultType(), (String)vertices.get(0).<String>property("resource-version").orElse(null), resourceVersion, obj.getURI());
+ isNewVertex = false;
+ } else {
+ serializer.verifyResourceVersion("create", query.getResultType(), "", resourceVersion, obj.getURI());
+ isNewVertex = true;
+ }
+ } else {
+ if (vertices.size() == 0) {
+ String msg = createNotFoundMessage(query.getResultType(), request.getUri());
+ throw new AAIException("AAI_6114", msg);
+ } else {
+ isNewVertex = false;
+ }
+ }
+ Vertex v = null;
+ if (isNewVertex) {
+ v = serializer.createNewVertex(obj);
+ } else {
+ v = vertices.get(0);
+ if (isModificationMethod(method)) {
+ serializer.touchStandardVertexProperties(v, false);
+ }
+ }
+ HashMap<String, Introspector> relatedObjects = new HashMap<>();
+ switch (method) {
+ case GET:
+ obj = this.getObjectFromDb(serializer, g, query, obj, request.getUri(), depth, cleanUp);
+ if (obj != null) {
+ status = Status.OK;
+ MarshallerProperties properties =
+ new MarshallerProperties.Builder(org.openecomp.aai.rest.MediaType.getEnum(outputMediaType)).build();
+ result = obj.marshal(properties);
+ }
+
+ break;
+ case PUT:
+ response = this.invokeExtension(dbEngine, g, method, request.getTransactionId(), sourceOfTruth, version, loader, obj, uri, request.getHeaders(), true);
+ serializer.serializeToDb(obj, v, query, uri.getRawPath());
+ this.invokeExtension(dbEngine, g, HttpMethod.PUT, request.getTransactionId(), sourceOfTruth, version, loader, obj, uri, request.getHeaders(), false);
+ status = Status.OK;
+ if (isNewVertex) {
+ status = Status.CREATED;
+ }
+ obj = serializer.getLatestVersionView(v);
+ if (query.isDependent()) {
+ relatedObjects = this.getRelatedObjects(serializer, v);
+ }
+ notification.createNotificationEvent(sourceOfTruth, status, uri, obj, relatedObjects);
+
+ break;
+ case PUT_EDGE:
+ serializer.createEdge(obj, v);
+ status = Status.OK;
+ break;
+ case MERGE_PATCH:
+ Introspector existingObj = (Introspector) obj.clone();
+ existingObj = this.getObjectFromDb(serializer, g, query, existingObj, request.getUri(), depth, cleanUp);
+ String existingJson = existingObj.marshal(false);
+ String newJson = request.getRawContent();
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ JsonNode existingNode = mapper.readTree(existingJson);
+ JsonNode newNode = mapper.readTree(newJson);
+ JsonMergePatch patch = JsonMergePatch.fromJson(newNode);
+ JsonNode completed = patch.apply(existingNode);
+ String patched = mapper.writeValueAsString(completed);
+ Introspector patchedObj = loader.unmarshal(existingObj.getName(), patched);
+ serializer.serializeToDb(patchedObj, v, query, uri.getRawPath());
+ status = Status.OK;
+ patchedObj = serializer.getLatestVersionView(v);
+ if (query.isDependent()) {
+ relatedObjects = this.getRelatedObjects(serializer, v);
+ }
+ notification.createNotificationEvent(sourceOfTruth, status, uri, patchedObj, relatedObjects);
+ } catch (IOException | JsonPatchException e) {
+ throw new AAIException("AAI_3000", "could not perform patch operation");
+ }
+ break;
+ case DELETE:
+ String resourceVersion = params.getFirst("resource-version");
+ obj = serializer.getLatestVersionView(v);
+ if (query.isDependent()) {
+ relatedObjects = this.getRelatedObjects(serializer, v);
+ }
+ this.invokeExtension(dbEngine, g, method, request.getTransactionId(), sourceOfTruth, version, loader, obj, uri, request.getHeaders(), true);
+ serializer.delete(v, resourceVersion);
+ this.invokeExtension(dbEngine, g, method, request.getTransactionId(), sourceOfTruth, version, loader, obj, uri, request.getHeaders(), false);
+ status = Status.NO_CONTENT;
+ notification.createNotificationEvent(sourceOfTruth, status, uri, obj, relatedObjects);
+ break;
+ case DELETE_EDGE:
+ serializer.deleteEdge(obj, v);
+ status = Status.NO_CONTENT;
+ break;
+ default:
+ break;
+ }
+
+
+ /* temporarily adding vertex id to the headers
+ * to be able to use for testing the vertex id endpoint functionality
+ * since we presently have no other way of generating those id urls
+ */
+ if (response == null && (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.GET))) {
+ List<Vertex> results = dbEngine.getQueryEngine().executeQuery(g, query.getQueryBuilder());
+ Vertex myvert = results.get(0);
+ String myvertid = myvert.id().toString();
+ response = Response.status(status)
+ .header("vertex-id", myvertid)
+ .entity(result)
+ .type(outputMediaType).build();
+ } else if (response == null) {
+ response = Response.status(status)
+ .type(outputMediaType).build();
+ } else {
+ //response already set to something
+ }
+ Pair<URI,Response> pairedResp = Pair.with(request.getUri(), response);
+ responses.add(pairedResp);
+ } catch (AAIException e) {
+ success = false;
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(request.getMethod().toString()); //GET, PUT, etc
+ templateVars.add(request.getUri().getPath().toString());
+ templateVars.addAll(e.getTemplateVars());
+ LogLine logline = new LogLine();
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ Pair<URI,Response> pairedResp = Pair.with(request.getUri(), response);
+ responses.add(pairedResp);
+ continue;
+ } catch (Exception e) {
+ success = false;
+ AAIException ex = new AAIException("AAI_4000", e);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(request.getMethod().toString()); //GET, PUT, etc
+ templateVars.add(request.getUri().getPath().toString());
+ LogLine logline = new LogLine();
+ response = Response
+ .status(ex.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response);
+ responses.add(pairedResp);
+ continue;
+ }
+ }
+
+ notification.triggerEvents();
+ Pair<Boolean, List<Pair<URI, Response>>> tuple = Pair.with(success, responses);
+ return tuple;
+ }
+
+ /**
+ * Gets the media type.
+ *
+ * @param mediaTypeList the media type list
+ * @return the media type
+ */
+ private String getMediaType(List <MediaType> mediaTypeList) {
+ String mediaType = MediaType.APPLICATION_JSON; // json is the default
+ for (MediaType mt : mediaTypeList) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
+ mediaType = MediaType.APPLICATION_XML;
+ }
+ }
+ return mediaType;
+ }
+
+ /**
+ * Gets the object from db.
+ *
+ * @param serializer the serializer
+ * @param g the g
+ * @param query the query
+ * @param obj the obj
+ * @param uri the uri
+ * @param depth the depth
+ * @param cleanUp the clean up
+ * @return the object from db
+ * @throws AAIException the AAI exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ private Introspector getObjectFromDb(DBSerializer serializer, Graph g, QueryParser query, Introspector obj, URI uri, int depth, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, MalformedURLException {
+ String objType = "";
+ if (!query.getContainerType().equals("")) {
+ objType = query.getContainerType();
+ } else {
+ objType = query.getResultType();
+ }
+
+ obj = loader.introspectorFromName(objType);
+ List<Vertex> results = dbEngine.getQueryEngine().executeQuery(g, query.getQueryBuilder());
+ //nothing found
+ if (results.size() == 0) {
+ String msg = createNotFoundMessage(query.getResultType(), uri);
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ obj = serializer.dbToObject(results, obj, depth, cleanUp);
+ return obj;
+ }
+
+ /**
+ * Invoke extension.
+ *
+ * @param dbEngine the db engine
+ * @param g the g
+ * @param httpMethod the http method
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param apiVersion the api version
+ * @param loader the loader
+ * @param obj the obj
+ * @param uri the uri
+ * @param headers the headers
+ * @param isPreprocess the is preprocess
+ * @return the response
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ private Response invokeExtension(TransactionalGraphEngine dbEngine, TitanTransaction g, HttpMethod httpMethod, String transId, String fromAppId, Version apiVersion, Loader loader, Introspector obj, URI uri, HttpHeaders headers, boolean isPreprocess) throws IllegalArgumentException, UnsupportedEncodingException, AAIException {
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ ModelInjestor injestor = ModelInjestor.getInstance();
+ Response response = null;
+ URIToExtensionInformation extensionInformation = new URIToExtensionInformation(loader, uri);
+ aaiExtMap.setTransId(transId);
+ aaiExtMap.setFromAppId(fromAppId);
+ aaiExtMap.setAaiLogger(aaiLogger);
+ aaiExtMap.setLogline(new LogLine());
+ aaiExtMap.setGraph(g);
+ aaiExtMap.setApiVersion(apiVersion.toString());
+ aaiExtMap.setObjectFromRequest(obj.getUnderlyingObject());
+ aaiExtMap.setObjectFromRequestType(obj.getJavaClassName());
+ aaiExtMap.setObjectFromResponse(obj.getUnderlyingObject());
+ aaiExtMap.setObjectFromResponseType(obj.getJavaClassName());
+ aaiExtMap.setJaxbContext(injestor.getContextForVersion(apiVersion));
+ aaiExtMap.setUri(uri.getRawPath());
+ aaiExtMap.setTransactionalGraphEngine(dbEngine);
+ aaiExtMap.setLoader(loader);
+ aaiExtMap.setNamespace(extensionInformation.getNamespace());
+
+ ExtensionController ext = new ExtensionController();
+ ext.runExtension(aaiExtMap.getApiVersion(),
+ extensionInformation.getNamespace(),
+ extensionInformation.getTopObject(),
+ extensionInformation.getMethodName(httpMethod, isPreprocess),
+ aaiExtMap,
+ isPreprocess);
+
+ if (aaiExtMap.getPrecheckAddedList().size() > 0) {
+ response = notifyOnSkeletonCreation(aaiExtMap, obj, headers);
+ }
+
+ return response;
+ }
+
+ /**
+ * Notify on skeleton creation.
+ *
+ * @param aaiExtMap the aai ext map
+ * @param input the input
+ * @param headers the headers
+ * @return the response
+ */
+ //Legacy support
+ private Response notifyOnSkeletonCreation(AAIExtensionMap aaiExtMap, Introspector input, HttpHeaders headers) {
+ Response response = null;
+ LogLine logline = new LogLine();
+ HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>();
+
+ String keyString = "";
+
+ List<String> resourceKeys = input.getKeys();
+ for (String key : resourceKeys) {
+ keyString += key + "=" + input.getValue(key) + " ";
+ }
+
+ for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) {
+ ArrayList<String> templateVars = new ArrayList<String>();
+
+ templateVars.add("PUT " + input.getDbName());
+ templateVars.add(keyString);
+ List<String> keys = new ArrayList<String>();
+ templateVars.add(msg.getAaiResponseMessageResourceType());
+ for (AAIResponseMessageDatum dat : msg.getAaiResponseMessageData().getAAIResponseMessageDatum()) {
+ keys.add(dat.getAaiResponseMessageDatumKey() + "=" + dat.getAaiResponseMessageDatumValue());
+ }
+ templateVars.add(StringUtils.join(keys, ", "));
+ exceptionList.put(new AAIException("AAI_0004", msg.getAaiResponseMessageResourceType()),
+ templateVars);
+ }
+ response = Response
+ .status(Status.ACCEPTED).entity(ErrorLogHelper
+ .getRESTAPIInfoResponse(headers.getAcceptableMediaTypes(), exceptionList, logline))
+ .build();
+
+ return response;
+ }
+
+ /**
+ * Creates the not found message.
+ *
+ * @param resultType the result type
+ * @param uri the uri
+ * @return the string
+ */
+ private String createNotFoundMessage(String resultType, URI uri) {
+
+ String msg = "No Node of type " + resultType + " found at: " + uri.getPath();
+
+ return msg;
+ }
+
+ /**
+ * Sets the depth.
+ *
+ * @param depthParam the depth param
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ protected int setDepth(String depthParam) throws AAIException {
+ int depth = Integer.MAX_VALUE; //default
+ if (depthParam != null && depthParam.length() > 0 && !depthParam.equals("all")){
+ try {
+ depth = Integer.valueOf(depthParam);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4016");
+ }
+ }
+ return depth;
+ }
+
+ /**
+ * Checks if is modification method.
+ *
+ * @param method the method
+ * @return true, if is modification method
+ */
+ private boolean isModificationMethod(HttpMethod method) {
+ boolean result = false;
+
+ if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PUT_EDGE) || method.equals(HttpMethod.DELETE_EDGE)) {
+ result = true;
+ }
+
+ return result;
+
+ }
+
+ private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, MalformedURLException, AAIException {
+ HashMap<String, Introspector> relatedVertices = new HashMap<>();
+ List<Vertex> vertexChain = dbEngine.getQueryEngine().findParents(v);
+ Introspector vertexObj = null;
+ for (Vertex vertex : vertexChain) {
+ vertexObj = serializer.getVertexProperties(vertex);
+ relatedVertices.put(vertexObj.getObjectId(), vertexObj);
+
+ }
+
+ return relatedVertices;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java
new file mode 100644
index 0000000..23872ff
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+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 org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.dbmap.SearchGraph;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.RESTAPI;
+import org.openecomp.aai.util.AAIApiVersion;
+import org.openecomp.aai.domain.yang.SearchResults;
+
+/**
+ * Implements the search subdomain in the REST API. All API calls must include
+ * X-FromAppId and X-TransactionId in the header.
+ *
+
+ *
+ */
+
+@Path("/search")
+public class ModelAndNamedQueryRestProvider extends RESTAPI {
+
+ protected static String authPolicyFunctionName = "search";
+
+ protected static AAILogger aaiLogger = new AAILogger(ModelAndNamedQueryRestProvider.class.getName());
+
+ public static final String NAMED_QUERY = "/named-query";
+
+ public static final String MODEL_QUERY = "/model";
+
+ /**
+ * Gets the named query response.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param queryParameters the query parameters
+ * @return the named query response
+ */
+ /* ---------------- Start Named Query --------------------- */
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path(NAMED_QUERY)
+ public Response getNamedQueryResponse(@Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ String queryParameters) {
+ AAIException ex = null;
+ Response response = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ String rqstTm = genDate(logline);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+
+ logline.init(COMPONENT, transId, fromAppId, "getNamedQueryResponse");
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+ aaiExtMap.setApiVersion(AAIApiVersion.get());
+
+ SearchGraph searchGraph = new SearchGraph();
+ response = searchGraph.runNamedQuery(fromAppId, transId, queryParameters, aaiExtMap);
+
+ String respTm = genDate();
+ logTransaction(fromAppId, transId, "GETSDNZONERESPONSE",
+ req.getRequestURI(), rqstTm, respTm, "", response, logline);
+
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("POST Search");
+ templateVars.add("getNamedQueryResponse");
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("POST Search");
+ templateVars.add("getNamedQueryResponse");
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Gets the model query response.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param inboundPayload the inbound payload
+ * @param action the action
+ * @return the model query response
+ */
+ /* ---------------- Start Named Query --------------------- */
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path(MODEL_QUERY)
+ public Response getModelQueryResponse(@Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ String inboundPayload,
+ @QueryParam("action") String action) {
+ AAIException ex = null;
+ Response response = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ String rqstTm = genDate(logline);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+
+ logline.init(COMPONENT, transId, fromAppId, "getNamedQueryResponse");
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+ aaiExtMap.setApiVersion(AAIApiVersion.get());
+ aaiExtMap.setFromAppId(fromAppId);
+ aaiExtMap.setTransId(transId);
+ SearchGraph searchGraph = new SearchGraph();
+ if (action != null && action.equalsIgnoreCase("DELETE")) {
+ response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, true, aaiExtMap);
+ } else {
+ response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, false, aaiExtMap);
+ }
+ String respTm = genDate();
+ logTransaction(fromAppId, transId, "POSTMODELQUERYRESPONSE",
+ req.getRequestURI(), rqstTm, respTm, "", response, logline);
+
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("POST Search");
+ templateVars.add("getModelQueryResponse");
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("POST Search");
+ templateVars.add("getModelQueryResponse");
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return response;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java
new file mode 100644
index 0000000..ca3add1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java
@@ -0,0 +1,241 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+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 org.openecomp.aai.dbmap.SearchGraph;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.RESTAPI;
+import org.openecomp.aai.util.AAIApiVersion;
+import org.openecomp.aai.domain.yang.SearchResults;
+
+/**
+ * Implements the search subdomain in the REST API. All API calls must include
+ * X-FromAppId and X-TransactionId in the header.
+ *
+
+ *
+ */
+
+@Path("/{parameter: v[8]}/search")
+public class SearchProvider extends RESTAPI {
+
+ protected static String authPolicyFunctionName = "search";
+
+ protected static AAILogger aaiLogger = new AAILogger(SearchProvider.class.getName());
+
+
+ public static final String GENERIC_QUERY = "/generic-query";
+
+ public static final String NODES_QUERY = "/nodes-query";
+
+
+
+ /**
+ * Gets the generic query response.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param startNodeType the start node type
+ * @param startNodeKeyParams the start node key params
+ * @param includeNodeTypes the include node types
+ * @param depth the depth
+ * @return the generic query response
+ */
+ /* ---------------- Start Generic Query --------------------- */
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path(GENERIC_QUERY)
+ public Response getGenericQueryResponse(@Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @QueryParam("start-node-type") final String startNodeType,
+ @QueryParam("key") final List<String> startNodeKeyParams,
+ @QueryParam("include") final List<String> includeNodeTypes,
+ @QueryParam("depth") final int depth) {
+
+ AAIException ex = null;
+ Response searchResult = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ String rqstTm = genDate(logline);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+
+ logline.init(COMPONENT, transId, fromAppId, "getGenericQueryResponse");
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+ aaiExtMap.setApiVersion(AAIApiVersion.get());
+
+ SearchGraph searchGraph = new SearchGraph();
+ searchResult = searchGraph.runGenericQuery(fromAppId,
+ transId,
+ startNodeType,
+ startNodeKeyParams,
+ includeNodeTypes,
+ depth,
+ aaiExtMap);
+
+ String respTm = genDate();
+ logTransaction(fromAppId, transId,
+ "GETGENERICQUERYRESPONSE", req.getRequestURI(), rqstTm, respTm,
+ "", searchResult, logline);
+
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("GET Search");
+ templateVars.add("getGenericQueryResponse");
+ searchResult = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("GET Search");
+ templateVars.add("getGenericQueryResponse");
+ searchResult = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null){
+ aaiLogger.info(logline, true, "0");
+ }
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+
+ return searchResult;
+ }
+
+ /* ---------------- End Generic Query --------------------- */
+
+ /**
+ * Gets the nodes query response.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param searchNodeType the search node type
+ * @param edgeFilterList the edge filter list
+ * @param filterList the filter list
+ * @return the nodes query response
+ */
+ /* ---------------- Start Nodes Query --------------------- */
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Path(NODES_QUERY)
+ public Response getNodesQueryResponse(@Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @QueryParam("search-node-type") final String searchNodeType,
+ @QueryParam("edge-filter") final List<String> edgeFilterList,
+ @QueryParam("filter") final List<String> filterList) {
+ AAIException ex = null;
+ Response searchResult = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ String rqstTm = genDate(logline);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+
+ logline.init(COMPONENT, transId, fromAppId, "getNodesQueryResponse");
+
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setHttpHeaders(headers);
+ aaiExtMap.setServletRequest(req);
+ aaiExtMap.setApiVersion(AAIApiVersion.get());
+
+ SearchGraph searchGraph = new SearchGraph();
+ searchResult = searchGraph.runNodesQuery(fromAppId,
+ transId,
+ searchNodeType,
+ edgeFilterList,
+ filterList,
+ aaiExtMap);
+
+ String respTm = genDate();
+ logTransaction(fromAppId, transId, "GETNODESQUERYRESPONSE",
+ req.getRequestURI(), rqstTm, respTm, "", searchResult, logline);
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("GET Search");
+ templateVars.add("getNodesQueryResponse");
+ searchResult = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("GET Search");
+ templateVars.add("getNodesQueryResponse");
+ searchResult = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null){
+ aaiLogger.info(logline, true, "0");
+ }
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return searchResult;
+ }
+
+ /* ---------------- End Nodes Query --------------------- */
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/translog/TransLogRestProvider.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/translog/TransLogRestProvider.java
new file mode 100644
index 0000000..a2f8ed8
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/translog/TransLogRestProvider.java
@@ -0,0 +1,284 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.translog;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+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.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 org.openecomp.aai.domain.translog.TransactionLogEntries;
+import org.openecomp.aai.domain.translog.TransactionLogEntry;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.RESTAPI;
+import org.openecomp.aai.rest.RESTAPI.Action;
+import org.openecomp.aai.rest.search.SearchProvider;
+import org.openecomp.aai.util.AAITxnLog;
+
+
+/**
+ * The Class TransLogRestProvider.
+ */
+@Path("/{parameter: v[8]}/translog")
+public class TransLogRestProvider extends RESTAPI {
+
+ protected static String authPolicyFunctionName = "util";
+
+ public static final String TRANSLOG_GET_ID = "/get/{id}";
+
+ public static final String TRANSLOG_SCAN = "/scan";
+
+ /**
+ * Gets the hbase trans.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param id the id
+ * @return the hbase trans
+ */
+ @GET
+ @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Path(TRANSLOG_GET_ID)
+ public Response getHbaseTrans(@Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @PathParam("id") String id) {
+ AAIException ex = null;
+ Response response = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+ logline.init(COMPONENT, transId, fromAppId, "getHbaseTrans");
+ txn = new AAITxnLog(transId, fromAppId);
+ TransactionLogEntry txObj = txn.get(id);
+ if (txObj.getTransactionLogEntryId() == null || txObj.getTransactionLogEntryId() == "")
+ throw new AAIException("AAI_3001");
+ response = Response.ok(txObj).type(getMediaType(headers.getAcceptableMediaTypes())).build();
+
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("GET translog");
+ templateVars.add("id=" + id);
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("GET translog");
+ templateVars.add("id=" + id);
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return response;
+
+ }
+
+ /**
+ * Scan hbase transactions.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param startTime the start time
+ * @param endTime the end time
+ * @param methods the methods
+ * @param getFilter the get filter
+ * @param putFilter the put filter
+ * @param resourceFilter the resource filter
+ * @param fromAppIdFilter the from app id filter
+ * @return the response
+ */
+ @GET
+ @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Path(TRANSLOG_SCAN)
+ public Response scanHbaseTransactions(@Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @QueryParam("startTime") String startTime,
+ @QueryParam("endTime") String endTime,
+ @QueryParam("methods") String methods,
+ @QueryParam("getFilter") String getFilter,
+ @QueryParam("putFilter") String putFilter,
+ @QueryParam("resourceFilter") String resourceFilter,
+ @QueryParam("fromAppIdFilter") String fromAppIdFilter
+ ) {
+ String sb = new String();
+ TransactionLogEntries txs = null;
+ AAIException ex = null;
+ Response response = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+ ArrayList<String> templateVars = new ArrayList<String>();
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+ logline.init(COMPONENT, fromAppId, transId, "scanHbaseTransactions");
+
+ long now = System.currentTimeMillis();
+ long then = now - 600 * 1000; // 10 minutes, maybe make it configurable?
+
+ Date start = new Date(then);
+ Date end = new Date(now);
+
+ if (startTime != null) {
+ if (startTime.length() == 8) {
+ startTime = startTime + "T000000";
+ } else if (startTime.length() == 11) {
+ startTime = startTime + "0000";
+ } else if (startTime.length() == 13) {
+ startTime = startTime + "00";
+ }
+ start = getDateFromString(startTime);
+ }
+
+ if (endTime != null) {
+ if (endTime.length() == 8) {
+ endTime = endTime + "T235959";
+ } else if (endTime.length() == 11) {
+ endTime = endTime + "5959";
+ } else if (endTime.length() == 13) {
+ endTime = endTime + "59";
+ }
+ end = getDateFromString(endTime);
+ }
+ // should probably gripe about invalid dates from the URI
+ long endMillis = end.getTime();
+ long startMillis = start.getTime();
+
+ List<String> methodList = new ArrayList<String>();
+
+ if (methods != null) {
+ for (String ent : methods.split(",")) {
+ methodList.add(ent);
+ }
+ } else {
+ methodList.add("PUT");
+ }
+ txn = new AAITxnLog(transId, fromAppId);
+ txs = txn.scanFiltered(startMillis, endMillis, methodList, putFilter, getFilter, resourceFilter, fromAppIdFilter);
+
+ if (txs == null)
+ throw new AAIException("AAI_3001", sb);
+ response = Response.ok(txs).type(getMediaType(headers.getAcceptableMediaTypes())).build();
+
+ } catch (AAIException e) {
+ // send error response
+ ex = e;
+ templateVars.add("GET translog");
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ } catch (Exception e) {
+ // send error response
+ ex = new AAIException("AAI_4000", e);
+ templateVars.add("GET translog");
+ templateVars.add("scan=" + req.getQueryString());
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars, logline))
+ .build();
+ } finally {
+ // log success or failure
+ if (ex == null)
+ aaiLogger.info(logline, true, "0");
+ else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Gets the date from string.
+ *
+ * @param dateString the date string
+ * @return the date from string
+ */
+ private Date getDateFromString(String dateString) {
+ Date date = null;
+ try {
+ DateFormat df = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
+ date = df.parse(dateString);
+
+ } catch (ParseException e) {
+ //WebApplicationException ...("Date format should be yyyy-MM-dd'T'HH:mm:ss", Status.BAD_REQUEST);
+ }
+ return date;
+ }
+ // TODO: fix this to return one or more objects?
+/* @GET
+ @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Path("/scan/{id}")
+ public String scanHbaseTrans(@PathParam("id") String transId) {
+ String sb = new String();
+ try {
+ List<String> logList = txn.scan(transId);
+ for (String logValue : logList) {
+ sb += "\n<Row>" + logValue + "\n</Row>";
+ }
+ } catch (Exception e) {
+ sb = "hbase scan got error="+e.toString();
+ }
+ return "<aai_hbaseScan_logresult>"
+ + "\n<input>"
+ + transId
+ +"\n</input>"
+ + "\n<Result>"
+ + sb
+ + "\n</Result>"
+ +"\n</aai_hbaseScan_logresult>\n";
+
+ }*/
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java
new file mode 100644
index 0000000..fe95d7f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.ueb;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.util.StoreNotificationEvent;
+
+/**
+ * The Class NotificationEvent.
+ */
+public class NotificationEvent {
+
+ private Version notificationVersion = null;
+
+ private Introspector eventHeader = null;
+
+ private Introspector obj = null;
+
+ /**
+ * Instantiates a new notification event.
+ *
+ * @param version the version
+ * @param eventHeader the event header
+ * @param obj the obj
+ */
+ public NotificationEvent (Version version, Introspector eventHeader, Introspector obj) {
+ this.notificationVersion = version;
+ this.eventHeader = eventHeader;
+ this.obj = obj;
+ }
+
+ /**
+ * Trigger.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public void trigger() throws AAIException {
+
+ StoreNotificationEvent sne = new StoreNotificationEvent();
+
+ sne.storeDynamicEvent(ModelInjestor.getInstance().getContextForVersion(notificationVersion), notificationVersion.toString(), (DynamicEntity)eventHeader.getUnderlyingObject(), (DynamicEntity)obj.getUnderlyingObject());
+
+ }
+
+ /**
+ * Gets the notification version.
+ *
+ * @return the notification version
+ */
+ public Version getNotificationVersion() {
+ return notificationVersion;
+ }
+
+ /**
+ * Gets the event header.
+ *
+ * @return the event header
+ */
+ public Introspector getEventHeader() {
+ return eventHeader;
+ }
+
+ /**
+ * Gets the obj.
+ *
+ * @return the obj
+ */
+ public Introspector getObj() {
+ return obj;
+ }
+
+
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java
new file mode 100644
index 0000000..e0d7a0b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java
@@ -0,0 +1,173 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.ueb;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.parsers.uri.URIToObject;
+import org.openecomp.aai.util.AAIConfig;
+
+/**
+ * The Class UEBNotification.
+ */
+public class UEBNotification {
+
+
+ private Loader loader = null;
+
+ private Loader currentVersionLoader = null;
+
+ protected List<NotificationEvent> events = null;
+
+ private String urlBase = null;
+
+ private Version notificationVersion = null;
+
+ /**
+ * Instantiates a new UEB notification.
+ *
+ * @param loader the loader
+ */
+ public UEBNotification(Loader loader) {
+
+ events = new ArrayList<>();
+ this.loader = loader;
+ this.currentVersionLoader = LoaderFactory.createLoaderForVersion(loader.getModelType(), AAIProperties.LATEST, loader.getLogLineBuilder());
+ urlBase = AAIConfig.get("aai.server.url.base","");
+ notificationVersion = Version.valueOf(AAIConfig.get("aai.notification.current.version","v8"));
+ }
+
+
+ /**
+ * Creates the notification event.
+ *
+ * @param sourceOfTruth the source of truth
+ * @param status the status
+ * @param uri the uri
+ * @param obj the obj
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void createNotificationEvent(String sourceOfTruth, Status status, URI uri, Introspector obj, HashMap<String, Introspector> relatedObjects) throws AAIException, IllegalArgumentException, UnsupportedEncodingException {
+
+ String action = "UPDATE";
+
+ if (status.equals(Status.CREATED)) {
+ action = "CREATE";
+ } else if (status.equals(Status.OK)) {
+ action = "UPDATE";
+ } else if (status.equals(Status.NO_CONTENT)) {
+ action = "DELETE";
+ }
+// if (cloudRegionWorkaround.isAffected(uri)) {
+// uri = cloudRegionWorkaround.addToUri(uri);
+// }
+ Introspector eventHeader = currentVersionLoader.introspectorFromName("notification-event-header");
+
+ URIToObject parser = new URIToObject(currentVersionLoader, uri, relatedObjects);
+
+ String entityLink = urlBase + notificationVersion + "/" + uri;
+
+ eventHeader.setValue("entity-link", entityLink);
+ eventHeader.setValue("action", action);
+
+ eventHeader.setValue("entity-type", obj.getDbName());
+
+ eventHeader.setValue("top-entity-type", parser.getTopEntityName());
+
+ eventHeader.setValue("source-name", sourceOfTruth);
+
+ eventHeader.setValue("version", notificationVersion.toString());
+ List<Object> parentList = parser.getParentList();
+ parentList.clear();
+
+ Introspector eventObject = null;
+
+ if (!parser.getTopEntity().equals(parser.getEntity())) {
+ Introspector child = obj;
+ if (!parser.getLoader().getVersion().equals(obj.getVersion())) {
+ String json = obj.marshal(false);
+ child = parser.getLoader().unmarshal(parser.getEntity().getName(), json);
+ }
+
+ //wrap the child object in its parents
+ parentList.add(child.getUnderlyingObject());
+ }
+
+ //convert to most resent version
+ if (!parser.getLoader().getVersion().equals(currentVersionLoader.getVersion())) {
+ String json = "";
+ if (parser.getTopEntity().equals(parser.getEntity())) {
+ //convert the parent object passed in
+ json = obj.marshal(false);
+ eventObject = currentVersionLoader.unmarshal(obj.getName(), json);
+ } else {
+ //convert the object created in the parser
+ json = parser.getTopEntity().marshal(false);
+ eventObject = currentVersionLoader.unmarshal(parser.getTopEntity().getName(), json);
+ }
+ } else {
+ if (parser.getTopEntity().equals(parser.getEntity())) {
+ //take the top level parent object passed in
+ eventObject = obj;
+ } else {
+ //take the wrapped child objects (ogres are like onions)
+ eventObject = parser.getTopEntity();
+ }
+ }
+
+ NotificationEvent event = new NotificationEvent(notificationVersion, eventHeader, eventObject);
+ events.add(event);
+
+ }
+
+ /**
+ * Trigger events.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public void triggerEvents() throws AAIException {
+ for (NotificationEvent event : events) {
+ event.trigger();
+ }
+ events.clear();
+ }
+
+ public List<NotificationEvent> getEvents() {
+ return this.events;
+ }
+
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java
new file mode 100644
index 0000000..5bb6632
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+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 org.apache.commons.lang.StringUtils;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessage;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessageData;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessageDatum;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.RESTAPI;
+
+/**
+ * The Class EchoResponse.
+ */
+public class EchoResponse extends RESTAPI {
+
+ protected static String authPolicyFunctionName = "util";
+
+ protected static AAILogger aaiLogger = new AAILogger(EchoResponse.class.getName());
+
+ public static final String echoPath = "/util/echo";
+
+ /**
+ * Simple health-check API that echos back the X-FromAppId and X-TransactionId to clients.
+ * If there is a query string, a transaction gets logged into hbase, proving the application is connected to the data store.
+ * If there is no query string, no transacction logging is done to hbase.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param myAction if exists will cause transaction to be logged to hbase
+ * @return the response
+ */
+ @GET
+ @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Path(echoPath)
+ public Response echoResult(@Context HttpHeaders headers, @Context HttpServletRequest req,
+ @QueryParam("action") String myAction) {
+ Response response = null;
+ AAIResponseMessage aaiRespMessage = new AAIResponseMessage();
+ AAIResponseMessageData messageData = aaiRespMessage.getAaiResponseMessageData();
+
+ AAIException ex = null;
+ String fromAppId = null;
+ String transId = null;
+ LogLine logline = new LogLine();
+
+ try {
+ fromAppId = getFromAppId(headers, logline );
+ transId = getTransId(headers, logline);
+ } catch (AAIException e) {
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add("GET echo");
+ templateVars.add(fromAppId +" "+transId);
+ return Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars, logline))
+ .build();
+ }
+
+ try {
+ logline.init(COMPONENT, transId, fromAppId, "echoResult");
+
+ HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>();
+
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(fromAppId);
+ templateVars.add(transId);
+
+ exceptionList.put(new AAIException("AAI_0002", "OK"), templateVars);
+
+ response = Response.status(Status.OK)
+ .entity(ErrorLogHelper.getRESTAPIInfoResponse(
+ headers.getAcceptableMediaTypes(), exceptionList, logline))
+ .build();
+
+// } catch (AAIException e) {
+// ex = e;
+// ArrayList<String> templateVars = new ArrayList<String>();
+// templateVars.add(Action.GET.name());
+// templateVars.add(fromAppId +" "+transId);
+//
+// response = Response
+// .status(e.getErrorObject().getHTTPResponseCode())
+// .entity(ErrorLogHelper.getRESTAPIErrorResponse(
+// headers.getAcceptableMediaTypes(), e, templateVars,
+// logline)).build();
+ } catch (Exception e) {
+ ex = new AAIException("AAI_4000", e);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(Action.GET.name());
+ templateVars.add(fromAppId +" "+transId);
+
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(
+ headers.getAcceptableMediaTypes(), ex,
+ templateVars, logline)).build();
+
+ } finally {
+ if (ex == null) {
+ aaiLogger.info(logline, true, "0");
+ } else {
+ aaiLogger.error(ex.getErrorObject(), logline, ex);
+ aaiLogger.info(logline, false, ex.getErrorObject().getErrorCodeString());
+ }
+
+ }
+
+ return response;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java b/ajsc-aai/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java
new file mode 100644
index 0000000..428a78b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
+
+import org.springframework.web.util.UriUtils;
+
+/**
+ * The Class ValidateEncoding.
+ */
+public class ValidateEncoding {
+
+ private final String encoding = "UTF-8";
+
+ /**
+ * Instantiates a new validate encoding.
+ */
+ private ValidateEncoding() {
+
+ }
+
+ /**
+ * The Class Helper.
+ */
+ private static class Helper {
+
+ /** The Constant INSTANCE. */
+ private static final ValidateEncoding INSTANCE = new ValidateEncoding();
+ }
+
+ /**
+ * Gets the single instance of ValidateEncoding.
+ *
+ * @return single instance of ValidateEncoding
+ */
+ public static ValidateEncoding getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ /**
+ * Validate.
+ *
+ * @param uri the uri
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public boolean validate(URI uri) throws UnsupportedEncodingException {
+ boolean result = true;
+ if (!validatePath(uri.getRawPath())) {
+ result = false;
+ }
+ /*if (!validateQueryParams(uri.getRawQuery())) {
+ result = false;
+ } //TODO
+ */
+
+ return result;
+ }
+
+ /**
+ * Validate.
+ *
+ * @param info the info
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public boolean validate(UriInfo info) throws UnsupportedEncodingException {
+ boolean result = true;
+ if (!validatePath(info.getPath(false))) {
+ result = false;
+ }
+ if (!validateQueryParams(info.getQueryParameters(false))) {
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * Validate path.
+ *
+ * @param path the path
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private boolean validatePath(String path) throws UnsupportedEncodingException {
+ String[] segments = path.split("/");
+ boolean valid = true;
+ for (String segment : segments) {
+ if (!this.checkEncoding(segment)) {
+ valid = false;
+ }
+ }
+
+ return valid;
+
+ }
+
+ /**
+ * Validate query params.
+ *
+ * @param params the params
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private boolean validateQueryParams(MultivaluedMap<String, String> params) throws UnsupportedEncodingException {
+ boolean valid = true;
+
+ for (String key : params.keySet()) {
+ if (!this.checkEncoding(key)) {
+ valid = false;
+ }
+ for (String item : params.get(key)) {
+ if (!this.checkEncoding(item)) {
+ valid = false;
+ }
+ }
+ }
+ return valid;
+ }
+
+ /**
+ * Check encoding.
+ *
+ * @param segment the segment
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private boolean checkEncoding(String segment) throws UnsupportedEncodingException {
+ boolean result = false;
+ String decode = UriUtils.decode(segment, encoding);
+ String encode = UriUtils.encodePath(decode, encoding);
+ result = segment.equals(encode);
+
+ return result;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java
new file mode 100644
index 0000000..c84c51a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java
@@ -0,0 +1,1418 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+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.Vertex;
+import org.javatuples.Pair;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.uri.URIToRelationshipObject;
+import org.openecomp.aai.query.builder.QueryBuilder;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+import com.google.common.base.Joiner;
+import com.thinkaurelius.titan.core.SchemaViolationException;
+import com.thinkaurelius.titan.core.TitanException;
+
+public class DBSerializer {
+
+
+ /*
+ * Todo:
+ * - Generic query Interface
+ *
+ */
+ private final String className = DBSerializer.class.getSimpleName();
+ private AAILogger aaiLogger = new AAILogger(DBSerializer.class.getName());
+ private Graph graph = null;
+ private AtomicInteger totalCount = null;
+ private TransactionalGraphEngine engine = null;
+ private final String uniqueId = "aai-unique-key";
+ private String sourceOfTruth = "";
+ private ModelType introspectionType = null;
+ private String key = "";
+ private Version version = AAIProperties.LATEST;
+ private Loader latestLoader = null;
+ private EdgeRules edgeRules = EdgeRules.getInstance();
+ private Loader loader = null;
+ private final LogLineBuilder llBuilder;
+
+ /**
+ * Instantiates a new DB serializer.
+ *
+ * @param version the version
+ * @param engine the engine
+ * @param g the g
+ * @param introspectionType the introspection type
+ * @param sourceOfTruth the source of truth
+ * @param llBuilder the ll builder
+ */
+ public DBSerializer(Version version, TransactionalGraphEngine engine, Graph g, ModelType introspectionType, String sourceOfTruth, LogLineBuilder llBuilder) {
+ this(engine, g, introspectionType, sourceOfTruth, llBuilder);
+ this.version = version;
+ this.loader = LoaderFactory.createLoaderForVersion(introspectionType, version, llBuilder);
+
+ }
+
+ /**
+ * Instantiates a new DB serializer.
+ *
+ * @param engine the engine
+ * @param g the g
+ * @param introspectionType the introspection type
+ * @param sourceOfTruth the source of truth
+ * @param llBuilder the ll builder
+ */
+ public DBSerializer(TransactionalGraphEngine engine, Graph g, ModelType introspectionType, String sourceOfTruth, LogLineBuilder llBuilder) {
+ this.llBuilder = llBuilder;
+ this.engine = engine;
+ this.graph = g;
+ this.totalCount = engine.getCount();
+ this.sourceOfTruth = sourceOfTruth;
+ this.introspectionType = introspectionType;
+ this.loader = LoaderFactory.createLoaderForVersion(introspectionType, version, llBuilder);
+ this.latestLoader = LoaderFactory.createLoaderForVersion(introspectionType, AAIProperties.LATEST, llBuilder);
+ }
+
+ /**
+ * Touch standard vertex properties.
+ *
+ * @param v the v
+ * @param isNewVertex the is new vertex
+ */
+ /*
+ * to be defined and expanded later
+ */
+ public void touchStandardVertexProperties(Vertex v, boolean isNewVertex) {
+
+ /*v.setProperty(AAIProperties.NODE_TYPE, "");
+ v.setProperty("aai-last-mod-ts", "");
+ v.setProperty("aai-created-ts", "");
+ v.setProperty("source-of-truth", "");
+ v.setProperty("last-mod-source-of-truth", "");
+ v.setProperty("_rest-url", "");
+ */
+ long unixTimeNow = System.currentTimeMillis() / 1000L;
+ String timeNowInSec = "" + unixTimeNow;
+ if (isNewVertex) {
+ v.property(AAIProperties.SOURCE_OF_TRUTH, this.sourceOfTruth);
+ v.property(AAIProperties.CREATED_TS, timeNowInSec);
+
+ }
+ v.property(AAIProperties.RESOURCE_VERSION, timeNowInSec );
+ v.property(AAIProperties.LAST_MOD_TS, timeNowInSec);
+ v.property(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, this.sourceOfTruth);
+ }
+
+ /**
+ * Creates the new vertex.
+ *
+ * @param wrappedObject the wrapped object
+ * @param uri the uri
+ * @return the vertex
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private Vertex createNewVertex(Introspector wrappedObject, String uri) throws IllegalArgumentException, AAIException, UnsupportedEncodingException {
+
+ Vertex v = graph.addVertex();
+ v.property(AAIProperties.NODE_TYPE, wrappedObject.getDbName());
+ touchStandardVertexProperties(v, true);
+ return v;
+ }
+
+ /**
+ * Creates the new vertex.
+ *
+ * @param wrappedObject the wrapped object
+ * @return the vertex
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public Vertex createNewVertex(Introspector wrappedObject) throws UnsupportedEncodingException, AAIException {
+
+ return createNewVertex(wrappedObject, wrappedObject.getURI());
+ }
+
+ /**
+ * Trim class name.
+ *
+ * @param className the class name
+ * @return the string
+ */
+ /*
+ * Removes the classpath from a class name
+ */
+ public String trimClassName (String className) {
+ String returnValue = "";
+
+ if (className.lastIndexOf('.') == -1) {
+ return className;
+ }
+ returnValue = className.substring(className.lastIndexOf('.') + 1, className.length());
+
+ return returnValue;
+ }
+
+ /**
+ * Serialize to db.
+ *
+ * @param obj the obj
+ * @param v the v
+ * @param uriQuery the uri query
+ * @param identifier the identifier
+ * @throws SecurityException the security exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws InterruptedException the interrupted exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void serializeToDb(Introspector obj, Vertex v, QueryParser uriQuery, String identifier) throws SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, InterruptedException, NoSuchMethodException, AAIException, UnsupportedEncodingException {
+
+ int maxRetries = 10;
+ int objectCount = 1;
+ int retry = 0;
+ for (retry = 0; retry < maxRetries; ++retry) {
+ try {
+ if (uriQuery.isDependent()) {
+ //try to find the parent
+ List<Vertex> vertices = engine.getQueryEngine().executeParentQuery(graph, uriQuery.getQueryBuilder());
+ if (vertices.size() > 0) {
+ Vertex parent = vertices.get(0);
+ this.reflectDependentVertex(parent, v, obj);
+ } else {
+ throw new AAIException("AAI_6114", "No parent Node of type " + uriQuery.getParentResultType() + " for " + identifier);
+ }
+ } else {
+ processObject(obj, v);
+ }
+
+ break;
+ } catch (SchemaViolationException e) {
+ throw new AAIException("AAI_6117", e);
+ } catch (TitanException e) {
+ graph.tx().rollback();
+ AAIException ex = new AAIException("AAI_6142", e);
+ aaiLogger.error(ex.getErrorObject(), llBuilder.build(className, "serialize to db"), e);
+ Thread.sleep((retry + 1) * 20);
+ graph = engine.getGraph().newTransaction();
+ }
+ }
+
+ if (retry == maxRetries) {
+ throw new AAIException("AAI_6134");
+ }
+
+ totalCount.getAndAdd(objectCount);
+
+ }
+
+ /**
+ * Process object.
+ *
+ * @param <T> the generic type
+ * @param obj the obj
+ * @param v the v
+ * @return the list
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ /*
+ * Helper method for reflectToDb
+ * Handles all the property setting
+ */
+ private <T> List<Vertex> processObject (Introspector obj, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException, AAIException, UnsupportedEncodingException {
+ Object value = null;
+ int objectCount = 0;
+ String propertyType = "";
+ List<String> properties = obj.getProperties();
+ properties.remove(AAIProperties.RESOURCE_VERSION);
+ List<Vertex> dependentVertexes = new ArrayList<>();
+ List<Vertex> processedVertexes = new ArrayList<>();
+ boolean isComplexType = false;
+ boolean isListType = false;
+
+ for (String property : properties) {
+ propertyType = obj.getType(property);
+ isComplexType = obj.isComplexType(property);
+ isListType = obj.isListType(property);
+ value = obj.getValue(property);
+
+ if (!(isComplexType || isListType)) {
+ if (value != null) {
+ if (propertyType.toLowerCase().contains(".long")) {
+ v.property(property, new Integer(((Long)value).toString()));
+ } else {
+ v.property(property, value);
+ }
+ } else {
+ v.property(property).remove();
+ }
+ } else if (isListType) {
+ List list = (List)value;
+ if (obj.isComplexGenericType(property)) {
+ if (list != null) {
+ for (Object o : list) {
+ Introspector child = IntrospectorFactory.newInstance(this.introspectionType, o, llBuilder);
+ child.setURIChain(obj.getURI());
+ processedVertexes.add(reflectDependentVertex(v, child));
+ }
+ }
+ } else {
+ //simple list case
+ engine.setListProperty(v, property, list);
+ }
+ } else {
+ //method.getReturnType() is not 'simple' then create a vertex and edge recursively returning an edge back to this method
+ if (value != null) { //effectively ignore complex properties not included in the object we're processing
+ if (value.getClass().isArray()) {
+
+ int length = Array.getLength(value);
+ for (int i = 0; i < length; i ++) {
+ Object arrayElement = Array.get(value, i);
+ Introspector child = IntrospectorFactory.newInstance(this.introspectionType, arrayElement, llBuilder);
+ child.setURIChain(obj.getURI());
+ processedVertexes.add(reflectDependentVertex(v, child));
+
+ }
+ } else if (!property.equals("relationship-list")) {
+ // container case
+ Introspector introspector = IntrospectorFactory.newInstance(this.introspectionType, value, llBuilder);
+ if (introspector.isContainer()) {
+ dependentVertexes.addAll(this.getDependentVertexesOfType(v, introspector.getChildDBName()));
+ introspector.setURIChain(obj.getURI());
+
+ processedVertexes.addAll(processObject(introspector, v));
+
+ } else {
+ dependentVertexes.addAll(this.getDependentVertexesOfType(v, introspector.getDbName()));
+ processedVertexes.add(reflectDependentVertex(v, introspector));
+
+ }
+ } else if (property.equals("relationship-list")) {
+ handleRelationships(obj, v);
+ }
+ }
+ }
+ }
+ this.writeThroughDefaults(v, obj);
+ /* handle those vertexes not touched */
+ for (Vertex toBeRemoved : processedVertexes) {
+ dependentVertexes.remove(toBeRemoved);
+ }
+ this.deleteItemsWithTraversal(dependentVertexes);
+
+ this.totalCount.getAndAdd(objectCount);
+ return processedVertexes;
+ }
+
+ /**
+ * Handle relationships.
+ *
+ * @param obj the obj
+ * @param vertex the vertex
+ * @throws SecurityException the security exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ /*
+ * Handles the explicit relationships defined for an obj
+ */
+ private void handleRelationships(Introspector obj, Vertex vertex) throws SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, UnsupportedEncodingException, AAIException {
+
+
+ Object rl = null;
+
+ rl = obj.getValue("relationship-list");
+ Introspector wrappedRl = IntrospectorFactory.newInstance(this.introspectionType, rl, llBuilder);
+ processRelationshipList(wrappedRl, vertex);
+
+
+ }
+
+
+ /**
+ * Process relationship list.
+ *
+ * @param wrapped the wrapped
+ * @param v the v
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ private void processRelationshipList(Introspector wrapped, Vertex v) throws UnsupportedEncodingException, AAIException {
+
+ List<Object> relationships = (List<Object>)wrapped.getValue("relationship");
+
+ Vertex cousinVertex = null;
+ Edge e = null;
+ List<Edge> existingEdges = new ArrayList<>();
+ GraphTraversal<Vertex, Edge> pipeline = graph.traversal().V(v).bothE().has("isParent", false).dedup();
+
+ existingEdges = pipeline.toList();
+ for (Object relationship : relationships) {
+ Introspector wrappedRel = IntrospectorFactory.newInstance(this.introspectionType, relationship, llBuilder);
+ QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(wrappedRel);
+
+ List<Vertex> results = engine.getQueryEngine().executeQuery(graph, parser.getQueryBuilder());
+ if (results.size() == 0) {
+ AAIException ex = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
+ List<String> templateVars = new ArrayList<>();
+ templateVars.add(parser.getResultType());
+ templateVars.add(parser.getUri().toString());
+ ex.setTemplateVars(templateVars);
+ throw ex;
+ } else {
+ //still an issue if there's more than one
+ cousinVertex = results.get(0);
+ }
+
+ if (cousinVertex != null) {
+ e = this.getEdgeBetween(v, cousinVertex);
+
+ if (e == null) {
+ edgeRules.addEdge(v, cousinVertex);
+ } else {
+ existingEdges.remove(e);
+ }
+ }
+ }
+
+ for (Edge edge : existingEdges) {
+ edge.remove();
+ }
+
+ }
+
+ /**
+ * Write through defaults.
+ *
+ * @param v the v
+ * @param obj the obj
+ */
+ private void writeThroughDefaults(Vertex v, Introspector obj) {
+ Introspector latest = this.latestLoader.introspectorFromName(obj.getName());
+ if (latest != null) {
+ List<String> required = latest.getRequiredProperties();
+ String defaultValue = null;
+ Object vertexProp = null;
+ for (String field : required) {
+ defaultValue = latest.getPropertyMetadata(field).get("defaultValue");
+ if (defaultValue != null) {
+ vertexProp = v.<Object>property(field).orElse(null);
+ if (vertexProp == null) {
+ v.property(field, defaultValue);
+ }
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Reflect dependent vertex.
+ *
+ * @param v the v
+ * @param dependentObj the dependent obj
+ * @return the vertex
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private Vertex reflectDependentVertex(Vertex v, Introspector dependentObj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException, AAIException, UnsupportedEncodingException {
+
+ //QueryParser p = this.engine.getQueryBuilder().createQueryFromURI(obj.getURI());
+ //List<Vertex> items = this.engine.getQueryEngine().executeQuery(p.getQuery());
+ QueryBuilder query = this.engine.getQueryBuilder(v);
+ query.createEdgeTraversal(v, dependentObj);
+ query.createKeyQuery(dependentObj);
+
+ List<Vertex> items = this.engine.getQueryEngine().executeQuery(graph, query);
+
+ Vertex dependentVertex = null;
+ if (items.size() == 1) {
+ dependentVertex = items.get(0);
+ this.verifyResourceVersion("update", dependentObj.getDbName(), dependentVertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), (String)dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String)dependentObj.getURI());
+ } else {
+ this.verifyResourceVersion("create", dependentObj.getDbName(), "", (String)dependentObj.getValue(AAIProperties.RESOURCE_VERSION), (String)dependentObj.getURI());
+ dependentVertex = createNewVertex(dependentObj);
+ }
+
+ return reflectDependentVertex(v, dependentVertex, dependentObj);
+
+ }
+
+ /**
+ * Reflect dependent vertex.
+ *
+ * @param parent the parent
+ * @param child the child
+ * @param obj the obj
+ * @return the vertex
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private Vertex reflectDependentVertex(Vertex parent, Vertex child, Introspector obj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException, AAIException, UnsupportedEncodingException {
+
+
+ processObject(obj, child);
+
+ Edge e = this.getEdgeBetween(parent, child);
+ if (e == null) {
+ edgeRules.addTreeEdge(parent, child);
+ }
+
+ //e.setProperty("property-name", obj.getDbName());
+ this.totalCount.getAndAdd(2);
+ return child;
+
+ }
+
+ /**
+ * Db to object.
+ *
+ * @param vertices the vertices
+ * @param obj the obj
+ * @param depth the depth
+ * @param cleanUp the clean up
+ * @return the introspector
+ * @throws AAIException the AAI exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ public Introspector dbToObject(List<Vertex> vertices, Introspector obj, int depth, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, MalformedURLException {
+
+ if (vertices.size() > 1 && !obj.isContainer()) {
+ throw new AAIException("AAI_6136", "query object mismatch: this object cannot hold multiple items." + obj.getDbName());
+ } else if (obj.isContainer()) {
+ List getList = null;
+ String listProperty = "";
+ for (String property : obj.getProperties()) {
+ if (obj.isListType(property) && obj.isComplexGenericType(property)) {
+ listProperty = property;
+ break;
+ }
+ }
+
+ getList = (List)obj.getValue(listProperty);
+
+ for (Vertex v : vertices) {
+ Set<Vertex> seen = new HashSet<>();
+ Introspector childObject = obj.newIntrospectorInstanceOfNestedProperty(listProperty);
+ dbToObject(childObject, v, seen, depth, cleanUp);
+ getList.add(childObject.getUnderlyingObject());
+ }
+ } else if (vertices.size() == 1) {
+ Set<Vertex> seen = new HashSet<>();
+ obj = dbToObject(obj, vertices.get(0), seen, depth, cleanUp);
+ } else {
+ obj = null;
+ }
+
+
+ if (engine.shouldShutdown()) {
+ try {
+ graph.close();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return obj;
+ }
+
+ /**
+ * Db to object.
+ *
+ * @param obj the obj
+ * @param v the v
+ * @param seen the seen
+ * @param depth the depth
+ * @param cleanUp the clean up
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ private Introspector dbToObject(Introspector obj, Vertex v, Set<Vertex> seen, int depth, String cleanUp) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, MalformedURLException {
+
+ if (depth < 0) {
+ return null;
+ }
+ depth--;
+ seen.add(v);
+ List getList = null;
+ List<Vertex> vertices = null;
+ boolean modified = false;
+ for (String property : obj.getProperties()) {
+
+
+ if (!(obj.isComplexType(property) || obj.isListType(property))) {
+ this.copySimpleProperty(property, obj, v);
+ modified = true;
+ } else {
+ if (obj.isComplexType(property)) {
+ /* container case */
+
+ if (!property.equals("relationship-list") && depth >= 0) {
+ Introspector argumentObject = obj.newIntrospectorInstanceOfProperty(property);
+ Object result = dbToObject(argumentObject, v, seen, depth+1, cleanUp);
+ if (result != null) {
+ obj.setValue(property, argumentObject.getUnderlyingObject());
+ modified = true;
+ }
+ } else if (property.equals("relationship-list")){
+ /* relationships need to be handled correctly */
+ Object relationshipList = obj.newInstanceOfProperty(property);
+ relationshipList = createRelationshipList(v, relationshipList, cleanUp);
+ if (relationshipList != null) {
+ modified = true;
+ obj.setValue(property, relationshipList);
+ modified = true;
+ }
+
+ }
+ } else if (obj.isListType(property)) {
+
+ if (property.equals("any")) {
+ continue;
+ }
+ String genericType = obj.getGenericType(property);
+ String childDbName = "";
+ if (obj.isComplexGenericType(property) && depth >= 0) {
+ childDbName = convertFromCamelCase(genericType);
+ String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ EdgeRule rule = edgeRules.getEdgeRule(vType, childDbName);
+ if (rule.getDirection().equals(Direction.OUT)) {
+ vertices = this.engine.getQueryEngine().findRelatedVertices(v, Direction.OUT, rule.getLabel(), childDbName);
+
+ if (vertices.size() > 0) {
+ getList = (List)obj.getValue(property);
+ }
+ int removed = 0;
+ for (Vertex childVertex : vertices) {
+ if (!seen.contains(childVertex)) {
+ Introspector argumentObject = obj.newIntrospectorInstanceOfNestedProperty(property);
+
+ Object result = dbToObject(argumentObject, childVertex, seen, depth, cleanUp);
+ if (result != null) {
+ getList.add(argumentObject.getUnderlyingObject());
+ }
+ } else {
+ removed++;
+ LogLine line = llBuilder.build("db to object", "cycle has been found");
+ line.add("vertex id", childVertex.id().toString());
+ aaiLogger.info(line, true, "AAI_6144");
+ }
+ }
+ if (removed == vertices.size()) {
+ //vertices were all seen, reset the list
+ getList = null;
+ } else if (vertices.size() > 0) {
+ modified = true;
+ }
+ }
+ } else if (obj.isSimpleGenericType(property)) {
+ List temp = this.engine.getListProperty(v, property);
+ if (temp != null) {
+ getList = (List)obj.getValue(property);
+ getList.addAll(temp);
+ modified = true;
+ }
+
+ }
+
+ }
+
+ }
+ }
+
+ //no changes were made to this obj, discard the instance
+ if (!modified) {
+ return null;
+ }
+
+ return obj;
+
+ }
+ public Introspector getVertexProperties(Vertex v) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, MalformedURLException {
+ String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ if (nodeType == null) {
+ throw new AAIException("AAI_6143");
+ }
+ Introspector obj = this.latestLoader.introspectorFromName(nodeType);
+ Set<Vertex> seen = new HashSet<>();
+ int depth = 0;
+ String cleanUp = "false";
+ this.dbToObject(obj, v, seen, depth, cleanUp);
+
+ return obj;
+
+ }
+ public Introspector getLatestVersionView(Vertex v) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, MalformedURLException {
+ String nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ if (nodeType == null) {
+ throw new AAIException("AAI_6143");
+ }
+ Introspector obj = this.latestLoader.introspectorFromName(nodeType);
+ Set<Vertex> seen = new HashSet<>();
+ int depth = Integer.MAX_VALUE;
+ String cleanUp = "false";
+ this.dbToObject(obj, v, seen, depth, cleanUp);
+
+ return obj;
+ }
+ /**
+ * Copy simple property.
+ *
+ * @param property the property
+ * @param obj the obj
+ * @param v the v
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ private void copySimpleProperty(String property, Introspector obj, Vertex v) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ Object temp = v.<Object>property(property).orElse(null);
+ if (temp != null) {
+ /* this whole section is because of a disconnect between the types told to titan
+ * and the types in the POJOs. This may not be an issue anymore.
+ *
+ */
+ if (!temp.getClass().getName().equals(obj.getType(property))) {
+ temp = temp.toString();
+ Class<?> argumentClass = obj.getClass(property);
+ if (argumentClass.isPrimitive()) {
+ argumentClass = ClassUtils.primitiveToWrapper(argumentClass);
+ }
+ temp = argumentClass.getConstructor(String.class).newInstance(temp.toString());
+ }
+ obj.setValue(property, temp);
+ }
+ }
+
+ /**
+ * Simple db to object.
+ *
+ * @param obj the obj
+ * @param v the v
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ private void simpleDbToObject (Introspector obj, Vertex v) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ for (String property : obj.getProperties()) {
+
+
+ if (!(obj.isComplexType(property) || obj.isListType(property))) {
+ this.copySimpleProperty(property, obj, v);
+ }
+ }
+ }
+
+ /**
+ * Creates the relationship list.
+ *
+ * @param v the v
+ * @param obj the obj
+ * @param cleanUp the clean up
+ * @return the object
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ private Object createRelationshipList(Vertex v, Object obj, String cleanUp) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, UnsupportedEncodingException, AAIException, MalformedURLException {
+
+ Iterator<Edge> inEdges = v.edges(Direction.IN);
+ Iterator<Edge> outEdges = v.edges(Direction.OUT);
+
+ Introspector wrappedRelationshipList = IntrospectorFactory.newInstance(introspectionType, obj, llBuilder);
+ List<Object> relationshipObjList = (List<Object>)wrappedRelationshipList.getValue("relationship");
+ Object temp = null;
+ Object isParent = null;
+ Edge edge = null;
+ while (inEdges.hasNext()) {
+ edge = inEdges.next();
+ isParent = edge.<Boolean>property("isParent").orElse(null);
+ if (isParent == null || isParent.equals(Boolean.FALSE)) {
+ temp = wrappedRelationshipList.newInstanceOfNestedProperty("relationship");
+ Introspector relationshipObj = IntrospectorFactory.newInstance(introspectionType, temp, llBuilder);
+ Object result = processEdgeRelationship(relationshipObj, edge, Direction.OUT, cleanUp);
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+ }
+ }
+
+ while (outEdges.hasNext()) {
+ edge = outEdges.next();
+ isParent = edge.<Boolean>property("isParent").orElse(null);
+ if (isParent == null || isParent.equals(Boolean.FALSE)) {
+ temp = wrappedRelationshipList.newInstanceOfNestedProperty("relationship");
+ Introspector relationshipObj = IntrospectorFactory.newInstance(introspectionType, temp, llBuilder);
+ Object result = processEdgeRelationship(relationshipObj, edge, Direction.IN, cleanUp);
+ if (result != null) {
+ relationshipObjList.add(result);
+ }
+ }
+ }
+
+ if (relationshipObjList.isEmpty()) {
+ obj = null;
+ }
+ return obj;
+ }
+
+ /**
+ * Process edge relationship.
+ *
+ * @param relationshipObj the relationship obj
+ * @param edge the edge
+ * @param direction the direction
+ * @param cleanUp the clean up
+ * @return the object
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ private Object processEdgeRelationship(Introspector relationshipObj, Edge edge, Direction direction, String cleanUp) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, UnsupportedEncodingException, AAIException, MalformedURLException {
+ Vertex cousin = null;
+
+ if (direction.equals(Direction.IN)) {
+ cousin = edge.inVertex();
+ } else if (direction.equals(Direction.OUT)) {
+ cousin = edge.outVertex();
+ }
+ Pair<Vertex, List<Introspector>> tuple = this.getParents(cousin, true);
+ //damaged vertex found, ignore
+ if (tuple == null) {
+ return null;
+ }
+ List<Introspector> list = tuple.getValue1();
+ URI uri = this.getURIFromList(list);
+
+ URIToRelationshipObject uriParser = null;
+ try {
+ uriParser = new URIToRelationshipObject(this.loader, uri);
+ } catch (AAIException e) {
+ LogLine line = llBuilder.build("seralizer", "processing edge relationship");
+ line.add("bad vertex id", tuple.getValue0().id().toString());
+ aaiLogger.error(e.getErrorObject(), line, e);
+ if ("true".equals(cleanUp)) {
+ this.deleteWithTraversal(tuple.getValue0());
+ }
+ return null;
+ }
+ Introspector result = uriParser.getResult();
+ if (list.size() > 0) {
+ this.addRelatedToProperty(result, list.get(0));
+ }
+ return result.getUnderlyingObject();
+ }
+
+ /**
+ * Gets the URI for vertex.
+ *
+ * @param v the v
+ * @return the URI for vertex
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public URI getURIForVertex(Vertex v) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, UnsupportedEncodingException {
+ Pair<Vertex, List<Introspector>> tuple = this.getParents(v, false);
+ List<Introspector> list = tuple.getValue1();
+
+ return this.getURIFromList(list);
+ }
+
+ /**
+ * Gets the URI from list.
+ *
+ * @param list the list
+ * @return the URI from list
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private URI getURIFromList(List<Introspector> list) throws UnsupportedEncodingException {
+ String uri = "";
+ StringBuilder sb = new StringBuilder();
+ for (Introspector i : list) {
+ sb.insert(0, i.getURI());
+ }
+
+ uri = sb.toString();
+ URI result = UriBuilder.fromPath(uri).build();
+ return result;
+ }
+
+ /**
+ * Gets the parents.
+ *
+ * @param start the start
+ * @param removeDamaged the remove damaged
+ * @return the parents
+ * @throws InstantiationException the instantiation exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ private Pair<Vertex, List<Introspector>> getParents(Vertex start, boolean removeDamaged) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ String uri = "";
+ List<Vertex> results = this.engine.getQueryEngine().findParents(start);
+ List<Introspector> objs = new ArrayList<>();
+ String nodeType = "";
+ boolean shortCircuit = false;
+ for (Vertex v : results) {
+ nodeType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ //vertex on the other end of this edge is bad
+ if (nodeType == null) {
+ //log something here about what was found and that it was removed
+ LogLine line = llBuilder.build(className, "getParents");
+ line.add("vertexid", v.id().toString());
+ AAIException e = new AAIException("AAI_6143");
+ aaiLogger.error(e.getErrorObject(), line, e);
+ if (removeDamaged) {
+ this.deleteWithTraversal(v);
+ }
+ shortCircuit = true;
+ } else {
+ Introspector obj = this.loader.introspectorFromName(nodeType);
+ if (obj != null) {
+ this.simpleDbToObject(obj, v);
+ objs.add(obj);
+ }
+ }
+ }
+
+
+
+ //stop processing and don't return anything for this bad vertex
+ if (shortCircuit) {
+ return null;
+ }
+
+ return new Pair<>(results.get(results.size()-1), objs);
+ }
+
+ /**
+ * Adds the related to property.
+ *
+ * @param relationship the relationship
+ * @param child the child
+ */
+ public void addRelatedToProperty(Introspector relationship, Introspector child) {
+ String nameProps = child.getMetadata("nameProps");
+ List<Introspector> relatedToProperties = new ArrayList<>();
+
+ if (nameProps != null) {
+ String[] props = nameProps.split(",");
+ for (String prop : props) {
+ Introspector relatedTo = this.loader.introspectorFromName("related-to-property");
+ relatedTo.setValue("property-key", child.getDbName() + "." + prop);
+ relatedTo.setValue("property-value", child.getValue(prop));
+ relatedToProperties.add(relatedTo);
+ }
+ }
+
+ if (relatedToProperties.size() > 0) {
+ List relatedToList = (List)relationship.getValue("related-to-property");
+ for (Introspector obj : relatedToProperties) {
+ relatedToList.add(obj.getUnderlyingObject());
+ }
+ }
+
+ }
+
+ /**
+ * Creates the edge.
+ *
+ * @param relationship the relationship
+ * @param inputVertex the input vertex
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public boolean createEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
+
+ Vertex relatedVertex = null;
+
+ QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
+
+ List<Vertex> results = engine.getQueryEngine().executeQuery(graph, parser.getQueryBuilder());
+ if (results.size() == 0) {
+ AAIException e = new AAIException("AAI_6129", "Node of type " + parser.getResultType() + ". Could not find object at: " + parser.getUri());
+ List<String> templateVars = new ArrayList<>();
+ templateVars.add(parser.getResultType());
+ templateVars.add(parser.getUri().toString());
+ e.setTemplateVars(templateVars);
+ throw e;
+ } else {
+ //still an issue if there's more than one
+ relatedVertex = results.get(0);
+ }
+
+ if (relatedVertex != null) {
+
+ Edge e = this.getEdgeBetween(inputVertex, relatedVertex);
+ if (e == null) {
+ Edge edge = null;
+ edgeRules.addEdge(inputVertex, relatedVertex);
+
+ } else {
+ //attempted to link two vertexes already linked
+ }
+
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets the edges between.
+ *
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return the edges between
+ * @throws AAIException the AAI exception
+ */
+ private List<Edge> getEdgesBetween(Vertex outVertex, Vertex inVertex) throws AAIException {
+
+ List<Edge> result = new ArrayList<>();
+
+ if (inVertex != null) {
+ EdgeRule rule = edgeRules.getEdgeRule(outVertex, inVertex);
+ GraphTraversal<Vertex, Edge> findEdgesBetween = null;
+ findEdgesBetween = graph.traversal().V(outVertex).bothE().filter(__.otherV().hasId(inVertex.id()));
+ List<Edge> edges = findEdgesBetween.toList();
+ for (Edge edge : edges) {
+ if (edge.label().equals(rule.getLabel())) {
+ result.add(edge);
+ }
+ }
+
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets the edge between.
+ *
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return the edge between
+ * @throws AAIException the AAI exception
+ */
+ private Edge getEdgeBetween(Vertex outVertex, Vertex inVertex) throws AAIException {
+
+
+
+ if (inVertex != null) {
+
+ List<Edge> edges = this.getEdgesBetween(outVertex, inVertex);
+
+ if (edges.size() > 0) {
+ return edges.get(0);
+ }
+
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Delete edge.
+ *
+ * @param relationship the relationship
+ * @param inputVertex the input vertex
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public boolean deleteEdge(Introspector relationship, Vertex inputVertex) throws UnsupportedEncodingException, AAIException {
+
+ Vertex relatedVertex = null;
+
+ QueryParser parser = engine.getQueryBuilder().createQueryFromRelationship(relationship);
+
+ List<Vertex> results = engine.getQueryEngine().executeQuery(graph, parser.getQueryBuilder());
+ //dangerous
+ relatedVertex = results.get(0);
+
+ Edge edge = this.getEdgeBetween(inputVertex, relatedVertex);
+ if (edge != null) {
+ edge.remove();
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+
+ /**
+ * Gets the dependent vertexes of type.
+ *
+ * @param start the start
+ * @param nodeType the node type
+ * @return the dependent vertexes of type
+ */
+ private List<Vertex> getDependentVertexesOfType(Vertex start, String nodeType) {
+
+ List<Vertex> p = graph.traversal().V(start).outE().has("isParent", true).inV().has(AAIProperties.NODE_TYPE, nodeType).dedup().toList();
+
+ return p;
+ }
+
+ /**
+ * Delete items with traversal.
+ *
+ * @param vertexes the vertexes
+ * @throws IllegalStateException the illegal state exception
+ */
+ public void deleteItemsWithTraversal(List<Vertex> vertexes) throws IllegalStateException {
+ for (Vertex v : vertexes) {
+ deleteWithTraversal(v);
+ }
+ }
+
+ /**
+ * Delete with traversal.
+ *
+ * @param startVertex the start vertex
+ */
+ public void deleteWithTraversal(Vertex startVertex) {
+
+ List<Vertex> results = this.engine.getQueryEngine().findDeletable(startVertex);
+
+ for (Vertex v : results) {
+ v.remove();
+ }
+
+ }
+
+ /**
+ * Delete.
+ *
+ * @param v the v
+ * @param resourceVersion the resource version
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws InterruptedException the interrupted exception
+ */
+ public void delete(Vertex v, String resourceVersion) throws IllegalArgumentException, AAIException, InterruptedException {
+
+ boolean result = verifyDeleteSemantics(v, resourceVersion);
+ if (result) {
+ int maxRetries = 10;
+ int retry = 0;
+ for (retry = 0; retry < maxRetries; ++retry) {
+ try {
+ try {
+ deleteWithTraversal(v);
+ // deleteHelper(vertices);
+ break;
+ } catch (IllegalStateException e) {
+ throw new AAIException("AAI_6110", e);
+ }
+ } catch (TitanException e) {
+ graph.tx().rollback();
+ AAIException ex = new AAIException("AAI_6142", e);
+ aaiLogger.error(ex.getErrorObject(), llBuilder.build(className, "delete vertex"), e);
+ Thread.sleep((retry + 1) * 20);
+ graph = engine.getGraph().newTransaction();
+ }
+ }
+ if (retry == maxRetries) {
+ throw new AAIException("AAI_6134");
+ }
+ if (engine.shouldShutdown()) {
+ try {
+ graph.close();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+
+ /**
+ * Verify delete semantics.
+ *
+ * @param vertex the vertex
+ * @param resourceVersion the resource version
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ private boolean verifyDeleteSemantics(Vertex vertex, String resourceVersion) throws AAIException {
+ boolean result = false;
+ String nodeType = "";
+ DeleteSemantic semantic = null;
+ List<Edge> inEdges = null;
+ List<Edge> outEdges = null;
+ String errorDetail = " unknown delete semantic found";
+ String aaiExceptionCode = "";
+ nodeType = vertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ if (!this.verifyResourceVersion("delete", nodeType, vertex.<String>property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType)) {
+ }
+ semantic = edgeRules.getDeleteSemantic(nodeType);
+ inEdges = (List<Edge>)IteratorUtils.toList(vertex.edges(Direction.IN));
+ outEdges = (List<Edge>)IteratorUtils.toList(vertex.edges(Direction.OUT));
+ if (semantic.equals(DeleteSemantic.CASCADE_TO_CHILDREN)) {
+ result = true;
+ } else if (semantic.equals(DeleteSemantic.ERROR_IF_ANY_EDGES)) {
+ if (inEdges.size() == 0 && outEdges.size() == 0) {
+ result = true;
+ } else {
+ errorDetail = " Node cannot be deleted because it still has Edges and the " + semantic + " scope was used.\n";
+ aaiExceptionCode = "AAI_6110";
+ }
+ } else if (semantic.equals(DeleteSemantic.ERROR_IF_ANY_IN_EDGES) || semantic.equals(DeleteSemantic.ERROR_4_IN_EDGES_OR_CASCADE)) {
+
+ if (inEdges.size() == 0) {
+ result = true;
+ } else if (inEdges.size() == 1) {
+ //the only in edge is a parent edge, this node is still safe to delete
+ Boolean isParent = inEdges.get(0).<Boolean>property("isParent").orElse(null);
+ if (isParent != null && isParent) {
+ result = true;
+ }
+ }
+
+ if (!result) {
+ errorDetail = " Node cannot be deleted because it still has Edges and the " + semantic + " scope was used.\n";
+ aaiExceptionCode = "AAI_6110";
+ }
+ } else if (semantic.equals(DeleteSemantic.THIS_NODE_ONLY)) {
+ if (outEdges.size() == 0) {
+ result = true;
+ } else {
+ result = true;
+ for (Edge edge : outEdges) {
+ Object property = edge.<Boolean>property("isParent").orElse(null);
+ if (property != null && property.equals(Boolean.TRUE)) {
+ Vertex v = edge.inVertex();
+ String vType = v.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ errorDetail = " Node cannot be deleted using scope = " + semantic +
+ " another node (type = " + vType + ") depends on it for uniqueness.";
+ aaiExceptionCode = "AAI_6110";
+ result = false;
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (!result) {
+ throw new AAIException(aaiExceptionCode, errorDetail);
+ }
+ return result;
+ }
+
+ /**
+ * Verify resource version.
+ *
+ * @param action the action
+ * @param nodeType the node type
+ * @param currentResourceVersion the current resource version
+ * @param resourceVersion the resource version
+ * @param uri the uri
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ public boolean verifyResourceVersion(String action, String nodeType, String currentResourceVersion, String resourceVersion, String uri) throws AAIException {
+ String enabled = "";
+ String errorDetail = "";
+ String aaiExceptionCode = "";
+ if (currentResourceVersion == null) {
+ currentResourceVersion = "";
+ }
+
+ if (resourceVersion == null) {
+ resourceVersion = "";
+ }
+ try {
+ enabled = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
+ } catch (AAIException e) {
+ aaiLogger.error(e.getErrorObject(), llBuilder.build(className, "read property file"), e);
+
+ }
+
+ if (enabled.equals("true")) {
+ if (!currentResourceVersion.equals(resourceVersion)) {
+ if (action.equals("create") && !resourceVersion.equals("")) {
+ errorDetail = "resource-version passed for " + action + " of " + uri;
+ aaiExceptionCode = "AAI_6135";
+ } else if (resourceVersion.equals("")) {
+ errorDetail = "resource-version not passed for " + action + " of " + uri;
+ aaiExceptionCode = "AAI_6130";
+ } else {
+ errorDetail = "resource-version MISMATCH for " + action + " of " + uri;
+ aaiExceptionCode = "AAI_6131";
+ }
+
+ throw new AAIException(aaiExceptionCode, errorDetail);
+
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Convert from camel case.
+ *
+ * @param name the name
+ * @return the string
+ */
+ private String convertFromCamelCase (String name) {
+
+ Pattern p = Pattern.compile("(?:[A-Z][a-z0-9]+)|(?:[A-Z]+(?=[A-Z]))");
+ Matcher m = p.matcher(name);
+
+ ArrayList<String> list = new ArrayList<String>();
+ String result = "";
+ while(m.find()) {
+ list.add(m.group(0));
+ }
+ if (list.size() > 0) {
+ result = Joiner.on("-").join(list).toLowerCase();
+ if (result.equals("cvlan-tag-entry")) {
+ result = "cvlan-tag";
+ }
+ return result;
+ } else {
+ return name;
+ }
+ }
+
+
+ /**
+ * Gets the key.
+ *
+ * @return the key
+ */
+ public String getKey() {
+ return this.key;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DeleteSemantic.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DeleteSemantic.java
new file mode 100644
index 0000000..5b153c2
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DeleteSemantic.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+
+/**
+ * Possible values for deleteScope can be:
+ * USE_DEFAULT - Get the scope from ref data for this node
+ * THIS_NODE_ONLY (but should fail if it there are nodes that depend on it for uniqueness)
+ * CASCADE_TO_CHILDREN - will look for OUT-Edges that have parentOf/hasDelTarget = true and follow those down
+ * ERROR_4_IN_EDGES_OR_CASCADE - combo of error-if-any-IN-edges + CascadeToChildren
+ * ERROR_IF_ANY_IN_EDGES - Fail if this node has any existing IN edges
+ * ERROR_IF_ANY_EDGES - Fail if this node has any existing edges at all!
+ */
+public enum DeleteSemantic {
+ USE_DEFAULT,
+ THIS_NODE_ONLY,
+ CASCADE_TO_CHILDREN,
+ ERROR_4_IN_EDGES_OR_CASCADE,
+ ERROR_IF_ANY_IN_EDGES,
+ ERROR_IF_ANY_EDGES,
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRule.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRule.java
new file mode 100644
index 0000000..6d0acc6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRule.java
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+
+public class EdgeRule {
+
+ private String label = "";
+ private MultiplicityRule multiplicityRule = null;
+ private Direction direction = null;
+ private Map<String, String> edgeProperties = null;
+ private final String IS_PARENT = "isParent";
+ private final String USES_RESOURCE = "usesResource";
+ private final String HAS_DEL_TARGET = "hasDelTarget";
+ private final String SVC_INFRA = "SVC-INFRA";
+
+ /**
+ * Instantiates a new edge rule.
+ */
+ public EdgeRule() {
+ edgeProperties = new HashMap<>();
+ }
+
+ /**
+ * Gets the label.
+ *
+ * @return the label
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Sets the label.
+ *
+ * @param label the new label
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Gets the multiplicity rule.
+ *
+ * @return the multiplicity rule
+ */
+ public MultiplicityRule getMultiplicityRule() {
+ return multiplicityRule;
+ }
+
+ /**
+ * Sets the multiplicity rule.
+ *
+ * @param multiplicityRule the new multiplicity rule
+ */
+ public void setMultiplicityRule(MultiplicityRule multiplicityRule) {
+ this.multiplicityRule = multiplicityRule;
+ }
+
+ /**
+ * Gets the direction.
+ *
+ * @return the direction
+ */
+ public Direction getDirection() {
+ return direction;
+ }
+
+ /**
+ * Sets the direction.
+ *
+ * @param direction the new direction
+ */
+ public void setDirection(Direction direction) {
+ this.direction = direction;
+ }
+
+ /**
+ * Gets the checks if is parent.
+ *
+ * @return the checks if is parent
+ */
+ public String getIsParent() {
+ return this.getProp(this.IS_PARENT);
+ }
+
+ /**
+ * Sets the checks if is parent.
+ *
+ * @param isParent the new checks if is parent
+ */
+ public void setIsParent(String isParent) {
+ this.setProp(this.IS_PARENT, isParent);
+ }
+
+ /**
+ * Gets the uses resource.
+ *
+ * @return the uses resource
+ */
+ public String getUsesResource() {
+ return this.getProp(this.USES_RESOURCE);
+ }
+
+ /**
+ * Sets the uses resource.
+ *
+ * @param usesResource the new uses resource
+ */
+ public void setUsesResource(String usesResource) {
+ this.setProp(this.USES_RESOURCE, usesResource);
+ }
+
+ /**
+ * Gets the checks for del target.
+ *
+ * @return the checks for del target
+ */
+ public String getHasDelTarget() {
+ return this.getProp(this.HAS_DEL_TARGET);
+ }
+
+ /**
+ * Sets the checks for del target.
+ *
+ * @param hasDelTarget the new checks for del target
+ */
+ public void setHasDelTarget(String hasDelTarget) {
+ this.setProp(this.HAS_DEL_TARGET, hasDelTarget);
+ }
+
+ /**
+ * Gets the service infrastructure.
+ *
+ * @return the service infrastructure
+ */
+ public String getServiceInfrastructure() {
+ return this.getProp(this.SVC_INFRA);
+ }
+
+ /**
+ * Sets the service infrastructure.
+ *
+ * @param serviceInfrastructure the new service infrastructure
+ */
+ public void setServiceInfrastructure(String serviceInfrastructure) {
+ this.setProp(this.SVC_INFRA, serviceInfrastructure);
+ }
+
+ /**
+ * Gets the edge properties.
+ *
+ * @return the edge properties
+ */
+ public Map<String, String> getEdgeProperties() {
+ return this.edgeProperties;
+ }
+
+ /**
+ * Sets the prop.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ private void setProp(String key, String value) {
+ this.edgeProperties.put(key, value);
+ }
+
+ /**
+ * Gets the prop.
+ *
+ * @param key the key
+ * @return the prop
+ */
+ private String getProp(String key) {
+ return this.edgeProperties.get(key);
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java
new file mode 100644
index 0000000..079ae68
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java
@@ -0,0 +1,310 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+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.Vertex;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.openecomp.aai.exceptions.AAIException;
+
+import com.google.common.collect.Multimap;
+
+public class EdgeRules {
+
+ private Multimap<String, String> rules = DbEdgeRules.EdgeRules;
+ private Multimap<String, String> deleteScope = DbEdgeRules.DefaultDeleteScope;
+ private final int EDGE_NAME = 0;
+ private final int DIRECTION = 1;
+ private final int MULTIPLICITY_RULE = 2;
+ private final int IS_PARENT = 3;
+ private final int USES_RESOURCE = 4;
+ private final int HAS_DEL_TARGET = 5;
+ private final int SVC_INFRA = 6;
+
+ /**
+ * Instantiates a new edge rules.
+ */
+ private EdgeRules() {
+
+ }
+ private static class Helper {
+ private static final EdgeRules INSTANCE = new EdgeRules();
+
+ }
+
+ /**
+ * Gets the single instance of EdgeRules.
+ *
+ * @return single instance of EdgeRules
+ */
+ public static EdgeRules getInstance() {
+ return Helper.INSTANCE;
+
+ }
+
+ /**
+ * Adds the tree edge.
+ *
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return the edge
+ * @throws AAIException the AAI exception
+ */
+ public Edge addTreeEdge(Vertex outVertex, Vertex inVertex) throws AAIException {
+ return this.addEdge(EdgeType.TREE, outVertex, inVertex);
+ }
+
+ /**
+ * Adds the edge.
+ *
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return the edge
+ * @throws AAIException the AAI exception
+ */
+ public Edge addEdge(Vertex outVertex, Vertex inVertex) throws AAIException {
+ return this.addEdge(EdgeType.COUSIN, outVertex, inVertex);
+ }
+
+ /**
+ * Adds the edge.
+ *
+ * @param type the type
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return the edge
+ * @throws AAIException the AAI exception
+ */
+ private Edge addEdge(EdgeType type, Vertex outVertex, Vertex inVertex) throws AAIException {
+
+ EdgeRule rule = this.getEdgeRule(outVertex, inVertex);
+ if (type.equals(EdgeType.COUSIN) && rule.getIsParent().equals("true")) {
+ throw new AAIException("AAI_6145");
+ }
+ Edge e = null;
+ if (this.validateMultiplicity(rule, outVertex, inVertex)) {
+ if (rule.getDirection().equals(Direction.OUT)) {
+ e = outVertex.addEdge(rule.getLabel(), inVertex);
+ } else if (rule.getDirection().equals(Direction.IN)) {
+ e = inVertex.addEdge(rule.getLabel(), outVertex);
+ }
+
+ this.addProperties(e, rule);
+ }
+ return e;
+ }
+
+ /**
+ * Adds the properties.
+ *
+ * @param edge the edge
+ * @param rule the rule
+ */
+ public void addProperties(Edge edge, EdgeRule rule) {
+
+ // In DbEdgeRules.EdgeRules -- What we have as "edgeRule" is a comma-delimited set of strings.
+ // The first item is the edgeLabel.
+ // The second in the list is always "direction" which is always OUT for the way we've implemented it.
+ // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to
+ // tags as defined in EdgeInfoMap.
+ // Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it
+ Map<String, String> propMap = rule.getEdgeProperties();
+
+ for (String key : propMap.keySet()) {
+ String revKeyname = key + "-REV";
+ String triple = propMap.get(key);
+ if(triple.equals("true")){
+ edge.property(key, true);
+ edge.property(revKeyname,false);
+ } else if (triple.equals("false")) {
+ edge.property(key, false);
+ edge.property(revKeyname,false);
+ } else if (triple.equals("reverse")) {
+ edge.property(key, false);
+ edge.property(revKeyname,true);
+ }
+ }
+ }
+
+ /**
+ * Checks for edge rule.
+ *
+ * @param outType the out type
+ * @param inType the in type
+ * @return true, if successful
+ */
+ private boolean hasEdgeRule(String outType, String inType) {
+
+ Collection<String> collection = rules.get(outType + "|" + inType);
+
+ return !collection.isEmpty();
+
+ }
+
+ /**
+ * Checks for edge rule.
+ *
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return true, if successful
+ */
+ private boolean hasEdgeRule(Vertex outVertex, Vertex inVertex) {
+ String outType = (String)outVertex.<String>property("aai-node-type").orElse(null);
+ String inType = (String)inVertex.<String>property("aai-node-type").orElse(null);
+
+ return this.hasEdgeRule(outType, inType);
+
+ }
+
+ /**
+ * Gets the edge rule.
+ *
+ * @param outType the out type
+ * @param inType the in type
+ * @return the edge rule
+ * @throws AAIException the AAI exception
+ */
+ public EdgeRule getEdgeRule(String outType, String inType) throws AAIException {
+ EdgeRule rule = new EdgeRule();
+ Collection<String> collection = null;
+ boolean isFlipped = false;
+ if (this.hasEdgeRule(outType, inType)) {
+
+ } else if (this.hasEdgeRule(inType, outType)) {
+ //flip values
+ String tempType = inType;
+ inType = outType;
+ outType = tempType;
+ isFlipped = true;
+ } else {
+ String detail = "No EdgeRule found for passed nodeTypes: " + outType + ", " + inType + ".";
+ throw new AAIException("AAI_6120", detail);
+ }
+ collection = rules.get(outType + "|" + inType);
+
+ String[] info = collection.iterator().next().split(",");
+ rule.setLabel(info[this.EDGE_NAME]);
+ rule.setMultiplicityRule(MultiplicityRule.valueOf(info[this.MULTIPLICITY_RULE].toUpperCase()));
+ rule.setHasDelTarget(info[this.HAS_DEL_TARGET]);
+ rule.setUsesResource(info[this.USES_RESOURCE]);
+ rule.setIsParent(info[this.IS_PARENT]);
+ rule.setServiceInfrastructure(info[this.SVC_INFRA]);
+ Direction direction = Direction.valueOf(info[this.DIRECTION]);
+ if (isFlipped && direction.equals(Direction.OUT)) {
+ rule.setDirection(Direction.IN);
+ } else if (isFlipped && direction.equals(Direction.IN)){
+ rule.setDirection(Direction.OUT);
+ } else {
+ rule.setDirection(direction);
+ }
+
+ return rule;
+ }
+
+ /**
+ * Gets the edge rule.
+ *
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return the edge rule
+ * @throws AAIException the AAI exception
+ */
+ public EdgeRule getEdgeRule(Vertex outVertex, Vertex inVertex) throws AAIException {
+ String outType = (String)outVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String inType = (String)inVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+
+ return this.getEdgeRule(outType, inType);
+
+
+ }
+
+ /**
+ * Gets the delete semantic.
+ *
+ * @param nodeType the node type
+ * @return the delete semantic
+ */
+ public DeleteSemantic getDeleteSemantic(String nodeType) {
+ Collection<String> semanticCollection = deleteScope.get(nodeType);
+ String semantic = semanticCollection.iterator().next();
+
+ return DeleteSemantic.valueOf(semantic);
+
+ }
+
+ /**
+ * Validate multiplicity.
+ *
+ * @param rule the rule
+ * @param outVertex the out vertex
+ * @param inVertex the in vertex
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ private boolean validateMultiplicity(EdgeRule rule, Vertex outVertex, Vertex inVertex) throws AAIException {
+
+ if (rule.getDirection().equals(Direction.OUT)) {
+
+ } else if (rule.getDirection().equals(Direction.IN)) {
+ Vertex tempV = inVertex;
+ inVertex = outVertex;
+ outVertex = tempV;
+ }
+
+ String outVertexType = outVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String inVertexType = inVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+ String label = rule.getLabel();
+ MultiplicityRule multiplicityRule = rule.getMultiplicityRule();
+ List<Object> outEdges = outVertex.graph().traversal().V(outVertex).outE(label).as("outEdges").inV().has(AAIProperties.NODE_TYPE, inVertexType).select("outEdges").toList();
+ List<Object> inEdges = inVertex.graph().traversal().V(inVertex).inE(label).as("inEdges").outV().has(AAIProperties.NODE_TYPE, outVertexType).select("inEdges").toList();
+ String detail = "";
+ if (multiplicityRule.equals(MultiplicityRule.ONE2ONE)) {
+ if (inEdges.size() >= 1 || outEdges.size() >= 1 ) {
+ detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + outVertexType + " and " + inVertexType;
+ }
+ } else if (multiplicityRule.equals(MultiplicityRule.ONE2MANY)) {
+ if (inEdges.size() >= 1) {
+ detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + outVertexType + " and " + inVertexType;
+ }
+ } else if (multiplicityRule.equals(MultiplicityRule.MANY2ONE)) {
+ if (outEdges.size() >= 1) {
+ detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + outVertexType + " and " + inVertexType;
+ }
+ } else {
+
+ }
+
+ if (!detail.equals("")) {
+ throw new AAIException("AAI_6140", detail);
+ }
+
+ return true;
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeType.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeType.java
new file mode 100644
index 0000000..cf3219f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeType.java
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+public enum EdgeType {
+ COUSIN,
+ TREE;
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/GraphSingleton.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/GraphSingleton.java
new file mode 100644
index 0000000..f4552eb
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/GraphSingleton.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+
+
+public class GraphSingleton {
+
+ protected AAILogger aaiLogger = new AAILogger("AAIGraph");
+ protected LogLine logline = new LogLine();
+ protected LogLine vlogline = new LogLine();
+ protected LogLine tlogline = new LogLine();
+
+ protected static TitanGraph graph = null;
+ protected AtomicInteger totalCount = new AtomicInteger();
+
+ private static class Helper {
+ private static final GraphSingleton INSTANCE = new GraphSingleton();
+ }
+
+ /**
+ * Gets the single instance of GraphSingleton.
+ *
+ * @return single instance of GraphSingleton
+ */
+ public static GraphSingleton getInstance() {
+ return Helper.INSTANCE;
+
+ }
+
+ /**
+ * Gets the count.
+ *
+ * @return the count
+ */
+ public AtomicInteger getCount() {
+ return totalCount;
+ }
+
+ /**
+ * Gets the logger.
+ *
+ * @return the logger
+ */
+ public AAILogger getLogger() {
+ return aaiLogger;
+ }
+
+ /**
+ * Gets the tx graph.
+ *
+ * @return the tx graph
+ */
+ public TitanGraph getTxGraph() {
+ return graph;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/MultiplicityRule.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/MultiplicityRule.java
new file mode 100644
index 0000000..a1c9124
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/MultiplicityRule.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+public enum MultiplicityRule {
+ MANY2ONE,
+ ONE2MANY,
+ ONE2ONE,
+ MANY2MANY
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/TitanGraphSingleton.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/TitanGraphSingleton.java
new file mode 100644
index 0000000..549ce4d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/TitanGraphSingleton.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.LogLine;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+
+public class TitanGraphSingleton extends GraphSingleton {
+
+
+ /**
+ * Instantiates a new titan graph singleton.
+ */
+ private TitanGraphSingleton() {
+
+ LogLine alogline = new LogLine();
+ alogline.init("aaidbmap", "Init-000", "AAI", "AAI Graph loading");
+ try {
+ //graph = TitanFactory.open(AAIConstants.AAI_CONFIG_FILENAME);
+ /* just grab the one from the A&AI start up */
+ graph = AAIGraph.getInstance().getGraph();
+ if (graph != null) {
+ aaiLogger.info(alogline, true, "0");
+ } else {
+ aaiLogger.info(alogline, false, "AAI_5102");
+ throw new AAIException("AAI_5102");
+ }
+ } catch (Exception e) {
+ aaiLogger.info(alogline, false, "AAI_5102");
+ }
+ }
+
+ private static class Helper {
+ private static final TitanGraphSingleton INSTANCE = new TitanGraphSingleton();
+ }
+
+ /**
+ * Gets the single instance of TitanGraphSingleton.
+ *
+ * @return single instance of TitanGraphSingleton
+ */
+ public static TitanGraphSingleton getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TitanGraph getTxGraph() {
+ return graph;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/QueryStyle.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/QueryStyle.java
new file mode 100644
index 0000000..f6fae4d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/QueryStyle.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines;
+
+public enum QueryStyle {
+ GREMLIN_TRAVERSAL, GREMLIN_UNIQUE, GREMLINPIPELINE_TRAVERSAL, TRAVERSAL
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TitanDBEngine.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TitanDBEngine.java
new file mode 100644
index 0000000..fd01f84
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TitanDBEngine.java
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.thinkaurelius.titan.core.Cardinality;
+import com.thinkaurelius.titan.core.TitanProperty;
+import com.thinkaurelius.titan.core.TitanVertex;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.serialization.db.TitanGraphSingleton;
+
+public class TitanDBEngine extends TransactionalGraphEngine {
+
+ /**
+ * Instantiates a new titan DB engine.
+ *
+ * @param style the style
+ * @param loader the loader
+ */
+ public TitanDBEngine(QueryStyle style, Loader loader) {
+ super(style, loader);
+ this.singleton = TitanGraphSingleton.getInstance();
+ this.graph = singleton.getTxGraph();
+ }
+
+ /**
+ * Instantiates a new titan DB engine.
+ *
+ * @param style the style
+ * @param loader the loader
+ * @param connect the connect
+ */
+ public TitanDBEngine(QueryStyle style, Loader loader, boolean connect) {
+ super(style, loader);
+ if (connect) {
+ this.singleton = TitanGraphSingleton.getInstance();
+ this.graph = singleton.getTxGraph();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean setListProperty(Vertex v, String name, List<?> objs) {
+
+ //clear out list full replace style
+
+ Iterator<VertexProperty<Object>> iterator = ((TitanVertex)v).properties(name);
+ while (iterator.hasNext()) {
+ iterator.next().remove();
+ }
+ if (objs != null) {
+ for (Object obj : objs) {
+ v.property(name, obj);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List getListProperty(Vertex v, String name) {
+
+ List result = new ArrayList();
+
+ Iterator<VertexProperty<Object>> iterator = ((TitanVertex)v).properties(name);
+
+ while (iterator.hasNext()) {
+ result.add(iterator.next().value());
+ }
+
+ if (result.size() == 0) {
+ result = null;
+ }
+
+ return result;
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java
new file mode 100644
index 0000000..9ebd23a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.query.builder.GremlinTraversal;
+import org.openecomp.aai.query.builder.GremlinUnique;
+import org.openecomp.aai.query.builder.QueryBuilder;
+import org.openecomp.aai.query.builder.TraversalQuery;
+import org.openecomp.aai.serialization.db.GraphSingleton;
+import org.openecomp.aai.serialization.engines.query.GraphTraversalQueryEngine;
+import org.openecomp.aai.serialization.engines.query.QueryEngine;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+
+public abstract class TransactionalGraphEngine {
+
+ protected Graph graph = null;
+ protected GraphSingleton singleton = null;
+ protected QueryEngine queryEngine = null;
+ protected QueryBuilder queryBuilder = null;
+ protected QueryStyle style = null;
+ protected Loader loader = null;
+
+ /**
+ * Instantiates a new transactional graph engine.
+ *
+ * @param style the style
+ * @param loader the loader
+ */
+ public TransactionalGraphEngine (QueryStyle style, Loader loader) {
+ this.loader = loader;
+ this.style = style;
+ if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) {
+ //this.queryEngine = new GremlinQueryEngine(this);
+ } else if (style.equals(QueryStyle.GREMLIN_UNIQUE)) {
+ //this.queryEngine = new GremlinQueryEngine(this);
+ } else if (style.equals(QueryStyle.GREMLINPIPELINE_TRAVERSAL)) {
+ //this.queryEngine = new GremlinPipelineQueryEngine(this);
+ } else if (style.equals(QueryStyle.TRAVERSAL)) {
+ this.queryEngine = new GraphTraversalQueryEngine(this);
+ } else {
+ throw new IllegalArgumentException("Query Engine type not recognized");
+ }
+ }
+
+
+ /**
+ * Sets the list property.
+ *
+ * @param v the v
+ * @param name the name
+ * @param obj the obj
+ * @return true, if successful
+ */
+ public abstract boolean setListProperty(Vertex v, String name, List<?> obj);
+
+ /**
+ * Gets the list property.
+ *
+ * @param v the v
+ * @param name the name
+ * @return the list property
+ */
+ public abstract List getListProperty(Vertex v, String name);
+
+ /**
+ * Gets the graph.
+ *
+ * @return the graph
+ */
+ public TitanGraph getGraph() {
+ return singleton.getTxGraph();
+ }
+
+ /**
+ * Gets the count.
+ *
+ * @return the count
+ */
+ public AtomicInteger getCount() {
+ return singleton.getCount();
+ }
+
+ /**
+ * Should shutdown.
+ *
+ * @return true, if successful
+ */
+ public boolean shouldShutdown() {
+ return false;
+ }
+
+ /**
+ * Gets the query engine.
+ *
+ * @return the query engine
+ */
+ public QueryEngine getQueryEngine() {
+ return this.queryEngine;
+ }
+
+ /**
+ * Gets the query builder.
+ *
+ * @return the query builder
+ */
+ public QueryBuilder getQueryBuilder() {
+ if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) {
+ return new GremlinTraversal(loader);
+ } else if (style.equals(QueryStyle.GREMLIN_UNIQUE)) {
+ return new GremlinUnique(loader);
+ } else if (style.equals(QueryStyle.GREMLINPIPELINE_TRAVERSAL)) {
+ //return new GremlinPipelineTraversal(loader);
+ } else if (style.equals(QueryStyle.TRAVERSAL)) {
+ return new TraversalQuery(loader);
+ } else {
+ throw new IllegalArgumentException("Query Builder type not recognized");
+ }
+ return queryBuilder;
+ }
+
+ /**
+ * Gets the query builder.
+ *
+ * @param start the start
+ * @return the query builder
+ */
+ public QueryBuilder getQueryBuilder(Vertex start) {
+ if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) {
+ return new GremlinTraversal(loader,start);
+ } else if (style.equals(QueryStyle.GREMLIN_UNIQUE)) {
+ return new GremlinUnique(loader,start);
+ } else if (style.equals(QueryStyle.GREMLINPIPELINE_TRAVERSAL)) {
+ //return new GremlinPipelineTraversal(loader,start);
+ } else if (style.equals(QueryStyle.TRAVERSAL)) {
+ return new TraversalQuery(loader, start);
+ } else {
+ throw new IllegalArgumentException("Query Builder type not recognized");
+ }
+ return queryBuilder;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java
new file mode 100644
index 0000000..36eb227
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines.query;
+
+import java.util.List;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.query.builder.QueryBuilder;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+
+public class GraphTraversalQueryEngine extends QueryEngine {
+
+ /**
+ * Instantiates a new graph traversal query engine.
+ *
+ * @param graphEngine the graph engine
+ */
+ public GraphTraversalQueryEngine(TransactionalGraphEngine graphEngine) {
+ super(graphEngine);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> executeQuery(Graph g, QueryBuilder query) {
+ List<Vertex> results = null;
+ Vertex start = query.getStart();
+ GraphTraversal<Vertex, Vertex> traversal = (GraphTraversal)query.getQuery();
+ Traversal.Admin<Vertex, Vertex> admin = null;
+ if (start != null) {
+ results = ((GraphTraversal)query.getQuery()).toList();
+
+ } else {
+ admin = g.traversal().V().asAdmin();
+ TraversalHelper.insertTraversal(admin.getEndStep(), traversal.asAdmin(), admin);
+
+ results = admin.toList();
+ }
+
+
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> executeParentQuery(Graph g, QueryBuilder query) {
+ List<Vertex> results = null;
+ Vertex start = query.getStart();
+ GraphTraversal<Vertex, Vertex> traversal = (GraphTraversal)query.getParentQuery();
+ Traversal.Admin<Vertex, Vertex> admin = null;
+ if (start != null) {
+ results = ((GraphTraversal)query.getParentQuery()).toList();
+ } else {
+ admin = g.traversal().V().asAdmin();
+ TraversalHelper.insertTraversal(admin.getEndStep(), traversal.asAdmin(), admin);
+
+ results = admin.toList();
+ }
+
+
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> findParents(Vertex start) {
+ GraphTraversal<Vertex, Vertex> pipe = start.graph().traversal().V(start).emit()
+ .repeat(__.inE()
+ .has("isParent", true).outV());
+
+ List<Vertex> results = pipe.toList();
+ //results.add(0, start);
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> findChildren(Vertex start) {
+
+ GraphTraversal<Vertex, Vertex> pipe = start.graph().traversal().V(start).emit()
+ .repeat(__.outE().has("isParent", true).inV());
+
+ List<Vertex> results = pipe.toList();
+ //results.add(0, start);
+ return results;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> findDeletable(Vertex start) {
+
+ GraphTraversal<Vertex, Vertex> pipe = start.graph().traversal().V(start).emit()
+ .repeat(__.outE().or(
+ __.has("isParent", true),
+ __.has("hasDelTarget", true)).inV());
+
+ List<Vertex> results = pipe.toList();
+ //results.add(0, start);
+ return results;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
+ GraphTraversal<Vertex, Vertex> pipe = start.graph().traversal().V(start);
+ switch (direction) {
+ case OUT:
+ pipe.out(label);
+ break;
+ case IN:
+ pipe.in(label);
+ break;
+ case BOTH:
+ pipe.both(label);
+ break;
+ default:
+ break;
+ }
+
+ pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
+ List<Vertex> result = pipe.toList();
+ return result;
+ }
+
+}
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinPipelineQueryEngine.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinPipelineQueryEngine.java
new file mode 100644
index 0000000..b8e5e9c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinPipelineQueryEngine.java
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines.query;
+/*
+package org.openecomp.aai.serialization.engines.query;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.query.builder.QueryBuilder;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.TransactionalGraph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.gremlin.java.GremlinPipeline;
+import com.tinkerpop.pipes.IdentityPipe;
+import com.tinkerpop.pipes.PipeFunction;
+import com.tinkerpop.pipes.branch.LoopPipe;
+
+public class GremlinPipelineQueryEngine extends QueryEngine {
+
+ public GremlinPipelineQueryEngine(TransactionalGraphEngine graphEngine) {
+ super(graphEngine);
+ }
+
+ @Override
+ public List<Vertex> executeQuery(TransactionalGraph g, QueryBuilder query) {
+ List<Vertex> results = null;
+ Vertex start = query.getStart();
+ if (start != null) {
+ results = ((GremlinPipeline)query.getQuery()).cast(Vertex.class).toList();
+ } else {
+ GremlinPipeline pipe = new GremlinPipeline(g);
+ results = process(pipe, (GremlinPipeline)query.getQuery());
+
+ }
+ return results;
+ }
+
+ @Override
+ public List<Vertex> executeParentQuery(TransactionalGraph g, QueryBuilder query) {
+ List<Vertex> results = null;
+ Vertex start = query.getStart();
+ if (start != null) {
+ results = ((GremlinPipeline)query.getParentQuery()).cast(Vertex.class).toList();
+ } else {
+ GremlinPipeline pipe = new GremlinPipeline(g);
+ results = process(pipe, (GremlinPipeline)query.getParentQuery());
+
+ }
+ return results;
+ }
+
+ @Override
+ public List<Vertex> findParents(Vertex start) {
+ GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline(start).as("x").inE()
+ .has("isParent", true).outV().loop("x", new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
+
+ @Override
+ public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
+ GremlinPipeline<Vertex, Long> pipe = new GremlinPipeline<>(argument.getObject());
+ return pipe.inE().has("isParent", true).count() == 1 || argument.getLoops() < 100;
+ }
+
+ }, new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
+
+ @Override
+ public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
+ return true;
+ }
+
+ });
+
+ List<Vertex> results = pipe.toList();
+ results.add(0, start);
+ return results;
+ }
+
+ @Override
+ public List<Vertex> findChildren(Vertex start) {
+ Set<Vertex> seen = new HashSet<>();
+ seen.add(start);
+ GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline(start).as("x").outE().has("isParent", true).inV()
+ .except(seen).store(seen).loop("x", new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
+
+ @Override
+ public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
+ GremlinPipeline<Vertex, Long> pipe = new GremlinPipeline<>(argument.getObject());
+ return pipe.outE().has("isParent", true).count() >= 1 || argument.getLoops() < 100;
+ }
+
+ }, new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
+
+ @Override
+ public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
+ return true;
+ }
+
+ });
+
+ List<Vertex> results = pipe.toList();
+ results.add(0, start);
+ return results;
+ }
+
+ @Override
+ public List<Vertex> findDeletable(Vertex start) {
+ Set<Vertex> seen = new HashSet<>();
+ seen.add(start);
+ GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>(start).as("x").outE().or(
+ new GremlinPipeline(new IdentityPipe()).has("isParent", true),
+ new GremlinPipeline(new IdentityPipe()).has("hasDelTarget", true)).inV()
+ .except(seen).store(seen).loop("x", new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
+
+ @Override
+ public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
+ GremlinPipeline<Vertex, Long> pipe = new GremlinPipeline<>(argument.getObject());
+ return pipe.outE().or(
+ new GremlinPipeline(new IdentityPipe()).has("isParent", true),
+ new GremlinPipeline(new IdentityPipe()).has("hasDelTarget", true)).count() >= 1 || argument.getLoops() < 100;
+ }
+
+ }, new PipeFunction<LoopPipe.LoopBundle<Vertex>, Boolean>() {
+
+ @Override
+ public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
+ return true;
+ }
+
+ });
+ List<Vertex> results = pipe.toList();
+ results.add(0, start);
+
+ return results;
+ }
+
+ private List<Vertex> process(GremlinPipeline start, GremlinPipeline pipe) {
+
+
+ return start.add(pipe).cast(Vertex.class).toList();
+ }
+
+ @Override
+ public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
+ GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>(start);
+ switch (direction) {
+ case OUT:
+ pipe.out(label);
+ break;
+ case IN:
+ pipe.in(label);
+ break;
+ case BOTH:
+ pipe.both(label);
+ break;
+ default:
+ break;
+ }
+
+ pipe.has(AAIProperties.NODE_TYPE, nodeType).dedup();
+ List<Vertex> result = pipe.toList();
+ return result;
+ }
+
+}
+*/
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java
new file mode 100644
index 0000000..920d384
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines.query;
+//
+//package org.openecomp.aai.serialization.engines.query;
+//
+//import java.util.List;
+//import java.util.regex.Matcher;
+//import java.util.regex.Pattern;
+//
+//import org.apache.commons.collections.IteratorUtils;
+//
+//import org.openecomp.aai.db.AAIProperties;
+//import org.openecomp.aai.query.builder.QueryBuilder;
+//import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+//import com.tinkerpop.blueprints.Direction;
+//import com.tinkerpop.blueprints.Graph;
+//import com.tinkerpop.blueprints.TransactionalGraph;
+//import com.tinkerpop.blueprints.Vertex;
+//import com.tinkerpop.gremlin.groovy.Gremlin;
+//import com.tinkerpop.gremlin.java.GremlinPipeline;
+//import com.tinkerpop.pipes.Pipe;
+//import com.tinkerpop.pipes.util.iterators.SingleIterator;
+//
+//public class GremlinQueryEngine extends QueryEngine {
+//
+// public GremlinQueryEngine (TransactionalGraphEngine engine) {
+// super(engine);
+//
+// }
+//
+//
+// @Override
+// public List<Vertex> executeQuery(TransactionalGraph g, QueryBuilder query) {
+// List<Vertex> result = null;
+// Vertex start = query.getStart();
+// if (start != null) {
+// result = this.executeQuery(start, (String)query.getQuery());
+// } else {
+// result = this.processGremlinQuery((String)query.getQuery());
+// }
+// return result;
+//
+// }
+//
+// @Override
+// public List<Vertex> executeParentQuery(TransactionalGraph g, QueryBuilder query) {
+//
+// List<Vertex> result = null;
+// Vertex start = query.getStart();
+// if (start != null) {
+// result = this.executeQuery(start, (String)query.getParentQuery());
+// } else {
+// result = this.processGremlinQuery((String)query.getParentQuery());
+// }
+// return result;
+// }
+//
+// private List<Vertex> executeQuery(Vertex startVertex, String query) {
+//
+// return this.processGremlinQuery(startVertex, "_()" + query);
+//
+// }
+//
+// @Override
+// public List<Vertex> findParents(Vertex start) {
+//
+// String findAllParents = ".as('x').inE.has('isParent', true).outV"
+// + ".loop('x'){it.object.inE.has('isParent',true).count()==1}{true}";
+//
+// List<Vertex> results = this.executeQuery(start, findAllParents);
+// results.add(0, start);
+// return results;
+//
+// }
+//
+// @Override
+// public List<Vertex> findChildren(Vertex start) {
+// String findAllChildren = ".as('x').outE.has('isParent', true).inV"
+// + ".loop('x'){it.object.outE.has('isParent', true).count() >= 1}{true}";
+//
+// List<Vertex> results = this.executeQuery(start, findAllChildren);
+// results.add(0, start);
+// return results;
+//
+// }
+//
+// @Override
+// public List<Vertex> findDeletable(Vertex start) {
+// String findAllChildren = ".as('x').outE.or(_().has('isParent', true), _().has('hasDelTarget', true)).inV"
+// + ".loop('x'){it.object.outE.or(_().has('isParent', true), _().has('hasDelTarget', true)).count() >= 1}{true}";
+//
+// List<Vertex> results = this.executeQuery(start, findAllChildren);
+// results.add(0, start);
+// return results;
+// }
+// private List<Vertex> processGremlinQuery(String query) {
+//
+// Pattern firstHasSet = Pattern.compile("^(\\.has\\(.*?\\))(\\.has\\(.*?\\))*(?!\\.has)");
+// Pattern p = Pattern.compile("\\.has\\('(.*?)',\\s?'(.*?)'\\)");
+// Matcher m = firstHasSet.matcher(query);
+// List<Vertex> results = null;
+// GremlinPipeline<Graph, Vertex> pipe = new GremlinPipeline<>(dbEngine.getGraph());
+// if (m.find()) {
+// String hasSet = m.group();
+// query = query.replace(m.group(0), "");
+// m = p.matcher(hasSet);
+// pipe.V();
+// while (m.find()) {
+// pipe.has(m.group(1), m.group(2));
+// }
+// results = processGremlinQuery(pipe.toList(), "_()" + query);
+// }
+//
+// return results;
+//
+// }
+// private List<Vertex> processGremlinQuery(Vertex startVertex, String query) {
+//
+// Pipe pipe = Gremlin.compile(query);
+// pipe.setStarts(new SingleIterator<Vertex>(startVertex));
+//
+// return (List<Vertex>)IteratorUtils.toList(pipe.iterator());
+// }
+// private List<Vertex> processGremlinQuery(List<Vertex> list, String query) {
+//
+// Pipe pipe = Gremlin.compile(query);
+//
+// pipe.setStarts(list);
+//
+// return (List<Vertex>)IteratorUtils.toList(pipe.iterator());
+// }
+//
+//
+// @Override
+// public List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) {
+// String findRelatedVertices = "_()";
+// switch (direction) {
+// case OUT:
+// findRelatedVertices += ".out('" + label + "')";
+// break;
+// case IN:
+// findRelatedVertices += ".in('" + label + "')";
+// break;
+// case BOTH:
+// findRelatedVertices += ".both('" + label + "')";
+// break;
+// default:
+// break;
+// }
+// findRelatedVertices += ".has('" + AAIProperties.NODE_TYPE + "', '" + nodeType + "').dedup()";
+// List<Vertex> results = this.executeQuery(start, findRelatedVertices);
+// results.add(0, start);
+// return results;
+// }
+//
+//}
+//
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/QueryEngine.java b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/QueryEngine.java
new file mode 100644
index 0000000..00af5cc
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/QueryEngine.java
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.engines.query;
+
+import java.util.List;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openecomp.aai.query.builder.QueryBuilder;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+public abstract class QueryEngine {
+
+ protected TransactionalGraphEngine dbEngine = null;
+
+ /**
+ * Instantiates a new query engine.
+ *
+ * @param graphEngine the graph engine
+ */
+ public QueryEngine (TransactionalGraphEngine graphEngine) {
+ this.dbEngine = graphEngine;
+ }
+
+ /**
+ * Execute query.
+ *
+ * @param g the g
+ * @param query the query
+ * @return the list
+ */
+ public abstract List<Vertex> executeQuery(Graph g, QueryBuilder query);
+
+ /**
+ * Execute parent query.
+ *
+ * @param g the g
+ * @param query the query
+ * @return the list
+ */
+ public abstract List<Vertex> executeParentQuery(Graph g, QueryBuilder query);
+
+ /**
+ * Find parents.
+ *
+ * @param start the start
+ * @return the list
+ */
+ public abstract List<Vertex> findParents(Vertex start);
+
+ /**
+ * Find children.
+ *
+ * @param start the start
+ * @return the list
+ */
+ public abstract List<Vertex> findChildren(Vertex start);
+
+ /**
+ * Find deletable.
+ *
+ * @param start the start
+ * @return the list
+ */
+ public abstract List<Vertex> findDeletable(Vertex start);
+
+ /**
+ * Find related vertices.
+ *
+ * @param start the start
+ * @param direction the direction
+ * @param label the label
+ * @param nodeType the node type
+ * @return the list
+ */
+ public abstract List<Vertex> findRelatedVertices(Vertex start, Direction direction, String label, String nodeType);
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/tasks/ScheduledTasks.java b/ajsc-aai/src/main/java/org/openecomp/aai/tasks/ScheduledTasks.java
new file mode 100644
index 0000000..2ed7915
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/tasks/ScheduledTasks.java
@@ -0,0 +1,159 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.tasks;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.UUID;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.comparator.LastModifiedFileComparator;
+import org.openecomp.aai.dmaap.aaiWorkload.consumer.AAIWorkloadConsumer;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.AAIPrimaryHost;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ScheduledTasks {
+
+ protected static AAILogger aaiLogger = new AAILogger(ScheduledTasks.class.getName());
+ protected LogLine logline = new LogLine();
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+ protected String COMPONENT = "Scheduler";
+ private String transId = null;
+ private String fromAppId = "CronApp";
+
+ final static String INSTAR_CRON_ENTRY = "0 40 * 1/1 * ?";
+ // for now to test, every minute, should be something like "0 */5 * * *
+ // MON-FRI" i.e. every 5 minutes
+ final static long INSTAR_READ_MIN_INTERVAL = 300000; // every 5 minutes
+ static long instar_read_count = 0;
+ static long instarams_read_count = 0;
+ final static long PROPERTY_READ_INTERVAL = 60000; // every minute
+
+ private String GlobalPropFileName = AAIConstants.AAI_CONFIG_FILENAME;
+
+
+
+
+ // for read and possibly reloading aaiconfig.properties and other
+ /**
+ * Load AAI properties.
+ */
+ // configuration properties files
+ @Scheduled(fixedRate = PROPERTY_READ_INTERVAL)
+ public void loadAAIProperties() {
+ String methodName = "loadAAIProperties()";
+ transId = UUID.randomUUID().toString();
+ logline.init(COMPONENT, transId, fromAppId, "loadAAIProperties()");
+
+ String dir = FilenameUtils.getFullPathNoEndSeparator(GlobalPropFileName);
+ if (dir == null || dir.length() < 3) {
+ dir = "/opt/aai/etc";
+ }
+
+ File pdir = new File(dir);
+ File[] files = pdir.listFiles();
+ Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
+ String fn;
+
+ // leave this loop here since we may want to check other configurable
+ // property files in the SAME directory
+ for (File file : files) {
+ fn = file.getName();
+ if (fn.equals("aaiconfig.properties")) {
+ Date lastMod = new Date(file.lastModified());
+ long lastModTm = lastMod.getTime();
+ Date curTS = new Date();
+ long curTSTm = curTS.getTime();
+
+ if (curTSTm - lastModTm < PROPERTY_READ_INTERVAL + 1000) {
+ AAIConfig.reloadConfig();
+ logline.add(methodName, "reloaded from aaiconfig.properties");
+ aaiLogger.info(logline, true, "0");
+
+ }
+ break;
+ }
+ /*
+ * This is not needed now since we are using AJSC and logback.xml
+ * else if (fn.equals("log4j.properties")) { //Code changes
+ *
+ * Date lastMod = new Date(file.lastModified()); long lastModTm =
+ * lastMod.getTime(); Date curTS = new Date(); long curTSTm =
+ * curTS.getTime(); if ((curTSTm - lastModTm) <
+ * PROPERTY_READ_INTERVAL + 1000) { System.out.println(
+ * "log4j.properties has been changed in the past minute, reloading it now..."
+ * ); aaiLogger.debug(logline,
+ * "going to reload from log4j.properties");
+ * AAIConfig.reconfigAAILog4jProps(); aaiLogger.debug(logline,
+ * "After reloading from log4j.properties"); aaiLogger.info(logline,
+ * true, "0"); } }
+ */
+ }
+ }
+
+
+ /**
+ * Starts the aaiWorkloadConsumer 5 mins after task bean init.
+ * Will restart 5 mins after the previous one ended.
+ */
+ @Scheduled(fixedRate = 300000, initialDelay = 300000)
+ public void dmaapAAIWorkloadProcessor() {
+
+ String methodName = "dmaapAAIWorkloadProcessor()";
+ LogLine ll = new LogLine();
+ ll.init(COMPONENT, transId, fromAppId, methodName);
+
+ ll.add(methodName, "Started fixed rate job dmaapAAIWorkloadProcessor");
+ aaiLogger.info(logline, true, "0");
+
+ System.out.println("Started fixed rate job dmaapAAIWorkloadProcessor");
+ try {
+ if (AAIConfig.get("aai.dmaap.workload.enableEventProcessing").equals("true")) {
+ System.out.println("aai.dmaap.workload.enableEventProcessing set to true, starting AAIWorkloadConsumer.");
+ ll.add(methodName, "aai.dmaap.workload.enableEventProcessing set to true, starting AAIWorkloadConsumer.");
+ aaiLogger.info(logline, true, "0");
+ AAIWorkloadConsumer awc = new AAIWorkloadConsumer();
+ awc.startProcessing();
+ } else {
+ System.out.println("aai.dmaap.workload.enableEventProcessing set to false no start on AAIWorkloadConsumer.");
+ ll.add(methodName, "aai.dmaap.workload.enableEventProcessing set to false no start on AAIWorkloadConsumer.");
+ aaiLogger.info(logline, true, "0");
+ }
+ } catch (Exception e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4000", e.getMessage());
+ aaiLogger.error(errorObject, logline, e);
+ aaiLogger.info(logline, false, "AAI_4000");
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerateFitNesseTests.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerateFitNesseTests.java
new file mode 100644
index 0000000..e32d7c2
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerateFitNesseTests.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.io.FileUtils;
+import org.json.JSONException;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.testsuitegeneration.TestSuite;
+
+public class GenerateFitNesseTests {
+
+ private static final String currentEndpointsLocation = "../../automated-testing/FitNesseRoot/AAI/1702/Endpoints/";
+ private static final String currentRelationshipsLocation = "../../automated-testing/FitNesseRoot/AAI/1702/Relationships/";
+ private static final String regressionEndpointsLocation = "../../automated-testing/FitNesseRoot/AAI/Regression/Endpoints/";
+ private static final String regressionRelationshipsLocation = "../../automated-testing/FitNesseRoot/AAI/Regression/Relationships/";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws ClassNotFoundException the class not found exception
+ * @throws NoSuchFieldException the no such field exception
+ * @throws JAXBException the JAXB exception
+ */
+ public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, NoSuchMethodException, SecurityException, IOException, ClassNotFoundException, NoSuchFieldException, JAXBException {
+
+ /* set up properties */
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+
+ System.out.println("Starting FitNesse generation...");
+
+ TestSuite.TestSuiteBuilder builder = new TestSuite.TestSuiteBuilder();
+ builder
+ .setDbModelPackage("org.openecomp.aai.dbmodel")
+ .setApiVersion(AAIProperties.LATEST);
+
+ TestSuite suite = builder.build();
+ /*
+ String root = System.getenv(testCaseRootVar);
+
+ if (root == null) {
+ throw new IOException("No environment variable " + testCaseRootVar + " found. Please set it before continuing.");
+ }
+ root = System.getenv(jUnitRootVar);
+ if (root == null) {
+ throw new IOException("No environment variable " + jUnitRootVar + " found. Please set it before continuing.");
+ }
+ */
+
+ File endpoints = new File(currentEndpointsLocation + AAIProperties.LATEST);
+ File relationships = new File(currentRelationshipsLocation + AAIProperties.LATEST);
+ FileUtils.deleteDirectory(endpoints);
+ FileUtils.deleteDirectory(relationships);
+ suite.create(endpoints, relationships);
+ System.out.println("Generating current version suite.");
+
+ for (int i = 8; i > 1; i--) {
+ System.out.println("Generating v" + i + " suite.");
+
+ createVersionedTestSuite(Version.valueOf("v" + i));
+ }
+
+ System.out.println("Finished.");
+
+
+ }
+
+ /**
+ * Creates the versioned test suite.
+ *
+ * @param version the version
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws ClassNotFoundException the class not found exception
+ * @throws NoSuchFieldException the no such field exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JAXBException the JAXB exception
+ */
+ private static void createVersionedTestSuite(Version version) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, JSONException, IOException, ClassNotFoundException, NoSuchFieldException, InstantiationException, JAXBException {
+
+ TestSuite.TestSuiteBuilder builder = new TestSuite.TestSuiteBuilder();
+ File endpoints = new File(regressionEndpointsLocation + version);
+ File relationships = new File(regressionRelationshipsLocation + version);
+
+
+ builder
+ .setDbModelPackage("org.openecomp.aai.dbmodel." + version + ".gen")
+ .setApiVersion(version);
+
+ TestSuite suite = builder.build();
+ suite.create(endpoints, relationships);
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerationTest.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerationTest.java
new file mode 100644
index 0000000..325ad7c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerationTest.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.xml.bind.JAXBException;
+
+import org.json.JSONException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.springframework.web.util.UriUtils;
+
+public class GenerationTest {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException, JAXBException {
+ /*
+ PopulateObject pop = new PopulateObject();
+ UpdateObject update = new UpdateObject();
+ InjectResourceVersion inject = new InjectResourceVersion();
+ Loader v7Loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8);
+ Introspector wrappedObj = v7Loader.introspectorFromName("tenant");
+ pop.populateRecursively(wrappedObj, 1, 3, false);
+
+ System.out.println(wrappedObj.marshal(true));
+
+ System.out.println(wrappedObj.getURI());
+ System.out.println("-----------------------");
+ wrappedObj = inject.addResourceVersionDeep(wrappedObj);
+
+ Introspector obj2 = update.randomlyUpdateFieldValues(wrappedObj);
+ System.out.println(obj2.marshal(true));
+
+ */
+ String encode = UriUtils.encodePath("~hello/:()", "UTF-8");
+ String decode = UriUtils.decode(encode, "UTF-8");
+ System.out.println(encode);
+ System.out.println(decode);
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/InjectResourceVersion.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/InjectResourceVersion.java
new file mode 100644
index 0000000..d4505bd
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/InjectResourceVersion.java
@@ -0,0 +1,132 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorWalker;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+import com.google.common.base.Joiner;
+
+
+public class InjectResourceVersion extends TestDataGenerator {
+
+ protected List<String> blacklist = new ArrayList<>();
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new inject resource version.
+ */
+ public InjectResourceVersion() {
+ blacklist.add("any");
+ blacklist.add("relationship-list");
+ }
+
+ /**
+ * Adds the resource version deep.
+ *
+ * @param wrappedObj the wrapped obj
+ * @return the introspector
+ */
+ public Introspector addResourceVersionDeep(Introspector wrappedObj) {
+
+ Introspector clone = (Introspector)wrappedObj.clone();
+ IntrospectorWalker walker = new IntrospectorWalker(this, llBuilder);
+ walker.setBlacklist(blacklist);
+ walker.walk(clone);
+ return clone;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitive(String propName, Introspector obj) {
+ Object result = null;
+ if (propName.equals("resource-version")) {
+ List<String> keys = obj.getAllKeys();
+ List<Object> list = new ArrayList<>();
+ for (String key : keys) {
+ //Only add the first key for now, there should not be a problem with this method
+ //because the it is only being inspected at the object level itself
+ list.add(obj.getValue(key));
+ break;
+ }
+
+ result = Joiner.on("/").join(list);
+
+ } else {
+ result = obj.getValue(propName);
+
+ }
+ obj.setValue(propName, result);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitiveList(String propName, Introspector obj) {
+
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processComplexObj(Introspector obj) {
+
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child) {
+
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean createComplexObjIfNull() {
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int createComplexListSize(Introspector parent, Introspector child) {
+
+ return 0;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/LocateEndPoints.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/LocateEndPoints.java
new file mode 100644
index 0000000..8803df8
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/LocateEndPoints.java
@@ -0,0 +1,579 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONException;
+import org.openecomp.aai.audit.ListEndpoints;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+
+public class LocateEndPoints {
+
+ private String restPath = "";
+ private String pojoPath = "";
+
+ private PopulateObject populator = null;
+ private ArrayList<String> parentEndPoints = null;
+ private ArrayList<String> childEndPoints = null;
+ private final Pattern parentPattern = Pattern.compile("\\/(?:[\\w\\-]+?\\/)+?(?:\\{[\\w\\-]+?\\}\\/?)+");
+
+ private Map<String, List<String>> deprecatedEndpoints = new HashMap<>();
+ private Pattern apiVersionPattern = Pattern.compile("\\/(v\\d+)\\/");
+ private Version version = null;
+ private ModelType modelType = ModelType.MOXY;
+ private Loader loader = null;
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new locate end points.
+ *
+ * @param version the version
+ * @throws FileNotFoundException the file not found exception
+ * @throws JSONException the JSON exception
+ */
+ public LocateEndPoints (Version version) throws FileNotFoundException, JSONException {
+
+ this.version = version;
+ populator = new PopulateObject();
+ loader = LoaderFactory.createLoaderForVersion(modelType, version, llBuilder);
+ this.parentEndPoints = new ArrayList<>();
+ this.childEndPoints = new ArrayList<>();
+ String[] versions = {"v2","v3", "v4", "v5"};
+ deprecatedEndpoints.put("site-pair-set", Arrays.asList(versions));
+
+ this.process();
+
+ }
+
+ /**
+ * Instantiates a new locate end points.
+ */
+ @SuppressWarnings("unused")
+ private LocateEndPoints() {}
+
+ /**
+ * Process.
+ */
+ private void process(){
+
+ ListEndpoints endpoints = new ListEndpoints(this.version);
+ String filterOut = "relationship-list";
+ List<String> uris = endpoints.getEndpoints(filterOut);
+
+ for (String uri : uris) {
+ this.addEndPointName(uri);
+ }
+
+ }
+
+ /**
+ * Checks if is deprecated.
+ *
+ * @param name the name
+ * @return true, if is deprecated
+ */
+ private boolean isDeprecated(String name) {
+
+ Matcher m = apiVersionPattern.matcher(name);
+ name = name.substring(name.lastIndexOf('.') + 1, name.length());
+ String apiVersion = "";
+
+ if (m.find()) {
+ apiVersion = m.group(1);
+ }
+ for (String key : deprecatedEndpoints.keySet()) {
+ if (name.contains(key)) {
+ List<String> deprecatedVersions = this.deprecatedEndpoints.get(key);
+
+ if (deprecatedVersions != null && deprecatedVersions.contains(apiVersion)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets the parent paths.
+ *
+ * @return the parent paths
+ */
+ public List<String> getParentPaths() {
+
+ return (List<String>)this.parentEndPoints.clone();
+ }
+
+ /**
+ * Gets the child paths.
+ *
+ * @return the child paths
+ */
+ public List<String> getChildPaths() {
+
+ return (List<String>)this.childEndPoints.clone();
+ }
+
+ /**
+ * Gets the all paths.
+ *
+ * @return the all paths
+ */
+ public List<String> getAllPaths() {
+ List<String> returnList = new ArrayList<>();
+ returnList.addAll(getParentPaths());
+ returnList.addAll(getChildPaths());
+ return returnList;
+ }
+
+ /**
+ * Adds the end point name.
+ *
+ * @param path the path
+ */
+ private void addEndPointName(String path) {
+
+ if (!this.isDeprecated(path)) {
+ if (parentPattern.matcher(path).matches()) {
+ parentEndPoints.add(path);
+ } else {
+ childEndPoints.add(path);
+ }
+ }
+ }
+
+ /**
+ * Child path.
+ *
+ * @param path the path
+ * @return the string
+ */
+ public String childPath(String path) {
+
+ String childPath = "";
+ String[] pathSegments = path.split("/");
+ boolean foundNonVariable = false;
+ for (int i = pathSegments.length-1; i >= 0; i--) {
+
+ if (!foundNonVariable && pathSegments[i].contains("{")) {
+ childPath = pathSegments[i] + "/" + childPath;
+ } else if (foundNonVariable && pathSegments[i].contains("{")) {
+ break;
+ } else {
+ foundNonVariable = true;
+ childPath = pathSegments[i] + "/" + childPath;
+ }
+
+ }
+
+ childPath = childPath.substring(0, childPath.length()-1).replace("//", "/");
+
+ return childPath;
+
+ }
+
+ /**
+ * Creates the child for path.
+ *
+ * @param path the path
+ * @param min the min
+ * @param max the max
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public Introspector createChildForPath(String path, int min, int max) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException, JAXBException {
+ return createChildForPath(path, min, max, false);
+ }
+
+ /**
+ * Creates the child for path.
+ *
+ * @param path the path
+ * @param min the min
+ * @param max the max
+ * @param minimized the minimized
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public Introspector createChildForPath(String path, int min, int max, boolean minimized) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException, JAXBException {
+ Pattern p = Pattern.compile("([\\w\\-]+?)\\/(\\{[\\w\\-]+?\\}\\/?)+$");
+ Matcher m = p.matcher(path);
+ String objectName = "";
+ if (m.find()) {
+ objectName = m.group(1);
+ }
+ if (objectName.equals("cvlan-tag")) {
+ objectName = "cvlan-tag-entry";
+ }
+
+ return createChildFromClassName(objectName, min, max, minimized);
+ }
+
+ /**
+ * Creates the child from class name.
+ *
+ * @param objectName the object name
+ * @param min the min
+ * @param max the max
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public Introspector createChildFromClassName(String objectName, int min, int max) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException, JAXBException {
+ return createChildFromClassName(objectName, min, max, false);
+ }
+
+ /**
+ * Creates the child from class name.
+ *
+ * @param objectName the object name
+ * @param min the min
+ * @param max the max
+ * @param minimized the minimized
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public Introspector createChildFromClassName(String objectName, int min, int max, boolean minimized) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException, JAXBException {
+ Introspector returnObject = null;
+
+ returnObject = loader.introspectorFromName(objectName);
+ populator.populateRecursively(returnObject, min, max, minimized);
+
+
+ return returnObject;
+ }
+
+ /**
+ * Populate relationship.
+ *
+ * @param parent the parent
+ * @param dbName the db name
+ * @param fullPath the full path
+ * @return the introspector
+ */
+ public Introspector populateRelationship(Introspector parent, String dbName, String fullPath) {
+
+ String formattedClassName = parent.getDbName();
+
+ String advancedPath = StringUtils.substringAfter(fullPath, formattedClassName + "/");
+ String[] pathTokens = advancedPath.split("/");
+
+ // Create and format the relationship
+ Introspector relationship = loader.introspectorFromName("relationship");
+ relationship.setValue("related-to", dbName);
+ populateRelationshipHelper(parent, pathTokens, 0, relationship);
+
+ return relationship;
+ }
+
+ /**
+ * Populate relationship helper.
+ *
+ * @param parent the parent
+ * @param pathTokens the path tokens
+ * @param index the index
+ * @param relationship the relationship
+ */
+ // Recursively iterate through each token and add the necessary information to the relationship data array
+ private void populateRelationshipHelper(Introspector parent, String[] pathTokens, int index, Introspector relationship) {
+ Pattern p = Pattern.compile("\\{(.+?)\\}");
+ for(int i = index; i < pathTokens.length; ++i) {
+ Matcher m = p.matcher(pathTokens[i]);
+ if(m.find()) {
+ String pathVariable = m.group(1);
+ String trimmedClassName = parent.getDbName();
+ pathVariable = pathVariable.replaceFirst(trimmedClassName+ "-", "");
+ String key = this.callGetMethod(parent, pathVariable).toString();
+ pathTokens[i] = pathTokens[i].replaceAll("\\{.+?\\}", key);
+
+ // Add the relationship data object from token information
+ Introspector data = relationship.newIntrospectorInstanceOfNestedProperty("relationship-data");
+ data.setValue("relationship-key", trimmedClassName + "." + pathVariable);
+ data.setValue("relationship-value", key);
+ ((List)relationship.getValue("relationship-data")).add(data.getUnderlyingObject());
+ if (i == pathTokens.length-1) {
+ List<Introspector> relatedTos = new ArrayList<>();
+ String nameProps = parent.getMetadata("nameProps");
+ if (nameProps != null) {
+ String[] props = nameProps.split(",");
+ for (String prop : props) {
+ Introspector relatedTo = this.loader.introspectorFromName("related-to-property");
+ relatedTo.setValue("property-key", parent.getDbName() + "." + prop);
+ relatedTo.setValue("property-value", parent.getValue(prop));
+ relatedTos.add(relatedTo);
+ }
+
+ if (relatedTos.size() > 0) {
+ List list = (List)relationship.getValue("related-to-property");
+ for (Introspector obj : relatedTos) {
+ list.add(obj.getUnderlyingObject());
+ }
+ }
+ }
+ }
+ } else {
+ String getMethodName;
+ if (pathTokens[i].equals("cvlan-tag")) {
+ getMethodName = "cvlan-tag-entry";
+ } else {
+ getMethodName = pathTokens[i];
+ }
+ Object child = this.callGetMethod(parent, getMethodName);
+ if (child != null) {
+ if (child.getClass().getName().contains("List")) {
+ child = ((List)child).get(0);
+ }
+ populateRelationshipHelper(IntrospectorFactory.newInstance(parent.getModelType(), child, llBuilder), pathTokens, i+1, relationship);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Populate path.
+ *
+ * @param parent the parent
+ * @param path the path
+ * @return the list
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ public List<Object> populatePath(Introspector parent, String path) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+
+ String formattedClassName = parent.getDbName();
+
+ String prefix = StringUtils.substringBefore(path, "{");
+ String advancedPath = StringUtils.substringAfter(path, formattedClassName+"/");
+ String[] pathTokens = advancedPath.split("/");
+
+ Introspector end = populatePathHelper(parent, pathTokens, 0);
+ String parentPath = prefix + Joiner.on("/").join(pathTokens);
+ List<Object> result = new ArrayList<>();
+ result.add(parentPath);
+ result.add(end.clone());
+ return result;
+ }
+
+ /**
+ * Populate child path.
+ *
+ * @param topLevelObj the top level obj
+ * @param obj the obj
+ * @param path the path
+ * @return the string
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ public String populateChildPath(Introspector topLevelObj, Introspector obj, String path) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ String childPath = "/" + this.childPath(path);
+ String parentPath = path.replace(childPath, "");
+ String resultPath = (String)this.populatePath(topLevelObj, parentPath).get(0) + (String)this.populatePath(obj, childPath).get(0);
+
+ return resultPath;
+ }
+
+ /**
+ * Populate path helper.
+ *
+ * @param parent the parent
+ * @param pathTokens the path tokens
+ * @param index the index
+ * @return the introspector
+ */
+ private Introspector populatePathHelper(Introspector parent, String[] pathTokens, int index) {
+
+ Pattern p = Pattern.compile("\\{(.+?)\\}");
+ Matcher m = null;
+ String pathVariable = "";
+ String key = "";
+ Object child = null;
+ String getMethodName = "";
+ for (int i = index; i < pathTokens.length; i++) {
+ m = p.matcher(pathTokens[i]);
+ if (m.find()) {
+ pathVariable = m.group(1);
+
+ pathVariable = pathVariable.replaceFirst(parent.getDbName() + "-", "");
+
+ key = this.callGetMethod(parent, pathVariable).toString();
+ pathTokens[i] = pathTokens[i].replaceAll("\\{.+?\\}", key);
+ } else {
+
+ if (pathTokens[i].equals("cvlan-tag")) {
+ getMethodName = "cvlan-tag-entry";
+ } else {
+ getMethodName = pathTokens[i];
+ }
+ child = this.callGetMethod(parent, getMethodName);
+ if (child != null) {
+ if (child.getClass().getName().contains("List")) {
+ child = ((List)child).get(0);
+ }
+ return populatePathHelper(IntrospectorFactory.newInstance(parent.getModelType(), child, llBuilder), pathTokens, i+1);
+ }
+ }
+ }
+
+ return parent;
+ }
+
+ /**
+ * Gets the path for object.
+ *
+ * @param parentPath the parent path
+ * @param obj the obj
+ * @return the path for object
+ */
+ public String getPathForObject(String parentPath, Object obj) {
+
+ String name = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, this.trimClassName(obj));
+ String result = "";
+ Pattern p = Pattern.compile(".*?\\/" + name + "\\/\\{.*?\\}");
+ Matcher m = null;
+ for (String childPath : this.childEndPoints) {
+
+ m = p.matcher(childPath);
+ if (m.find()) {
+ result = m.group();
+ break;
+ }
+
+ }
+
+ return result;
+
+ }
+
+ /**
+ * Format path string.
+ *
+ * @param item the item
+ * @return the string
+ */
+ private String formatPathString(String item) {
+
+ String value = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, item);
+
+ return value;
+ }
+
+ /**
+ * Call get method.
+ *
+ * @param obj the obj
+ * @param variableName the variable name
+ * @return the object
+ */
+ private Object callGetMethod(Introspector obj, String variableName) {
+ Object key = null;
+
+ key = obj.getValue(variableName);
+
+ return key;
+ }
+
+ /**
+ * Make singular.
+ *
+ * @param word the word
+ * @return the string
+ */
+ private String makeSingular(String word) {
+
+ String result = word;
+ result = result.replaceAll("ies$", "y");
+ result = result.replaceAll("(?:s|([hox])es)$", "$1");
+
+ return result;
+ }
+
+ /**
+ * Trim class name.
+ *
+ * @param obj the obj
+ * @return the string
+ */
+ public String trimClassName (Object obj) {
+ String returnValue = "";
+ String name = obj.getClass().getName();
+ returnValue = name.substring(name.lastIndexOf('.') + 1, name.length());
+
+ if (returnValue.equals("CvlanTagEntry")) {
+ returnValue = "CvlanTag";
+ }
+ return returnValue;
+ }
+
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/OXMTest.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/OXMTest.java
new file mode 100644
index 0000000..70bab01
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/OXMTest.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.json.JSONException;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.Version;
+
+public class OXMTest {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws JAXBException the JAXB exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public static void main(String[] args) throws JAXBException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException {
+
+
+ ModelInjestor injestor = ModelInjestor.getInstance();
+
+ DynamicJAXBContext context =injestor.getContextForVersion(Version.v8);
+
+ List<Descriptor> test = context.getXMLContext().getDescriptors();
+
+ for (Descriptor d : test) {
+ System.out.println(context.newDynamicEntity(d.getJavaClass().getSimpleName()).getClass().getName());
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/PopulateObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/PopulateObject.java
new file mode 100644
index 0000000..d86ae9b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/PopulateObject.java
@@ -0,0 +1,232 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.bind.JAXBException;
+
+import org.json.JSONException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorWalker;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.EdgeRules;
+import org.openecomp.aai.serialization.db.MultiplicityRule;
+import org.openecomp.aai.testsuitegeneration.AbstractWriter;
+
+public class PopulateObject extends TestDataGenerator {
+
+ protected boolean isMinimumObject = false;
+ protected List<String> blacklist = new ArrayList<>();
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new populate object.
+ */
+ public PopulateObject() {
+ blacklist.add("any");
+ blacklist.add("relationship-list");
+ blacklist.add("resource-version");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitive(String propName, Introspector obj) {
+ Object val = null;
+ String type = obj.getType(propName);
+ if (this.isMinimumObject) {
+ List<String> required = obj.getRequiredProperties();
+ if (!required.contains(propName)) {
+ return;
+ }
+ }
+ /* If the key is not a string, don't worry about it being unique */
+ if (type.contains("java.lang.String") && isKey(obj, propName)) {
+ val = UUID.randomUUID().toString() + AbstractWriter.USERNAME_PLACEHOLDER;
+ }else{
+ val = createNewRandomObj(type);
+ String uniqueProps = obj.getMetadata("uniqueProps");
+ if (uniqueProps != null) {
+ String[] props = uniqueProps.split(",");
+ List<String> list = Arrays.asList(props);
+ if (list.contains(propName)) {
+ val += AbstractWriter.USERNAME_PLACEHOLDER;
+ }
+ }
+
+ }
+ obj.setValue(propName, val);
+
+ }
+
+ /**
+ * Populate.
+ *
+ * @param obj the obj
+ * @param isMinimumObject the is minimum object
+ * @return the introspector
+ * @throws JSONException the JSON exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public Introspector populate(Introspector obj, boolean isMinimumObject) throws JSONException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, IOException, JAXBException {
+ this.isMinimumObject = isMinimumObject;
+
+ IntrospectorWalker walker = new IntrospectorWalker(this, llBuilder);
+ walker.setBlacklist(this.blacklist);
+ walker.walk(obj);
+ return obj;
+ }
+
+ /**
+ * Populate recursively.
+ *
+ * @param obj the obj
+ * @param min the min
+ * @param max the max
+ * @param isMinimumObject the is minimum object
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws JSONException the JSON exception
+ * @throws InstantiationException the instantiation exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public Introspector populateRecursively(Introspector obj, int min, int max, boolean isMinimumObject) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, JSONException, InstantiationException, IOException, JAXBException {
+
+ IntrospectorWalker walker = new IntrospectorWalker(this, llBuilder);
+ this.isMinimumObject = isMinimumObject;
+ this.min = min;
+ this.max = max;
+ walker.setBlacklist(this.blacklist);
+ walker.preventCycles(true);
+ walker.walk(obj);
+ return obj;
+ //return populateHelper(o, min, max, true);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitiveList(String propName, Introspector obj) {
+ int numberOfObjects = getRandomInt();
+
+ String propType = "";
+ List<Object> list = new ArrayList<>();
+ for (int i = 0; i < numberOfObjects; i++) {
+ propType = obj.getGenericType(propName);
+ Object val = this.createNewRandomObj(propType);
+ list.add(val);
+ }
+ obj.setValue(propName, list);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processComplexObj(Introspector obj) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean createComplexObjIfNull() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int createComplexListSize(Introspector parent, Introspector child) {
+
+ EdgeRule rule;
+ int numberOfObjects = getRandomInt();
+
+ try {
+ rule = EdgeRules.getInstance().getEdgeRule(parent.getDbName(), child.getDbName());
+ if (rule.getMultiplicityRule().equals(MultiplicityRule.ONE2ONE)) {
+ numberOfObjects = 1;
+ } else if (rule.getMultiplicityRule().equals(MultiplicityRule.ONE2MANY) || rule.getMultiplicityRule().equals(MultiplicityRule.MANY2MANY)) {
+ if (numberOfObjects < max) {
+ numberOfObjects = max;
+ }
+ }
+ } catch (AAIException e) {
+ System.out.println(e.getErrorObject().getDetails());
+ }
+
+
+ return numberOfObjects;
+ }
+
+ /**
+ * Checks if is key.
+ *
+ * @param obj the obj
+ * @param prop the prop
+ * @return true, if is key
+ */
+ private boolean isKey(Introspector obj, String prop) {
+ /*String className = trimClassName(obj.getClass().getName());
+ Collection<String> keys = keyProps.get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className));
+ Collection<String> altKeys = altKeysProps.get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className));
+ String lowerHyphenFieldName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN,f.getName());
+ if (keys.contains(lowerHyphenFieldName) || altKeys.contains(lowerHyphenFieldName)){
+ return true;
+ }
+ return false;*/
+
+ return obj.getAllKeys().contains(prop);
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/TestDataGenerator.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/TestDataGenerator.java
new file mode 100644
index 0000000..25ff2e7
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/TestDataGenerator.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.openecomp.aai.introspection.Wanderer;
+
+public abstract class TestDataGenerator implements Wanderer {
+
+ protected int minStringLength = 3;
+ protected int maxStringLength = 13;
+ protected int min = 1;
+ protected int max = 2;
+
+ /**
+ * Creates the new random obj.
+ *
+ * @param type the type
+ * @return the object
+ */
+ protected Object createNewRandomObj (String type) {
+ Object newObj = null;
+ if ( type.contains("java.lang.String")) {
+ newObj = RandomStringUtils.randomAlphanumeric(ThreadLocalRandom.current().nextInt(minStringLength, maxStringLength + 1));
+ } else if ( type.toLowerCase().equals("long") ||type.contains("java.lang.Long")) {
+ newObj = new Long(RandomStringUtils.randomNumeric(ThreadLocalRandom.current().nextInt(minStringLength, minStringLength + 1)));
+ } else if(type.toLowerCase().equals("boolean") || type.contains("java.lang.Boolean")){
+ Random rand = new Random();
+ newObj = rand.nextBoolean();
+ }else if ( type.toLowerCase().equals("int") || type.contains("java.lang.Integer")){
+ newObj = new Integer(RandomStringUtils.randomNumeric(ThreadLocalRandom.current().nextInt(minStringLength, minStringLength + 1)));
+ }
+
+ return newObj;
+ }
+
+ /**
+ * Gets the random int.
+ *
+ * @return the random int
+ */
+ protected int getRandomInt() {
+ return ThreadLocalRandom.current().nextInt(this.min, this.max + 1);
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testing/UpdateObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/testing/UpdateObject.java
new file mode 100644
index 0000000..9d8500c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testing/UpdateObject.java
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testing;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import javax.xml.bind.JAXBException;
+
+import org.json.JSONException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorWalker;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.EdgeRules;
+import org.openecomp.aai.serialization.db.MultiplicityRule;
+
+public class UpdateObject extends TestDataGenerator {
+
+ private PopulateObject pop = new PopulateObject();
+
+ protected List<String> blacklist = new ArrayList<>();
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new update object.
+ */
+ public UpdateObject() {
+ blacklist.add("any");
+ blacklist.add("relationship-list");
+ blacklist.add("resource-version");
+ }
+
+ /**
+ * Randomly update field values.
+ *
+ * @param obj the obj
+ * @return the introspector
+ */
+ public Introspector randomlyUpdateFieldValues(Introspector obj){
+ Introspector clone = null;
+
+ clone = (Introspector)obj.clone();
+
+ IntrospectorWalker walker = new IntrospectorWalker(this, llBuilder);
+ walker.setBlacklist(blacklist);
+ walker.walk(clone);
+
+ return clone;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitive(String propName, Introspector obj) {
+ List<String> keys = obj.getKeys();
+ if (!keys.contains(propName)) {
+ Random random = new Random();
+ int num = random.nextInt(100);
+ if (num <= 33) {
+ Object val = this.createNewRandomObj(obj.getType(propName));
+ obj.setValue(propName, val);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processPrimitiveList(String propName, Introspector obj) {
+ Random random = new Random();
+ int num = random.nextInt(100);
+ if (num <= 33) {
+ List<Object> list = (List<Object>) obj.getValue(propName);
+ int size = list.size();
+ Random rand = new Random();
+ int newSize = 0;
+ if (size == 0) {
+ newSize = rand.nextInt(max);
+ } else {
+ newSize = rand.nextInt(size);
+ }
+ list.clear();
+ for (int i = 0; i < newSize; i++) {
+ list.add(this.createNewRandomObj(obj.getGenericType(propName)));
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processComplexObj(Introspector obj) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child) {
+
+ EdgeRule rule;
+ int numberOfObjects = max;
+
+ try {
+ rule = EdgeRules.getInstance().getEdgeRule(parent.getDbName(), child.getDbName());
+ if (rule.getMultiplicityRule().equals(MultiplicityRule.ONE2ONE)) {
+ numberOfObjects = 1;
+ }
+ } catch (AAIException e) {
+ System.out.println(e.getErrorObject().getDetails());
+ }
+
+ int editRemoveOrAdd;
+ List<Integer> randNumList = new ArrayList<Integer>();
+ Random rand = new Random();
+ int numOfItemstoUpdate = 0;
+
+ if (numberOfObjects == 1) {
+ numOfItemstoUpdate = rand.nextInt(numberOfObjects);
+ } else {
+ numOfItemstoUpdate = rand.nextInt(numberOfObjects-1)+1;
+ }
+ for (int i = 0; i < numOfItemstoUpdate; i++){
+ randNumList.add(i);
+ }
+ Collections.shuffle(randNumList);
+ for (int i = 0; i < numOfItemstoUpdate; i++) {
+ editRemoveOrAdd = rand.nextInt(numberOfObjects);
+ int index = randNumList.get(i);
+ Introspector newObject = null;
+ try {
+ newObject = pop.populateRecursively((Introspector)child.clone(), min, max, false);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | InstantiationException | JSONException | IOException | JAXBException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (list.size() < numberOfObjects){
+ if (editRemoveOrAdd == 0 && index < list.size()){
+ if (newObject != null) {
+ list.set(index, newObject.getUnderlyingObject());
+ }
+ }else if (editRemoveOrAdd == 1 && index < list.size()){
+ if (list.size() != 1) {
+ list.remove(index);
+ }
+ }else if (editRemoveOrAdd == 2 && list.size() + 1 <= numberOfObjects){
+ if (newObject != null) {
+ list.add(index, newObject.getUnderlyingObject());
+ }
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean createComplexObjIfNull() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int createComplexListSize(Introspector parent, Introspector child) {
+ return 0;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AbstractWriter.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AbstractWriter.java
new file mode 100644
index 0000000..c440c14
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AbstractWriter.java
@@ -0,0 +1,491 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.rest.CustomJacksonJaxBJsonProvider;
+import org.openecomp.aai.testing.LocateEndPoints;
+import org.openecomp.aai.testsuitegeneration.TestSuite.TestSuiteBuilder;
+import org.springframework.web.util.UriUtils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.Multimap;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+
+public abstract class AbstractWriter {
+
+ protected final String PROPERTIES_XML = "properties_xml.ftl";
+
+ protected final String TEMPLATE_PATH = "src/main/java/org/openecomp/aai/testsuitegeneration/";
+
+ public static final String USERNAME_PLACEHOLDER = "#!#username.placeholder#!#";
+
+ public final Integer START_PORT = 42671;
+ protected Map<String, Object> supplimentalMap = new HashMap<>();
+ protected Configuration configuration = new Configuration();
+ protected String outputPath;
+ protected Version apiVersion;
+ protected Version currentApiVersion;
+ protected String tearDownPath;
+ protected String tearDownPathChildren;
+ protected String deletePage;
+ protected String parentCleanUpPage;
+ protected String classPackagePath;
+ protected String cleanUpPage;
+ protected Multimap<String, String> DeleteScope;
+ protected Multimap<String, String> EdgeRules;
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+ protected final Loader loader;
+
+
+ /**
+ * Instantiates a new abstract writer.
+ *
+ * @param file the file
+ * @param builder the builder
+ */
+ // Abstract constructor
+ public AbstractWriter(File file, TestSuiteBuilder builder) {
+ this.outputPath = file.getAbsolutePath();
+ this.apiVersion = builder.getApiVersion();
+ this.currentApiVersion = builder.getCurrentApiVersion();
+ this.DeleteScope = builder.getDeleteScope();
+ this.EdgeRules = builder.getEdgeMap();
+ this.classPackagePath = builder.getPojoPackage();
+ this.deletePage = "";
+ this.tearDownPath = "";
+ this.parentCleanUpPage = "";
+ this.loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, apiVersion, llBuilder);
+ createVersionSuite();
+ }
+
+
+ /**
+ * Creates a suite for the writer's specified API version.
+ */
+ private void createVersionSuite() {
+ Map<String, Object> suiteMap = new HashMap<>();
+
+ // Set the PUT expected result
+ String createStatus = "200";
+ Pattern p = Pattern.compile("v(\\d+)");
+ Matcher m = p.matcher(apiVersion.toString());
+ Integer versionNumber = 0;
+ if (m.find()) {
+ versionNumber = Integer.parseInt(m.group(1));
+ }
+
+ createStatus = "201";
+ // Add the placeholder values to the map
+ suiteMap.put("version", apiVersion);
+ suiteMap.put("currentVersion", currentApiVersion);
+ suiteMap.put("createStatus", createStatus);
+ suiteMap.put("type", "suite");
+ suiteMap.put("slimPort", START_PORT + (versionNumber * 20));
+
+ // Create the directory
+ File dir = new File(this.outputPath);
+ dir.mkdir();
+
+ // Process the freemarker templates
+ this.processDataModel("version_suite_content_txt.ftl", "content.txt", dir, suiteMap);
+ this.processDataModel("properties_xml.ftl", "properties.xml", dir, suiteMap);
+ }
+
+
+ /**
+ * Generates the necessary pages to recursively clean up children objects.
+ *
+ * @param path the path
+ * @param fitnessePath the fitnesse path
+ * @param topLevel the top level
+ * @param lep the lep
+ * @param additionalName the additional name
+ * @param urlVariableName the url variable name
+ * @return the string
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ protected String generateRecursiveCleanUp(String path, String fitnessePath, Introspector topLevel, LocateEndPoints lep, String additionalName, String urlVariableName) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ String childPath = "";
+ String fitnessePageName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, topLevel.getDbName());
+
+ String folderName = fitnessePageName + "AdditionalTests";
+ String additionalPath = fitnessePath + "/" + folderName;
+ File dir = new File(additionalPath);
+ dir.mkdir();
+ Map<String, Object> additionalMap = new HashMap<>();
+ additionalMap.put("type", "static");
+ additionalMap.put("skip", "true");
+ processDataModel("static_page_content_txt.ftl", "content.txt", dir, additionalMap);
+ processDataModel("properties_xml.ftl", "properties.xml", dir, additionalMap);
+ List<String> pages = findCascadeDeleteChildren(topLevel, additionalPath, path, lep, additionalName);
+
+ Map<String, Object> map = new HashMap<>();
+
+ String testPageName = "ChildrenTearDown" + additionalName;
+ String tearDownPath = additionalPath + "/" + testPageName;
+ dir = new File(tearDownPath);
+ dir.mkdir();
+
+ map.put("type", "test");
+ map.put("pages", pages);
+ map.put("parentCleanUpPage", ".AAI.Tests.GenericTests.FauxRecursiveDelete");
+ map.put("errorCheckPage", ".AAI.Tests.GenericTests.DeleteErrorCheck");
+ String decodedUrl = urlVariableName;
+ try {
+ decodedUrl = UriUtils.decode(decodedUrl, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ map.put("urlVariableName", this.replaceUsernamePlaceholders(decodedUrl));
+ this.processDataModel("recursive_teardown_content_txt.ftl", "content.txt", dir, map);
+ this.processDataModel("properties_xml.ftl", "properties.xml", dir, map);
+
+
+
+ return folderName + "." + testPageName;
+ }
+
+
+ /**
+ * Searches for children to be deleted via cascade delete.
+ *
+ * @param obj the obj
+ * @param fitNessePath the fit nesse path
+ * @param restPath the rest path
+ * @param lep the lep
+ * @param additionalName the additional name
+ * @return the list
+ */
+ protected List<String> findCascadeDeleteChildren(Introspector obj, String fitNessePath, String restPath, LocateEndPoints lep, String additionalName) {
+ List<String> list = new ArrayList<>();
+ try {
+ findHelper(obj, list, fitNessePath, restPath, lep, additionalName);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException | UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return list;
+ }
+
+
+ /**
+ * Helper to the find method.
+ *
+ * @param obj the obj
+ * @param list the list
+ * @param fitNessePath the fit nesse path
+ * @param restPath the rest path
+ * @param lep the lep
+ * @param additionalName the additional name
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ protected void findHelper(Introspector obj, List<String> list, String fitNessePath, String restPath, LocateEndPoints lep, String additionalName) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, UnsupportedEncodingException {
+
+ if (obj == null) {
+ return;
+ }
+ List<String> properties = obj.getProperties();
+ properties.remove("relationship-list");
+ for (String prop : properties) {
+
+ if (obj.isComplexType(prop)) {
+ Introspector child = IntrospectorFactory.newInstance(obj.getModelType(), obj.getValue(prop), llBuilder);
+
+ findHelper(IntrospectorFactory.newInstance(obj.getModelType(), obj.getValue(prop), llBuilder), list, fitNessePath, restPath, lep, additionalName);
+ } else if (obj.isListType(prop)) {
+ if (DeleteScope.get(
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, this.trimClassName(obj.getGenericType(prop))))
+ .contains("CASCADE_TO_CHILDREN")) {
+ List<?> children = (List<?>)obj.getValue(prop);
+ Introspector temp = null;
+ List<String> urls = new ArrayList<>();
+ for (Object child : children) {
+ temp = IntrospectorFactory.newInstance(obj.getModelType(), child, llBuilder);
+ String decodedUrl = restPath + temp.getURI();
+ try {
+ decodedUrl = UriUtils.decode(decodedUrl, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ urls.add(replaceUsernamePlaceholders(decodedUrl));
+ }
+
+ Map<String, Object> map = new HashMap<>();
+
+ map.put("deleteChildren", ".AAI.Tests.GenericTests.CleanUp");
+ map.put("urls", urls);
+ map.put("type", "test");
+ String childrenTestPage = "RemoveChildren" + additionalName;
+ String removeChildrenPath = fitNessePath + "/" + childrenTestPage;
+ File dir = new File(removeChildrenPath);
+ dir.mkdir();
+ this.processDataModel("remove_children_content_txt.ftl", "content.txt", dir, map);
+ this.processDataModel("properties_xml.ftl", "properties.xml", dir, map);
+ list.add(childrenTestPage);
+ } else {
+ //still wrong
+ Introspector temp = obj.newIntrospectorInstanceOfNestedProperty(prop);
+ if (this.hasChildren(temp) && DeleteScope.get(
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, this.trimClassName(obj.getGenericType(prop))))
+ .contains("THIS_NODE_ONLY")) {
+ List<?> children = (List<?>)obj.getValue(prop);
+ String result = "";
+ for (int i = 0; i < children.size(); i++) {
+ Introspector child = IntrospectorFactory.newInstance(obj.getModelType(), children.get(i), llBuilder);
+
+ try {
+ result = generateRecursiveCleanUp(restPath + child.getURI(), fitNessePath, child, lep, additionalName + new Integer(i).toString(), "!-" + restPath + child.getURI() + "-!");
+ } catch (NoSuchMethodException | SecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ list.add(result);
+
+ }
+
+ }
+ }
+
+ }
+ }
+
+ }
+
+ /**
+ * Checks for children.
+ *
+ * @param obj the obj
+ * @return true, if successful
+ */
+ protected boolean hasChildren(Introspector obj) {
+
+ for (String prop : obj.getProperties()) {
+ if (!prop.equals("relationship-list")) {
+
+ if (obj.isComplexType(prop) || (obj.isListType(prop) && obj.isComplexGenericType(prop))) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Processes the template file through freemarker.
+ *
+ * @param templateFilename The filename of the template to process.
+ * @param outputFilename THe filename of the output file to generate.
+ * @param outputDirectory The directory of the output file.
+ * @param variableMap The variable map where key is the placeholder variable name.
+ */
+ protected void processDataModel(String templateFilename, String outputFilename, File outputDirectory, Map<String, Object> variableMap) {
+
+ try {
+ Template template = configuration.getTemplate(TEMPLATE_PATH + templateFilename);
+ Writer file = new FileWriter(new File(outputDirectory.getPath() + "/" + outputFilename));
+ template.process(variableMap, file);
+ file.flush();
+ } catch(Exception e) {
+ System.out.println("Failed to process file {" + outputFilename + "}");
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Marshals an object into a JSON string.
+ *
+ * @param obj The object to marshal
+ * @return A string representation of the object in JSON format.
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ protected String jsonMarshal(Object obj) throws IOException {
+ CustomJacksonJaxBJsonProvider provider = new CustomJacksonJaxBJsonProvider();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ provider.writeTo(obj, obj.getClass(), null, null, null, null, os);
+ String output = new String(os.toByteArray(), "UTF-8");
+ ObjectMapper mapper = provider.getMapper();
+ Object json = mapper.readValue(output, obj.getClass());
+ output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
+ return output;
+ }
+
+
+ /**
+ * Retrieves the root to FitNesse from the full path.
+ *
+ * @param fullPath The full output path.
+ * @return The root to FitNesseRoot
+ */
+ protected String getFitNesseRoot(String fullPath) {
+ String result = fullPath;
+ Pattern p = Pattern.compile("Root(?:/|\\\\)(.*)");
+ Matcher m = p.matcher(fullPath);
+ if(m.find()) {
+ result = m.group(1);
+ }
+ return result;
+ }
+
+
+ /**
+ * Converts an UpperCamel class name to a lower-hyphen class name.
+ * @param className The class name in UpperCamel format.
+ * @return The class name is lower-hyphen format.
+ */
+ protected String getHyphenatedClassName(String className) {
+ String output = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
+
+ // Special case for cvlan-tag
+ if(output.equals("cvlan-tag-entry")) {
+ output = "cvlan-tag";
+ }
+
+ return output;
+ }
+
+ /**
+ * Checks if is plural.
+ *
+ * @param word the word
+ * @return true, if is plural
+ */
+ protected boolean isPlural(String word) {
+ return word.matches(".*?(es|(?<!s)s)$");
+ }
+
+ /**
+ * Trim class name.
+ *
+ * @param name the name
+ * @return the string
+ */
+ protected String trimClassName(String name) {
+
+ return name.substring(name.lastIndexOf('.') + 1, name.length());
+ }
+
+ /**
+ * Gets the key from path.
+ *
+ * @param path the path
+ * @return the key from path
+ */
+ protected String getKeyFromPath(String path) {
+ Pattern p = Pattern.compile("(\\{(.+?)\\}\\/?)+$");
+ Matcher m = p.matcher(path);
+ String key = "";
+ if (m.matches()) {
+ key = m.group();
+ }
+ return key;
+ }
+ protected String encodeUsernamePlaceholders(String body) {
+ String encode = "";
+ try {
+ encode = UriUtils.encodePath(USERNAME_PLACEHOLDER, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return body.replace(USERNAME_PLACEHOLDER, encode);
+ }
+ protected String decodeUserNamePlaceholders(String body) {
+ String decode = "";
+ try {
+ decode = UriUtils.decode(body, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return decode;
+ }
+ /**
+ * Replace username placeholders.
+ *
+ * @param body the body
+ * @return the string
+ */
+ protected String replaceUsernamePlaceholders(String body) {
+ return body.replace(USERNAME_PLACEHOLDER, "--!${username}!-");
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AddNamedPropWildcard.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AddNamedPropWildcard.java
new file mode 100644
index 0000000..f043769
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AddNamedPropWildcard.java
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.util.List;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorWalker;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.introspection.Wanderer;
+import org.openecomp.aai.logging.LogLineBuilder;
+
+public class AddNamedPropWildcard implements Wanderer {
+
+
+ private final LogLineBuilder llBuilder;
+ private Loader loader;
+ public AddNamedPropWildcard(Loader loader) {
+ this.llBuilder = new LogLineBuilder();
+ this.loader = loader;
+
+ }
+
+ public void process(Introspector obj) {
+
+ IntrospectorWalker walker = new IntrospectorWalker(this, llBuilder);
+ walker.walk(obj);
+
+ }
+ @Override
+ public void processPrimitive(String propName, Introspector obj) {
+ //NO-OP
+ }
+
+ @Override
+ public void processPrimitiveList(String propName, Introspector obj) {
+ //NO-OP
+ }
+
+ @Override
+ public void processComplexObj(Introspector obj) {
+ String nameProp = obj.getMetadata("nameProps");
+ if (nameProp != null && !nameProp.equals("")) {
+ String[] nameProps = nameProp.split(",");
+ for (String prop : nameProps) {
+ if (obj.getClass(prop).equals(String.class)) {
+
+ if (obj.getValue(prop) == null) {
+ if (!isDefaultCloudRegion(obj)) {
+ obj.setValue(prop, "*");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isDefaultCloudRegion(Introspector obj) {
+ return false;
+ }
+ @Override
+ public void modifyComplexList(List<Object> list, Introspector parent, Introspector child) {
+ //NO-OP
+ }
+
+ @Override
+ public boolean createComplexObjIfNull() {
+ return false;
+ }
+
+ @Override
+ public int createComplexListSize(Introspector parent, Introspector child) {
+ return 0;
+ }
+
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FMObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FMObject.java
new file mode 100644
index 0000000..ed6a152
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FMObject.java
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+
+import org.openecomp.aai.rest.CustomJacksonJaxBJsonProvider;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+
+public class FMObject {
+ private Configuration cfg;
+ private Map<String, Object> root;
+ private String jsonString;
+ private String key;
+ private String featureURL;
+ private String className;
+ private String dirPath;
+ private final String templatePath = "src/main/java/org/openecomp/aai/freemarker/";
+
+ /**
+ * Instantiates a new FM object.
+ *
+ * @param obj the obj
+ * @param dirPath the dir path
+ * @param className the class name
+ * @param key the key
+ * @param featureURL the feature URL
+ */
+ public FMObject (Object obj, String dirPath, String className, String key, String featureURL){
+ this.cfg = new Configuration();
+ this.root = new HashMap<String, Object>();
+ this.key = key;
+ this.featureURL = featureURL;
+ this.className = className.substring(className.lastIndexOf('.')+1, className.length());
+ this.dirPath = dirPath;
+ try {
+ this.jsonString = jsonMarshal(obj);
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ this.root.put("fields", jsonString);
+ this.root.put("key", this.key);
+ this.root.put("featureURL", this.featureURL);
+
+ }
+
+ /**
+ * Gets the template.
+ *
+ * @param name the name
+ * @return the template
+ */
+ private Template getTemplate(String name) {
+ Template template = null;
+ try {
+ template = cfg.getTemplate(templatePath + name);
+ } catch (IOException e) {
+ System.out.println("Template not found: " + e.getMessage());
+ }
+ return template;
+ }
+
+ /**
+ * Process data model.
+ *
+ * @param tempFileName the temp file name
+ * @param outFileName the out file name
+ * @param dir the dir
+ */
+ public void processDataModel(String tempFileName, String outFileName, File dir){
+ Template template = this.getTemplate(tempFileName);
+ try {
+ Writer file = new FileWriter (new File(dir.getPath()+"/"+outFileName));
+ template.process(this.root, file);
+ file.flush();
+ } catch (IOException | TemplateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Creates the output files.
+ */
+ public void createOutputFiles(){
+ File dir = new File(this.dirPath+"/"+this.className);
+ dir.mkdir();
+ processDataModel("content_txt.ftl", "content.txt", dir);
+ processDataModel("test_properties_xml.ftl", "properties.xml", dir);
+ }
+
+ /**
+ * Json marshal.
+ *
+ * @param o the o
+ * @return the string
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ private String jsonMarshal(Object o) throws IOException {
+ CustomJacksonJaxBJsonProvider provider = new CustomJacksonJaxBJsonProvider();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ provider.writeTo(o, o.getClass(), null, null, MediaType.APPLICATION_JSON_TYPE, null, os);
+
+ String output = new String(os.toByteArray(), "UTF-8");
+
+ ObjectMapper mapper = provider.getMapper();
+
+ Object json = mapper.readValue(output, o.getClass());
+
+ output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
+ return output;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FitNesseJUnitWriter.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FitNesseJUnitWriter.java
new file mode 100644
index 0000000..01b0784
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FitNesseJUnitWriter.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.openecomp.aai.introspection.Version;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+
+public class FitNesseJUnitWriter {
+
+ private Configuration cfg = new Configuration();
+ private String templatePath = "src/main/java/org/openecomp/aai/freemarker/";
+ private String outputPath = "";
+
+
+ /**
+ * Instantiates a new fit nesse J unit writer.
+ *
+ * @param outputPath the output path
+ */
+ public FitNesseJUnitWriter(String outputPath) {
+
+ this.outputPath = outputPath;
+ }
+
+ /**
+ * Instantiates a new fit nesse J unit writer.
+ */
+ @SuppressWarnings("unused")
+ private FitNesseJUnitWriter() {
+
+ }
+
+ /**
+ * Creates the J unit class.
+ *
+ * @param packageName the package name
+ * @param apiVersion the api version
+ * @param fullSuitePath the full suite path
+ */
+ public void createJUnitClass(String packageName, Version apiVersion, String fullSuitePath) {
+ Map<String, Object> map = new HashMap<>();
+
+ packageName = packageName + "." + apiVersion;
+ String suiteName = this.getFitNesseRoot(fullSuitePath);
+ String[] parts = suiteName.split("\\.");
+ String className = parts[parts.length-1] + "IT";
+ map.put("packageName", packageName);
+ map.put("className", className);
+ map.put("suiteName", suiteName);
+ File dir = new File(this.outputPath + "/" + packageName.replaceAll("\\.", "/") + "/");
+ dir.mkdirs();
+ this.processDataModel("junit_class_java.ftl", className + ".java", dir, map);
+
+ }
+
+ /**
+ * Gets the template.
+ *
+ * @param name the name
+ * @return the template
+ */
+ private Template getTemplate(String name) {
+ Template template = null;
+ try {
+ template = cfg.getTemplate(templatePath + name);
+ } catch (IOException e) {
+ System.out.println("Template not found: " + e.getMessage());
+ }
+ return template;
+ }
+
+ /**
+ * Process data model.
+ *
+ * @param tempFileName the temp file name
+ * @param outFileName the out file name
+ * @param dir the dir
+ * @param map the map
+ */
+ public void processDataModel(String tempFileName, String outFileName, File dir, Map<?,?> map){
+ Template template = this.getTemplate(tempFileName);
+ try {
+ Writer file = new FileWriter (new File(dir.getPath()+"/"+outFileName));
+ template.process(map, file);
+ file.flush();
+ } catch (IOException | TemplateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Gets the fit nesse root.
+ *
+ * @param fullPath the full path
+ * @return the fit nesse root
+ */
+ private String getFitNesseRoot(String fullPath) {
+ String result = fullPath;
+ Pattern p = Pattern.compile("FitNesseRoot(?:/|\\\\)(.*)");
+ Matcher m = p.matcher(fullPath);
+
+ if (m.find()) {
+ result = m.group(1);
+ }
+
+ return result.replaceAll("/|\\\\", ".");
+
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/RelationshipWriter.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/RelationshipWriter.java
new file mode 100644
index 0000000..cfc2a62
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/RelationshipWriter.java
@@ -0,0 +1,405 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBException;
+
+import org.eclipse.persistence.exceptions.DynamicException;
+import org.json.JSONException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.testing.LocateEndPoints;
+import org.openecomp.aai.testsuitegeneration.TestSuite.TestSuiteBuilder;
+
+import com.att.aft.dme2.internal.google.common.base.CaseFormat;
+
+public class RelationshipWriter extends AbstractWriter {
+
+ protected final String RELATIONSHIP_CONTENT = "relationship_content_txt.ftl";
+ protected final String RELATIONSHIP_SINGLE_CONTENT = "relationship_single_content_txt.ftl";
+ protected final String RELATIONSHIP_SINGLE_CONTENT_REVERSED = "relationship_single_reversed_content_txt.ftl";
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ // Hash map used for storing parent objects for re-use
+ //HashMap<String, Introspector> parentMap = new HashMap<>();
+ Loader loader = null;
+
+ /**
+ * Instantiates a new relationship writer.
+ *
+ * @param file the file
+ * @param builder the builder
+ * @param loader the loader
+ */
+ // Constructor
+ public RelationshipWriter(File file, TestSuiteBuilder builder, Loader loader) {
+
+ // Just call the super constructor
+ super(file, builder);
+
+ this.loader = loader;
+
+ }
+
+
+ /**
+ * Generate relationship test.
+ *
+ * @param objA the obj A
+ * @param objB the obj B
+ * @param lep the lep
+ * @param edgeMapProperties the edge map properties
+ * @param minListSize the min list size
+ * @param maxListSize the max list size
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws Exception the exception
+ */
+ public void generateRelationshipTest(Introspector objA, Introspector objB, LocateEndPoints lep, String edgeMapProperties, int minListSize, int maxListSize) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, Exception {
+ if(objA.getDbName().equals("ipaddress") || objB.getDbName().equals("ipaddress")) return;
+
+ // Get the unpopulated feature URls
+ String featureUrlA = this.getUnpopulatedFeatureUrl(objA, lep);
+ String featureUrlB = this.getUnpopulatedFeatureUrl(objB, lep);
+ String inputA = objA.getDbName();
+ String inputB = objB.getDbName();
+ String classA = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, inputA);
+ String classB = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, inputB);
+ // Prepare variable map
+ Map<String, Object> variableMap = new HashMap<>();
+ variableMap.put("type", "test");
+
+
+
+ ////////////////////////////////
+ // Process object A //
+ ////////////////////////////////
+ cleanUpPage = ".AAI.Tests.GenericTests.CleanUp";
+ if(hasDependency(featureUrlA)) {
+ objA = createParentObject(featureUrlA, lep);
+
+ // Get the parent name lower-hyphen format
+ String hyphenatedParentName = this.getHyphenatedParentName(featureUrlA);
+ Introspector parentObj =loader.introspectorFromName(hyphenatedParentName);
+ String topFeatureUrl = this.getUnpopulatedFeatureUrl(parentObj, lep);
+ String populatedUrl = replaceUsernamePlaceholders((String)lep.populatePath(objA, topFeatureUrl).get(0));
+ variableMap.put("topFeatureUrlA", populatedUrl);
+
+ boolean hasChildren = this.hasChildren(parentObj);
+
+ if(hasChildren && DeleteScope.get(hyphenatedParentName).contains("THIS_NODE_ONLY")) {
+ try {
+ cleanUpPage = generateRecursiveCleanUp(populatedUrl, outputPath, objA, lep, classA + "To" + classB + "A", "${topFeatureURL_A}");
+
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ e.printStackTrace();
+ }
+ }
+
+ } else {
+ objA = lep.createChildFromClassName(objA.getName(), 1, 1, true);
+ String populatedUrl = replaceUsernamePlaceholders((String)lep.populatePath(objA, featureUrlA).get(0));
+ variableMap.put("topFeatureUrlA", populatedUrl);
+ boolean hasChildren = this.hasChildren(objA);
+
+ if(hasChildren && DeleteScope.get(objA.getDbName()).contains("THIS_NODE_ONLY")) {
+ try {
+ cleanUpPage = generateRecursiveCleanUp(populatedUrl, outputPath, objA, lep, classA + "To" + classB + "A", "${topFeatureURL_A}");
+
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // Create the relationship object
+ Introspector relationshipA = lep.populateRelationship(objA, inputA, featureUrlA);
+ relationshipA.setValue("related-link", "-!${address}${relationshipURLA}!-/");
+ // Put the values to the map
+ List<Object> rubbishTuple = lep.populatePath(objA, featureUrlA);
+ String populatedPathA = (String)rubbishTuple.get(0);
+ Introspector childA = (Introspector)rubbishTuple.get(1);
+ variableMap.put("deletePageA", cleanUpPage);
+ variableMap.put("objectBodyA", replaceUsernamePlaceholders(objA.marshal(true)));
+ variableMap.put("featureUrlA", replaceUsernamePlaceholders(populatedPathA));
+ variableMap.put("relationshipURLA", replaceUsernamePlaceholders(populatedPathA));
+ variableMap.put("objectRelationshipA", replaceUsernamePlaceholders(relationshipA.marshal(true)));
+
+
+
+ ////////////////////////////////
+ // Process object B //
+ ////////////////////////////////
+ cleanUpPage = ".AAI.Tests.GenericTests.CleanUp";
+ if(hasDependency(featureUrlB)) {
+ objB = createParentObject(featureUrlB, lep);
+
+ // Get the parent name lower-hyphen format
+ String hyphenatedParentName = this.getHyphenatedParentName(featureUrlB);
+ Introspector parentObj = IntrospectorFactory.newInstance(objB.getModelType(), loader.objectFromName(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, hyphenatedParentName)), llBuilder);
+ String topFeatureUrl = this.getUnpopulatedFeatureUrl(parentObj, lep);
+ String populatedUrl = replaceUsernamePlaceholders((String)lep.populatePath(objB, topFeatureUrl).get(0));
+
+ variableMap.put("topFeatureUrlB", populatedUrl);
+ boolean hasChildren = this.hasChildren(parentObj);
+
+ if(hasChildren && DeleteScope.get(hyphenatedParentName).contains("THIS_NODE_ONLY")) {
+ try {
+ cleanUpPage = generateRecursiveCleanUp(populatedUrl, outputPath, objB, lep, classA + "To" + classB + "B", "${topFeatureURL_B}");
+
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ e.printStackTrace();
+ }
+ }
+
+ } else {
+ objB = lep.createChildFromClassName(objB.getName(), 1, 1, true);
+ String populatedUrl = replaceUsernamePlaceholders((String)lep.populatePath(objB, featureUrlB).get(0));
+ variableMap.put("topFeatureUrlB", populatedUrl);
+ boolean hasChildren = this.hasChildren(objB);
+
+ if(hasChildren && DeleteScope.get(objB.getDbName()).contains("THIS_NODE_ONLY")) {
+ try {
+ cleanUpPage = generateRecursiveCleanUp(populatedUrl, outputPath, objB, lep, classA + "To" + classB + "B", "${topFeatureURL_B}");
+
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ e.printStackTrace();
+ } }
+ }
+
+ // Create the relationship object
+ Introspector relationshipB = lep.populateRelationship(objB, inputB, featureUrlB);
+ relationshipB.setValue("related-link", "-!${address}${relationshipURLB}!-/");
+
+ if(hasDelTarget(edgeMapProperties)) {
+ cleanUpPage = ".AAI.Tests.GenericTests.VerifyDeletion";
+ }
+ rubbishTuple = lep.populatePath(objB, featureUrlB);
+ String populatedPathB = (String)rubbishTuple.get(0);
+ Introspector childB = (Introspector)rubbishTuple.get(1);
+ variableMap.put("deletePageB", cleanUpPage);
+ variableMap.put("objectBodyB", replaceUsernamePlaceholders(objB.marshal(true)));
+ variableMap.put("featureUrlB", replaceUsernamePlaceholders(populatedPathB));
+ variableMap.put("relationshipURLB", replaceUsernamePlaceholders(populatedPathB));
+ variableMap.put("objectRelationshipB", replaceUsernamePlaceholders(relationshipB.marshal(true)));
+
+
+ // Now, we have all the objects we need and need to generate the files
+ File dir = new File(outputPath + "/" + classA + "To" + classB + "RelationshipTest");
+ dir.mkdir();
+
+
+ //////////////////////////////////
+ // Special processing //
+ //////////////////////////////////
+ Object relationshipList = null;
+ relationshipList = this.loader.objectFromName("relationship-list");
+ childA.setValue("relationship-list", relationshipList);
+ relationshipList = this.loader.objectFromName("relationship-list");
+ childB.setValue("relationship-list", relationshipList);
+
+ ((List)IntrospectorFactory.newInstance(childA.getModelType(), childA.getValue("relationship-list"), llBuilder).getValue("relationship")).add(relationshipB.getUnderlyingObject());
+ ((List)IntrospectorFactory.newInstance(childB.getModelType(), childB.getValue("relationship-list"), llBuilder).getValue("relationship")).add(relationshipA.getUnderlyingObject());
+
+ variableMap.put("expectedResultA", replaceUsernamePlaceholders(childA.marshal(true)));
+ variableMap.put("expectedResultB", replaceUsernamePlaceholders(childB.marshal(true)));
+
+ processDataModel(RELATIONSHIP_CONTENT, "content.txt", dir, variableMap);
+ processDataModel(PROPERTIES_XML, "properties.xml", dir, variableMap);
+
+ }
+
+ /**
+ * Transform relationship UR is for vserver.
+ *
+ * @param variableMap the variable map
+ */
+ private void transformRelationshipURIsForVserver(Map<String, Object> variableMap) {
+ String aURL = (String)variableMap.get("relationshipURLA");
+ String bURL = (String)variableMap.get("relationshipURLB");
+
+ variableMap.put("relationshipURLA", this.replaceWithLegacyURI(aURL));
+ variableMap.put("relationshipURLB", this.replaceWithLegacyURI(bURL));
+
+ }
+
+ /**
+ * Replace with legacy URI.
+ *
+ * @param s the s
+ * @return the string
+ */
+ private String replaceWithLegacyURI(String s) {
+ String substring = "/aai/(v\\d)/cloud-infrastructure/tenants/tenant/(.*?)/vservers/vserver/([^/]*?$)";
+ String replacement = "/aai/servers/$1/$2/vservers/$3";
+ if (s.matches(substring)) {
+ s = s.replaceFirst(substring, replacement);
+ }
+
+ return s;
+ }
+
+
+ /**
+ * Gets the unpopulated feature url.
+ *
+ * @param hyphenatedClassName the hyphenated class name
+ * @param key the key
+ * @param lep the lep
+ * @return the unpopulated feature url
+ * @throws Exception the exception
+ */
+ private String getUnpopulatedFeatureUrl(String hyphenatedClassName, String key, LocateEndPoints lep) throws Exception {
+
+ // Each path ends with the endpoint suffix
+ String endpointSuffix = "{" + hyphenatedClassName + "-" + key + "}";
+
+ // Special case feature urls
+ switch(hyphenatedClassName) {
+ case "ctag-pool":
+ // Note that these have dual keys and dependencies are not working properly (availabilityZoneName is null)
+ endpointSuffix = "{ctag-pool-target-pe}/{ctag-pool-availability-zone-name}";
+ break;
+
+ case "service-capability":
+ // Note that these have dual keys and dependencies are not working properly (vnfType is null)
+ endpointSuffix = "{service-capability-service-type}/{service-capability-vnf-type}";
+ break;
+ case "cloud-region":
+ endpointSuffix = "{cloud-region-cloud-owner}/{cloud-region-cloud-region-id}";
+ break;
+ }
+
+ // Search the endpoints for the class endpoint
+ for(String path : lep.getAllPaths()) {
+ if(path.endsWith(endpointSuffix)) {
+ return path;
+ }
+ }
+
+ // The path was not found
+ throw new IllegalArgumentException("The endpoint URL for " + hyphenatedClassName + " was not found!");
+ }
+
+ /**
+ * Gets the unpopulated feature url.
+ *
+ * @param obj the obj
+ * @param lep the lep
+ * @return the unpopulated feature url
+ * @throws Exception the exception
+ */
+ private String getUnpopulatedFeatureUrl(Introspector obj, LocateEndPoints lep) throws Exception {
+ return this.getUnpopulatedFeatureUrl(obj.getDbName(), obj.getKeys().get(0), lep);
+ }
+
+ /**
+ * Determines if a class has a parent via the url.
+ *
+ * @param featureUrl The URL
+ * @return true, if successful
+ */
+ private boolean hasDependency(String featureUrl) {
+ return featureUrl.split("/").length > 7;
+ }
+
+ /**
+ * Creates the top-level parent object for a given feature URL.
+ *
+ * @param featureUrl the feature url
+ * @param lep the lep
+ * @return the introspector
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JSONException the JSON exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ private Introspector createParentObject(String featureUrl, LocateEndPoints lep) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, JSONException, IOException, JAXBException {
+
+ String topLevelClass = getHyphenatedParentName(featureUrl);
+
+ return lep.createChildFromClassName(topLevelClass, 1, 1, true);
+ }
+
+ /**
+ * Checks for del target.
+ *
+ * @param properties the properties
+ * @return true, if successful
+ */
+ private boolean hasDelTarget(String properties) {
+ String[] arr = properties.split(",");
+
+ if (arr.length > 5) {
+ return arr[5].equals("true");
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines if the specified object contains a relationship list.
+ *
+ * @param obj the obj
+ * @return true, if successful
+ * @throws ClassNotFoundException the class not found exception
+ * @throws SecurityException the security exception
+ */
+ private boolean hasRelationshipList(Introspector obj) throws ClassNotFoundException, SecurityException {
+
+ return obj.hasProperty("relationship-list");
+ }
+
+ /**
+ * Gets the hyphenated parent name from the given feature URL.
+ *
+ * @param featureUrl the feature url
+ * @return the hyphenated parent name
+ */
+ private String getHyphenatedParentName(String featureUrl) {
+ return featureUrl.split("/")[5];
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuite.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuite.java
new file mode 100644
index 0000000..68ee508
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuite.java
@@ -0,0 +1,441 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.json.JSONException;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.testing.LocateEndPoints;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.Multimap;
+
+public class TestSuite {
+
+
+ private final int minListSize;
+ private final int maxListSize;
+ private final Version apiVersion;
+ private TestSuiteBuilder builder = null;
+ protected final LogLineBuilder llBuilder = new LogLineBuilder();
+
+ /**
+ * Instantiates a new test suite.
+ *
+ * @param builder the builder
+ */
+ private TestSuite(TestSuiteBuilder builder) {
+
+ this.maxListSize = builder.maxListSize;
+ this.minListSize = builder.minListSize;
+ this.apiVersion = builder.apiVersion;
+
+ this.builder = builder;
+
+ }
+
+ /**
+ * Creates the.
+ *
+ * @param endpoints the endpoints
+ * @param relationships the relationships
+ * @throws JSONException the JSON exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws ClassNotFoundException the class not found exception
+ * @throws NoSuchFieldException the no such field exception
+ * @throws InstantiationException the instantiation exception
+ * @throws JAXBException the JAXB exception
+ */
+ public void create(File endpoints, File relationships) throws JSONException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IOException, ClassNotFoundException, NoSuchFieldException, InstantiationException, JAXBException {
+
+ // Load all endpoints in the system
+ LocateEndPoints lep = new LocateEndPoints(this.apiVersion);
+
+ // Create the endpoints and relationship test folders in case they don't exist
+ //createRequiredDirectories(testCaseDirPath);
+
+ // Create the test suite and JUnit test writers
+ TestSuiteWriter endpointWriter = new TestSuiteWriter(endpoints, builder);
+ //FitNesseJUnitWriter jUnitWriter = new FitNesseJUnitWriter(jUnitDirPath);
+
+ // Iterate through all the parent paths
+ for (String parentPath : lep.getParentPaths()) {
+
+ // Create a parent object
+ Introspector parentObject = lep.createChildForPath(parentPath, minListSize, maxListSize);
+
+ // Write the parent test suites
+ String endpointSuitePath = endpointWriter.createParentSuite(parentPath, parentObject, lep, null);
+ //String relationshipSuitePath = relationshipWriter.createTestSuite(parentPath, parentObject, lep, null);
+ //jUnitWriter.createJUnitClass("aai.fitnesse.suites", apiVersion, endpointSuitePath);
+
+ // Iterate through all the children paths
+ for (String childPath : lep.getChildPaths()) {
+ String genericPath = childPath;
+ if (childPath.contains(parentPath)) {
+
+ // Create a child object
+ Introspector obj = lep.createChildForPath(childPath, minListSize, maxListSize);
+ String path = lep.populateChildPath(parentObject, obj, childPath);
+ endpointWriter.addTestCase(endpointSuitePath, path, obj, genericPath, lep);
+
+ }
+ }
+ }
+
+
+ // Generate all relationship tests
+ RelationshipWriter relationshipWriter = new RelationshipWriter(relationships, builder, LoaderFactory.createLoaderForVersion(ModelType.MOXY, apiVersion, llBuilder));
+
+ // Iterate through all the relationships
+ for(String key : builder.getEdgeMap().keys()) {
+
+ String edgeMapProperties = builder.getEdgeMap().get(key).iterator().next();
+
+ // Checking to see if this is a parent-child relationship, if so then skip
+ if(edgeMapProperties.split(",")[3].equals("true")) {
+ continue;
+ }
+
+ // Extract the class names
+ String classNameA = key.substring(0, key.indexOf('|'));
+ String classNameB = key.substring(key.indexOf('|') + 1);
+
+ // Check if we need to skip this test
+ if(!builder.apiVersion.equals(builder.currentApiVersion)) {
+ if(classNameA.equals("site-pair-set") || classNameB.equals("site-pair-set")) {
+ continue;
+ }
+ }
+
+ // Prepare full class path
+
+ Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, apiVersion, llBuilder);
+
+ // Create the objects
+
+ // Generate the relationship test
+ try {
+ relationshipWriter.generateRelationshipTest(loader.introspectorFromName(classNameA), loader.introspectorFromName(classNameB), lep, edgeMapProperties, minListSize, maxListSize);
+ } catch (Exception e) {
+ System.out.println("Failed to generate relationship test for " + classNameA + "-" + classNameB + ".");
+ e.printStackTrace();
+ }
+
+ }
+ }
+
+ /**
+ * Creates the required directories.
+ *
+ * @param root the root
+ */
+ // Creates all the required directories in the system in case they don't already exist.
+ private void createRequiredDirectories(String root) {
+ File dir = new File(root + "/Endpoints");
+ dir.mkdir();
+ dir = new File(root + "/Relationships");
+ dir.mkdir();
+ dir = new File(root + "/Endpoints/" + apiVersion);
+ dir.mkdir();
+ dir = new File(root + "/Relationships/" + apiVersion);
+ dir.mkdir();
+ // TODO Generate suite content files for the root folders
+ }
+
+ /**
+ * Class exists.
+ *
+ * @param className the class name
+ * @return true, if successful
+ */
+ private boolean classExists(String className) {
+ try {
+ Class.forName(className);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static class TestSuiteBuilder {
+
+ private String pojoPackage = "";
+ private String restPackage = "";
+ private String dbmodelPackage = "";
+ private int minListSize = 1;
+ private int maxListSize = 2;
+ private String topLevelPath = "";
+ private List<String> children = null;
+ private Version apiVersion = null;
+ private Version currentApiVersion = AAIProperties.LATEST;
+
+ private Multimap<String, String> DeleteScope;
+ private Multimap<String, String> EdgeMap;
+
+
+ /**
+ * Instantiates a new test suite builder.
+ */
+ public TestSuiteBuilder() {
+
+ }
+
+ /**
+ * Gets the top level path.
+ *
+ * @return the top level path
+ */
+ public String getTopLevelPath() {
+ return topLevelPath;
+ }
+
+ /**
+ * Sets the top level path.
+ *
+ * @param topLevelPath the top level path
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setTopLevelPath(String topLevelPath) {
+ this.topLevelPath = topLevelPath;
+ return this;
+ }
+
+ /**
+ * Gets the children.
+ *
+ * @return the children
+ */
+ public List<String> getChildren() {
+ return children;
+ }
+
+ /**
+ * Sets the children.
+ *
+ * @param children the children
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setChildren(List<String> children) {
+ this.children = children;
+ return this;
+ }
+
+ /**
+ * Gets the pojo package.
+ *
+ * @return the pojo package
+ */
+ public String getPojoPackage() {
+ return pojoPackage;
+ }
+
+ /**
+ * Gets the db model package.
+ *
+ * @return the db model package
+ */
+ public String getDbModelPackage() {
+ return dbmodelPackage;
+ }
+
+ /**
+ * Sets the pojo package.
+ *
+ * @param pojoPackage the pojo package
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setPojoPackage(String pojoPackage) {
+ this.pojoPackage = pojoPackage;
+ return this;
+ }
+
+ /**
+ * Gets the min list size.
+ *
+ * @return the min list size
+ */
+ public int getMinListSize() {
+ return minListSize;
+ }
+
+ /**
+ * Sets the min list size.
+ *
+ * @param minListSize the min list size
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setMinListSize(int minListSize) {
+ this.minListSize = minListSize;
+ return this;
+ }
+
+ /**
+ * Gets the max list size.
+ *
+ * @return the max list size
+ */
+ public int getMaxListSize() {
+ return maxListSize;
+ }
+
+ /**
+ * Sets the max list size.
+ *
+ * @param maxListSize the max list size
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setMaxListSize(int maxListSize) {
+ this.maxListSize = maxListSize;
+ return this;
+ }
+
+ /**
+ * Gets the rest package.
+ *
+ * @return the rest package
+ */
+ public String getRestPackage() {
+ return restPackage;
+ }
+
+ /**
+ * Sets the rest package.
+ *
+ * @param restPackage the rest package
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setRestPackage(String restPackage) {
+ this.restPackage = restPackage;
+ return this;
+ }
+
+ /**
+ * Gets the api version.
+ *
+ * @return the api version
+ */
+ public Version getApiVersion() {
+ return apiVersion;
+ }
+
+ /**
+ * Sets the api version.
+ *
+ * @param apiVersion the api version
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setApiVersion(Version apiVersion) {
+ this.apiVersion = apiVersion;
+ return this;
+ }
+
+ /**
+ * Sets the db model package.
+ *
+ * @param dbmodelPackage the dbmodel package
+ * @return the test suite builder
+ */
+ public TestSuiteBuilder setDbModelPackage(String dbmodelPackage) {
+ this.dbmodelPackage = dbmodelPackage;
+ return this;
+ }
+
+ /**
+ * Gets the current api version.
+ *
+ * @return the current api version
+ */
+ public Version getCurrentApiVersion() {
+ return currentApiVersion;
+ }
+
+ /**
+ * Sets the current api version.
+ *
+ * @param currentApiVersion the new current api version
+ */
+ public void setCurrentApiVersion(Version currentApiVersion) {
+ this.currentApiVersion = currentApiVersion;
+ }
+
+
+ /**
+ * Gets the delete scope.
+ *
+ * @return the delete scope
+ */
+ public Multimap<String, String> getDeleteScope() {
+ return DeleteScope;
+ }
+
+ /**
+ * Gets the edge map.
+ *
+ * @return the edge map
+ */
+ public Multimap<String, String> getEdgeMap() {
+ return EdgeMap;
+ }
+
+
+ /**
+ * Builds the.
+ *
+ * @return the test suite
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws NoSuchFieldException the no such field exception
+ * @throws SecurityException the security exception
+ * @throws ClassNotFoundException the class not found exception
+ */
+ @SuppressWarnings("unchecked")
+ public TestSuite build() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
+ Class<?> dbEdgeRules = Class.forName(dbmodelPackage + ".DbEdgeRules");
+
+ DeleteScope = (Multimap<String, String>)dbEdgeRules.getDeclaredField("DefaultDeleteScope").get(null);
+ EdgeMap = (Multimap<String, String>)dbEdgeRules.getDeclaredField("EdgeRules").get(null);
+
+ return new TestSuite(this);
+
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuiteWriter.java b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuiteWriter.java
new file mode 100644
index 0000000..9b35aa0
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuiteWriter.java
@@ -0,0 +1,375 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.testsuitegeneration;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.core.Response.Status;
+import javax.xml.bind.JAXBException;
+
+import org.json.JSONException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.rest.ueb.NotificationEvent;
+import org.openecomp.aai.rest.ueb.UEBNotification;
+import org.openecomp.aai.serialization.db.EdgeRule;
+import org.openecomp.aai.serialization.db.MultiplicityRule;
+import org.openecomp.aai.testing.InjectResourceVersion;
+import org.openecomp.aai.testing.LocateEndPoints;
+import org.openecomp.aai.testing.UpdateObject;
+import org.openecomp.aai.testsuitegeneration.TestSuite.TestSuiteBuilder;
+import org.springframework.web.util.UriUtils;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+
+import edu.emory.mathcs.backport.java.util.Arrays;
+
+public class TestSuiteWriter extends AbstractWriter {
+
+ protected final String END_POINT_SUITE_CONTENT = "end_point_suite_content_txt.ftl";
+ protected final String CHILD_TEST_CONTENT = "child_test_content_txt.ftl";
+
+ protected final String[] TOP_ENTITY_EXCEPTIONS = new String[] { "tenant", "volume-group", "dvs-switch", "image", "flavor", "oam-network", "availability-zone"};
+ protected final Set<String> EXCEPTION_SET = new HashSet<String>(Arrays.asList(TOP_ENTITY_EXCEPTIONS));
+
+ /**
+ * Instantiates a new test suite writer.
+ *
+ * @param file the file
+ * @param builder the builder
+ */
+ public TestSuiteWriter(File file, TestSuiteBuilder builder) {
+
+ // Just call the super constructor
+ super(file, builder);
+
+ }
+
+ /**
+ * Creates a suite for the parent object creation/teardown.
+ *
+ * @param path the path
+ * @param parentObject the parent object
+ * @param lep the lep
+ * @param genericPath the generic path
+ * @return the string
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ */
+ protected String createParentSuite(String path, Introspector parentObject, LocateEndPoints lep, String genericPath) throws IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ if(genericPath == null) genericPath = path;
+
+ // Extract the object name to create the suite path
+ String name = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, parentObject.getDbName());
+ String suitePath = outputPath + "/" + name + "Suite";
+
+ // Create the suite directory
+ File suiteDir = new File(suitePath);
+ suiteDir.mkdir();
+
+ // Randomly generate field values to update the parent object
+ InjectResourceVersion inject = new InjectResourceVersion();
+ Introspector injectedObject = inject.addResourceVersionDeep(parentObject);
+ Introspector updatedParentObject = (new UpdateObject()).randomlyUpdateFieldValues(injectedObject);
+
+ String populatedPath = (String)lep.populatePath(parentObject, path).get(0);
+ //check the child map
+ String lowerHyphenName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, name);
+ Pattern p = Pattern.compile("^[\\w\\-]+?,,");
+ Matcher m = null;
+ boolean hasChildren = this.hasChildren(parentObject);
+
+ // Create the variable mapping for the suite
+ Map<String, Object> suiteMap = new HashMap<>();
+
+ if (hasChildren && DeleteScope.get(lowerHyphenName).contains("THIS_NODE_ONLY")) {
+
+ try {
+ tearDownPath = generateRecursiveCleanUp(populatedPath, suitePath, updatedParentObject, lep, "", "${topLevelFeatureURL}");
+ //tearDownPathChildren = generateRecursiveCleanUp(path, additionalPath, parentObject, lep, "OfParent");
+
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ e.printStackTrace();
+ }
+ parentCleanUpPage = this.tearDownPath;
+
+ } else {
+ parentCleanUpPage = ".AAI.Tests.GenericTests.SimpleParentCleanUp";
+ }
+ String encodedPath = this.encodeUsernamePlaceholders(populatedPath);
+ encodedPath = encodedPath.replaceFirst("/aai/v\\d+/", "");
+ UEBNotification notification = new UEBNotification(loader);
+ Introspector uebObj = null;
+ Introspector uebUpdatedObj = null;
+ String uebLink = "";
+ try {
+ notification.createNotificationEvent("test-generation", Status.CREATED, new URI(encodedPath), parentObject, new HashMap<String, Introspector>());
+ notification.createNotificationEvent("test-generation", Status.OK, new URI(encodedPath), updatedParentObject, new HashMap<String, Introspector>());
+ List<NotificationEvent> events = notification.getEvents();
+ uebObj = events.get(0).getObj();
+ uebUpdatedObj = events.get(1).getObj();
+ AddNamedPropWildcard addWildCard = new AddNamedPropWildcard(loader);
+ addWildCard.process(uebObj);
+ addWildCard.process(uebUpdatedObj);
+ uebLink = "-!${address}!-"+new URI((String)events.get(0).getEventHeader().getValue("entity-link")).getPath();
+ uebLink = this.decodeUserNamePlaceholders(uebLink);
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (URISyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ String entity = this.getHyphenatedClassName(name);
+ String topEntity = this.computeTopEntity(entity);
+ suiteMap.put("topLevelBody", replaceUsernamePlaceholders(parentObject.marshal(true)));
+ suiteMap.put("topLevelUpdatedBody", replaceUsernamePlaceholders(updatedParentObject.marshal(true)));
+ suiteMap.put("topUebBody", replaceUsernamePlaceholders(uebObj.marshal(true)));
+ suiteMap.put("topUebUpdatedBody", replaceUsernamePlaceholders(uebUpdatedObj.marshal(true)));
+ suiteMap.put("topUebLink", replaceUsernamePlaceholders(uebLink));
+ suiteMap.put("topLevelFeatureURL", replaceUsernamePlaceholders(populatedPath));
+ suiteMap.put("type", "suite");
+ suiteMap.put("entity", entity);
+ suiteMap.put("topEntity", topEntity);
+ suiteMap.put("topLevelCleanUpPage", parentCleanUpPage);
+
+ Map<String, String> symLinks = new HashMap<>();
+ symLinks.put("SuiteSetUp", ".AAI.Tests.GenericTests.SuiteSetUpTemplate");
+ symLinks.put("SuiteTearDown", ".AAI.Tests.GenericTests.SuiteTearDownTemplate");
+ suiteMap.put("symLinks", symLinks);
+ // Process the freemarker files
+ processDataModel(END_POINT_SUITE_CONTENT, "content.txt", suiteDir, suiteMap);
+ processDataModel(PROPERTIES_XML, "properties.xml", suiteDir, suiteMap);
+
+ // Create a placeholder page for the parent test
+ String parentTest = suitePath + "/" + name + "Test";
+ suiteDir = new File(parentTest);
+ suiteDir.mkdir();
+ suiteMap = new HashMap<>();
+ suiteMap.put("type", "test");
+ processDataModel("empty_context_txt.ftl", "content.txt", suiteDir, suiteMap);
+ processDataModel(PROPERTIES_XML, "properties.xml", suiteDir, suiteMap);
+
+ return suitePath;
+ }
+
+ /**
+ * Format test name.
+ *
+ * @param genericPath the generic path
+ * @return the string
+ */
+ protected String formatTestName(String genericPath) {
+ String dropSuiteName = genericPath.substring(genericPath.indexOf("}")+1);
+ String removeVariables = dropSuiteName.replaceAll("\\/\\{.*?\\}", "");
+ String[] split = removeVariables.split("/");
+ List<String> result = new ArrayList<>();
+ for (int i = 0; i < split.length; i++) {
+
+ if (!this.isPlural(split[i])) {
+ result.add(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, split[i]));
+ }
+ }
+ String addHyphens = Joiner.on("-").join(result).replaceFirst("-", "");
+
+ return addHyphens;
+ }
+
+ /**
+ * Adds the test case.
+ *
+ * @param suitePath the suite path
+ * @param path the path
+ * @param obj the obj
+ * @param genericPath the generic path
+ * @param lep the lep
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public void addTestCase(String suitePath, String path, Introspector obj, String genericPath, LocateEndPoints lep) throws IOException {
+ if (genericPath == null){
+ genericPath = suitePath;
+ }
+ supplimentalMap.put("tearDownPath", this.tearDownPathChildren);
+
+ this.addTestCase(suitePath, path, obj, supplimentalMap, CHILD_TEST_CONTENT, genericPath, lep);
+ }
+
+ /**
+ * Adds the test case.
+ *
+ * @param parentPath the parent path
+ * @param path the path
+ * @param obj the obj
+ * @param supplimentalMap the supplimental map
+ * @param templateName the template name
+ * @param genericPath the generic path
+ * @param lep the lep
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ protected void addTestCase(String parentPath, String path, Introspector obj, Map<String, Object> supplimentalMap,
+ String templateName, String genericPath, LocateEndPoints lep) throws IOException {
+
+ if (genericPath == null){
+ genericPath = parentPath;
+ }
+
+ InjectResourceVersion inject = new InjectResourceVersion();
+ Introspector injectedResource = inject.addResourceVersionDeep(obj);
+ Introspector updatedObj = (new UpdateObject()).randomlyUpdateFieldValues(injectedResource);
+
+ String name = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, obj.getDbName());
+ String entityName = this.getHyphenatedClassName(name);
+ String nameWithDepth = this.formatTestName(genericPath);
+
+ if (!nameWithDepth.equals("")) {
+ name = nameWithDepth;
+ }
+ String testPath = parentPath + "/" + name + "Test";
+
+ File dir = new File(testPath);
+
+ dir.mkdir();
+
+ Map<String, Object> testMap = new HashMap<>();
+
+ boolean hasChildren = this.hasChildren(obj);
+
+ if (hasChildren && DeleteScope.get(obj.getDbName()).contains("THIS_NODE_ONLY")) {
+
+ try {
+ tearDownPath = generateRecursiveCleanUp(path, parentPath, updatedObj, lep, "", "${featureURL}");
+ //tearDownPathChildren = generateRecursiveCleanUp(path, additionalPath, parentObject, lep, "OfParent");
+
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | NoSuchMethodException
+ | SecurityException e) {
+ e.printStackTrace();
+ }
+ this.deletePage = this.tearDownPath;
+ } else {
+ this.deletePage = ".AAI.Tests.GenericTests.DeleteTop";
+ }
+ String testPagePath = ".AAI.Tests.GenericTests.GenericTest";
+ try {
+ Introspector parent = null;
+ if (!genericPath.equals(obj.getFullGenericURI())) {
+ String parentObjectPath = genericPath.replace(obj.getFullGenericURI(), "");
+ parent = lep.createChildForPath(parentObjectPath, 1, 1);
+ EdgeRule rule = org.openecomp.aai.serialization.db.EdgeRules.getInstance().getEdgeRule(parent.getDbName(), obj.getDbName());
+
+ if (rule.getMultiplicityRule().equals(MultiplicityRule.ONE2ONE)) {
+ testPagePath = ".AAI.Tests.GenericTests.PlaceholderTest";
+ }
+ }
+ } catch (IllegalArgumentException | AAIException | IllegalAccessException | InvocationTargetException | InstantiationException | JSONException | JAXBException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ String featureUrl = replaceUsernamePlaceholders(path);
+ String encodedPath = this.encodeUsernamePlaceholders(path);
+ encodedPath = encodedPath.replaceFirst("/aai/v\\d+/", "");
+
+ UEBNotification notification = new UEBNotification(loader);
+ Introspector uebObj = null;
+ Introspector uebUpdatedObj = null;
+ String uebLink = "";
+ try {
+ notification.createNotificationEvent("test-generation", Status.CREATED, new URI(encodedPath), obj, new HashMap<String, Introspector>());
+ notification.createNotificationEvent("test-generation", Status.OK, new URI(encodedPath), updatedObj, new HashMap<String, Introspector>());
+ List<NotificationEvent> events = notification.getEvents();
+ uebObj = events.get(0).getObj();
+ uebUpdatedObj = events.get(1).getObj();
+ AddNamedPropWildcard addWildCard = new AddNamedPropWildcard(loader);
+ addWildCard.process(uebObj);
+ addWildCard.process(uebUpdatedObj);
+ uebLink = "-!${address}!-"+new URI((String)events.get(0).getEventHeader().getValue("entity-link")).getPath();
+ uebLink = this.decodeUserNamePlaceholders(uebLink);
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (URISyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+
+ testMap.put("body", replaceUsernamePlaceholders(obj.marshal(true)));
+ testMap.put("updatedBody", replaceUsernamePlaceholders(updatedObj.marshal(true)));
+ testMap.put("uebBody", replaceUsernamePlaceholders(uebObj.marshal(true)));
+ testMap.put("uebUpdatedBody", replaceUsernamePlaceholders(uebUpdatedObj.marshal(true)));
+ testMap.put("uebLink", replaceUsernamePlaceholders(uebLink));
+ testMap.put("featureURL", featureUrl);
+ testMap.put("type", "test");
+ testMap.put("testPath", testPagePath);
+ testMap.put("deletePage", this.deletePage);
+ testMap.put("putPage", ".AAI.Tests.GenericTests.StandardPut");
+ testMap.put("entity", entityName);
+ testMap.putAll(supplimentalMap);
+
+ this.processDataModel(templateName, "content.txt", dir, testMap);
+ this.processDataModel(PROPERTIES_XML, "properties.xml", dir, testMap);
+ }
+
+ /**
+ * Compute top entity.
+ *
+ * @param entity the entity
+ * @return the string
+ */
+ private String computeTopEntity(String entity) {
+ String result = entity;
+ if (!this.apiVersion.equals("v7")) {
+ if (EXCEPTION_SET.contains(entity)) {
+ result = "cloud-region";
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/child_test_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/child_test_content_txt.ftl
new file mode 100644
index 0000000..e051471
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/child_test_content_txt.ftl
@@ -0,0 +1,33 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!contents -R2 -g -p -f -h
+!*> Test Variables
+!define entity {${entity}}
+!define body {!-${body}-!}
+!define updatedBody {!-${updatedBody}-!}
+!define uebBody {!-${uebBody}-!}
+!define uebUpdatedBody {!-${uebUpdatedBody}-!}
+!define uebLink {!-${uebLink}-!}
+!define featureURL {!-${featureURL}-!}
+!define putPage {!include -c ${putPage}}
+!define deletePage {!include ${deletePage}}
+*!
+!include -setup ${testPath}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/empty_context_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/empty_context_txt.ftl
new file mode 100644
index 0000000..2118995
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/empty_context_txt.ftl
@@ -0,0 +1,21 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!include .AAI.Tests.GenericTests.PlaceholderTest
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/end_point_suite_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/end_point_suite_content_txt.ftl
new file mode 100644
index 0000000..271c6d6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/end_point_suite_content_txt.ftl
@@ -0,0 +1,32 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!contents -R2 -g -p -f -h
+!*> Suite Variables
+!define entity {${entity}}
+!define topEntity {${topEntity}}
+!define topLevelBody {!-${topLevelBody}-!}
+!define topLevelUpdatedBody {!-${topLevelUpdatedBody}-!}
+!define topUebBody {!-${topUebBody}-!}
+!define topUebUpdatedBody {!-${topUebUpdatedBody}-!}
+!define topUebLink {!-${topUebLink}-!}
+!define topLevelFeatureURL {!-${topLevelFeatureURL}-!}
+!define topLevelCleanUpPage {!include ${topLevelCleanUpPage}}
+*!
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/junit_class_java.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/junit_class_java.ftl
new file mode 100644
index 0000000..7a882fb
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/junit_class_java.ftl
@@ -0,0 +1,33 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+package ${packageName};
+
+import org.junit.runner.RunWith;
+
+import fitnesse.junit.FitNesseRunner;
+
+@RunWith(FitNesseRunner.class)
+@FitNesseRunner.Suite("${suiteName}")
+@FitNesseRunner.FitnesseDir(".")
+@FitNesseRunner.OutputDir("./target/fitnesse-results")
+public class ${className} {
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/properties_xml.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/properties_xml.ftl
new file mode 100644
index 0000000..36e2059
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/properties_xml.ftl
@@ -0,0 +1,48 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<properties>
+<Edit/>
+<Files/>
+<Properties/>
+<#if skip??>
+ <Prune/><#lt>
+</#if>
+<RecentChanges/>
+<Refactor/>
+<Search/>
+<#if type == "test">
+ <Test/><#lt>
+<#elseif type == "suite">
+ <Suite/><#lt>
+<#elseif type == "static">
+ <Static/><#lt>
+</#if>
+<#if symLinks??>
+ <SymbolicLinks><#lt>
+ <#list symLinks?keys as link><#lt>
+ <${link}>${symLinks[link]}</${link}><#lt>
+ </#list><#lt>
+ </SymbolicLinks><#lt>
+</#if>
+<Versions/>
+<WhereUsed/>
+</properties>
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/recursive_teardown_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/recursive_teardown_content_txt.ftl
new file mode 100644
index 0000000..5573795
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/recursive_teardown_content_txt.ftl
@@ -0,0 +1,29 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!include .AAI.Tests.GenericTests.RestFixtureSetup
+
+!define deleteURL {${urlVariableName}}
+!include ${errorCheckPage}
+<#list pages as page>
+ !include ${page}<#lt>
+</#list>
+!define deleteURL {${urlVariableName}}
+!include ${parentCleanUpPage}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_content_txt.ftl
new file mode 100644
index 0000000..69b731e
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_content_txt.ftl
@@ -0,0 +1,37 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!*> User-defined Variables
+!define topFeatureURL_A {!-${topFeatureUrlA}-!}
+!define topFeatureURL_B {!-${topFeatureUrlB}-!}
+!define featureURL_A {!-${featureUrlA}-!}
+!define featureURL_B {!-${featureUrlB}-!}
+!define relationshipURLA {!-${relationshipURLA}-!}
+!define relationshipURLB {!-${relationshipURLB}-!}
+!define body_A {!-${objectBodyA}-!}
+!define body_B {!-${objectBodyB}-!}
+!define body_RA {!-${objectRelationshipA}-!}
+!define body_RB {!-${objectRelationshipB}-!}
+!define deletePageA {!include ${deletePageA}}
+!define deletePageB {!include ${deletePageB}}
+!define expectedResultA {!-${expectedResultA}-!}
+!define expectedResultB {!-${expectedResultB}-!}
+*!
+!include -setup .AAI.Tests.GenericTests.GenericRelationshipTest
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_content_txt.ftl
new file mode 100644
index 0000000..55d4177
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_content_txt.ftl
@@ -0,0 +1,36 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!*> User-defined Variables
+!define topFeatureURL_A {!-${topFeatureUrlA}-!}
+!define topFeatureURL_B {!-${topFeatureUrlB}-!}
+!define featureURL_A {!-${featureUrlA}-!}
+!define featureURL_B {!-${featureUrlB}-!}
+!define relationshipURLA {!-${relationshipURLA}-!}
+!define relationshipURLB {!-${relationshipURLB}-!}
+!define body_A {!-${objectBodyA}-!}
+!define body_B {!-${objectBodyB}-!}
+!define body_RA {!-${objectRelationshipA}-!}
+!define body_RB {!-${objectRelationshipB}-!}
+!define deletePageA {!include ${deletePageA}}
+!define deletePageB {!include ${deletePageB}}
+!define expectedResultA {!-${expectedResultA}-!}
+*!
+!include -setup .AAI.Tests.GenericTests.GenericSingleRelationshipTest
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_reversed_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_reversed_content_txt.ftl
new file mode 100644
index 0000000..b9f4a0d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_reversed_content_txt.ftl
@@ -0,0 +1,36 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!*> User-defined Variables
+!define topFeatureURL_A {!-${topFeatureUrlA}-!}
+!define topFeatureURL_B {!-${topFeatureUrlB}-!}
+!define featureURL_A {!-${featureUrlA}-!}
+!define featureURL_B {!-${featureUrlB}-!}
+!define relationshipURLA {!-${relationshipURLA}-!}
+!define relationshipURLB {!-${relationshipURLB}-!}
+!define body_A {!-${objectBodyA}-!}
+!define body_B {!-${objectBodyB}-!}
+!define body_RA {!-${objectRelationshipA}-!}
+!define body_RB {!-${objectRelationshipB}-!}
+!define deletePageA {!include ${deletePageA}}
+!define deletePageB {!include ${deletePageB}}
+!define expectedResultB {!-${expectedResultB}-!}
+*!
+!include -setup .AAI.Tests.GenericTests.GenericSingleRelationshipReversedTest
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/remove_children_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/remove_children_content_txt.ftl
new file mode 100644
index 0000000..660bdf4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/remove_children_content_txt.ftl
@@ -0,0 +1,25 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+<#list urls as url>
+ !define deleteURL {!-${url}-!}<#lt>
+ !include ${deleteChildren}<#lt>
+
+</#list>
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/static_page_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/static_page_content_txt.ftl
new file mode 100644
index 0000000..a6736d3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/static_page_content_txt.ftl
@@ -0,0 +1,21 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!contents -R2 -g -p -f -h
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/version_suite_content_txt.ftl b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/version_suite_content_txt.ftl
new file mode 100644
index 0000000..ebfa08d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/version_suite_content_txt.ftl
@@ -0,0 +1,31 @@
+<#--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+-->
+
+!1 Test suite ${version}
+!contents -R2 -g -p -f -h!contents -R2 -g -p -f -h
+!*> Suite Variables
+!define slim.port {${slimPort?c}}
+!define defns {http://org.openecomp.aai.inventory/${version}}
+!define createStatus {${createStatus}}
+!define version {${version}}
+!define currentApiVersion {${currentVersion}}
+#disable ueb tests
+!define uebTest {}
+*!
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiServerURLBase.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiServerURLBase.java
new file mode 100644
index 0000000..2e715b5
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiServerURLBase.java
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Version;
+
+public class AAIApiServerURLBase {
+
+ /**
+ * Gets the.
+ *
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String get() throws AAIException {
+
+ String hostName = null;
+ try {
+ Message message = PhaseInterceptorChain.getCurrentMessage();
+ Map<String, List<String>> headers = CastUtils.cast((Map) message.get(Message.PROTOCOL_HEADERS));
+ List sa = null;
+ if (headers != null) {
+ sa = headers.get("host");
+ }
+
+ if (sa != null && sa.size() == 1) {
+ hostName = "https://"+ sa.get(0).toString() + "/aai/";
+ }
+ } catch (Exception e) {
+ // TODO: we may want to log an error here
+ }
+ // TODO: should this check the value a little closer and look for a pattern?
+ if (hostName == null) {
+ hostName = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE);
+ //AAIConstants.AAI_SERVER_URL_BASE;
+ }
+ return hostName;
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param v the v
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String get(Version v) throws AAIException {
+ String hostName = null;
+ hostName = AAIApiServerURLBase.get();
+
+ return hostName;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiVersion.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiVersion.java
new file mode 100644
index 0000000..62764db
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiVersion.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.openecomp.aai.exceptions.AAIException;
+
+public class AAIApiVersion {
+
+ private static final Pattern versionPattern = Pattern.compile("(^|\\/)(v\\d+)\\/");
+
+ private static final Pattern latestVersionPattern = Pattern.compile("(^|\\/)(latest)\\/");
+
+ /**
+ * Gets the.
+ *
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String get() throws AAIException {
+
+ String apiVersion = null;
+ try {
+ Message message = PhaseInterceptorChain.getCurrentMessage();
+ String requestURI = (String) message.get(Message.REQUEST_URI);
+
+ if (requestURI != null) {
+ Matcher matcher = versionPattern.matcher(requestURI);
+ if (matcher.find() && matcher.groupCount() >= 2) {
+ apiVersion = matcher.group(2);
+ }
+ if (apiVersion == null) {
+ Matcher latestMatcher = latestVersionPattern.matcher(requestURI);
+ if (latestMatcher.find() && latestMatcher.groupCount() >= 2) {
+ apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP, AAIConstants.AAI_DEFAULT_API_VERSION);
+ }
+ }
+
+ }
+
+ } catch (Exception e) {
+ // TODO: we may want to log an error here
+ }
+ // TODO: should this check the value a little closer and look for a pattern?
+ if (apiVersion == null || !apiVersion.startsWith("v")) {
+ apiVersion = AAIConfig.get (AAIConstants.AAI_DEFAULT_API_VERSION_PROP, AAIConstants.AAI_DEFAULT_API_VERSION);
+ //apiVersion = AAIConstants.AAI_DEFAULT_API_VERSION;
+ }
+ return apiVersion;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java
new file mode 100644
index 0000000..a7880a4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java
@@ -0,0 +1,119 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.UUID;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.activemq.broker.BrokerService;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+
+public class AAIAppServletContextListener implements ServletContextListener {
+
+ /**
+ * Destroys Context
+ *
+ * @param arg0 the ServletContextEvent
+ */
+ public void contextDestroyed(ServletContextEvent arg0) {
+
+ AAILogger aaiLogger = new AAILogger(AAIAppServletContextListener.class.getName());
+ LogLine logline = new LogLine();
+
+ logline.init("aaigen", UUID.randomUUID().toString(), "AAI", "AAI Server shutdown");
+ aaiLogger.debug(logline, "AAI graph shutdown");
+ System.out.println("Shutting down graph database");
+ AAIGraph.getInstance().graphShutdown();
+ System.out.println("AAI Server stopped");
+ aaiLogger.info(logline, true, "0");
+ }
+
+/**
+ * Initializes Context
+ *
+ * @param arg0 the ServletContextEvent
+ */
+ public void contextInitialized(ServletContextEvent arg0) {
+ System.setProperty("org.openecomp.aai.serverStarted", "false");
+ System.out.println("***AAI Server initialization started...");
+
+ AAILogger aaiLogger = new AAILogger(AAIAppServletContextListener.class.getName());
+ LogLine logline = new LogLine();
+
+ try {
+ String transId = UUID.randomUUID().toString();
+ String fromAppId = "AAI-INIT";
+ logline.init("aaigen", transId, fromAppId, "AAI Server initialization");
+
+ aaiLogger.debug(logline, "Loading aaiconfig.properties");
+ System.out.println("Loading aaiconfig.properties");
+ AAIConfig.init(transId, fromAppId);
+
+ aaiLogger.debug(logline, "Loading error.properties");
+ System.out.println("Loading error.properties");
+ ErrorLogHelper.loadProperties();
+
+ aaiLogger.debug(logline, "Loading graph database");
+ System.out.println("Loading graph database");
+
+ AAIGraph.getInstance();
+ ModelInjestor.getInstance();
+ aaiLogger.info(logline, true, "0");
+
+ // Jsm internal broker for aai events
+ BrokerService broker = new BrokerService();
+ broker.addConnector("tcp://localhost:61616");
+ broker.setPersistent(false);
+ broker.setUseJmx(false);
+ broker.setSchedulerSupport(false);
+ broker.start();
+
+ System.out.println("***AAI Server initialization succcessful.");
+ } catch (AAIException e) {
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.out.println("***AAI Server initialization failed.");
+ } catch (Exception e) {
+ // log the error
+ ErrorObject errorObject = new ErrorObject();
+ errorObject.setDisposition("5");
+ errorObject.setCategory("4");
+ errorObject.setSeverity("FATAL");
+ errorObject.setErrorCode("4000");
+ errorObject.setErrorText("Internal Error");
+ errorObject.setDetails(e.getMessage());
+
+ aaiLogger.error(errorObject, logline, e);
+ aaiLogger.info(logline, false, "AAI_4000");
+ System.out.println("***AAI Server initialization failed.");
+ }
+
+ System.setProperty("org.openecomp.aai.serverStarted", "true");
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfig.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfig.java
new file mode 100644
index 0000000..1df9d04
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfig.java
@@ -0,0 +1,320 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Timer;
+import java.util.UUID;
+
+import org.eclipse.jetty.util.security.Password;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+
+
+public class AAIConfig {
+
+ private static LogLine ilogline = new LogLine();
+ private static LogLine rlogline = new LogLine();
+ private static AAILogger aailogger = new AAILogger(AAIConfig.class.getName());
+ private static String transId = UUID.randomUUID().toString();
+ private static String fromAppId = "AAI-INIT";
+ private static String component = "aaigen";
+
+ private static String GlobalPropFileName = AAIConstants.AAI_CONFIG_FILENAME;
+ //private static String GlobalPropFileName = null;
+ private static Properties serverProps;
+ private static boolean propsInitialized = false;
+
+ // this (probably) won't change between releases, put it in the config if it gets annoying...
+ private static HashMap<String,ArrayList<String>> defaultBools = new HashMap<String,ArrayList<String>>();
+ //
+ private static Timer timer = new Timer();
+
+ /**
+ * Instantiates a new AAI config.
+ */
+ // Don't instantiate
+ private AAIConfig() {}
+
+ /**
+ * Inits the.
+ *
+ * @param tId the t id
+ * @param appId the app id
+ * @throws AAIException the AAI exception
+ */
+ public synchronized static void init(String tId, String appId) throws AAIException{
+ transId = tId;
+ fromAppId = appId;
+ init();
+ }
+
+ /**
+ * Inits the.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public synchronized static void init() throws AAIException{
+ ilogline.init(component, transId, fromAppId, "init");
+ aailogger.debug(ilogline, "Initializing Config");
+
+ ArrayList<String> genericVnfBools = new ArrayList<String>();
+ ArrayList<String> l3NetworkBools = new ArrayList<String>();
+ ArrayList<String> pserverBools = new ArrayList<String>();
+ ArrayList<String> subnetBools = new ArrayList<String>();
+ ArrayList<String> vserverBools = new ArrayList<String>();
+ ArrayList<String> vnfcBools = new ArrayList<String>();
+
+ genericVnfBools.add("in-maint");
+ genericVnfBools.add("is-closed-loop-disabled");
+ l3NetworkBools.add("is-bound-to-vpn");
+ pserverBools.add("in-maint");
+ subnetBools.add("dhcp-enabled");
+ vserverBools.add("in-maint");
+ vserverBools.add("is-closed-loop-disabled");
+ vnfcBools.add("in-maint");
+ vnfcBools.add("is-closed-loop-disabled");
+
+ defaultBools.put("generic-vnf", genericVnfBools);
+ defaultBools.put("l3-network", l3NetworkBools);
+ defaultBools.put("pserver", pserverBools);
+ defaultBools.put("subnet", subnetBools);
+ defaultBools.put("vserver", vserverBools);
+ defaultBools.put("vnfc", vnfcBools);
+
+ AAIConfig.getConfigFile();
+ AAIConfig.reloadConfig();
+
+/*** For User Story 568: using @Scheduler(...) now, so we don't need the following timmer anymore
+ * TimerTask task = null;
+ * task = new FileWatcher ( new File(GlobalPropFileName)) {
+ * protected void onChange( File file ) {
+ * // here we implement the onChange
+ * AAIConfig.reloadConfig();
+ * }
+ * };
+ *
+ * if (!timerSet) {
+ * timerSet = true;
+ * // repeat the check every second
+ * String fwi = AAIConfig.get(AAIConstants.AAI_CONFIG_CHECKINGTIME);
+ * timer.schedule( task , new Date(), Integer.parseInt(fwi) );
+ * ilogline.add("Config Watcher Interval", fwi);
+ *
+ * ilogline.add("File", GlobalPropFileName+" Loaded!");
+ * }
+ */
+
+ if (AAIConstants.AAI_NODENAME == null || AAIConstants.AAI_NODENAME == "") {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4005", " AAI_NODENAME is not defined");
+ aailogger.error(errorObject, ilogline, null);
+ aailogger.info(ilogline, false, "AAI_4005");
+ } else {
+ ilogline.add("AAI_SERVER_NODENAME", AAIConstants.AAI_NODENAME);
+ aailogger.info(ilogline, true, "0");
+ }
+ }
+
+ /**
+ * Gets the default bools.
+ *
+ * @return the default bools
+ */
+ public static HashMap<String,ArrayList<String>> getDefaultBools() {
+ return defaultBools;
+ }
+
+ /**
+ * Cleanup.
+ */
+ public static void cleanup() {
+ timer.cancel();
+ }
+
+ /**
+ * Gets the config file.
+ *
+ * @return the config file
+ */
+ public static String getConfigFile() {
+// if (GlobalPropFileName == null) {
+// String nc = System.getProperty("aaiconfig");
+// if (nc == null) nc = "/home/aaiadmin/etc/aaiconfig.props";
+// logger.info( "aaiconfig = " + nc==null?"null":nc);
+// GlobalPropFileName = nc;
+// }
+ return GlobalPropFileName;
+ }
+
+ /**
+ * Reload config.
+ */
+ public synchronized static void reloadConfig() {
+
+ String propFileName = GlobalPropFileName;
+
+ Properties newServerProps = null;
+
+ rlogline.init(component, transId, fromAppId, "reloadConfig");
+ aailogger.debug(rlogline, "Reloading config from " + propFileName);
+
+ try {
+ InputStream is = new FileInputStream(propFileName);
+ newServerProps = new Properties();
+ newServerProps.load(is);
+ propsInitialized = true;
+
+ serverProps = newServerProps;
+ newServerProps = null;
+ aailogger.info(rlogline, true, "0");
+
+ } catch (FileNotFoundException fnfe) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4001", " " + propFileName + ". Exception: "+fnfe.getMessage());
+ aailogger.error(errorObject, rlogline, fnfe);
+ aailogger.info(rlogline, false, "AAI_4001");
+
+ } catch (IOException e) {
+ ErrorObject errorObject = ErrorLogHelper.getErrorObject("AAI_4002", " " + propFileName + ". IOException: "+e.getMessage());
+ aailogger.error(errorObject, rlogline, e);
+ aailogger.info(rlogline, false, "AAI_4002");
+ }
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param key the key
+ * @param defaultValue the default value
+ * @return the string
+ */
+ public static String get(String key, String defaultValue) {
+ String result = defaultValue;
+ try {
+ result = get (key);
+ }
+ catch ( AAIException a ) {
+
+ }
+ return ( result );
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param key the key
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String get(String key) throws AAIException {
+ String response = null;
+
+ /*if (key.equals(AAIConstants.AAI_NODENAME)) {
+ // Get this from InetAddress rather than the properties file
+ String nodeName = getNodeName();
+ if (nodeName != null) {
+ return nodeName;
+ }
+ // else get from property file
+ }*/
+
+ if (!propsInitialized || (serverProps == null)) {
+ reloadConfig();
+ }
+
+ if ((key.endsWith("password") || key.endsWith("passwd") || key.endsWith("apisecret")) && serverProps.containsKey(key+".x")) {
+ String valx = serverProps.getProperty(key+".x");
+ return Password.deobfuscate(valx);
+ }
+
+ if (!serverProps.containsKey(key)) {
+ throw new AAIException("AAI_4005", "Property key "+key+" cannot be found");
+ } else {
+ response = serverProps.getProperty(key);
+ if (response == null || response.isEmpty()) {
+ throw new AAIException("AAI_4005", "Property key "+key+" is null or empty");
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Gets the int.
+ *
+ * @param key the key
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ public static int getInt(String key) throws AAIException{
+ return Integer.valueOf(AAIConfig.get(key));
+ }
+
+ /**
+ * Gets the server props.
+ *
+ * @return the server props
+ */
+ public static Properties getServerProps() {
+ return serverProps;
+ }
+
+ /**
+ * Gets the node name.
+ *
+ * @return the node name
+ */
+ public static String getNodeName() {
+ try {
+ InetAddress ip = InetAddress.getLocalHost();
+ if (ip != null) {
+ String hostname = ip.getHostName();
+ if (hostname != null) {
+ return hostname;
+ }
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ return null;
+ }
+
+
+ /**
+ * Check if a null or an Empty string is passed in.
+ *
+ * @param s the s
+ * @return boolean
+ */
+ public static boolean isEmpty(String s)
+ {
+ return (s == null || s.length() == 0);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfigCommandLinePropGetter.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfigCommandLinePropGetter.java
new file mode 100644
index 0000000..c6ddc4f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfigCommandLinePropGetter.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import org.openecomp.aai.exceptions.AAIException;
+
+/*
+ * The script deobfuscatePW.sh needs to retrieve pws from the AAIConfig file.
+ * As AAIConfig has no main to be callable on the command line, this class helps
+ * by providing one for accessing AAIConfig that way.
+ * (AAIConfig deobfuscates pws itself, so we just need to call its .get() on the desired pw.)
+ *
+ * This could be used to get any property from AAIConfig via the command line,
+ * not just the pws, even though it was made for pw-related needs.
+ */
+public class AAIConfigCommandLinePropGetter {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ /*
+ * usage:
+ * AAIConfigCommandLinePropGetter propertyname
+ */
+ public static void main(String[] args) {
+ if (args.length != 1) {
+ System.out.println("only one property may be requested at a time");
+ System.out.println("usage: AAIConfigCommandLinePropGetter propertyname");
+ }
+ try {
+ AAIConfig.init();
+ String value = AAIConfig.get(args[0]);
+ if (value != null) {
+ System.out.println(value); //bc this utility used by a shell script so it needs the result sent to stdout
+ } else {
+ System.out.println("requested property could not be found");
+ }
+ } catch(AAIException e) {
+ System.out.println("exception:" + e.toString()); //TODO is this reasonable?
+ } finally {
+ System.exit(0);
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConstants.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConstants.java
new file mode 100644
index 0000000..324e2f8
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConstants.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+public final class AAIConstants {
+
+ /** Default to unix file separator if system property file.separator is null */
+ public static final String AAI_FILESEP = (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator");
+
+ /** Default to opt aai if system property aai.home is null, using file.separator */
+ public static final String AAI_HOME = (System.getProperty("AJSC_HOME") == null) ? AAI_FILESEP + "opt" + AAI_FILESEP + "app" + AAI_FILESEP +"aai" : System.getProperty("AJSC_HOME");
+ public static final String AAI_BUNDLECONFIG_NAME = (System.getProperty("BUNDLECONFIG_DIR") == null) ? "bundleconfig" : System.getProperty("BUNDLECONFIG_DIR");
+ public static final String AAI_HOME_BUNDLECONFIG = (System.getProperty("AJSC_HOME") == null) ? AAI_FILESEP + "opt" + AAI_FILESEP + "app" + AAI_FILESEP + "aai" + AAI_FILESEP + AAI_BUNDLECONFIG_NAME : System.getProperty("AJSC_HOME")+ AAI_FILESEP + AAI_BUNDLECONFIG_NAME;
+
+ /** etc directory, relative to AAI_HOME */
+ public static final String AAI_HOME_ETC = AAI_HOME_BUNDLECONFIG + AAI_FILESEP + "etc" + AAI_FILESEP;
+ public static final String AAI_HOME_ETC_APP_PROPERTIES = AAI_HOME_ETC + "appprops" + AAI_FILESEP;
+ public static final String AAI_HOME_ETC_AUTH = AAI_HOME_ETC + "auth" + AAI_FILESEP;
+ public static final String AAI_CONFIG_FILENAME = AAI_HOME_ETC_APP_PROPERTIES + "aaiconfig.properties";
+
+ public static final String AAI_HOME_ETC_OXM = AAI_HOME_ETC + "oxm" + AAI_FILESEP;
+
+ public static final String AAI_GETRES_LOGBACK_PROPS = "getres-logback.xml";
+ public static final String AAI_DELTOOL_LOGBACK_PROPS = "deltool-logback.xml";
+ public static final String AAI_UPDTOOL_LOGBACK_PROPS = "updtool-logback.xml";
+ public static final String AAI_PUTTOOL_LOGBACK_PROPS = "puttool-logback.xml";
+ public static final String AAI_POSTTOOL_LOGBACK_PROPS = "posttool-logback.xml";
+ public static final String AAI_RSHIPTOOL_LOGBACK_PROPS = "rshiptool-logback.xml";
+ public static final String AAI_LOGBACK_PROPS = "logback.xml";
+
+
+ public static final String AAI_CREATE_DB_SCHEMA_LOGBACK_PROPS = "createDBSchema-logback.xml";
+
+ public static final String AAI_DATA_GROOMING_LOGBACK_PROPS = "dataGrooming-logback.xml";
+ public static final String AAI_DATA_SNAPSHOT_LOGBACK_PROPS = "dataSnapshot-logback.xml";
+ public static final String AAI_SCHEMA_MOD_LOGBACK_PROPS = "schemaMod-logback.xml";
+
+ public static final String AAI_TRUSTSTORE_FILENAME = "aai.truststore.filename";
+ public static final String AAI_TRUSTSTORE_PASSWD = "aai.truststore.passwd";
+ public static final String AAI_KEYSTORE_FILENAME = "aai.keystore.filename";
+ public static final String AAI_KEYSTORE_PASSWD = "aai.keystore.passwd";
+
+ public static final String AAI_SERVER_URL_BASE = "aai.server.url.base";
+ public static final String AAI_SERVER_URL = "aai.server.url";
+ public static final String AAI_GLOBAL_CALLBACK_URL = "aai.global.callback.url";
+
+ public static final String AAI_DEFAULT_API_VERSION = "v8";
+ public static final String AAI_DEFAULT_API_VERSION_PROP = "aai.default.api.version";
+ public static final String AAI_NOTIFICATION_CURRENT_VERSION = "aai.notification.current.version";
+
+ public static final String AAI_NODENAME = "aai.config.nodename";
+
+ public static final String AAI_LOGGING_HBASE_INTERCEPTOR = "aai.logging.hbase.interceptor";
+ public static final String AAI_LOGGING_HBASE_ENABLED = "aai.logging.hbase.enabled";
+ public static final String AAI_LOGGING_HBASE_LOGREQUEST = "aai.logging.hbase.logrequest";
+ public static final String AAI_LOGGING_HBASE_LOGRESPONSE = "aai.logging.hbase.logresponse";
+
+ public static final String AAI_LOGGING_TRACE_ENABLED = "aai.logging.trace.enabled";
+ public static final String AAI_LOGGING_TRACE_LOGREQUEST = "aai.logging.trace.logrequest";
+ public static final String AAI_LOGGING_TRACE_LOGRESPONSE = "aai.logging.trace.logresponse";
+
+ public static final String AAI_CONFIG_CHECKINGTIME = "aai.config.checktime";
+ public static final String AAI_DBMODEL_FILENAME = "aai.dbmodel.filename";
+ public static final String AAI_RESVERSION_ENABLEFLAG = "aai.resourceversion.enableflag";
+
+ public static final String HBASE_TABLE_NAME = "hbase.table.name";
+ public static final String HBASE_TABLE_TIMESTAMP_FORMAT = "hbase.table.timestamp.format";
+ public static final String HBASE_CONFIGURATION_ZOOKEEPER_QUORUM = "hbase.zookeeper.quorum";
+ public static final String HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT = "hbase.zookeeper.property.clientPort";
+ public static final String HBASE_ZOOKEEPER_ZNODE_PARENT = "hbase.zookeeper.znode.parent";
+ public static final String ZOOKEEPER_ZNODE_PARENT = "zookeeper.znode.parent";
+
+ public static final int AAI_MAX_TRANS_RETRIES = 5;
+ public static final long AAI_TRANS_RETRY_SLEEP_MSEC = 500;
+
+ public static final int AAI_GROOMING_DEFAULT_MAX_FIX = 150;
+ public static final int AAI_GROOMING_DEFAULT_SLEEP_MINUTES = 7;
+
+ public static final String LOGGING_MAX_STACK_TRACE_ENTRIES = "aai.logging.maxStackTraceEntries";
+
+ /** Default to skipping real-time grooming unless system property aai.skiprealtime.grooming is set to "false" */
+ public static final String AAI_SKIPREALTIME_GROOMING = (System.getProperty("aai.skiprealtime.grooming") == null) ? "true" : System.getProperty("aai.skiprealtime.grooming");
+
+ /*** UEB ***/
+ public static final String UEB_PUB_PARTITION_AAI = "AAI";
+
+
+ /**
+ * Instantiates a new AAI constants.
+ */
+ private AAIConstants() {
+ // prevent instantiation
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIPrimaryHost.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIPrimaryHost.java
new file mode 100644
index 0000000..80fbbd3
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIPrimaryHost.java
@@ -0,0 +1,444 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+
+
+/**
+ * This class provides Logger methods for the AAI application
+ */
+
+public class AAIPrimaryHost {
+
+ protected static AAILogger aaiLogger = new AAILogger(AAIPrimaryHost.class.getName());
+ protected LogLine logline = new LogLine();
+ public EELFLogger logger;
+
+ private final String isReachable = new String("isReachable");
+ private final String binPing = new String("binPing");
+ private final String netcat = new String("netcat");
+ private final String echo = new String("echo");
+ private final String DEFAULT_CHECK = new String("aai.primary.filetransfer.");
+ private String transId = UUID.randomUUID().toString();
+ private String fromAppId = "AAI-INIT";
+
+
+ /**
+ * Instantiates a new AAI primary host.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ */
+ public AAIPrimaryHost(String transId, String fromAppId) {
+ this.fromAppId = fromAppId;
+ this.transId = transId;
+ }
+
+ /**
+ * Do command.
+ *
+ * @param command the command
+ * @return the int
+ * @throws Exception the exception
+ */
+ public int doCommand(List<String> command)
+ throws Exception
+ {
+ String s = null;
+
+ ProcessBuilder pb = new ProcessBuilder(command);
+ Process process = pb.start();
+
+ BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+
+ // read the output from the command
+ //System.out.println("Here is the standard output of the command:\n");
+ while ((s = stdInput.readLine()) != null)
+ {
+ //System.out.println(s);
+ aaiLogger.debug(logline, "stdout "+ s );
+ }
+
+ // read any errors from the attempted command
+ System.out.println("Here is the standard error of the command (if any):\n");
+ while ((s = stdError.readLine()) != null)
+ {
+ //System.out.println(s);
+ aaiLogger.debug(logline, "stderrbbbbbb "+ s );
+ }
+ return process.waitFor();
+ }
+
+
+
+ /**
+ * Method amIPrimary.
+ * @return boolean
+ */
+
+ public boolean amIPrimary()
+ {
+ return amIPrimary( DEFAULT_CHECK );
+ }
+
+ /**
+ * Am I primary using echo.
+ *
+ * @param hostname the hostname
+ * @param aaiPrimaryCheck the aai primary check
+ * @param aaiServerList the aai server list
+ * @return true, if successful
+ */
+ public boolean amIPrimaryUsingEcho( String hostname, String aaiPrimaryCheck, String aaiServerList) {
+
+ String methodName = "amIPrimaryUsingEcho";
+
+ logline.init("aaigen", transId, fromAppId, methodName);
+
+ StringTokenizer st = new StringTokenizer( aaiServerList, "|" );
+ String host;
+ String msg = null;
+ while ( st.hasMoreTokens() ) {
+ host = st.nextToken();
+
+ String portWithEndpoint = aaiPrimaryCheck.substring(aaiPrimaryCheck.indexOf(":"));
+ //System.out.println( "using portEndpoint: " + portWithEndpoint);
+ Client client = null;
+
+ try {
+ client = HttpsAuthClient.getTwoWaySSLClient();
+ }
+ catch (KeyManagementException kme){
+ msg = "KeyManagementException in REST call to echo: " + kme.toString();
+ } catch (Exception e) {
+ msg = " Exception in REST call to echo: " + e.toString();
+ }
+
+ if ( msg != null ) {
+ logline.add( "problem using echo " + msg + " no primary found ", aaiServerList );
+ aaiLogger.info(logline, false, "AAI_7401");
+ return false;
+ }
+ String resource = "https://" + host + portWithEndpoint;
+ WebResource webResource = client
+ .resource(resource);
+
+
+
+ try {
+ ClientResponse response = webResource.accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", "PrimaryCheck")
+ .get(ClientResponse.class);
+
+ String output = response.getEntity(String.class);
+
+ if (response.getStatus() != 200) {
+ aaiLogger.debug(logline, "echo status " + response.getStatus() + " echo response "+ output );
+ logline.add( "unexpected status ", response.getStatus() );
+ aaiLogger.info(logline, false, "AAI_7402");
+ } else {
+ aaiLogger.debug(logline, "echo response from server "+ output );
+ if ( host.contains(hostname)) {
+ return true;
+ }
+ return false;
+ }
+ } catch ( Exception e) {
+ logline.add( "exception checking primary ", resource );
+ aaiLogger.info(logline, false, "AAI_4000", e);
+ }
+ }
+ logline.add( "no primary found ", aaiServerList );
+ aaiLogger.info(logline, false, "AAI_4000");
+ return false;
+ }
+
+ /**
+ * Am I primary.
+ *
+ * @param checkName the check name
+ * @return true, if successful
+ */
+ public boolean amIPrimary(String checkName)
+ {
+ String methodName = "amIPrimary";
+
+ logline.init("aaigen", transId, fromAppId, methodName);
+ String aaiServerList = null;
+ String aaiPrimaryCheck = null;
+ String aaiPingTimeout = null;
+ String aaiPingCount = null;
+
+ int timeout = -1;
+
+ String msg = null;
+
+ try {
+
+ aaiServerList = AAIConfig.get(checkName + "serverlist");
+ //aaiPrimaryCheck = isReachable;
+ aaiPrimaryCheck = AAIConfig.get(checkName + "primarycheck");
+ //String aaiPingTimeout = "5000";
+ aaiPingTimeout = AAIConfig.get(checkName + "pingtimeout");
+ timeout = (new Integer(aaiPingTimeout)).intValue();
+ //aaiPingCount = "5";
+ aaiPingCount = AAIConfig.get(checkName + "pingcount");
+ } catch ( Exception e ) {
+ msg = "missing aaiconfig.properties for primary check, no check is done";
+ logline.add( "unable to check primary ", msg );
+ aaiLogger.info(logline, true, "0");
+ return true;
+ }
+
+ aaiLogger.debug(logline, "checking primary "+ aaiPrimaryCheck + " on " + aaiServerList + " timeout " + timeout );
+
+ InetAddress ip;
+ String hostname = null;
+
+ try {
+ ip = InetAddress.getLocalHost();
+ if ( ip != null ) {
+ hostname = ip.getHostName();
+ if ( hostname != null ) {
+ if ( !( aaiServerList.contains(hostname) ) )
+ msg = "host name not found in server list " + hostname;
+ } else
+ msg = "InetAddress returned null hostname";
+ }
+ } catch (UnknownHostException e) {
+
+ e.printStackTrace();
+ msg = "InetAddress getLocalHost exception " + e.getMessage();
+ }
+ if ( ( msg != null ) && !aaiPrimaryCheck.startsWith( "echo1") ) { //for unit testing
+ logline.add( "unable to check primary ", msg );
+ aaiLogger.info(logline, true, "0");
+ return true;
+ }
+
+ if (aaiPrimaryCheck.startsWith(echo)) {
+ return amIPrimaryUsingEcho( hostname, aaiPrimaryCheck, aaiServerList );
+ }
+ StringTokenizer st = new StringTokenizer( aaiServerList, "|" );
+ String host;
+ while ( st.hasMoreTokens() ) {
+ host = st.nextToken();
+ try {
+
+ if ( aaiPrimaryCheck.equals(isReachable)) {
+ ip = InetAddress.getByName(host);
+ if ( ip == null ) {
+ logline.add( "getByName failed ", host );
+ aaiLogger.info(logline, true, "0");
+ return true;
+ }
+ if ( ip.isReachable(timeout) ) {
+ aaiLogger.debug(logline, "primary is " + host );
+ if ( host.contains(hostname)) {
+ aaiLogger.info(logline, true, "0");
+ return true;
+ }
+ aaiLogger.info(logline, false, "AAI_4000");
+ return false;
+ } else {
+ aaiLogger.debug(logline, "isReachable false for "+ host );
+ }
+ } else if ( aaiPrimaryCheck.equals(binPing)) {
+ List<String> commands = new ArrayList<String>();
+ commands.add("/bin/ping");
+ commands.add("-c");
+ commands.add(aaiPingTimeout);
+ commands.add(host);
+ int pingResult = doCommand(commands);
+ if ( pingResult == 0 ) {
+ if ( host.contains(hostname)) {
+ aaiLogger.info(logline, true, "0");
+ return true;
+ }
+ aaiLogger.info(logline, false, "AAI_4000");
+ return false;
+ }else {
+ aaiLogger.debug(logline, "pingResult " + pingResult + "for "+ host );
+ }
+ } else if ( aaiPrimaryCheck.equals(netcat)) {
+ List<String> commands = new ArrayList<String>();
+ commands.add("/usr/bin/nc");
+ commands.add("-w");
+ commands.add(aaiPingCount); // seconds
+ commands.add(host);
+ commands.add("22"); // SCP port
+ int pingResult = doCommand(commands);
+ if ( pingResult == 0 ) {
+ if ( host.contains(hostname)) {
+ aaiLogger.info(logline, true, "0");
+ return true;
+ }
+ aaiLogger.info(logline, false, "AAI_4000");
+ return false;
+ }else {
+ aaiLogger.debug(logline, "netcat " + pingResult + "for "+ host );
+ }
+ }
+
+ } catch ( Exception e) {
+ e.printStackTrace();
+ msg = "processing serverList for host " + host + " exception " + e.getMessage();
+ logline.add( "no server found ", msg );
+ aaiLogger.info(logline, false, "AAI_4000");
+ return false;
+ }
+ }
+ logline.add( "no primary found ", aaiServerList );
+ aaiLogger.info(logline, false, "AAI_4000");
+ return false;
+ }
+
+ /**
+ * Which is primary.
+ *
+ * @return the string
+ */
+ public String whichIsPrimary()
+ {
+ return whichIsPrimary( DEFAULT_CHECK );
+ }
+
+ /**
+ * Which is primary using echo.
+ *
+ * @param aaiPrimaryCheck the aai primary check
+ * @param aaiServerList the aai server list
+ * @return the string
+ */
+ public String whichIsPrimaryUsingEcho( String aaiPrimaryCheck, String aaiServerList) {
+
+ String methodName = "whichIsPrimaryUsingEcho";
+
+ logline.init("aaigen", transId, fromAppId, methodName);
+
+ StringTokenizer st = new StringTokenizer( aaiServerList, "|" );
+ String host;
+ String msg = null;
+ while ( st.hasMoreTokens() ) {
+ host = st.nextToken();
+
+ String portWithEndpoint = aaiPrimaryCheck.substring(aaiPrimaryCheck.indexOf(":"));
+ //System.out.println( "using portEndpoint: " + portWithEndpoint);
+ Client client = null;
+
+ try {
+ client = HttpsAuthClient.getTwoWaySSLClient();
+ }
+ catch (KeyManagementException kme){
+ msg = "KeyManagementException in REST call to echo: " + kme.toString();
+ } catch (Exception e) {
+ msg = " Exception in REST call to echo: " + e.toString();
+ }
+
+ if ( msg != null ) {
+ logline.add( "problem using echo " + msg + " no primary found ", aaiServerList );
+ aaiLogger.info(logline, false, "AAI_7401");
+ return null;
+ }
+ String resource = "https://" + host + portWithEndpoint;
+ WebResource webResource = client
+ .resource(resource);
+
+ try {
+ ClientResponse response = webResource.accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", "PrimaryCheck")
+ .get(ClientResponse.class);
+ String output = response.getEntity(String.class);
+ if (response.getStatus() != 200) {
+ aaiLogger.debug(logline, "echo status " + response.getStatus() + " echo response "+ output );
+ logline.add( "unexpected status ", response.getStatus() );
+ aaiLogger.info(logline, false, "AAI_7402");
+ } else {
+ return host;
+ }
+ } catch ( Exception e ) {
+ logline.add( "exception checking primary ", resource );
+ aaiLogger.info(logline, false, "AAI_4000", e);
+ }
+ }
+ logline.add( "no primary found ", aaiServerList );
+ aaiLogger.info(logline, false, "AAI_4000");
+ return null;
+ }
+
+ /**
+ * Which is primary.
+ *
+ * @param checkName the check name
+ * @return the string
+ */
+ public String whichIsPrimary( String checkName )
+ {
+ String methodName = "whichIsPrimary";
+
+ logline.init("aaigen", transId, fromAppId, methodName);
+ String aaiServerList = null;
+ String aaiPrimaryCheck = null;
+ String aaiPingTimeout = null;
+ String aaiPingCount = null;
+
+ int timeout = -1;
+
+ String msg = null;
+
+ try {
+
+ aaiServerList = AAIConfig.get(checkName + "serverlist");
+ aaiPrimaryCheck = AAIConfig.get(checkName + "primarycheck");
+
+ } catch ( Exception e ) {
+ msg = "missing aaiconfig.properties to find primary, returning";
+ logline.add( "unable to find primary ", msg );
+ aaiLogger.info(logline, true, "0");
+ return null;
+ }
+
+ aaiLogger.debug(logline, "finding primary "+ aaiPrimaryCheck + " on " + aaiServerList + " timeout " + timeout );
+
+ return whichIsPrimaryUsingEcho( aaiPrimaryCheck, aaiServerList );
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIRSyncUtility.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIRSyncUtility.java
new file mode 100644
index 0000000..7c36ee6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIRSyncUtility.java
@@ -0,0 +1,224 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ */
+package org.openecomp.aai.util;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.eelf.configuration.EELFLogger;
+
+
+public class AAIRSyncUtility {
+
+ protected static AAILogger aaiLogger = new AAILogger(AAIRSyncUtility.class.getName());
+ protected LogLine logline = new LogLine();
+ public EELFLogger logger;
+
+ private final String DEFAULT_CHECK = new String("aai.primary.filetransfer.");
+
+ /**
+ * Instantiates a new AAIR sync utility.
+ */
+ public AAIRSyncUtility() {
+
+ }
+
+ /**
+ * Do command.
+ *
+ * @param command the command
+ * @return the int
+ * @throws Exception the exception
+ */
+ public int doCommand(List<String> command)
+ throws Exception
+ {
+ String s = null;
+
+ ProcessBuilder pb = new ProcessBuilder(command);
+ Process process = pb.start();
+
+ BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+
+ // read the output from the command
+ //System.out.println("Here is the standard output of the command:\n");
+ while ((s = stdInput.readLine()) != null)
+ {
+ //System.out.println(s);
+ aaiLogger.debug(logline, "stdout "+ s );
+ }
+
+ // read any errors from the attempted command
+ System.out.println("Here is the standard error of the command (if any):\n");
+ while ((s = stdError.readLine()) != null)
+ {
+ //System.out.println(s);
+ aaiLogger.debug(logline, "stderrbbbbbb "+ s );
+ }
+ return process.waitFor();
+ }
+
+
+ /**
+ * Method sendRsyncCommand.
+ *
+ * @param transId the trans id
+ * @param fileName the file name
+ */
+ public void sendRsyncCommand(String transId, String fileName)
+ {
+ String methodName = "sendRsyncCommand";
+
+ logline.init("aaigen", transId, "AAI-Tools", methodName);
+ String aaiServerList = null;
+ String rsyncOptionsList = null;
+ String msg = null;
+
+ try {
+
+ aaiServerList = AAIConfig.get(DEFAULT_CHECK + "serverlist");
+ rsyncOptionsList = AAIConfig.get("aai.rsync.options.list");
+ String enableRsync = AAIConfig.get("aai.rsync.enabled");
+
+ if (!AAIConfig.isEmpty(enableRsync) && "n".equalsIgnoreCase(enableRsync)){
+ msg = " rsync is not enabled in aaiconfig.properties ";
+ logline.add( "rsync not invoked for "+fileName, msg );
+ aaiLogger.info(logline, true, "0");
+ return;
+ }
+ } catch ( Exception e ) {
+ msg = "missing aaiconfig.properties entries for rsync";
+ logline.add( "rsync not invoked ", msg );
+ aaiLogger.info(logline, true, "0");
+ }
+
+ aaiLogger.debug(logline, "rsync to copy files started....");
+
+ ArrayList<String> remoteHostList = new ArrayList<String>();
+ StringTokenizer serverList = new StringTokenizer( aaiServerList, "|" );
+ String host = null;
+ try {
+ host = getHost();
+ String remoteConnString = null;
+
+ remoteHostList = getRemoteHostList(serverList, host);
+ aaiLogger.debug(logline, " this host:" + host);
+ String pickUpDirectory = AAIConfig.get("instar.pickup.dir");
+ String user = AAIConfig.get("aai.rsync.remote.user");
+ String rsyncCmd = AAIConfig.get("aai.rsync.command");
+
+ //Push: rsync [OPTION...] SRC... [USER@]HOST:DEST
+
+ java.util.Iterator<String> remoteHostItr = remoteHostList.iterator();
+ while (!remoteHostList.isEmpty() && remoteHostItr.hasNext()) {
+ String remoteHost = remoteHostItr.next();
+ remoteConnString =user+"@"+remoteHost+":"+pickUpDirectory;
+
+ List<String> commands = new ArrayList<String>();
+ commands.add(rsyncCmd);
+ StringTokenizer optionTks = new StringTokenizer( rsyncOptionsList, "|" );
+ while (optionTks.hasMoreTokens()){
+ commands.add(optionTks.nextToken());
+ }
+ commands.add(fileName); // src directory/fileName
+ commands.add(remoteConnString); // target username/host/path
+ aaiLogger.debug(logline, commands.toString());
+ int rsyncResult = doCommand(commands);
+ if ( rsyncResult == 0 ) {
+ aaiLogger.debug(logline, "rsync completed for "+remoteHost);
+ }else {
+ aaiLogger.debug(logline, "rsync failed for "+ remoteHost+ " with response code "+rsyncResult );
+ }
+ }
+ } catch ( Exception e) {
+ e.printStackTrace();
+ msg = "processing serverList for host " + host + " exception " + e.getMessage();
+ logline.add( "no server found ", msg );
+ aaiLogger.info(logline, false, "AAI_4000");
+ }
+ aaiLogger.info(logline, true, "0");
+ }
+
+ /**
+ * Gets the remote host list.
+ *
+ * @param serverList the server list
+ * @param host the host
+ * @return the remote host list
+ */
+ private ArrayList<String> getRemoteHostList(StringTokenizer serverList, String host) {
+ ArrayList<String> remoteHostList = new ArrayList<String>();
+ String remoteHost = null;
+ while ( serverList.hasMoreTokens() ) {
+ remoteHost = serverList.nextToken();
+ if (!host.equalsIgnoreCase(remoteHost)){
+ remoteHostList.add(remoteHost);
+ }
+ }
+ return remoteHostList;
+ }
+
+ /**
+ * Gets the host.
+ *
+ * @return the host
+ * @throws AAIException the AAI exception
+ */
+ private String getHost() throws AAIException {
+ String aaiServerList = AAIConfig.get(DEFAULT_CHECK + "serverlist");
+ String msg = null;
+ String hostname = null;
+ try {
+ InetAddress ip = InetAddress.getLocalHost();
+ if ( ip != null ) {
+ hostname = ip.getHostName();
+ if ( hostname != null ) {
+ if ( !( aaiServerList.contains(hostname) ) )
+ msg = "host name not found in server list " + hostname;
+ } else
+ msg = "InetAddress returned null hostname";
+ }
+
+ } catch (UnknownHostException e) {
+ msg = "InetAddress getLocalHost exception " + e.getMessage();
+ aaiLogger.debug(logline, msg);
+ }
+ if ( msg != null ) {
+ aaiLogger.info(logline, true, "0");
+ }
+ return hostname;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAITxnLog.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAITxnLog.java
new file mode 100644
index 0000000..64a38a4
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAITxnLog.java
@@ -0,0 +1,563 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+/*
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.ConnectionUtils;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HConnection;
+import org.apache.hadoop.hbase.client.HConnectionManager;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.util.Bytes;
+ */
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.openecomp.aai.domain.notificationEvent.NotificationEvent;
+import org.openecomp.aai.domain.translog.TransactionLogEntries;
+import org.openecomp.aai.domain.translog.TransactionLogEntry;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+
+public class AAITxnLog {
+
+ private static final String COMPONENT = "aaitxnlog";
+ protected static AAILogger aaiLogger = new AAILogger(AAITxnLog.class.getName());
+ protected LogLine logline = new LogLine();
+
+ private org.apache.hadoop.conf.Configuration config = null;
+ private HTable table = null;
+ private String tm = null;
+
+ /**
+ * Instantiates a new AAI txn log.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ */
+ public AAITxnLog(String transId, String fromAppId) {
+ try {
+ /* When you create a HBaseConfiguration, it reads in whatever you've set
+ into your hbase-site.xml and in hbase-default.xml, as long as these can
+ be found on the CLASSPATH */
+ logline.init(COMPONENT, transId, fromAppId, "AAITxnLog() constructor");
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ tm = formatter.format(date);
+
+ config = HBaseConfiguration.create();
+
+ //org.apache.hadoop.conf.Configuration config = new org.apache.hadoop.conf.Configuration();
+ //config = HBaseConfiguration.create();
+
+ if (config == null) {
+ aaiLogger.debug(logline, "AAITxnLog: Default Constructor: can't create HBase configuration");
+ return;
+ }
+
+ config.set(AAIConstants.ZOOKEEPER_ZNODE_PARENT, AAIConfig.get(AAIConstants.HBASE_ZOOKEEPER_ZNODE_PARENT));
+ config.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM, AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM));
+ config.set(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT, AAIConfig.get(AAIConstants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT));
+
+ /*
+ InputStream confResourceAsInputStream = config.getConfResourceAsInputStream("hbase-site.xml");
+ int available = 0;
+ try {
+ available = confResourceAsInputStream.available();
+ } catch (Exception e) {
+ //for debug purpose
+ System.out.println("configuration files not found locally");
+ } finally {
+ IOUtils.closeQuietly(confResourceAsInputStream);
+ }
+
+ System.out.println("available="+available);
+
+ if (available == 0 ) {
+ config.addResource("core-site.xml");
+ config.addResource("./hbase-site.xml");
+ config.addResource("hdfs-site.xml");
+ }
+ */
+
+ /*This instantiates an HTable object that connects you to the "test" table*/
+ //HConnection connection = HConnectionManager.createConnection(config);
+
+ //HTableInterface table = connection.getTable(TableName.valueOf("aai_props"));
+ aaiLogger.info(logline, true, "0");
+
+ } catch (Exception e) {
+ aaiLogger.debug(logline, "AAITxnLog: Default Constructor: Exception=" + e.toString());
+ aaiLogger.info(logline, false, "AAI_4000");
+ }
+ }
+
+ /**
+ * Put.
+ *
+ * @param status the status
+ * @param srcId the src id
+ * @param rsrcId the rsrc id
+ * @param rsrcType the rsrc type
+ * @param rqstBuf the rqst buf
+ * @param respBuf the resp buf
+ * @return the string
+ */
+ public String put(
+ String status,
+ String srcId,
+ String rsrcId,
+ String rsrcType,
+ String rqstBuf,
+ String respBuf
+ ) {
+ return put ("",status,"","",srcId,rsrcId,rsrcType,rqstBuf,respBuf,false,new NotificationEvent());
+
+ }
+
+ /**
+ * Put.
+ *
+ * @param tid the tid
+ * @param status the status
+ * @param srcId the src id
+ * @param rsrcId the rsrc id
+ * @param rsrcType the rsrc type
+ * @param rqstBuf the rqst buf
+ * @param respBuf the resp buf
+ * @return the string
+ */
+ public String put(
+ String tid,
+ String status,
+ String srcId,
+ String rsrcId,
+ String rsrcType,
+ String rqstBuf,
+ String respBuf
+ ) {
+ return put (tid,status,"","",srcId,rsrcId,rsrcType,rqstBuf,respBuf,false,new NotificationEvent());
+ }
+
+ /**
+ * Put.
+ *
+ * @param tid the tid
+ * @param status the status
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param srcId the src id
+ * @param rsrcId the rsrc id
+ * @param rsrcType the rsrc type
+ * @param rqstBuf the rqst buf
+ * @param respBuf the resp buf
+ * @return the string
+ */
+ public String put(
+ String tid,
+ String status,
+ String rqstTm,
+ String respTm,
+ String srcId,
+ String rsrcId,
+ String rsrcType,
+ String rqstBuf,
+ String respBuf
+ ) {
+ return put (tid,status,"","",srcId,rsrcId,rsrcType,rqstBuf,respBuf,false,new NotificationEvent());
+ }
+
+ /**
+ * Put.
+ *
+ * @param tid the tid
+ * @param status the status
+ * @param rqstTm the rqst tm
+ * @param respTm the resp tm
+ * @param srcId the src id
+ * @param rsrcId the rsrc id
+ * @param rsrcType the rsrc type
+ * @param rqstBuf the rqst buf
+ * @param respBuf the resp buf
+ * @param hasNotificationEvent the has notification event
+ * @param ne the ne
+ * @return the string
+ */
+ public String put(
+ String tid,
+ String status,
+ String rqstTm,
+ String respTm,
+ String srcId,
+ String rsrcId,
+ String rsrcType,
+ String rqstBuf,
+ String respBuf,
+ boolean hasNotificationEvent,
+ NotificationEvent ne
+ ) {
+ logline.init(COMPONENT, tid, srcId, "put()");
+ //FINEGRAINaaiLogger.debug(logline, "In put: storing hbase config file...");
+
+ if (tid == null || "".equals(tid)) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (Exception e) {
+ formatter = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS");
+ }
+ tm = formatter.format(date);
+ tid = tm + "-";
+ }
+ // String htid = tid + rsrcType; // orig
+ // String htid = tid + srcId; //final version?
+ String htid = tid;// + srcId + "_" + rsrcType; // use this one for now
+ //FINEGRAINaaiLogger.debug(logline, "In put...: htid="+htid);
+ //FINEGRAINaaiLogger.debug(logline, "tid: " + tid + ", srcId: " + srcId + " rsrcType: " + rsrcType);
+
+ //need to add a prefix for better hbase logging server balancing
+ htid = HbaseSaltPrefixer.getInstance().prependSalt(htid);
+
+ if (rqstTm == null || "".equals(rqstTm)) {
+ rqstTm = tm;
+ }
+
+ if (respTm == null || "".equals(respTm)) {
+ respTm = tm;
+ }
+
+ try {
+ table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME));
+
+ Put p = new Put(Bytes.toBytes(htid));
+
+ p.add(Bytes.toBytes("transaction"),Bytes.toBytes("tid"),Bytes.toBytes(tid));
+ p.add(Bytes.toBytes("transaction"),Bytes.toBytes("status"),Bytes.toBytes(status));
+ p.add(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate"),Bytes.toBytes(rqstTm));
+ p.add(Bytes.toBytes("transaction"),Bytes.toBytes("respDate"),Bytes.toBytes(respTm));
+ p.add(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId"),Bytes.toBytes(srcId));
+
+ p.add(Bytes.toBytes("resource"),Bytes.toBytes("resourceId"),Bytes.toBytes(rsrcId));
+ p.add(Bytes.toBytes("resource"),Bytes.toBytes("resourceType"),Bytes.toBytes(rsrcType));
+
+ p.add(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf"),Bytes.toBytes(rqstBuf));
+ p.add(Bytes.toBytes("payload"),Bytes.toBytes("respBuf"),Bytes.toBytes(respBuf));
+
+ /* Once you've adorned your Put instance with all the updates you want to
+ make, to commit it do the following */
+ table.put(p);
+ table.flushCommits();
+ table.close();
+ aaiLogger.info(logline, true, "0");
+ return htid;
+ } catch (Exception e) {
+ aaiLogger.debug(logline, "AAITxnLog: put: Exception=", e);
+ aaiLogger.info(logline, false, "AAI_4000");
+ return htid;
+ }
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param htid the htid
+ * @return the transaction log entry
+ * @throws AAIException the AAI exception
+ */
+ public TransactionLogEntry get(String htid) throws AAIException {
+
+ logline.init(COMPONENT, htid, "aaiInternal", "get()");
+ aaiLogger.debug(logline, "In get: searching hbase config file...");
+ String tidStr = "";
+ TransactionLogEntry txObj = new TransactionLogEntry();
+
+ try {
+ table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME));
+
+ Get g = new Get(Bytes.toBytes(htid));
+
+ Result r = table.get(g);
+ byte [] tid = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("tid"));
+ byte [] status = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("status"));
+ byte [] rqstDate = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate"));
+ byte [] respDate = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("respDate"));
+ byte [] sourceId = r.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId"));
+
+ byte [] resourceId = r.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceId"));
+ byte [] resourceType = r.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceType"));
+
+ byte [] rqstBuf = r.getValue(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf"));
+ byte [] respBuf = r.getValue(Bytes.toBytes("payload"),Bytes.toBytes("respBuf"));
+
+ byte [] notificationPayload = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationPayload"));
+ byte [] notificationStatus = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationStatus"));
+ byte [] notificationId = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationId"));
+ byte [] notificationTopic = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationTopic"));
+ byte [] notificationEntityLink = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationEntityLink"));
+ byte [] notificationAction = r.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationAction"));
+ // TODO: if tx logging in on, we're going to duplicate this, do we want to?
+// aaiLogger.debug(logline, "AAITxnLog: got row=" +
+// tidStr + "|" +
+// Bytes.toString(status) + "|" +
+// Bytes.toString(rqstDate) + "|" +
+// Bytes.toString(respDate) + "|" +
+// Bytes.toString(sourceId) + "|" +
+// Bytes.toString(resourceId) + "|" +
+// Bytes.toString(resourceType) + "|" +
+// Bytes.toString(rqstBuf) + "|" +
+// Bytes.toString(respBuf));
+
+ table.close();
+
+ tidStr = Bytes.toString(tid);
+ txObj.setTransactionLogEntryId(tidStr);
+ txObj.setStatus(Bytes.toString(status));
+ txObj.setRqstDate(Bytes.toString(rqstDate));
+ txObj.setRespDate(Bytes.toString(respDate));
+ txObj.setSourceId(Bytes.toString(sourceId));
+ txObj.setResourceId(Bytes.toString(resourceId));
+ txObj.setResourceType(Bytes.toString(resourceType));
+ txObj.setRqstBuf(Bytes.toString(rqstBuf));
+ txObj.setrespBuf(Bytes.toString(respBuf));
+ txObj.setNotificationPayload(Bytes.toString(notificationPayload));
+ txObj.setNotificationStatus(Bytes.toString(notificationStatus));
+ txObj.setNotificationId(Bytes.toString(notificationId));
+ txObj.setNotificationTopic(Bytes.toString(notificationTopic));
+ txObj.setNotificationEntityLink(Bytes.toString(notificationEntityLink));
+ txObj.setNotificationAction(Bytes.toString(notificationAction));
+ } catch (IOException e) {
+ aaiLogger.debug(logline, "IOException on hbase call", e);
+ throw new AAIException("AAI_4000");
+ }
+
+ return txObj;
+ }
+
+
+ /**
+ * Scan filtered.
+ *
+ * @param startMillis the start millis
+ * @param endMillis the end millis
+ * @param methodList the method list
+ * @param putFilter the put filter
+ * @param getFilter the get filter
+ * @param resourceFilter the resource filter
+ * @param fromAppIdFilter the from app id filter
+ * @return the transaction log entries
+ */
+ public TransactionLogEntries scanFiltered(long startMillis, long endMillis, List<String> methodList,
+ String putFilter, String getFilter, String resourceFilter, String fromAppIdFilter) {
+
+ logline.init(COMPONENT, "scanFiltered", "aaiInternal", "scanFiltered()");
+ aaiLogger.debug(logline, "Starting scanFiltered()");
+
+ // we should have the config ready from the constructor
+
+ TransactionLogEntries txs = new TransactionLogEntries();
+
+ if (config == null) {
+ aaiLogger.debug(logline, "in scan: can't create HBase configuration");
+ return txs;
+ }
+
+ try {
+ table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME));
+ //Scan s = new Scan();
+ //s.addColumn(Bytes.toBytes("transaction"), Bytes.toBytes("tid"));
+ //s.addColumn(Bytes.toBytes("payload"), Bytes.toBytes("rqstBuf"));
+ Scan s = new Scan();
+ FilterList flMaster = new FilterList(FilterList.Operator.MUST_PASS_ALL);
+ FilterList methodflMaster = new FilterList(FilterList.Operator.MUST_PASS_ONE);
+ if (methodList != null) {
+ for (String method : methodList) {
+ Filter filt = new SingleColumnValueFilter(Bytes.toBytes("resource"),
+ Bytes.toBytes("resourceType"), CompareOp.EQUAL, Bytes.toBytes(method));
+ methodflMaster.addFilter(filt);
+ }
+ flMaster.addFilter(methodflMaster);
+ }
+
+ if (getFilter != null) {
+ Filter filt = new SingleColumnValueFilter(Bytes.toBytes("payload"),
+ Bytes.toBytes("respBuf"), CompareOp.EQUAL, new RegexStringComparator(getFilter));
+ flMaster.addFilter(filt);
+ }
+ if (putFilter != null) {
+ Filter filt = new SingleColumnValueFilter(Bytes.toBytes("payload"),
+ Bytes.toBytes("rqstBuf"), CompareOp.EQUAL, new RegexStringComparator(putFilter));
+ flMaster.addFilter(filt);
+ }
+ if (resourceFilter != null) {
+ Filter filt = new SingleColumnValueFilter(Bytes.toBytes("resource"),
+ Bytes.toBytes("resourceId"), CompareOp.EQUAL, new RegexStringComparator(resourceFilter));
+ flMaster.addFilter(filt);
+ }
+ if (fromAppIdFilter != null) {
+ Filter filt = new SingleColumnValueFilter(Bytes.toBytes("transaction"),
+ Bytes.toBytes("sourceId"), CompareOp.EQUAL, new RegexStringComparator("^" + fromAppIdFilter));
+ flMaster.addFilter(filt);
+ }
+
+ if (flMaster.hasFilterRow()) {
+ s.setFilter(flMaster);
+ }
+
+ s.setTimeRange(startMillis, endMillis);
+ ResultScanner scanner = table.getScanner(s);
+
+ try {
+ for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
+
+ byte [] tid = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("tid"));
+ byte [] status = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("status"));
+ byte [] rqstDate = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate"));
+ byte [] respDate = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("respDate"));
+ byte [] sourceId = rr.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId"));
+
+ byte [] resourceId = rr.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceId"));
+ byte [] resourceType = rr.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceType"));
+
+ byte [] rqstBuf = rr.getValue(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf"));
+ byte [] respBuf = rr.getValue(Bytes.toBytes("payload"),Bytes.toBytes("respBuf"));
+
+ byte [] notificationPayload = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationPayload"));
+ byte [] notificationStatus = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationStatus"));
+ byte [] notificationId = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationId"));
+ byte [] notificationTopic = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationTopic"));
+ byte [] notificationEntityLink = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationEntityLink"));
+ byte [] notificationAction = rr.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationAction"));
+ TransactionLogEntry txObj = new TransactionLogEntry();
+ String tidStr = Bytes.toString(tid);
+ txObj.setTransactionLogEntryId(tidStr);
+ txObj.setStatus(Bytes.toString(status));
+ txObj.setRqstDate(Bytes.toString(rqstDate));
+ txObj.setRespDate(Bytes.toString(respDate));
+ txObj.setSourceId(Bytes.toString(sourceId));
+ txObj.setResourceId(Bytes.toString(resourceId));
+ txObj.setResourceType(Bytes.toString(resourceType));
+ txObj.setRqstBuf(Bytes.toString(rqstBuf));
+ txObj.setrespBuf(Bytes.toString(respBuf));
+ txObj.setNotificationPayload(Bytes.toString(notificationPayload));
+ txObj.setNotificationStatus(Bytes.toString(notificationStatus));
+ txObj.setNotificationId(Bytes.toString(notificationId));
+ txObj.setNotificationTopic(Bytes.toString(notificationTopic));
+ txObj.setNotificationEntityLink(Bytes.toString(notificationEntityLink));
+ txObj.setNotificationAction(Bytes.toString(notificationAction));
+ txs.getTransactionLogEntries().add(txObj);
+ }
+ } finally {
+ // Make sure you close your scanners when you are done!
+ scanner.close();
+ }
+ table.close();
+ } catch (Exception e) {
+ aaiLogger.debug(logline, "AAITxnLog: scan: Exception=" + e.toString());
+ }
+
+ return txs;
+ }
+
+ /**
+ * Scan.
+ *
+ * @param htid the htid
+ * @return the list
+ */
+ public List<String> scan(String htid) {
+
+ List<String> list = new ArrayList<String>();
+ logline.init(COMPONENT, htid, "aaiInternal", "scan()");
+ aaiLogger.debug(logline, "In scan: searching hbase config file...");
+ // we should have the config ready from the constructor
+ if (config == null) {
+ aaiLogger.debug(logline, "in scan: can't create HBase configuration");
+ return list;
+ }
+
+ try {
+ table = new HTable(config, AAIConfig.get(AAIConstants.HBASE_TABLE_NAME));
+ //Scan s = new Scan();
+ //s.addColumn(Bytes.toBytes("transaction"), Bytes.toBytes("tid"));
+ //s.addColumn(Bytes.toBytes("payload"), Bytes.toBytes("rqstBuf"));
+ Scan s = new Scan(Bytes.toBytes(htid));
+ ResultScanner scanner = table.getScanner(s);
+
+ try {
+ for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
+ list.add(rr.toString());
+ aaiLogger.debug(logline, "in scan: Found row : " + rr);
+
+ }
+ } finally {
+ // Make sure you close your scanners when you are done!
+ scanner.close();
+ }
+ table.close();
+ } catch (Exception e) {
+
+ aaiLogger.debug(logline, "AAITxnLog: scan: Exception=" + e.toString());
+ }
+ return list;
+ }
+
+}
+
+/*
+Need to implement HBase Connection Pooling in the future.
+This is to reduce the 1 second delay during the first open of HConnection, and HTable instantiation.
+Hbase provides the Hconnection class and the HConnectionManager class.
+Both provifde the functionaltity similar to jdbc connection pooling
+to share pre-existing opened connections.
+Here we should be able to use the getTable() method to get a
+reference to an HTable instance.
+
+ */
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIUtils.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIUtils.java
new file mode 100644
index 0000000..9c1602d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/AAIUtils.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class AAIUtils {
+
+ /**
+ * Null check.
+ *
+ * @param <T> the generic type
+ * @param iterable the iterable
+ * @return the iterable
+ */
+ public static <T> Iterable<T> nullCheck(Iterable<T> iterable) {
+ return iterable == null ? Collections.<T>emptyList() : iterable;
+ }
+
+ /**
+ * Gen date.
+ *
+ * @return the string
+ */
+ public static String genDate() {
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
+ return formatter.format(date);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/CNName.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/CNName.java
new file mode 100644
index 0000000..11de8ad
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/CNName.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+
+import ch.qos.logback.access.pattern.AccessConverter;
+import ch.qos.logback.access.spi.IAccessEvent;
+
+import static java.util.Base64.getDecoder;
+
+public class CNName extends AccessConverter {
+
+ /**
+ * Converts access events to String response codes
+ *
+ * @param accessEvent the IAccessEvent
+ */
+ public String convert(IAccessEvent accessEvent) {
+ if (!isStarted()) {
+ return "INACTIVE_HEADER_CONV";
+ }
+
+ String cipherSuite = (String) accessEvent.getRequest().getAttribute("javax.servlet.request.cipher_suite");
+ String authUser = null;
+ if (cipherSuite != null) {
+ try {
+ X509Certificate certChain[] = (X509Certificate[]) accessEvent.getRequest()
+ .getAttribute("javax.servlet.request.X509Certificate");
+ if(certChain == null || certChain.length == 0){
+
+ HttpServletRequest request = accessEvent.getRequest();
+
+ String authorization = request.getHeader("Authorization");
+
+ // Set the auth user to "-" so if the authorization header is not found
+ // Or if the decoded basic auth credentials are not found in the format required
+ // it should return "-"
+ // If the decoded string is in the right format, find the index of ":"
+ // Then get the substring of the starting point to the colon not including the colon
+
+ authUser = "-";
+
+ if(authorization != null && authorization.startsWith("Basic ")){
+ String credentials = authorization.replace("Basic ", "");
+ byte[] userCredentials = getDecoder().decode(credentials.getBytes("utf-8"));
+ credentials = new String(userCredentials);
+
+ int codePoint = credentials.indexOf(':');
+
+ if(codePoint != -1){
+ authUser = credentials.substring(0, codePoint);
+ }
+
+ }
+
+ return authUser;
+
+ } else {
+ X509Certificate clientCert = certChain[0];
+ X500Principal subjectDN = clientCert.getSubjectX500Principal();
+ authUser = subjectDN.toString();
+ return authUser;
+ }
+ } catch(Exception ex){
+ return "-";
+ }
+ } else {
+ return "-";
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayout.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayout.java
new file mode 100644
index 0000000..b9e767f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayout.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+public class CustomLogPatternLayout extends ch.qos.logback.access.PatternLayout {
+ static {
+ defaultConverterMap.put("z", CNName.class.getName());
+ defaultConverterMap.put("y", DME2RestFlag.class.getName());
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayoutEncoder.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayoutEncoder.java
new file mode 100644
index 0000000..79a9c62
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayoutEncoder.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import ch.qos.logback.access.PatternLayout;
+
+public class CustomLogPatternLayoutEncoder extends ch.qos.logback.access.PatternLayoutEncoder {
+
+/**
+ * @{inheritDoc}
+ */
+ @Override
+ public void start(){
+ PatternLayout patternLayout = new CustomLogPatternLayout();
+ patternLayout.setContext(context);
+ patternLayout.setPattern(getPattern());
+ patternLayout.start();
+ this.layout = patternLayout;
+ super.start();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/DME2RestFlag.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/DME2RestFlag.java
new file mode 100644
index 0000000..231768d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/DME2RestFlag.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import ch.qos.logback.access.pattern.AccessConverter;
+import ch.qos.logback.access.spi.IAccessEvent;
+
+public class DME2RestFlag extends AccessConverter {
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public String convert(IAccessEvent accessEvent) {
+ if (!isStarted()) {
+ return "INACTIVE_HEADER_CONV";
+ }
+
+ String flag = "-";
+
+ if (accessEvent.getRequestParameter("envContext").length > 0
+ && !accessEvent.getRequestParameter("envContext")[0].isEmpty()
+ && !accessEvent.getRequestParameter("envContext")[0].equals("-")
+ && accessEvent.getRequestParameter("routeOffer").length > 0
+ && !accessEvent.getRequestParameter("routeOffer")[0].isEmpty()
+ && !accessEvent.getRequestParameter("routeOffer")[0].equals("-")
+ && accessEvent.getRequestParameter("version").length > 0
+ && !accessEvent.getRequestParameter("version")[0].isEmpty()
+ && !accessEvent.getRequestParameter("version")[0].equals("-")) {
+ flag = "DME2";
+ } else {
+ flag = "REST";
+ }
+
+ return flag;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/DataConversionHelper.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/DataConversionHelper.java
new file mode 100644
index 0000000..c1d601d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/DataConversionHelper.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+
+/**
+ * Utility to convert data from one form to another
+ *
+ */
+public class DataConversionHelper {
+
+ public static final String IPVERSION_IPV4 = "ipv4";
+ public static final String IPVERSION_IPV6 = "ipv6";
+ public static final String IPVERSION_UNKNOWN = "unknown";
+
+ /**
+ * Instantiates a new data conversion helper.
+ */
+ public DataConversionHelper() { }
+
+ /**
+ * Convert from 4 or 6 to ipv4 or ipv6. Returns unknown if 4 or 6 not passed.
+ * @param numVal expects good input but won't error if that's not what's passed
+ * @return IPVERSION constant, .
+ * @see org.openecomp.aai.domain.yang.IpVersion
+ */
+ public static String convertIPVersionNumToString(String numVal) {
+ if ("4".equals(numVal)) return IPVERSION_IPV4;
+ else if ("6".equals(numVal))return IPVERSION_IPV6;
+ else return IPVERSION_UNKNOWN;
+ }
+
+ /**
+ * Convert from ipv4 or ipv6 to 4 or 6. Returns 0 on bad input.
+ * @param stringVal expects good input but won't error if that's not what's passed
+ * @return 4 or 6, or 0 if a bad string is sent.
+ * @see org.openecomp.aai.domain.yang.IpVersion
+ */
+ public static String convertIPVersionStringToNum(String stringVal) {
+ if (IPVERSION_IPV4.equals(stringVal)) return "4";
+ else if (IPVERSION_IPV6.equals(stringVal)) return "6";
+ else return "0";
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/DeleteResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/DeleteResource.java
new file mode 100644
index 0000000..07024d9
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/DeleteResource.java
@@ -0,0 +1,302 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.UUID;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.eelf.configuration.Configuration;
+import com.google.common.base.CaseFormat;
+
+
+public class DeleteResource {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAI-TOOLS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ // the logic below to parse the url is dependent on the node types
+ // code may need to be adjusted if different nodetypes are added here
+ private static final String[] nodeTypeList = {"complex", "availability-zone", "oam-network",
+ "dvs-switch", "vserver", "vpe", "vpls-pe"};
+
+ private static final String USAGE_STRING = "Usage: deleteTool.sh <resource-path> \n + "
+ + "for example: resource-path for a particular customer is business/customers/customer/global-customer-id-1 \n";
+
+ /**
+ * The main method.
+ *
+ * @param <T> the generic type
+ * @param args the arguments
+ */
+ public static <T> void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_DELTOOL_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(DeleteResource.class.getName());
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+ String url = null;
+ try {
+ if ((args.length < 1) ) {
+ System.out.println("Insufficient or Invalid arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient or Invalid arguments");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7403"), logline, null);
+ aaiLogger.info(logline, false, "AAI_7403");
+ System.exit(1);
+ }
+
+ Boolean bResVersionEnabled = false;
+
+ try
+ {
+ String strEnableResVersion = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
+ if (strEnableResVersion != null && !strEnableResVersion.isEmpty())
+ bResVersionEnabled = Boolean.valueOf(strEnableResVersion);
+ }
+ catch (Exception e) {
+
+ }
+
+ // Assume the config AAI_SERVER_URL has a last slash so remove if
+ // resource-path has it as the first char
+ String path = args[0].replaceFirst("^/", "");
+ //url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+
+ Path p = Paths.get(path);
+
+ // if the node type has one key
+ String resource = p.getName(p.getNameCount() - 2).toString();
+
+ IngestModelMoxyOxm moxyMod = new IngestModelMoxyOxm();
+ DbMaps dbMaps = null;
+ try {
+ ArrayList <String> defaultVerLst = new ArrayList <String> ();
+ defaultVerLst.add( AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP) );
+ moxyMod.init( defaultVerLst, false);
+ // Just make sure we can get DbMaps - don't actually need it until later.
+ dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not get the DbMaps object. ";
+ System.out.println( emsg );
+ aaiLogger.info(logline, false, "AAI_7402");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402"), logline, ex);
+ System.exit(1);
+ }
+ // if the node type has two keys - this assumes max 2 keys
+ if (!dbMaps.NodeKeyProps.containsKey(resource))
+ resource = p.getName(p.getNameCount() - 3).toString();
+ String resourceClass = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, resource);
+ resourceClass = "org.openecomp.aai.domain.yang." + resourceClass;
+
+ logline.add("class", resourceClass);
+ logline.add("path", path);
+ System.out.println("class=" + resourceClass);
+ System.out.println("path=" + path);
+
+ //logline.add("url", url);
+ //System.out.println("url=" + url);
+
+ if (bResVersionEnabled)
+ {
+ RestObject<T> restObj = new RestObject<T>();
+ @SuppressWarnings("unchecked")
+ T t = (T)getInstance(Class.forName(resourceClass));
+ restObj.set(t);
+
+ try
+ {
+ RestController.<T>Get(t, FROMAPPID, TRANSID, path, restObj, false);
+ t = restObj.get();
+ System.out.println(" GET resoruceversion succeeded\n");
+ String resourceUpdateVersion = GetResourceVersion(t);
+ path += "?resource-version=" + resourceUpdateVersion;
+ }
+ catch (Exception e1)
+ {
+ System.out.println("Delete failed. Resource Not found in the DB.");
+
+ System.exit(1);
+ }
+ }
+ System.out.print("\nAre you sure you would like to delete the resource \n" + url + "? (y/n): ");
+ Scanner s = new Scanner(System.in);
+ s.useDelimiter("");
+ String confirm = s.next();
+
+ if (!confirm.equalsIgnoreCase("y")) {
+ System.out.println("\nExiting...");
+ logline.add("msg", "User chose to exit before deleting");
+ aaiLogger.info(logline, true, "0");
+ System.exit(1);
+ }
+
+ //deleteNode(aaiLogger, logline, url);
+ RestController.Delete(FROMAPPID, TRANSID, path);
+
+ /*if (args.length > 1 ) {
+ // remove if resource-path has it as the first char
+ url= args[0].replaceFirst("^/", "");
+ String[] splitURL = url.split("/");
+ String nodeType = splitURL[splitURL.length - 2];
+
+ if (Arrays.asList(nodeTypeList).contains(nodeType)) {
+ s.reset();
+ System.out.print("\nAre you sure you would like to notify about the deletion of this "+ nodeType + " \n" + url + "? (y/n): ");
+ confirm= s.next();
+
+ if (!confirm.equalsIgnoreCase("y")) {
+ System.out.println("\nExiting...");
+ logline.add("msg", "deleted resource ");
+ aaiLogger.info(logline, true, "0");
+ s.close();
+ System.exit(1);
+ }
+ logline.add("msg1", "deleted resource");
+ url = AAIConfig.get(AAIConstants.AAI_GLOBAL_CALLBACK_URL)
+ + AAIConfig.get(AAIConstants.AAI_NOTIFICATION_CURRENT_VERSION) + "/" + url + "/";
+ } else {
+ redacted
+ }
+ }*/
+ s.close();
+ logline.add("msg2", "notified");
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+
+ } catch (AAIException e) {
+ System.out.println("Delete failed:" + e.getMessage());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println("Delete failed:" + e.toString());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+
+ }
+
+ /**
+ * Gets the single instance of DeleteResource.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return single instance of DeleteResource
+ * @throws IllegalAccessException the illegal access exception
+ * @throws InstantiationException the instantiation exception
+ */
+ public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException
+ {
+ return clazz.newInstance();
+ }
+
+ /**
+ * Gets the resource version.
+ *
+ * @param <T> the generic type
+ * @param resource the resource
+ * @return the string
+ */
+ public static <T> String GetResourceVersion(T resource)
+ {
+ Field[] fields = resource.getClass().getDeclaredFields();
+ if (fields != null)
+ {
+ for (Field field : fields)
+ {
+ try
+ {
+ field.setAccessible(true);
+ if ( field.getName().equalsIgnoreCase("resource-version") )
+ {
+ Object obj = field.get(resource);
+ return (String)obj;
+ }
+
+
+ }
+ catch (Exception e)
+ {
+
+ }
+
+
+ }
+ }
+ return null;
+ }
+ /*public static void deleteNode(AAILogger aaiLogger, LogLine logline, String url) throws AAIException {
+ try {
+ Client client = HttpsAuthClient.getClient();
+
+ System.out.println("Deleting the resource...: " + url);
+
+ ClientResponse cres = client.resource(url)
+ .header("X-TransactionId", TRANSID)
+ .header("X-FromAppId", FROMAPPID)
+ .accept("application/json")
+ .delete(ClientResponse.class);
+
+ if (cres.getStatus() == 404) { // resource not found
+ String msg = "Resource does not exist...: " + cres.getStatus()
+ + ":" + cres.getEntity(String.class);
+ System.out.println("\n" + msg);
+ logline.add("msg", msg );
+ throw new AAIException("AAI_7404", "Resource does not exist");
+ } else if (cres.getStatus() == 200 || cres.getStatus() == 204){
+ System.out.println("\nResource " + url + " deleted");
+ logline.add("msg", "Resource " + url + " deleted");
+ } else {
+ String msg = "Deleting Resource failed: " + cres.getStatus()
+ + ":" + cres.getEntity(String.class);
+ System.out.println("\n" + msg);
+ logline.add("msg", msg);
+ throw new AAIException("AAI_7402", "Error during DELETE");
+ }
+ } catch (AAIException e) {
+ throw e;
+ } catch (KeyManagementException e) {
+ throw new AAIException("AAI_7401", e, "Error during DELETE");
+ } catch (Exception e) {
+ throw new AAIException("AAI_7402", e, "Error during DELETE");
+ }
+ } */
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/Entity.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/Entity.java
new file mode 100644
index 0000000..c132404
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/Entity.java
@@ -0,0 +1,196 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "equipment-role",
+ "action",
+ "key-value-list",
+ "self-link"
+})
+public class Entity {
+
+ @JsonProperty("equipment-role")
+ private String equipmentRole;
+ @JsonProperty("action")
+ private String action;
+ @JsonProperty("key-value-list")
+ private List<KeyValueList> keyValueList = new ArrayList<KeyValueList>();
+ @JsonProperty("self-link")
+ private String selfLink;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The equipmentRole
+ */
+ @JsonProperty("equipment-role")
+ public String getEquipmentRole() {
+ return equipmentRole;
+ }
+
+ /**
+ *
+ * @param equipmentRole
+ * The equipment-role
+ */
+ @JsonProperty("equipment-role")
+ public void setEquipmentRole(String equipmentRole) {
+ this.equipmentRole = equipmentRole;
+ }
+
+ public Entity withEquipmentRole(String equipmentRole) {
+ this.equipmentRole = equipmentRole;
+ return this;
+ }
+
+ /**
+ *
+ * @return
+ * The action
+ */
+ @JsonProperty("action")
+ public String getAction() {
+ return action;
+ }
+
+ /**
+ *
+ * @param action
+ * The action
+ */
+ @JsonProperty("action")
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public Entity withAction(String action) {
+ this.action = action;
+ return this;
+ }
+
+ /**
+ *
+ * @return
+ * The keyValueList
+ */
+ @JsonProperty("key-value-list")
+ public List<KeyValueList> getKeyValueList() {
+ return keyValueList;
+ }
+
+ /**
+ *
+ * @param keyValueList
+ * The key-value-list
+ */
+ @JsonProperty("key-value-list")
+ public void setKeyValueList(List<KeyValueList> keyValueList) {
+ this.keyValueList = keyValueList;
+ }
+
+ public Entity withKeyValueList(List<KeyValueList> keyValueList) {
+ this.keyValueList = keyValueList;
+ return this;
+ }
+
+ /**
+ *
+ * @return
+ * The selfLink
+ */
+ @JsonProperty("self-link")
+ public String getSelfLink() {
+ return selfLink;
+ }
+
+ /**
+ *
+ * @param selfLink
+ * The self-link
+ */
+ @JsonProperty("self-link")
+ public void setSelfLink(String selfLink) {
+ this.selfLink = selfLink;
+ }
+
+ public Entity withSelfLink(String selfLink) {
+ this.selfLink = selfLink;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+ public Entity withAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder().append(equipmentRole).append(action).append(keyValueList).append(selfLink).append(additionalProperties).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if ((other instanceof Entity) == false) {
+ return false;
+ }
+ Entity rhs = ((Entity) other);
+ return new EqualsBuilder().append(equipmentRole, rhs.equipmentRole).append(action, rhs.action).append(keyValueList, rhs.keyValueList).append(selfLink, rhs.selfLink).append(additionalProperties, rhs.additionalProperties).isEquals();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/EntityList.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/EntityList.java
new file mode 100644
index 0000000..7da426b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/EntityList.java
@@ -0,0 +1,114 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.openecomp.aai.util.Entity;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "entity"
+})
+public class EntityList {
+
+ @JsonProperty("entity")
+ private List<Entity> entity = new ArrayList<Entity>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The entity
+ */
+ @JsonProperty("entity")
+ public List<Entity> getEntity() {
+ return entity;
+ }
+
+ /**
+ *
+ * @param entity
+ * The entity
+ */
+ @JsonProperty("entity")
+ public void setEntity(List<Entity> entity) {
+ this.entity = entity;
+ }
+
+ public EntityList withEntity(List<Entity> entity) {
+ this.entity = entity;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+ public EntityList withAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder().append(entity).append(additionalProperties).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if ((other instanceof EntityList) == false) {
+ return false;
+ }
+ EntityList rhs = ((EntityList) other);
+ return new EqualsBuilder().append(entity, rhs.entity).append(additionalProperties, rhs.additionalProperties).isEquals();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/FileWatcher.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/FileWatcher.java
new file mode 100644
index 0000000..84e7a1a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/FileWatcher.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.*;
+import java.io.*;
+
+public abstract class FileWatcher extends TimerTask {
+ private long timeStamp;
+ private File file;
+
+ /**
+ * Instantiates a new file watcher.
+ *
+ * @param file the file
+ */
+ public FileWatcher( File file ) {
+ this.file = file;
+ this.timeStamp = file.lastModified();
+ }
+
+ /**
+ * runs a timer task
+ * @see java.util.TimerTask.run
+ */
+ public final void run() {
+ long timeStamp = file.lastModified();
+
+ if( (timeStamp - this.timeStamp) > 500 ) {
+ this.timeStamp = timeStamp;
+ onChange(file);
+ }
+ }
+
+ /**
+ * On change.
+ *
+ * @param file the file
+ */
+ protected abstract void onChange( File file );
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java
new file mode 100644
index 0000000..013b3e0
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.FileWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.openecomp.aai.audit.ListEndpoints;
+import org.openecomp.aai.introspection.Version;
+
+public class GenerateMethodMapper {
+
+ private final static String filePath = "bundleconfig-local/etc/appprops/methodMapper.properties";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws Exception the exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ ListEndpoints le = null;
+ JSONObject jo = new JSONObject();
+ JSONArray ja = new JSONArray();
+
+ for (Version version : Version.values()) {
+
+ le = new ListEndpoints(version);
+ Map<String, String> ln = le.getLogicalNames();
+ List<String> keys = new ArrayList<String>(ln.keySet());
+ Collections.sort(keys);
+ for (String key : keys) {
+ addEndpointToJsonArray(key, ln.get(key), ja, version.toString());
+ }
+
+ }
+
+ addUniqueEndpoints(ja);
+
+ jo.put("ActiveAndAvailableInventory-CloudNetwork", ja);
+ try (FileWriter file = new FileWriter(filePath)) {
+ file.write(jo.toString(4));
+ }
+
+ System.exit(0);
+
+ }
+
+ /**
+ * Adds the unique endpoints.
+ *
+ * @param ja the ja
+ * @throws JSONException the JSON exception
+ */
+ private static void addUniqueEndpoints(JSONArray ja) throws JSONException {
+ JSONObject joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/models*");
+ joItem.put("method", "get");
+ joItem.put("logicalName", "GetModel");
+ ja.put(joItem);
+ joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/models*");
+ joItem.put("method", "put");
+ joItem.put("logicalName", "PutModel");
+ ja.put(joItem);
+ joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/models*");
+ joItem.put("method", "delete");
+ joItem.put("logicalName", "DeleteModel");
+ ja.put(joItem);
+ joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/named-queries/*");
+ joItem.put("method", "get");
+ joItem.put("logicalName", "GetNamedQuery");
+ ja.put(joItem);
+ }
+
+ /**
+ * Adds the endpoint to json array.
+ *
+ * @param url the url
+ * @param name the name
+ * @param ja the ja
+ * @param apiVersion the api version
+ * @throws JSONException the JSON exception
+ */
+ private static void addEndpointToJsonArray(String url, String name, JSONArray ja, String apiVersion)
+ throws JSONException {
+
+ JSONObject joGet = new JSONObject();
+ JSONObject joPut = new JSONObject();
+ JSONObject joDel = new JSONObject();
+
+ if (!url.endsWith("relationship")) {
+ joGet.put("url", url);
+ joGet.put("method", "get");
+ joGet.put("logicalName", apiVersion + "Get" + name);
+ ja.put(joGet);
+ }
+
+ if (url.endsWith("}") || url.endsWith("relationship")) {
+ joPut.put("url", url);
+ joPut.put("method", "put");
+ joPut.put("logicalName", apiVersion + "Put" + name);
+ ja.put(joPut);
+
+ joDel.put("url", url);
+ joDel.put("method", "delete");
+ joDel.put("logicalName", apiVersion + "Delete" + name);
+ ja.put(joDel);
+
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateXsd.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateXsd.java
new file mode 100644
index 0000000..6169b2f
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateXsd.java
@@ -0,0 +1,1491 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.openecomp.aai.dbmodel.DbEdgeRules;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+import com.google.common.base.Joiner;
+
+
+public class GenerateXsd {
+ static String apiVersion = null;
+ static String apiVersionFmt = null;
+ static String responsesUrl = null;
+ static String responsesLabel = null;
+ static Map<String, String> generatedJavaType = new HashMap<String, String>();
+ static Map<String, String> appliedPaths = new HashMap<String, String>();
+ static NodeList javaTypeNodes;
+
+
+ public static final int VALUE_NONE = 0;
+ public static final int VALUE_DESCRIPTION = 1;
+ public static final int VALUE_INDEXED_PROPS = 2;
+
+ private static XPath xpath = XPathFactory.newInstance().newXPath();
+
+ public static void main(String[] args) throws IOException {
+ // TODO Auto-generated method stub
+
+ if (args.length > 0) {
+ if (args[0] != null) {
+ apiVersion = args[0];
+ }
+ }
+ boolean genDoc = false;
+ if ( args.length > 1 ) {
+ genDoc = true;
+ int index = args[1].indexOf("|");
+ if ( index > 0 ) {
+ responsesUrl = args[1].substring(0, index);
+ responsesLabel = args[1].substring(index+1);
+ //System.out.println( "response URL " + responsesUrl);
+ //System.out.println( "response label " + responsesLabel);
+ responsesUrl = "description: "+ responsesLabel + "(" +
+ responsesUrl + ").\n";
+ //System.out.println( "operation described with " + responsesUrl);
+ }
+ }
+ String oxmPath = null;
+ if ( apiVersion == null || genDoc ) {
+ // to run from eclipse, set these env, e.g. v7, \sources\aai\aaimastergit\bundleconfig-local\etc\oxm\
+ String envRev= System.getenv("OXM_REV");
+ if ( envRev != null )
+ apiVersion = envRev;
+
+ }
+ oxmPath = System.getenv("OXM_PATH");
+ String outfilePath = System.getenv("OXM_OUTFILEPATH");
+ String outfileName = null;
+ if ( outfilePath == null ) {
+ if ( genDoc ) {
+ outfileName = "c:\\temp\\aai.yaml";
+ } else
+ outfileName = "c:\\temp\\aai_schema.xsd";
+ } else {
+ if ( genDoc ) {
+ outfileName = outfilePath + "aai.yaml";
+ } else
+ outfileName = outfilePath + "aai_schema.xsd";
+ }
+ if ( apiVersion != null ) { // generate from oxm
+ apiVersionFmt = "." + apiVersion + ".";
+ if ( oxmPath == null ) {
+ oxmPath = AAIConstants.AAI_HOME_ETC_OXM + AAIConstants.AAI_FILESEP;
+ //oxmPath = "\\sources\\aai\\aaimastergit\\bundleconfig-local\\etc\\oxm\\";
+ }
+ File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml");
+ String xsd;
+ File outfile;
+ if ( genDoc ) {
+ xsd = generateSwaggerFromOxmFile( oxm_file);
+ outfile =new File(outfileName);
+ } else {
+ xsd = processOxmFile( oxm_file);
+ outfile =new File(outfileName);
+ }
+
+
+ try {
+ outfile.createNewFile();
+ } catch (IOException e) {
+ System.out.println( "Exception creating output file " + outfileName);
+ e.printStackTrace();
+ }
+ try {
+ FileWriter fw = new FileWriter(outfile.getAbsoluteFile());
+ BufferedWriter bw = new BufferedWriter(fw);
+ bw.write(xsd);
+ bw.close();
+
+ } catch ( IOException e) {
+ System.out.println( "Exception writing output file " + outfileName);
+ e.printStackTrace();
+ }
+ System.out.println( "GeneratedXSD successful, saved in " + outfileName);
+ return;
+ }
+
+ JAXBContext jaxbContext = null;
+ try {
+ jaxbContext = JAXBContext.newInstance(org.openecomp.aai.domain.yang.GenericVnf.class);
+ } catch (JAXBException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ SchemaOutputResolver sor = new MySchemaOutputResolver();
+ jaxbContext.generateSchema(sor);
+
+ }
+
+ public static class MySchemaOutputResolver extends SchemaOutputResolver {
+
+ public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
+ File file = new File("c:\\temp\\aai_schema.xsd");
+ StreamResult result = new StreamResult(file);
+ result.setSystemId(file.toURI().toURL().toString());
+ return result;
+ }
+
+ }
+
+ public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) {
+
+ String xmlRootElementName = null;
+
+ Map<String, String> addJavaType = new HashMap<String, String>();
+
+
+ NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
+ StringBuffer sb = new StringBuffer();
+ if ( parentNodes.getLength() == 0 ) {
+ System.out.println( "no java-attributes for java-type " + javaTypeName);
+ return "";
+
+ }
+
+ NamedNodeMap attributes;
+
+ NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
+ Element valElement = (Element) valNodes.item(0);
+ attributes = valElement.getAttributes();
+ for ( int i = 0; i < attributes.getLength(); ++i ) {
+ Attr attr = (Attr) attributes.item(i);
+ String attrName = attr.getNodeName();
+
+ String attrValue = attr.getNodeValue();
+ //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
+ if ( attrName.equals("name"))
+ xmlRootElementName = attrValue;
+ }
+ /*
+ if ( javaTypeName.equals("RelationshipList")) {
+ System.out.println( "Skipping " + javaTypeName);
+ generatedJavaType.put(javaTypeName, null);
+ return "";
+ }
+ */
+
+ Element parentElement = (Element)parentNodes.item(0);
+ NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
+ NodeList childNodes;
+ Element childElement;
+ String xmlElementWrapper;
+
+ Element xmlElementElement;
+ String addType;
+ String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType;
+ StringBuffer sb1 = new StringBuffer();
+ if ( xmlElementNodes.getLength() > 0 ) {
+ sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
+ sb1.append(" <xs:complexType>\n");
+ NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement);
+ if (properties != null) {
+ System.out.println("properties found for: " + xmlRootElementName);
+ sb1.append(" <xs:annotation>\r\n");
+ insertAnnotation(properties, false, "class", sb1, " ");
+
+ sb1.append(" </xs:annotation>\r\n");
+ } else {
+ System.out.println("no properties found for: " + xmlRootElementName);
+ }
+ sb1.append(" <xs:sequence>\n");
+ for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
+
+ xmlElementElement = (Element)xmlElementNodes.item(i);
+ childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
+
+ xmlElementWrapper = null;
+ if ( childNodes.getLength() > 0 ) {
+ childElement = (Element)childNodes.item(0);
+ // get name
+ attributes = childElement.getAttributes();
+ for ( int k = 0; k < attributes.getLength(); ++k ) {
+ Attr attr = (Attr) attributes.item(k);
+ String attrName = attr.getNodeName();
+ String attrValue = attr.getNodeValue();
+ if ( attrName.equals("name")) {
+ xmlElementWrapper = attrValue;
+ //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
+ }
+ }
+
+ }
+ attributes = xmlElementElement.getAttributes();
+ addType = null;
+
+
+ elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ Attr attr = (Attr) attributes.item(j);
+ String attrName = attr.getNodeName();
+
+ String attrValue = attr.getNodeValue();
+ //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
+ if ( attrName.equals("name")) {
+ elementName = attrValue;
+ }
+ if ( attrName.equals("type")) {
+ elementType = attrValue;
+ if ( attrValue.contains(apiVersionFmt) ) {
+ addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
+ if ( !generatedJavaType.containsKey(addType) ) {
+ generatedJavaType.put(addType, attrValue);
+ sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) ));
+
+ }
+ }
+
+ }
+ if ( attrName.equals("xml-key")) {
+ elementIsKey = attrValue;
+ }
+ if ( attrName.equals("required")) {
+ elementIsRequired = attrValue;
+ }
+ if ( attrName.equals("container-type")) {
+ elementContainerType = attrValue;
+ }
+ }
+
+ if ( xmlElementWrapper != null ) {
+ sb1.append(" <xs:element name=\"" + xmlElementWrapper +"\"");
+ if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
+ sb1.append(" minOccurs=\"0\"");
+ }
+ sb1.append(">\n");
+ sb1.append(" <xs:complexType>\n");
+ properties = GenerateXsd.locateXmlProperties(javaTypeElement);
+ if (properties != null) {
+ sb1.append(" <xs:annotation>\r\n");
+ insertAnnotation(properties, false, "class", sb1, " ");
+ sb1.append(" </xs:annotation>\r\n");
+ } else {
+ System.out.println("no properties found for: " + xmlElementWrapper);
+ }
+ sb1.append(" <xs:sequence>\n");
+ sb1.append(" ");
+ }
+ if ( addType != null ) {
+ //sb1.append(" <xs:element ref=\"tns:" + elementName +"\"");
+ sb1.append(" <xs:element ref=\"tns:" + getXmlRootElementName(addType) +"\"");
+ } else {
+ sb1.append(" <xs:element name=\"" + elementName +"\"");
+ }
+ if ( elementType.equals("java.lang.String"))
+ sb1.append(" type=\"xs:string\"");
+ //if ( elementType.equals("java.lang.String"))
+ //sb1.append(" type=\"xs:string\"");
+ if ( elementType.equals("java.lang.Long"))
+ sb1.append(" type=\"xs:unsignedInt\"");
+ if ( elementType.equals("java.lang.Integer"))
+ sb1.append(" type=\"xs:int\"");
+ if ( elementType.equals("java.lang.Boolean"))
+ sb1.append(" type=\"xs:boolean\"");
+ //if ( elementIsRequired != null && elementIsRequired.equals("true")||addType != null) {
+ if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
+ sb1.append(" minOccurs=\"0\"");
+ }
+ if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
+ sb1.append(" maxOccurs=\"unbounded\"");
+ }
+ properties = GenerateXsd.locateXmlProperties(xmlElementElement);
+ if (properties != null || elementIsKey != null) {
+ sb1.append(">\n");
+ sb1.append(" <xs:annotation>\r\n");
+ insertAnnotation(properties, elementIsKey != null, "field", sb1, " ");
+ sb1.append(" </xs:annotation>\r\n");
+
+ if (xmlElementWrapper== null) {
+ sb1.append(" </xs:element>\n");
+ }
+ } else {
+ sb1.append("/>\n");
+ }
+ if ( xmlElementWrapper != null ) {
+ sb1.append(" </xs:sequence>\n");
+ sb1.append(" </xs:complexType>\n");
+ sb1.append(" </xs:element>\n");
+ }
+ }
+ /*
+ if ( xmlRootElementName.equals("notify") ||
+ xmlRootElementName.equals("relationship") ||
+ xmlRootElementName.equals("relationship-data") ||
+ xmlRootElementName.equals("related-to-property") )
+
+ sb1.append(" <xs:any namespace=\"##other\" processContents=\"lax\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n");
+ */
+ sb1.append(" </xs:sequence>\n");
+ sb1.append(" </xs:complexType>\n");
+ sb1.append(" </xs:element>\n");
+ }
+ /*
+ NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
+ Element valElement = (Element) valNodes.item(0);
+ attributes = valElement.getAttributes();
+ for ( int i = 0; i < attributes.getLength(); ++i ) {
+ Attr attr = (Attr) attributes.item(i);
+ String attrName = attr.getNodeName();
+
+ String attrValue = attr.getNodeValue();
+ System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
+ if ( attrValue.equals("name"))
+ xmlRootElementName = attrValue;
+ }
+ */
+
+ if ( xmlElementNodes.getLength() < 1 ) {
+ sb.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
+ sb.append(" <xs:complexType>\n");
+ sb.append(" <xs:sequence/>\n");
+ sb.append(" </xs:complexType>\n");
+ sb.append(" </xs:element>\n");
+ generatedJavaType.put(javaTypeName, null);
+ return sb.toString();
+ }
+
+ sb.append( sb1 );
+
+ return sb.toString();
+ }
+
+ private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) {
+ if (items != null || isKey) {
+ List<String> metadata = new ArrayList<>();
+
+ String name = "";
+ String value = "";
+ Element item = null;
+ if (isKey) {
+ metadata.add("isKey=true");
+ }
+ if (items != null) {
+ for (int i = 0; i < items.getLength(); i++) {
+ item = (Element)items.item(i);
+ name = item.getAttribute("name");
+ value = item.getAttribute("value");
+ if (name.equals("abstract")) {
+ name = "isAbstract";
+ } else if (name.equals("extends")) {
+ name = "extendsFrom";
+ }
+ metadata.add(name + "=\"" + value.replaceAll("&", "&amp;") + "\"");
+ System.out.println("property name: " + name);
+
+ }
+ }
+ sb1.append(
+ indentation + " <xs:appinfo>\r\n" +
+ indentation + " <annox:annotate target=\""+target+"\">@org.openecomp.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" +
+ indentation + " </xs:appinfo>\r\n");
+ }
+
+ }
+
+ private static Element getJavaTypeElement( String javaTypeName )
+ {
+
+ String attrName, attrValue;
+ Attr attr;
+ Element javaTypeElement;
+ for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
+ javaTypeElement = (Element) javaTypeNodes.item(i);
+ NamedNodeMap attributes = javaTypeElement.getAttributes();
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ attr = (Attr) attributes.item(j);
+ attrName = attr.getNodeName();
+ attrValue = attr.getNodeValue();
+ if ( attrName.equals("name") && attrValue.equals(javaTypeName))
+ return javaTypeElement;
+ }
+ }
+ System.out.println( "oxm file format error, missing java-type " + javaTypeName);
+ return (Element) null;
+ }
+
+ private static Element getJavaTypeElementSwagger( String javaTypeName )
+ {
+
+ String attrName, attrValue;
+ Attr attr;
+ Element javaTypeElement;
+ for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
+ javaTypeElement = (Element) javaTypeNodes.item(i);
+ NamedNodeMap attributes = javaTypeElement.getAttributes();
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ attr = (Attr) attributes.item(j);
+ attrName = attr.getNodeName();
+ attrValue = attr.getNodeValue();
+ if ( attrName.equals("name") && attrValue.equals(javaTypeName))
+ return javaTypeElement;
+ }
+ }
+ System.out.println( "oxm file format error, missing java-type " + javaTypeName);
+ return (Element) null;
+ }
+ private static String getXmlRootElementName( String javaTypeName )
+ {
+
+ String attrName, attrValue;
+ Attr attr;
+ Element javaTypeElement;
+ for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
+ javaTypeElement = (Element) javaTypeNodes.item(i);
+ NamedNodeMap attributes = javaTypeElement.getAttributes();
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ attr = (Attr) attributes.item(j);
+ attrName = attr.getNodeName();
+ attrValue = attr.getNodeValue();
+ if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
+ NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
+ Element valElement = (Element) valNodes.item(0);
+ attributes = valElement.getAttributes();
+ for ( int k = 0; k < attributes.getLength(); ++k ) {
+ attr = (Attr) attributes.item(k);
+ attrName = attr.getNodeName();
+
+ attrValue = attr.getNodeValue();
+ //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
+ if ( attrName.equals("name"))
+ return (attrValue);
+ }
+ }
+ }
+ }
+ System.out.println( "oxm file format error, missing java-type " + javaTypeName);
+ return null;
+ }
+
+
+ public static String processOxmFile( File oxmFile )
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
+ sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://org.openecomp.aai.inventory/"
+ + apiVersion + "\" xmlns:tns=\"http://org.openecomp.aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
+ + "\n"
+ + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" +
+ " jaxb:version=\"2.1\" \r\n" +
+ " xmlns:annox=\"http://annox.dev.java.net\" \r\n" +
+ " jaxb:extensionBindingPrefixes=\"annox\">\n\n");
+
+ try {
+
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ Document doc = dBuilder.parse(oxmFile);
+
+ NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
+ Element bindingElement;
+ NodeList javaTypesNodes;
+ Element javaTypesElement;
+
+ Element javaTypeElement;
+
+
+ if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
+ System.out.println( "missing <binding-nodes> in " + oxmFile );
+ return null;
+ }
+
+ bindingElement = (Element) bindingsNodes.item(0);
+ javaTypesNodes = bindingElement.getElementsByTagName("java-types");
+ if ( javaTypesNodes.getLength() < 1 ) {
+ System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
+ return null;
+ }
+ javaTypesElement = (Element) javaTypesNodes.item(0);
+ javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
+ if ( javaTypeNodes.getLength() < 1 ) {
+ System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
+ return null;
+ }
+
+ String javaTypeName;
+ String attrName, attrValue;
+ Attr attr;
+ for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
+ javaTypeElement = (Element) javaTypeNodes.item(i);
+ NamedNodeMap attributes = javaTypeElement.getAttributes();
+ javaTypeName = null;
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ attr = (Attr) attributes.item(j);
+ attrName = attr.getNodeName();
+ attrValue = attr.getNodeValue();
+ if ( attrName.equals("name"))
+ javaTypeName = attrValue;
+ }
+ if ( javaTypeName == null ) {
+ System.out.println( "<java-type> has no name attribute in " + oxmFile );
+ return null;
+ }
+ if ( !generatedJavaType.containsKey(javaTypeName) ) {
+ generatedJavaType.put(javaTypeName, null);
+ sb.append(processJavaTypeElement( javaTypeName, javaTypeElement ));
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ sb.append("</xs:schema>\n");
+ return sb.toString();
+ }
+
+ private static boolean isStandardType( String elementType )
+ {
+ switch ( elementType ) {
+ case "java.lang.String":
+ case "java.lang.Long":
+ case "java.lang.Integer":
+ case"java.lang.Boolean":
+ return true;
+ }
+ return false;
+ }
+
+ private static Vector<String> getIndexedProps( String attrValue )
+ {
+ if ( attrValue == null )
+ return null;
+ StringTokenizer st = new StringTokenizer( attrValue, ",");
+ if ( st.countTokens() == 0 )
+ return null;
+ Vector<String> result = new Vector<String>();
+ while ( st.hasMoreTokens()) {
+ result.add(st.nextToken());
+ }
+ return result;
+ }
+
+ static private Vector<String> getEdgeRules( String nodeName )
+ {
+
+ Vector<String> result = new Vector<String>();
+ Iterator<String> edgeRulesIterator;
+ edgeRulesIterator = org.openecomp.aai.dbmodel.DbEdgeRules.EdgeRules.keySet().iterator();
+
+ while( edgeRulesIterator.hasNext() ){
+ String ruleKey = edgeRulesIterator.next();
+ if ( ruleKey.startsWith(nodeName + "|" ) ||
+ ruleKey.endsWith("|" + nodeName)) {
+ Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey);
+ Iterator <String> ruleItr = edRuleColl.iterator();
+ if( ruleItr.hasNext() ){
+ //String fullRuleString = ruleItr.next();
+ //System.out.println( "nodeName " + nodeName + " ruleKey " + ruleKey + " ruleString " + fullRuleString);
+ //result.add(ruleKey + "-" + fullRuleString);
+ result.add(ruleKey );
+ }
+ }
+ }
+ return result;
+ }
+
+ public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement,
+ StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId,
+ String getItemName, StringBuffer pathParams, String queryParams, String validEdges) {
+
+ String xmlRootElementName = null;
+
+ //Map<String, String> addJavaType = new HashMap<String, String>();
+ String useTag = null;
+ String useOpId = null;
+
+ if ( tag != null ) {
+ switch ( tag ) {
+ case "Network":
+ case "ServiceDesignAndCreation":
+ case "Business":
+ case "CloudInfrastructure":
+ break;
+ default:
+ return null;
+ }
+ }
+ /*
+ if ( path == null )
+ System.out.println( "processJavaTypeElementSwagger called with null path for javaTypeName " + javaTypeName);
+ */
+ /*
+ if ( path == null || !(path.contains("cloud-infrastructure")))
+ switch ( javaTypeName) {
+ case "Inventory":
+ useTag = null;
+ break;
+
+ case "CloudInfrastructure":
+ case "Search":
+ case "Actions":
+ case "ServiceDesignAndCreation":
+ case "Network":
+ if ( tag == null )
+ useTag = javaTypeName;
+
+ break;
+ default:
+ return null;
+
+ }
+ */
+
+ if ( !javaTypeName.equals("Inventory") ) {
+ if ( javaTypeName.equals("AaiInternal"))
+ return null;
+ if ( opId == null )
+ useOpId = javaTypeName;
+ else
+ useOpId = opId + javaTypeName;
+ if ( tag == null )
+ useTag = javaTypeName;
+ }
+
+ /*
+ if ( javaTypeName.equals("GenericVnf"))
+ System.out.println( "Processing " + javaTypeName);
+ else if ( javaTypeName.equals("Service"))
+ System.out.println( "Processing " + javaTypeName);
+ else if ( javaTypeName.equals("SitePair"))
+ System.out.println( "Processing " + javaTypeName);
+ */
+ NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
+ StringBuffer sb = new StringBuffer();
+ if ( parentNodes.getLength() == 0 ) {
+ System.out.println( "no java-attributes for java-type " + javaTypeName);
+ return "";
+
+ }
+
+ NamedNodeMap attributes;
+
+ NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
+ Element valElement = (Element) valNodes.item(0);
+ attributes = valElement.getAttributes();
+ for ( int i = 0; i < attributes.getLength(); ++i ) {
+ Attr attr = (Attr) attributes.item(i);
+ String attrName = attr.getNodeName();
+
+ String attrValue = attr.getNodeValue();
+ //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
+ if ( attrName.equals("name"))
+ xmlRootElementName = attrValue;
+ }
+ /*
+ if ( xmlRootElementName.equals("oam-networks"))
+ System.out.println( "xmlRootElement oam-networks with getItemData [" + getItemName + "]");
+ */
+ //already processed
+ /*
+ if ( generatedJavaType.containsKey(xmlRootElementName) ) {
+ return null;
+ }
+ */
+ NodeList childNodes;
+ Element childElement;
+ NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
+ Element xmlPropElement;
+ String pathDescriptionProperty = null;
+
+
+ Vector<String> indexedProps = null;
+
+ /*System.out.println( "javaTypeName " + javaTypeName + " has xml-properties length " + xmlPropNodes.getLength());
+ if ( path != null && path.equals("/network/generic-vnfs"))
+ System.out.println("path is " + "/network/generic-vnfs with getItemName " + getItemName);
+ */
+ if ( xmlPropNodes.getLength() > 0 ) {
+
+ for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
+ xmlPropElement = (Element)xmlPropNodes.item(i);
+ if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
+ continue;
+ childNodes = xmlPropElement.getElementsByTagName("xml-property");
+
+ if ( childNodes.getLength() > 0 ) {
+ for ( int j = 0; j < childNodes.getLength(); ++j ) {
+ childElement = (Element)childNodes.item(j);
+ // get name
+ int useValue = VALUE_NONE;
+ attributes = childElement.getAttributes();
+ for ( int k = 0; k < attributes.getLength(); ++k ) {
+ Attr attr = (Attr) attributes.item(k);
+ String attrName = attr.getNodeName();
+ String attrValue = attr.getNodeValue();
+ if ( attrName == null || attrValue == null )
+ continue;
+ if ( attrName.equals("name") && attrValue.equals("description")) {
+ useValue = VALUE_DESCRIPTION;
+ }
+ if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
+ pathDescriptionProperty = attrValue;
+ //break;
+ //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
+ }
+ if ( attrValue.equals("indexedProps")) {
+ useValue = VALUE_INDEXED_PROPS;
+ }
+ if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
+ indexedProps = getIndexedProps( attrValue );
+ }
+ }
+ }
+ }
+ }
+ }
+ //System.out.println("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
+
+ /*
+ if ( javaTypeName.equals("RelationshipList")) {
+ System.out.println( "Skipping " + javaTypeName);
+ generatedJavaType.put(javaTypeName, null);
+ return "";
+ }
+ */
+
+ Element parentElement = (Element)parentNodes.item(0);
+ NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
+
+ String xmlElementWrapper;
+ String attrDescription = null;
+
+ Element xmlElementElement;
+ String addType = null;
+ String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
+ String elementName = null;
+ StringBuffer sbParameters = new StringBuffer();
+
+ StringBuffer sbRequired = new StringBuffer();
+ int requiredCnt = 0;
+ int propertyCnt = 0;
+ StringBuffer sbProperties = new StringBuffer();
+ StringBuffer sbIndexedParams = new StringBuffer();
+
+ xmlElementWrapper = null;
+ StringTokenizer st;
+ if ( xmlRootElementName.equals("inventory"))
+ path = "";
+ else if ( path == null )
+ //path = "/aai/" + apiVersion;
+ path = "/" + xmlRootElementName;
+ else
+ path += "/" + xmlRootElementName;
+ st = new StringTokenizer(path, "/");
+ /*
+ if ( path.equals("/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription"))
+ System.out.println("processing path /business/customers/customer/{global-customer-id}/service-subscriptions with tag " + tag);
+ */
+ boolean genPath = false;
+ /*
+ if ( path != null && path.equals("/network/generic-vnfs/generic-vnf"))
+ System.out.println("path is " + "/network/generic-vnfs/generic-vnf");
+ */
+ if ( st.countTokens() > 1 && getItemName == null ) {
+ if ( appliedPaths.containsKey(path))
+ return null;
+ appliedPaths.put(path, null);
+ genPath = true;
+ if ( path.contains("/relationship/") ) { // filter paths with relationship-list
+ genPath = false;
+ }
+ if ( path.endsWith("/relationship-list")) {
+ genPath = false;
+ }
+
+ }
+
+ Vector<String> addTypeV = null;
+ if ( xmlElementNodes.getLength() > 0 ) {
+ boolean hasKey = false;
+
+ for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
+ xmlElementElement = (Element)xmlElementNodes.item(i);
+ if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
+ continue;
+ /*childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
+ if ( childNodes.getLength() > 0 ) {
+ childElement = (Element)childNodes.item(0);
+ // get name
+ attributes = childElement.getAttributes();
+ for ( int k = 0; k < attributes.getLength(); ++k ) {
+ Attr attr = (Attr) attributes.item(k);
+ String attrName = attr.getNodeName();
+ String attrValue = attr.getNodeValue();
+ if ( attrName.equals("name")) {
+ xmlElementWrapper = attrValue;
+ //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
+ }
+ }
+
+ }
+ */
+ valNodes = xmlElementElement.getElementsByTagName("xml-properties");
+ attrDescription = null;
+ if ( valNodes.getLength() > 0 ) {
+ for ( int j = 0; j < valNodes.getLength(); ++j ) {
+ valElement = (Element)valNodes.item(j);
+ if ( !valElement.getParentNode().isSameNode(xmlElementElement))
+ continue;
+ childNodes = valElement.getElementsByTagName("xml-property");
+ if ( childNodes.getLength() > 0 ) {
+ childElement = (Element)childNodes.item(0);
+ // get name
+ attributes = childElement.getAttributes();
+ attrDescription = null;
+ boolean useValue = false;
+ for ( int k = 0; k < attributes.getLength(); ++k ) {
+ Attr attr = (Attr) attributes.item(k);
+ String attrName = attr.getNodeName();
+ String attrValue = attr.getNodeValue();
+ if ( attrName.equals("name") && attrValue.equals("description")) {
+ useValue = true;
+ }
+ if ( useValue && attrName.equals("value")) {
+ attrDescription = attrValue;
+ //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
+ }
+ }
+
+ }
+ }
+ }
+
+ attributes = xmlElementElement.getAttributes();
+ addTypeV = null; // vector of 1
+ addType = null;
+
+ elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ Attr attr = (Attr) attributes.item(j);
+ String attrName = attr.getNodeName();
+
+ String attrValue = attr.getNodeValue();
+ //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
+ if ( attrName.equals("name")) {
+ elementName = attrValue;
+
+ }
+ if ( attrName.equals("type") && getItemName == null ) {
+ elementType = attrValue;
+ if ( attrValue.contains(apiVersionFmt) ) {
+ addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
+ if ( addTypeV == null )
+ addTypeV = new Vector<String>();
+ addTypeV.add(addType);
+ }
+
+ }
+ if ( attrName.equals("xml-key")) {
+ elementIsKey = attrValue;
+ path += "/{" + elementName + "}";
+ }
+ if ( attrName.equals("required")) {
+ elementIsRequired = attrValue;
+ }
+ if ( attrName.equals("container-type")) {
+ elementContainerType = attrValue;
+ }
+ }
+ if ( getItemName != null ) {
+ if ( getItemName.equals("array") ) {
+ if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
+ //System.out.println( " returning array " + elementName );
+ return elementName;
+ }
+
+ } else { // not an array check
+ if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
+ //System.out.println( " returning object " + elementName );
+ return elementName;
+ }
+
+ }
+ //System.out.println( " returning null" );
+ return null;
+ }
+ if ( elementIsRequired != null ) {
+ if ( requiredCnt == 0 )
+ sbRequired.append(" required:\n");
+ ++requiredCnt;
+ if ( addTypeV != null ) {
+ for ( int k = 0; k < addTypeV.size(); ++i ) {
+ sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
+ }
+ } else
+ sbRequired.append(" - " + elementName + "\n");
+
+ }
+
+ if ( elementIsKey != null ) {
+ hasKey = true;
+
+
+ sbParameters.append((" - name: " + elementName + "\n"));
+ sbParameters.append((" in: path\n"));
+ if ( attrDescription != null && attrDescription.length() > 0 )
+ sbParameters.append((" description: " + attrDescription + "\n"));
+ sbParameters.append((" required: true\n"));
+ if ( elementType.equals("java.lang.String"))
+ sbParameters.append(" type: string\n");
+ if ( elementType.equals("java.lang.Long")) {
+ sbParameters.append(" type: integer\n");
+ sbParameters.append(" format: int64\n");
+ }
+ if ( elementType.equals("java.lang.Integer")) {
+ sbParameters.append(" type: integer\n");
+ sbParameters.append(" format: int32\n");
+ }
+ if ( elementType.equals("java.lang.Boolean"))
+ sbParameters.append(" type: boolean\n");
+
+
+ } else if ( indexedProps != null
+ && indexedProps.contains(elementName ) ) {
+ sbIndexedParams.append((" - name: " + elementName + "\n"));
+ sbIndexedParams.append((" in: query\n"));
+ if ( attrDescription != null && attrDescription.length() > 0 )
+ sbIndexedParams.append((" description: " + attrDescription + "\n"));
+ sbIndexedParams.append((" required: false\n"));
+ if ( elementType.equals("java.lang.String"))
+ sbIndexedParams.append(" type: string\n");
+ if ( elementType.equals("java.lang.Long")) {
+ sbIndexedParams.append(" type: integer\n");
+ sbIndexedParams.append(" format: int64\n");
+ }
+ if ( elementType.equals("java.lang.Integer")) {
+ sbIndexedParams.append(" type: integer\n");
+ sbIndexedParams.append(" format: int32\n");
+ }
+ if ( elementType.equals("java.lang.Boolean"))
+ sbIndexedParams.append(" type: boolean\n");
+ }
+
+ /*
+ if ( elementName != null && elementName.equals("inventory-item"))
+ System.out.println( "processing inventory-item elementName");
+ */
+
+ if ( isStandardType(elementType)) {
+ sbProperties.append(" " + elementName + ":\n");
+ ++propertyCnt;
+ sbProperties.append(" type: ");
+
+ if ( elementType.equals("java.lang.String"))
+ sbProperties.append("string\n");
+ else if ( elementType.equals("java.lang.Long")) {
+ sbProperties.append("integer\n");
+ sbProperties.append(" format: int64\n");
+ }
+ else if ( elementType.equals("java.lang.Integer")){
+ sbProperties.append("integer\n");
+ sbProperties.append(" format: int32\n");
+ }
+ else if ( elementType.equals("java.lang.Boolean"))
+ sbProperties.append("boolean\n");
+ if ( attrDescription != null && attrDescription.length() > 0 )
+ sbProperties.append(" description: " + attrDescription + "\n");
+ }
+
+ //if ( addType != null && elementContainerType != null && elementContainerType.equals("java.util.ArrayList") ) {
+ boolean addingAaiInternal = false;
+ if ( addTypeV != null ) {
+ StringBuffer newPathParams = null;
+ if ( pathParams != null ) {
+ newPathParams = new StringBuffer();
+ newPathParams.append(pathParams);
+ }
+ if ( sbParameters.toString().length() > 0 ) {
+ if ( newPathParams == null )
+ newPathParams = new StringBuffer();
+ newPathParams.append(sbParameters);
+ }
+ String newQueryParams = null;
+ if ( sbIndexedParams.toString().length() > 0 ) {
+ if ( queryParams == null )
+ newQueryParams = sbIndexedParams.toString();
+ else
+ newQueryParams = queryParams + sbIndexedParams.toString();
+ } else {
+ newQueryParams = queryParams;
+ }
+ for ( int k = 0; k < addTypeV.size(); ++k ) {
+ addType = addTypeV.elementAt(k);
+
+ if ( opId == null || !opId.contains(addType)) {
+ /*
+ if ( validEdges == null ) {
+ */
+ if ( addType.equals("RelationshipList") ) {
+ // get edge rule
+ Vector<String> edges = getEdgeRules(xmlRootElementName );
+ if ( edges.size() > 0 ) {
+ StringBuffer sbEdge = new StringBuffer();
+ sbEdge.append(" description: |\n");
+ sbEdge.append(" ###### related-to\n");
+ for ( int xx = 0; xx < edges.size(); ++ xx) {
+ if ( edges.elementAt(xx).startsWith(xmlRootElementName))
+ sbEdge.append(" - TO " + edges.elementAt(xx).substring(edges.elementAt(xx).indexOf("|")+1) + "\n");
+ }
+ for ( int xx = 0; xx < edges.size(); ++ xx) {
+ if ( edges.elementAt(xx).endsWith(xmlRootElementName))
+ sbEdge.append(" - FROM " + edges.elementAt(xx).substring(0, edges.elementAt(xx).indexOf("|")) + "\n");
+ }
+ validEdges = sbEdge.toString();
+ }
+
+ }
+ /*
+ }
+ */
+ processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
+ pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null,
+ newPathParams, newQueryParams, validEdges);
+ }
+ // need item name of array
+ String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
+ pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
+ "array", null, null, null );
+
+ if ( itemName != null ) {
+ if ( addType.equals("AaiInternal") ) {
+ //System.out.println( "addType AaiInternal, skip properties");
+ addingAaiInternal = true;
+ } else if ( getItemName == null) {
+ ++propertyCnt;
+ sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
+ sbProperties.append(" type: array\n items:\n");
+ sbProperties.append(" $ref: \"#/definitions/" + itemName + "\"\n");
+ if ( attrDescription != null && attrDescription.length() > 0 )
+ sbProperties.append(" description: " + attrDescription + "\n");
+ }
+ } else {
+ /*itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
+ pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, "other" );
+ if ( itemName != null ) {
+ */
+ if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
+ // need properties for getXmlRootElementName(addType)
+ newPathParams = null;
+ if ( pathParams != null ) {
+ newPathParams = new StringBuffer();
+ newPathParams.append(pathParams);
+ }
+ if ( sbParameters.toString().length() > 0 ) {
+ if ( newPathParams == null )
+ newPathParams = new StringBuffer();
+ newPathParams.append(sbParameters);
+ }
+ newQueryParams = null;
+ if ( sbIndexedParams.toString().length() > 0 ) {
+ if ( queryParams == null )
+ newQueryParams = sbIndexedParams.toString();
+ else
+ newQueryParams = queryParams + sbIndexedParams.toString();
+ } else {
+ newQueryParams = queryParams;
+ }
+ /*
+ if ( validEdges == null ) {
+ */
+ if ( addType.equals("RelationshipList") ) {
+ // get edge rule
+ Vector<String> edges = getEdgeRules(xmlRootElementName );
+ if ( edges.size() > 0 ) {
+ StringBuffer sbEdge = new StringBuffer();
+ sbEdge.append(" description: |\n");
+ sbEdge.append(" ###### related-to\n");
+ for ( int xx = 0; xx < edges.size(); ++ xx) {
+ if ( edges.elementAt(xx).startsWith(xmlRootElementName))
+ sbEdge.append(" - TO " + edges.elementAt(xx).substring(edges.elementAt(xx).indexOf("|")+1) + "\n");
+ }
+ for ( int xx = 0; xx < edges.size(); ++ xx) {
+ if ( edges.elementAt(xx).endsWith(xmlRootElementName))
+ sbEdge.append(" - FROM " + edges.elementAt(xx).substring(0, edges.elementAt(xx).indexOf("|")) + "\n");
+ }
+ validEdges = sbEdge.toString();
+ }
+ }
+ /*
+ }
+ */
+ processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
+ pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
+ null, newPathParams, newQueryParams, validEdges );
+ sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
+ sbProperties.append(" type: array\n items: \n");
+ sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
+ } else {
+ sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
+ sbProperties.append(" type: object\n");
+ sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
+ }
+ if ( attrDescription != null && attrDescription.length() > 0 )
+ sbProperties.append(" description: " + attrDescription + "\n");
+ ++propertyCnt;
+ /*}
+ else {
+ System.out.println(" unable to define swagger object for " + addType);
+ }
+ */
+ }
+ //if ( getItemName == null) looking for missing properties
+ //generatedJavaType.put(addType, null);
+ }
+ }
+ }
+ }
+ if ( genPath ) {
+ /*
+ if ( useOpId.equals("CloudInfrastructureComplexesComplexCtagPools"))
+ System.out.println( "adding path CloudInfrastructureComplexesComplexCtagPools");
+ */
+
+ if ( !path.endsWith("/relationship") ) {
+ pathSb.append(" " + path + ":\n" );
+ pathSb.append(" get:\n");
+ pathSb.append(" tags:\n");
+ pathSb.append(" - " + tag + "\n");
+ pathSb.append(" summary: returns " + xmlRootElementName + "\n");
+
+ pathSb.append(" description: returns " + xmlRootElementName + "\n");
+ pathSb.append(" operationId: get" + useOpId + "\n");
+ pathSb.append(" produces:\n");
+ pathSb.append(" - application/json\n");
+ pathSb.append(" - application/xml\n");
+
+ pathSb.append(" responses:\n");
+ pathSb.append(" \"200\":\n");
+ pathSb.append(" description: successful operation\n");
+ pathSb.append(" schema:\n");
+ pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
+ pathSb.append(" \"default\":\n");
+ pathSb.append(" " + responsesUrl);
+ /*
+ pathSb.append(" \"200\":\n");
+ pathSb.append(" description: successful operation\n");
+ pathSb.append(" schema:\n");
+ pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
+ pathSb.append(" \"404\":\n");
+ pathSb.append(" description: resource was not found\n");
+ pathSb.append(" \"400\":\n");
+ pathSb.append(" description: bad request\n");
+ */
+ if ( path.indexOf('{') > 0 ) {
+
+ if ( sbParameters.toString().length() > 0 ) {
+ if ( pathParams == null )
+ pathParams = new StringBuffer();
+ pathParams.append(sbParameters);
+ }
+ if ( pathParams != null) {
+ pathSb.append(" parameters:\n");
+ pathSb.append(pathParams);
+ } else
+ System.out.println( "null pathParams for " + useOpId);
+ if ( sbIndexedParams.toString().length() > 0 ) {
+ if ( queryParams == null )
+ queryParams = sbIndexedParams.toString();
+ else
+ queryParams = queryParams + sbIndexedParams.toString();
+ }
+ if ( queryParams != null ) {
+ if ( pathParams == null ) {
+ pathSb.append(" parameters:\n");
+ }
+ pathSb.append(queryParams);
+ }
+ }
+ }
+ boolean skipPutDelete = false; // no put or delete for "all"
+ if ( !path.endsWith("/relationship") ) {
+ if ( !path.endsWith("}") ){
+ skipPutDelete = true;
+ }
+
+ }
+ if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
+ // add PUT
+ if ( path.endsWith("/relationship") ) {
+ pathSb.append(" " + path + ":\n" );
+ }
+ pathSb.append(" put:\n");
+ pathSb.append(" tags:\n");
+ pathSb.append(" - " + tag + "\n");
+
+ if ( validEdges != null && path.endsWith("/relationship") ) {
+ pathSb.append(" summary: see description for " + xmlRootElementName + " valid edges\n");
+ pathSb.append( validEdges );
+ } else {
+ pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n");
+ pathSb.append(" description: create or update an existing " + xmlRootElementName + "\n");
+ }
+ pathSb.append(" operationId: createOrUpdate" + useOpId + "\n");
+ pathSb.append(" consumes:\n");
+ pathSb.append(" - application/json\n");
+ pathSb.append(" - application/xml\n");
+ pathSb.append(" produces:\n");
+ pathSb.append(" - application/json\n");
+ pathSb.append(" - application/xml\n");
+ pathSb.append(" responses:\n");
+ pathSb.append(" \"default\":\n");
+ pathSb.append(" " + responsesUrl);
+ /*
+ pathSb.append(" responses:\n");
+ pathSb.append(" \"200\":\n");
+ pathSb.append(" description: existing resource has been modified and there is a response buffer\n");
+ pathSb.append(" \"201\":\n");
+ pathSb.append(" description: new resource is created\n");
+ pathSb.append(" \"202\":\n");
+ pathSb.append(" description: action requested but may have taken other actions as well, which are returned in the response payload\n");
+ pathSb.append(" \"204\":\n");
+ pathSb.append(" description: existing resource has been modified and there is no response buffer\n");
+ pathSb.append(" \"400\":\n");
+ pathSb.append(" description: Bad Request will be returned if headers are missing\n");
+ pathSb.append(" \"404\":\n");
+ pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
+ */
+ pathSb.append(" parameters:\n");
+ //pathSb.append(" - in: path\n");
+ pathSb.append(pathParams); // for nesting
+ pathSb.append(" - name: body\n");
+ pathSb.append(" in: body\n");
+ pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n");
+ pathSb.append(" required: true\n");
+ pathSb.append(" schema:\n");
+ pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
+ /*
+ if ( queryParams != null ) {
+ pathSb.append(queryParams);
+ }
+ */
+ // add DELETE
+ pathSb.append(" delete:\n");
+ pathSb.append(" tags:\n");
+ pathSb.append(" - " + tag + "\n");
+ pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n");
+
+ pathSb.append(" description: delete an existing " + xmlRootElementName + "\n");
+
+ pathSb.append(" operationId: delete" + useOpId + "\n");
+ pathSb.append(" consumes:\n");
+ pathSb.append(" - application/json\n");
+ pathSb.append(" - application/xml\n");
+ pathSb.append(" produces:\n");
+ pathSb.append(" - application/json\n");
+ pathSb.append(" - application/xml\n");
+ pathSb.append(" responses:\n");
+ pathSb.append(" \"default\":\n");
+ pathSb.append(" " + responsesUrl);
+ /*
+ pathSb.append(" responses:\n");
+ pathSb.append(" \"200\":\n");
+ pathSb.append(" description: successful, the response includes an entity describing the status\n");
+ pathSb.append(" \"204\":\n");
+ pathSb.append(" description: successful, action has been enacted but the response does not include an entity\n");
+ pathSb.append(" \"400\":\n");
+ pathSb.append(" description: Bad Request will be returned if headers are missing\n");
+ pathSb.append(" \"404\":\n");
+ pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
+ */
+ pathSb.append(" parameters:\n");
+ //pathSb.append(" - in: path\n");
+ pathSb.append(pathParams); // for nesting
+ if ( !path.endsWith("/relationship") ) {
+ pathSb.append(" - name: resource-version\n");
+
+ pathSb.append(" in: query\n");
+ pathSb.append(" description: resource-version for concurrency\n");
+ pathSb.append(" required: true\n");
+ pathSb.append(" type: string\n");
+ }
+ /*
+ if ( queryParams != null ) {
+ pathSb.append(queryParams);
+ }
+ */
+ }
+
+ }
+ if ( generatedJavaType.containsKey(xmlRootElementName) ) {
+ return null;
+ }
+ definitionsSb.append(" " + xmlRootElementName + ":\n");
+ if ( pathDescriptionProperty != null )
+ definitionsSb.append(" description: >\n " + pathDescriptionProperty
+ + "\n" );
+
+ if ( requiredCnt > 0 )
+ definitionsSb.append(sbRequired);
+ if ( propertyCnt > 0 ) {
+ definitionsSb.append(" properties:\n");
+ definitionsSb.append(sbProperties);
+ }
+ generatedJavaType.put(xmlRootElementName, null);
+ return null;
+ }
+
+ public static String generateSwaggerFromOxmFile( File oxmFile )
+ {
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("swagger: \"2.0\"\ninfo:\n description:\n A&AI REST API\n version: \"" + apiVersion +"\"\n");
+ sb.append(" title: Active and Available Inventory REST API\n");
+ sb.append(" contact:\n name: A&AI Delivery Team\n");
+ sb.append("host: host.openecomp.com\nbasePath: /aai/" + apiVersion + "\n");
+ sb.append("schemes:\n - https\npaths:\n");
+ /*
+ sb.append("responses:\n");
+ sb.append(" \"200\":\n");
+ sb.append(" description: successful operation\n");
+ sb.append(" \"404\":\n");
+ sb.append(" description: resource was not found\n");
+ sb.append(" \"400\":\n");
+ sb.append(" description: bad request\n");
+ */
+ try {
+
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ Document doc = dBuilder.parse(oxmFile);
+
+ NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
+ Element bindingElement;
+ NodeList javaTypesNodes;
+ Element javaTypesElement;
+
+ Element javaTypeElement;
+
+
+ if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
+ System.out.println( "missing <binding-nodes> in " + oxmFile );
+ return null;
+ }
+
+ bindingElement = (Element) bindingsNodes.item(0);
+ javaTypesNodes = bindingElement.getElementsByTagName("java-types");
+ if ( javaTypesNodes.getLength() < 1 ) {
+ System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
+ return null;
+ }
+ javaTypesElement = (Element) javaTypesNodes.item(0);
+
+ javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
+ if ( javaTypeNodes.getLength() < 1 ) {
+ System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
+ return null;
+ }
+
+ String javaTypeName;
+ String attrName, attrValue;
+ Attr attr;
+ StringBuffer pathSb = new StringBuffer();
+
+ StringBuffer definitionsSb = new StringBuffer("definitions:\n");
+
+ for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
+ javaTypeElement = (Element) javaTypeNodes.item(i);
+ NamedNodeMap attributes = javaTypeElement.getAttributes();
+ javaTypeName = null;
+ for ( int j = 0; j < attributes.getLength(); ++j ) {
+ attr = (Attr) attributes.item(j);
+ attrName = attr.getNodeName();
+ attrValue = attr.getNodeValue();
+ if ( attrName.equals("name"))
+ javaTypeName = attrValue;
+ }
+ if ( javaTypeName == null ) {
+ System.out.println( "<java-type> has no name attribute in " + oxmFile );
+ return null;
+ }
+ if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
+
+ //generatedJavaType.put(javaTypeName, null);
+ //if ( javaTypeName.equals("search")||javaTypeName.equals("actions"))
+
+ processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
+ definitionsSb, null, null, null, null, null, null, null);
+ }
+ }
+ sb.append(pathSb);
+ //System.out.println( "definitions block\n" + definitionsSb.toString());
+ sb.append(definitionsSb.toString());
+ //sb.append(definitionsSb);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ //System.out.println("generated " + sb.toString());
+ return sb.toString();
+ }
+
+ private static NodeList locateXmlProperties(Element element) {
+ XPathExpression expr;
+ try {
+ expr = xpath.compile("xml-properties");
+ Object result = expr.evaluate(element, XPathConstants.NODESET);
+ NodeList nodes = (NodeList) result;
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Element xmlProperty = (Element)nodes.item(i);
+ return xmlProperty.getElementsByTagName("xml-property");
+ }
+ } catch (XPathExpressionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/GetResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/GetResource.java
new file mode 100644
index 0000000..491f7b1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/GetResource.java
@@ -0,0 +1,161 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.eelf.configuration.Configuration;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+
+public class GetResource {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAI-TOOLS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ private static final String USAGE_STRING = "Usage: getTool.sh <resource-path> \n + "
+ + "for example: resource-path for a particular customer is business/customers/customer/global-customer-id-1 \n";
+
+ /**
+ * The main method.
+ *
+ * @param args
+ * the arguments
+ */
+ public static void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_GETRES_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(GetResource.class.getName());
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+ String url = null;
+ try {
+ if (args.length < 1) {
+ System.out.println("Nothing to get or Insufficient arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient arguments");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7403"), logline, null);
+ aaiLogger.info(logline, false, "AAI_7403");
+ System.exit(1);
+ } else {
+ // Assume the config AAI_SERVER_URL has a last slash so remove
+ // if
+ // resource-path has it as the first char
+ url = args[0].replaceFirst("^/", "");
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + url;
+
+ logline.add("url", url);
+ System.out.println("url=" + url);
+ getNode(aaiLogger, logline, url);
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+ }
+ } catch (AAIException e) {
+ System.out.println("GET failed:" + e.getMessage());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println("GET failed");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+
+ }
+
+ /**
+ * Gets the node.
+ *
+ * @param aaiLogger
+ * the aai logger
+ * @param logline
+ * the logline
+ * @param url
+ * the url
+ * @return the node
+ * @throws AAIException
+ * the AAI exception
+ */
+
+ public static void getNode(AAILogger aaiLogger, LogLine logline, String url) throws AAIException {
+ try {
+
+ String useBasicAuth = AAIConfig.get("aai.tools.enableBasicAuth");
+ Client client = null;
+
+ if (useBasicAuth != null && useBasicAuth.equals("true")) {
+ client = HttpsAuthClient.getBasicAuthClient();
+ } else {
+ client = HttpsAuthClient.getTwoWaySSLClient();
+ }
+
+ System.out.println("Getting the resource...: " + url);
+
+ ClientResponse cres = client.resource(url).header("X-TransactionId", TRANSID)
+ .header("X-FromAppId", FROMAPPID).header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue()).accept("application/json").get(ClientResponse.class);
+
+ logline.add("status", cres.getStatus());
+
+ if (cres.getStatus() == 404) { // resource not found
+ String msg = "Resource does not exist: " + cres.getStatus() + ":" + cres.getEntity(String.class);
+ System.out.println("\n" + msg);
+ logline.add("msg", msg);
+ throw new AAIException("AAI_7404", "Resource does not exist");
+ } else if (cres.getStatus() == 200) {
+ String msg = cres.getEntity(String.class);
+ ObjectMapper mapper = new ObjectMapper();
+ Object json = mapper.readValue(msg, Object.class);
+ String indented = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
+ System.out.println(indented);
+ } else {
+ System.out.println(
+ "Getting the Resource failed: " + cres.getStatus() + ":\n" + cres.getEntity(String.class));
+ throw new AAIException("AAI_7402", "Error during GET");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/HbaseSaltPrefixer.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/HbaseSaltPrefixer.java
new file mode 100644
index 0000000..ba1575c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/HbaseSaltPrefixer.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+/*
+ * logging to hbase encountered hotspotting issues, so per
+ * http://archive.cloudera.com/cdh5/cdh/5/hbase-0.98.6-cdh5.3.8/book/rowkey.design.html
+ * we decided to salt the rowkeys
+ * as these keys are generated in a couple places, I made a class to contain that logic
+ */
+public class HbaseSaltPrefixer {
+ private int NUM_REGION_BUCKETS = 3; //the number of hbase region servers per cluster
+
+ private static class SingletonHolder{
+ private static final HbaseSaltPrefixer INSTANCE = new HbaseSaltPrefixer();
+ }
+
+ /**
+ * Instantiates a new hbase salt prefixer.
+ */
+ private HbaseSaltPrefixer(){}
+
+ /**
+ * Gets the single instance of HbaseSaltPrefixer.
+ *
+ * @return single instance of HbaseSaltPrefixer
+ */
+ public static HbaseSaltPrefixer getInstance() {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * Prepend salt.
+ *
+ * @param key the key
+ * @return the string
+ */
+ public String prependSalt(String key) {
+ int salt = Math.abs(key.hashCode()) % NUM_REGION_BUCKETS;
+ return salt + "-" + key;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java
new file mode 100644
index 0000000..c5636e6
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.FileInputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+
+import org.openecomp.aai.exceptions.AAIException;
+
+//import org.openecomp.aai.domain.yang.Customers;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+import com.sun.jersey.api.json.JSONConfiguration;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+//import com.sun.jndi.toolkit.chars.BASE64Encoder;
+//import org.apache.commons.codec.binary.Base64;
+import static java.util.Base64.getEncoder;
+
+
+
+public class HttpsAuthClient {
+
+ /**
+ * The main method.
+ *
+ * @param args
+ * the arguments
+ */
+ public static void main(String[] args) {
+ try {
+ String url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + "business/customers";
+ System.out.println("Making Jersey https call...");
+ Client client = HttpsAuthClient.getTwoWaySSLClient();
+
+ ClientResponse res = client.resource(url).accept("application/json").header("X-TransactionId", "PROV001")
+ .header("X-FromAppId", "AAI").type("application/json").get(ClientResponse.class);
+
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static Client getBasicAuthClient() throws AAIException {
+
+ String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME);
+ System.setProperty("javax.net.ssl.trustStore", truststore_path);
+
+ javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
+ public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
+ return true;
+ }
+ });
+
+ String userName = AAIConfig.get("aai.tools.username");
+ String password = AAIConfig.get("aai.tools.password");
+ // ClientConfig config = new DefaultClientConfig();
+ Client client = Client.create();
+ //client.addFilter(new HTTPBasicAuthFilter(userName, password));
+
+
+
+
+ return client;
+ }
+
+ public static String getBasicAuthHeaderValue() throws AAIException {
+
+
+ String userName = AAIConfig.get("aai.tools.username");
+ String password = AAIConfig.get("aai.tools.password");
+ String authString = userName + ":" + password;
+ byte[] s = getEncoder().encode(authString.getBytes());
+ String basicauthStringEnc = new String(s);
+
+ return "Basic " + basicauthStringEnc;
+
+ }
+
+
+
+
+ /**
+ * Gets the client.
+ *
+ * @return the client
+ * @throws KeyManagementException
+ * the key management exception
+ */
+ public static Client getTwoWaySSLClient() throws KeyManagementException {
+
+ ClientConfig config = new DefaultClientConfig();
+ config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+ config.getClasses().add(org.openecomp.aai.rest.CustomJacksonJaxBJsonProvider.class);
+
+ SSLContext ctx = null;
+ try {
+ String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH
+ + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME);
+ String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD);
+ String keystore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_KEYSTORE_FILENAME);
+ String keystore_password = AAIConfig.get(AAIConstants.AAI_KEYSTORE_PASSWD);
+
+ System.setProperty("javax.net.ssl.trustStore", truststore_path);
+ System.setProperty("javax.net.ssl.trustStorePassword", truststore_password);
+ HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+ public boolean verify(String string, SSLSession ssls) {
+ return true;
+ }
+ });
+
+ ctx = SSLContext.getInstance("TLSv1.2");
+ KeyManagerFactory kmf = null;
+ try {
+ kmf = KeyManagerFactory.getInstance("SunX509");
+ FileInputStream fin = new FileInputStream(keystore_path);
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ char[] pwd = keystore_password.toCharArray();
+ ks.load(fin, pwd);
+ kmf.init(ks, pwd);
+ } catch (Exception e) {
+ System.out.println("Error setting up kmf: exiting");
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ ctx.init(kmf.getKeyManagers(), null, null);
+ config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
+ new HTTPSProperties(new HostnameVerifier() {
+ @Override
+ public boolean verify(String s, SSLSession sslSession) {
+ return true;
+ }
+ }, ctx));
+ } catch (Exception e) {
+ System.out.println("Error setting up config: exiting");
+ e.printStackTrace();
+ System.exit(1);
+ }
+
+ Client client = Client.create(config);
+
+ return client;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthExternalClient.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthExternalClient.java
new file mode 100644
index 0000000..dccbeb8
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthExternalClient.java
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.FileInputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+
+import org.openecomp.aai.domain.yang.Customers;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+import com.sun.jersey.api.json.JSONConfiguration;
+import com.sun.jersey.client.urlconnection.HTTPSProperties;
+
+public class HttpsAuthExternalClient {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+ try {
+ String url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + "business/customers";
+ System.out.println("Making Jersey https call...");
+ String keystore = args[0];
+ String keypasswd = args[1];
+ Client client = HttpsAuthExternalClient.getClient(keystore, keypasswd);
+
+ ClientResponse res = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", "PROV001")
+ .header("X-FromAppId", "AAI")
+ .type("application/json")
+ .get(ClientResponse.class);
+
+// System.out.println("Jersey result: ");
+// System.out.println(res.getEntity(String.class).toString());
+
+ Customers customers = res.getEntity(Customers.class);
+ System.out.println("Jersey result: ");
+ System.out.println("Number of customers: " + customers.getCustomer().size());
+
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Gets the client.
+ *
+ * @param keystoreFileName the keystore file name
+ * @param keystorePassword the keystore password
+ * @return the client
+ * @throws Exception the exception
+ */
+ public static Client getClient ( String keystoreFileName, String keystorePassword ) throws Exception {
+
+ ClientConfig config = new DefaultClientConfig();
+ config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+ config.getClasses().add(org.openecomp.aai.rest.CustomJacksonJaxBJsonProvider.class);
+ Client client = null;
+ SSLContext ctx = null;
+
+ try {
+ String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME);
+ String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD);
+ String keystore_path = AAIConstants.AAI_HOME_ETC_AUTH + keystoreFileName;
+ String keystore_password = keystorePassword;
+
+ //System.setProperty("javax.net.ssl.trustStore", truststore_path);
+ //System.setProperty("javax.net.ssl.trustStorePassword", truststore_password);
+ HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
+ public boolean verify(String string,SSLSession ssls) {
+ return true;
+ }
+ });
+
+ ctx = SSLContext.getInstance("TLS");
+ KeyManagerFactory kmf = null;
+
+
+ /**** kmf = KeyManagerFactory.getInstance("SunX509");
+ FileInputStream fin = new FileInputStream(keystore_path);
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ char[] pwd = keystore_password.toCharArray();
+ ks.load(fin, pwd);
+ kmf.init(ks, pwd);
+ ***/
+
+ String alg = TrustManagerFactory.getDefaultAlgorithm();
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg);
+ FileInputStream tin = new FileInputStream(truststore_path);
+ KeyStore ts = KeyStore.getInstance("PKCS12");
+ char[] tpwd = truststore_password.toCharArray();
+ ts.load(tin, tpwd);
+ tmf.init(ts);
+
+ //ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ // Updating key manager to null, to disable two way SSL
+ ctx.init(null, tmf.getTrustManagers(), null);
+
+ config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
+ new HTTPSProperties( new HostnameVerifier() {
+ @Override
+ public boolean verify( String s, SSLSession sslSession ) {
+ return true;
+ }
+ }, ctx));
+
+ client = Client.create(config);
+ // uncomment this line to get more logging for the request/response
+ // client.addFilter(new LoggingFilter(System.out));
+ } catch (Exception e) {
+ throw e;
+ }
+ return client;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java
new file mode 100644
index 0000000..f08fa7c
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.eclipse.jetty.util.security.Password;
+import org.openecomp.aai.exceptions.AAIException;
+
+/*
+ * The purpose of this class is to be a tool for
+ * manually applying jetty obfuscation/deobfuscation
+ * so that one can obfuscate the various passwords/secrets
+ * in aaiconfig.properties.
+ *
+ * Originally, they were being encrypted by a similar
+ * command line utility, however the encryption key
+ * was being hardcoded in the src package
+ * which is a security violation.
+ * Since this ultimately just moved the problem of how
+ * to hide secrets to a different secret in a different file,
+ * and since that encryption was really just being done to
+ * obfuscate those values in case someone needed to look at
+ * properties with others looking at their screen,
+ * we decided that jetty obfuscation would be adequate
+ * for that task as well as
+ * removing the "turtles all the way down" secret-to-hide-
+ * the-secret-to-hide-the-secret problem.
+ */
+public class JettyObfuscationConversionCommandLineUtil {
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args){
+ Options options = new Options();
+ options.addOption("e", true, "obfuscate the given string");
+ options.addOption("d", true, "deobfuscate the given string");
+
+ CommandLineParser parser = new BasicParser();
+
+ try {
+ CommandLine cmd = parser.parse(options, args);
+ String toProcess = null;
+
+ if (cmd.hasOption("e")){
+ toProcess = cmd.getOptionValue("e");
+ String encoded = Password.obfuscate(toProcess);
+ System.out.println(encoded);
+ } else if (cmd.hasOption("d")) {
+ toProcess = cmd.getOptionValue("d");
+ String decoded_str = Password.deobfuscate(toProcess);
+ System.out.println(decoded_str);
+ } else {
+ usage();
+ }
+ } catch (ParseException e) {
+ System.out.println("failed to parse input");
+ System.out.println(e.toString());
+ usage();
+ } catch (Exception e) {
+ System.out.println("exception:" + e.toString());
+ }
+ }
+
+ /**
+ * Usage.
+ */
+ private static void usage(){
+ System.out.println("usage:");;
+ System.out.println("-e [string] to obfuscate");
+ System.out.println("-d [string] to deobfuscate");
+ System.out.println("-h help");
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/KeyValueList.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/KeyValueList.java
new file mode 100644
index 0000000..9628f99
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/KeyValueList.java
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "key",
+ "value"
+})
+public class KeyValueList {
+
+ @JsonProperty("key")
+ private String key;
+ @JsonProperty("value")
+ private String value;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The key
+ */
+ @JsonProperty("key")
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ *
+ * @param key
+ * The key
+ */
+ @JsonProperty("key")
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public KeyValueList withKey(String key) {
+ this.key = key;
+ return this;
+ }
+
+ /**
+ *
+ * @return
+ * The value
+ */
+ @JsonProperty("value")
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ *
+ * @param value
+ * The value
+ */
+ @JsonProperty("value")
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public KeyValueList withValue(String value) {
+ this.value = value;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+ public KeyValueList withAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder().append(key).append(value).append(additionalProperties).toHashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if ((other instanceof KeyValueList) == false) {
+ return false;
+ }
+ KeyValueList rhs = ((KeyValueList) other);
+ return new EqualsBuilder().append(key, rhs.key).append(value, rhs.value).append(additionalProperties, rhs.additionalProperties).isEquals();
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/MapperUtil.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/MapperUtil.java
new file mode 100644
index 0000000..b3193c8
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/MapperUtil.java
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import org.openecomp.aai.exceptions.AAIException;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+
+public class MapperUtil {
+
+
+ /**
+ * Read as object of.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param value the value
+ * @return the t
+ * @throws AAIException the AAI exception
+ */
+ public static <T> T readAsObjectOf(Class<T> clazz, String value) throws AAIException {
+ com.fasterxml.jackson.databind.ObjectMapper MAPPER = new ObjectMapper();
+ try {
+ return MAPPER.readValue(value, clazz);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4007", e);
+ }
+ }
+
+ /**
+ * Read with dashes as object of.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param value the value
+ * @return the t
+ * @throws AAIException the AAI exception
+ */
+ public static <T> T readWithDashesAsObjectOf(Class<T> clazz, String value) throws AAIException {
+ com.fasterxml.jackson.databind.ObjectMapper MAPPER = new ObjectMapper();
+ try {
+ MAPPER.registerModule(new JaxbAnnotationModule());
+ MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
+
+ return MAPPER.readValue(value, clazz);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4007", e);
+ }
+ }
+
+ /**
+ * Write as JSON string.
+ *
+ * @param obj the obj
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String writeAsJSONString(Object obj) throws AAIException {
+ com.fasterxml.jackson.databind.ObjectMapper MAPPER = new ObjectMapper();
+ try {
+ String s = MAPPER.writeValueAsString(obj);
+ return s;
+ //readValue(value, clazz);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4008", e);
+ }
+ }
+
+ /**
+ * Write as JSON string with dashes.
+ *
+ * @param obj the obj
+ * @return the string
+ * @throws AAIException the AAI exception
+ */
+ public static String writeAsJSONStringWithDashes(Object obj) throws AAIException {
+ com.fasterxml.jackson.databind.ObjectMapper MAPPER = new ObjectMapper();
+ try {
+ MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ MAPPER.configure(SerializationFeature.INDENT_OUTPUT, false);
+ MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
+
+ MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
+
+ MAPPER.registerModule(new JaxbAnnotationModule());
+ String s = MAPPER.writeValueAsString(obj);
+ return s;
+ } catch (Exception e) {
+ throw new AAIException("AAI_4008", e);
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/MergeResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/MergeResource.java
new file mode 100644
index 0000000..427f65b
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/MergeResource.java
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import com.sun.tools.javac.util.List;
+
+//SWGK - 01/08/2016 - Helper function to deal with concurrency control
+public class MergeResource {
+
+ //Merge Assumptions:
+ //fromresource and toresource are the same resource type and same resource object
+ //fromresource is the latest version from the DB
+ //toresource is the version of the same resource with updates
+ //merging of child elements are complete overwrite of fromresource corresponding child element
+ //merging of relationshiplist is complete overwrite of fromresource corresponding releationship element
+ //In case of supplying the only specific child element update, please specify the child element type (need not be in canonical form)
+ //For parent only update (not involving child or relationship element update), then all the child elements and relationship list will be set as null in the merged object
+ //For setting null to primitive type (including String) you have to do it after the merge is called specifically for parent only copy
+
+
+ /**
+ * Merge.
+ *
+ * @param <T> the generic type
+ * @param fromresource the fromresource
+ * @param toresource the toresource
+ * @param bupdateChildren the bupdate children
+ * @param childNamelist the child namelist
+ * @param bupdateRelatedLink the bupdate related link
+ * @return the t
+ */
+ public static <T> T merge(T fromresource, T toresource, boolean bupdateChildren, String childNamelist[], boolean bupdateRelatedLink)
+ {
+ Field[] fields = fromresource.getClass().getDeclaredFields();
+ if (fields != null)
+ {
+ for (Field field : fields)
+ {
+ try
+ {
+ field.setAccessible(true);
+ if ( field.getName().equalsIgnoreCase("resourceVersion") )
+ continue;
+ if ( isValidMergeType(field.getType()) )
+ {
+ Object obj = field.get(toresource);
+ // If the updated resource's any property to be set null then one has to set it separately for the merged object
+ if (obj != null)
+ field.set(fromresource, obj);
+ continue;
+ }
+ else
+ // set the child list or relatedTo link to be null so no updates takes place
+ field.set(fromresource, null);
+ //override situation
+ if (bupdateChildren || bupdateRelatedLink)
+ {
+ if (bupdateRelatedLink && field.getName().equalsIgnoreCase("relationshipList"))
+ {
+ Object obj = field.get(toresource);
+ field.set(fromresource, obj);
+ continue;
+ }
+ if (field.getName().equalsIgnoreCase("relationshipList"))
+ if (!bupdateRelatedLink)
+ continue;
+ // not an efficient as it blindly updates all children - onus is on callee to nullify
+ // specific child(ren) that they don't want to update after the merge call.
+ // can be optimized to send a list of children class names in canonical form
+ // but deferring for next release so that only those children can be merged
+ if (bupdateChildren && (childNamelist != null))
+ {
+ for (String classStringName : childNamelist)
+ {
+ if ( !classStringName.isEmpty() && field.getType().toString().toLowerCase().endsWith(classStringName.toLowerCase()) )
+ {
+ Object obj = field.get(toresource);
+ field.set(fromresource, obj);
+ }
+ }
+ continue;
+ }
+
+ if (bupdateChildren && (childNamelist == null))
+ {
+ Object obj = field.get(toresource);
+ field.set(fromresource, obj);
+
+ }
+ }
+
+ }
+ catch (Exception e)
+ {
+
+ }
+
+
+ }
+ }
+ return fromresource;
+ }
+
+
+ /**
+ * Merge.
+ *
+ * @param <T> the generic type
+ * @param fromresource the fromresource
+ * @param toresource the toresource
+ * @return the t
+ */
+ public static <T> T merge(T fromresource, T toresource)
+ {
+ return merge(fromresource, toresource, false, false);
+ }
+
+ /**
+ * Merge.
+ *
+ * @param <T> the generic type
+ * @param fromresource the fromresource
+ * @param toresource the toresource
+ * @param bupdateChildren the bupdate children
+ * @param bupdateRelatedLink the bupdate related link
+ * @return the t
+ */
+ public static <T> T merge(T fromresource, T toresource, boolean bupdateChildren, boolean bupdateRelatedLink)
+ {
+ return merge(fromresource, toresource, bupdateChildren, null, bupdateRelatedLink);
+ }
+
+ /**
+ * Checks if is valid merge type.
+ *
+ * @param fieldType the field type
+ * @return true, if is valid merge type
+ */
+ public static boolean isValidMergeType(Class<?> fieldType) {
+ if (fieldType.equals(String.class)) {
+ return true;
+ } else if (Date.class.isAssignableFrom(fieldType)) {
+ return true;
+ } else if (Number.class.isAssignableFrom(fieldType)) {
+ return true;
+ } else if (fieldType.equals(Integer.TYPE)) {
+ return true;
+ } else if (fieldType.equals(Long.TYPE)) {
+ return true;
+ } else if (Enum.class.isAssignableFrom(fieldType)) {
+ return true;
+ } else if (Boolean.class.isAssignableFrom(fieldType)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the child return type.
+ *
+ * @param classname the classname
+ * @param methodname the methodname
+ * @return the class
+ */
+ public static Class<?> GetChildReturnType(String classname, String methodname)
+ {
+ try {
+ Class<?> c = Class.forName(classname);
+ Method[] allMethods = c.getDeclaredMethods();
+ for (Method m : allMethods) {
+ if (!m.getName().equals(methodname)) {
+ return m.getReturnType();
+ }
+ }
+ } catch (ClassNotFoundException x) {
+
+ }
+
+ return null;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/PojoUtils.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/PojoUtils.java
new file mode 100644
index 0000000..f7b195d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/PojoUtils.java
@@ -0,0 +1,990 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+import java.util.Map.Entry;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.openecomp.aai.dbmodel.RestRules;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.Multimap;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class PojoUtils {
+
+ /**
+ * Gets the key value list.
+ *
+ * @param <T> the generic type
+ * @param e the e
+ * @param clazz the clazz
+ * @return the key value list
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ */
+ public <T> List<KeyValueList> getKeyValueList(Entity e, T clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ List<KeyValueList> kvList = e.getKeyValueList();
+ Object value = null;
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String propertyName = "";
+
+ for (Method method : methods) {
+ if (method.getName().startsWith("get")) {
+ propertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ if (!(method.getReturnType().getName().contains("aai")) || method.getReturnType().getName().contains("java.util.List")) {
+ value = method.invoke(clazz);
+ KeyValueList kv = new KeyValueList();
+ kv.setKey(propertyName);
+ if (value != null) {
+ kv.setValue(value.toString());
+ } else {
+ kv.setValue("");
+ }
+ kvList.add(kv);
+ }
+ }
+ }
+ return kvList;
+ }
+
+ /**
+ * Gets the json from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return the json from object
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public <T> String getJsonFromObject(T clazz) throws JsonGenerationException, JsonMappingException, IOException {
+ return getJsonFromObject(clazz, false, true);
+ }
+
+ /**
+ * Gets the json from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param wrapRoot the wrap root
+ * @param indent the indent
+ * @return the json from object
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public <T> String getJsonFromObject(T clazz, boolean wrapRoot, boolean indent) throws JsonGenerationException, JsonMappingException, IOException {
+ ObjectMapper mapper = new ObjectMapper();
+
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ mapper.configure(SerializationFeature.INDENT_OUTPUT, indent);
+ mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, wrapRoot);
+
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, wrapRoot);
+
+ mapper.registerModule(new JaxbAnnotationModule());
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ mapper.writeValue(baos, clazz);
+
+ return baos.toString();
+ }
+
+ /**
+ * Gets the json from dynamic object.
+ *
+ * @param ent the ent
+ * @param jaxbContext the jaxb context
+ * @param includeRoot the include root
+ * @return the json from dynamic object
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public String getJsonFromDynamicObject(DynamicEntity ent, org.eclipse.persistence.jaxb.JAXBContext jaxbContext, boolean includeRoot) throws JsonGenerationException, JsonMappingException, IOException, JAXBException {
+ org.eclipse.persistence.jaxb.JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+
+ marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+ marshaller.setProperty("eclipselink.json.include-root", includeRoot);
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(ent, writer);
+
+ return writer.toString();
+ }
+
+ /**
+ * Gets the xml from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return the xml from object
+ * @throws JAXBException the JAXB exception
+ */
+ public <T> String getXmlFromObject(T clazz) throws JAXBException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ JAXBContext jc = JAXBContext.newInstance(clazz.getClass().getPackage().getName());
+
+ Marshaller marshaller = jc.createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ marshaller.marshal(clazz, baos);
+
+ return baos.toString();
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @param baseUrl the base url
+ * @param lookupHash the lookup hash
+ * @param keyProps the key props
+ * @param objectType the object type
+ * @return the uri
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public String getUri (String baseUrl, HashMap<String,Object> lookupHash, Collection<String> keyProps, String objectType) throws UnsupportedEncodingException, AAIException {
+ int baseKeyLen = baseUrl.length();
+ StringBuffer newUrl = new StringBuffer();
+ if (baseKeyLen > 0) {
+ newUrl.append(baseUrl);
+ }
+ String plural = (String)RestRules.getResRules(objectType)[2];
+ if (plural != null) {
+ newUrl.append("/" + plural);
+ }
+
+ if (objectType != null) {
+ newUrl.append("/" + objectType);
+ }
+
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String keyProp = keyPropI.next();
+ String keyVal = "";
+ Object obj = lookupHash.get(keyProp);
+ if (obj instanceof String) {
+ keyVal = (String) obj;
+ } else if (obj instanceof Long) {
+ Long val = (Long)obj;
+ keyVal = val.toString();
+ } else if (obj instanceof Short) {
+ Short val = (Short)obj;
+ keyVal = val.toString();
+ } else if (obj instanceof Integer) {
+ Integer val = (Integer)obj;
+ keyVal = val.toString();
+ }
+ newUrl.append("/" + RestURL.encodeURL(keyVal));
+ }
+ return newUrl.toString();
+ }
+
+ /**
+ * Gets the lookup key.
+ *
+ * @param baseKey the base key
+ * @param lookupHash the lookup hash
+ * @param keyProps the key props
+ * @return the lookup key
+ */
+ public String getLookupKey (String baseKey, HashMap<String,Object> lookupHash, Collection<String> keyProps) {
+ int baseKeyLen = baseKey.length();
+ StringBuffer newKey = new StringBuffer();
+ if (baseKeyLen > 0) {
+ newKey.append(baseKey);
+ }
+
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String keyProp = keyPropI.next();
+ if (baseKeyLen > 0) {
+ newKey.append("&");
+ }
+ newKey.append(keyProp + "=" + lookupHash.get(keyProp));
+ }
+ return newKey.toString();
+ }
+
+ /**
+ * Gets the lookup keys.
+ *
+ * @param lookupHashes the lookup hashes
+ * @param _dbRulesNodeKeyProps the db rules node key props
+ * @return the lookup keys
+ */
+ public String getLookupKeys (LinkedHashMap<String,HashMap<String,Object>> lookupHashes, Multimap<String, String> _dbRulesNodeKeyProps) {
+ Iterator<String> it = lookupHashes.keySet().iterator();
+ String lookupKeys = "";
+ while (it.hasNext()) {
+ String objectType = (String)it.next();
+ HashMap<String,Object> lookupHash = lookupHashes.get(objectType);
+
+ Collection<String> keyProps = _dbRulesNodeKeyProps.get(objectType);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ lookupKeys += lookupHash.get(keyPropI.next());
+ }
+ }
+ return lookupKeys;
+ }
+
+ /**
+ * Sets the prop hash keys.
+ *
+ * @param aaiRes the aai res
+ * @param propHash the prop hash
+ * @param _propertyDataTypeMap the property data type map
+ * @param keysWithVals the keys with vals
+ * @param aaiExtMap the aai ext map
+ */
+ public void setPropHashKeys(AAIResource aaiRes, HashMap<String, Object> propHash,
+ Map<String, String> _propertyDataTypeMap, LinkedHashMap<String, Object> keysWithVals, AAIExtensionMap aaiExtMap) {
+
+ for (Entry<String,Object> ent : keysWithVals.entrySet()) {
+ propHash.put(ent.getKey(), ent.getValue());
+ }
+
+ }
+
+ /**
+ * Fill prop hash from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param propHash the prop hash
+ * @param _propertyDataTypeMap the property data type map
+ * @param aaiExtMap the aai ext map
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ */
+ public <T> void fillPropHashFromObject(T clazz,
+ HashMap<String, Object> propHash, Map<String, String> _propertyDataTypeMap, AAIExtensionMap aaiExtMap)
+ throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+
+
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+ String dnHypTitanPropertyName = "";
+ // couldn't i prechew this?
+ for (Method method : methods) {
+ boolean go = false;
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ go = true;
+ } else if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ go = true;
+ }
+ dnHypTitanPropertyName = dnHypPropertyName;
+ if (dnHypPropertyName.equals("cvlan-tag-entry")) {
+ dnHypTitanPropertyName = "cvlan-tag";
+ }
+
+ if (propHash.containsKey(dnHypTitanPropertyName)) {
+ // maybe check to see if the payload matches the URL, but we're not doing that now...
+ continue;
+ }
+
+ if (go) {
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+
+ if (retType.contains("String")) {
+ String val = (String)method.invoke(clazz);
+ if (val != null) {
+ propHash.put(dnHypTitanPropertyName, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ String titanType = _propertyDataTypeMap.get(dnHypTitanPropertyName);
+
+ Long val = (Long)method.invoke(clazz);
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (val != null) {
+ if (titanType.toLowerCase().contains("int")) {
+ propHash.put(dnHypTitanPropertyName, val.intValue());
+ } else {
+ propHash.put(dnHypTitanPropertyName, val);
+ }
+ }
+
+ } else if (retType.toLowerCase().contains("int")) {
+ Integer val = (Integer)method.invoke(clazz);
+ if (val != null) {
+ propHash.put(dnHypTitanPropertyName, val);
+ }
+ } else if (retType.toLowerCase().contains("short")) {
+ Short val = (Short)method.invoke(clazz);
+ if (val != null) {
+ propHash.put(dnHypTitanPropertyName, val);
+ }
+ } else if (retType.toLowerCase().contains("boolean")) {
+ Boolean val = (Boolean)method.invoke(clazz);
+ if (val != null) {
+ propHash.put(dnHypTitanPropertyName, val);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the example object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param singleton the singleton
+ * @return the example object
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ */
+ public <T> void getExampleObject(T clazz, boolean singleton) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException {
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+ String upCamPropertyName = "";
+ Random rand = new Random();
+ int randInt = rand.nextInt(10000000);
+
+ for (Method method : methods) {
+ boolean go = false;
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(3));
+ go = true;
+ } else if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(2));
+ go = true;
+ }
+ // don't return resource-version on a singleton
+ if (singleton && dnHypPropertyName.equals("resource-version")) {
+ go = false;
+ }
+ if (go) {
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+ Method meth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+
+ if (retType.contains("String")) {
+ String val = "example-" + dnHypPropertyName + "-val-" + randInt;
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ Integer foo = rand.nextInt(100000);
+ meth.invoke(clazz, foo.longValue());
+ } else if (retType.toLowerCase().contains("int")) {
+ meth.invoke(clazz, rand.nextInt(100000));
+ } else if (retType.toLowerCase().contains("short")) {
+ Integer randShort = rand.nextInt(10000);
+ meth.invoke(clazz, randShort.shortValue());
+ } else if (retType.toLowerCase().contains("boolean")) {
+ meth.invoke(clazz, true);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Gets the aai object from vertex.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param vert the vert
+ * @param _propertyDataTypeMap the property data type map
+ * @return the aai object from vertex
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ */
+ public <T> void getAaiObjectFromVertex(T clazz, TitanVertex vert, Map<String, String> _propertyDataTypeMap) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException {
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+ String upCamPropertyName = "";
+ for (Method method : methods) {
+ boolean go = false;
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(3));
+ go = true;
+ } else if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(2));
+ go = true;
+ }
+ if (go) {
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+ Method meth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+
+ if (retType.contains("String")) {
+ String val = (String)vert.<String>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ String titanType = _propertyDataTypeMap.get(dnHypPropertyName);
+
+ Long val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(dnHypPropertyName).orElse(null);
+ if (intVal != null) {
+ val = intVal.longValue();
+ }
+ } else {
+ val = (Long)vert.<Long>property(dnHypPropertyName).orElse(null);
+ }
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("int")) {
+ Integer val = (Integer)vert.<Integer>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("short")) {
+ Short val = (Short)vert.<Short>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("boolean")) {
+ Boolean val = (Boolean)vert.<Boolean>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the topology object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param _dbRulesNodeNameProps the db rules node name props
+ * @param _dbRulesNodeKeyProps the db rules node key props
+ * @param vert the vert
+ * @return the topology object
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ */
+ public <T> void getTopologyObject(T clazz, Multimap<String, String> _dbRulesNodeNameProps, Multimap<String, String> _dbRulesNodeKeyProps, TitanVertex vert) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException {
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+// Object value = null;
+ List<String> includeProps = new ArrayList<String>();
+
+ if ("false".equals(AAIConfig.get("aai.notification.topology.allAttrs", "false"))) {
+ for (Method method : methods) {
+ if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ String upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(2));
+ String retType = method.getReturnType().getName();
+ if (retType.equals("java.lang.Boolean")) {
+ // get the setter
+ Method setterMeth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+ setterMeth.invoke(clazz, (Boolean)null);
+ }
+ }
+ }
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,clazz.getClass().getSimpleName());
+ Collection<String> keepProps = _dbRulesNodeNameProps.get(dnHypClassName);
+ Iterator <String> keepPropI = keepProps.iterator();
+ while( keepPropI.hasNext() ){
+ includeProps.add(keepPropI.next());
+ }
+ Collection<String> keepProps2 = _dbRulesNodeKeyProps.get(dnHypClassName);
+ Iterator <String> keepPropI2 = keepProps2.iterator();
+ while( keepPropI2.hasNext() ){
+ includeProps.add(keepPropI2.next());
+ }
+ }
+
+ for (Method method : methods) {
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ if (includeProps.size() > 0) {
+ if (!includeProps.contains(dnHypPropertyName)) {
+ continue;
+ }
+ }
+ String upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(3));
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+ Method meth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+
+ if (retType.contains("String")) {
+ String val = (String)vert.<String>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ Long val = (Long)vert.<Long>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("int")) {
+ Integer val = (Integer)vert.<Integer>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("short")) {
+ Short val = (Short)vert.<Short>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the dynamic topology object.
+ *
+ * @param aaiRes the aai res
+ * @param meObjectType the me object type
+ * @param _dbRulesNodeNameProps the db rules node name props
+ * @param _dbRulesNodeKeyProps the db rules node key props
+ * @param _propertyDataTypeMap the property data type map
+ * @param vert the vert
+ * @return the dynamic topology object
+ * @throws AAIException the AAI exception
+ */
+ public DynamicEntity getDynamicTopologyObject(AAIResource aaiRes, DynamicType meObjectType, Multimap<String, String> _dbRulesNodeNameProps,
+ Multimap<String, String> _dbRulesNodeKeyProps, Map<String, String> _propertyDataTypeMap, TitanVertex vert) throws AAIException {
+
+ DynamicEntity meObject = meObjectType.newDynamicEntity();
+
+ List<String> includeProps = new ArrayList<String>();
+
+ if ("false".equals(AAIConfig.get("aai.notification.topology.allAttrs", "false"))) {
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,meObjectType.getJavaClass().getSimpleName());
+ Collection<String> keepProps = _dbRulesNodeNameProps.get(dnHypClassName);
+ Iterator <String> keepPropI = keepProps.iterator();
+ while( keepPropI.hasNext() ){
+ includeProps.add(keepPropI.next());
+ }
+ Collection<String> keepProps2 = _dbRulesNodeKeyProps.get(dnHypClassName);
+ Iterator <String> keepPropI2 = keepProps2.iterator();
+ while( keepPropI2.hasNext() ) {
+ includeProps.add(keepPropI2.next());
+ }
+ }
+
+
+
+ for (String attrName : aaiRes.getStringFields()) {
+ if (includeProps.contains(attrName)) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), vert.<String>property(attrName).orElse(null));
+ }
+ }
+ // the attrName might need to be converted to camel case!!!
+ for (String attrName : aaiRes.getLongFields()) {
+ if (includeProps.contains(attrName)) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+
+ Long val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.longValue();
+ }
+ } else {
+ val = (Long)vert.<Long>property(attrName).orElse(null);
+ }
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+
+ for (String attrName : aaiRes.getIntFields()) {
+ if (includeProps.contains(attrName)) {
+ Integer val = (Integer)vert.<Integer>property(attrName).orElse(null);
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+
+ for (String attrName : aaiRes.getShortFields()) {
+ if (includeProps.contains(attrName)) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+
+ Short val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.shortValue();
+ }
+ } else {
+ val = (Short)vert.<Short>property(attrName).orElse(null);
+ }
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+
+ for (String attrName : aaiRes.getBooleanFields()) {
+ if (includeProps.contains(attrName)) {
+ Boolean val = (Boolean)vert.<Boolean>property(attrName).orElse(null);
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ return meObject;
+ }
+
+ /**
+ * Gets the aai dynamic object from vertex.
+ *
+ * @param aaiRes the aai res
+ * @param meObject the me object
+ * @param vert the vert
+ * @param _propertyDataTypeMap the property data type map
+ * @return the aai dynamic object from vertex
+ */
+ public void getAaiDynamicObjectFromVertex(AAIResource aaiRes, DynamicEntity meObject, TitanVertex vert,
+ Map<String, String> _propertyDataTypeMap) {
+ getAaiDynamicObjectFromVertex(aaiRes, meObject, vert, _propertyDataTypeMap, null);
+ }
+
+ /**
+ * Gets the aai dynamic object from vertex.
+ *
+ * @param aaiRes the aai res
+ * @param meObject the me object
+ * @param vert the vert
+ * @param _propertyDataTypeMap the property data type map
+ * @param propertyOverRideHash the property over ride hash
+ * @return the aai dynamic object from vertex
+ */
+ @SuppressWarnings("unchecked")
+ public void getAaiDynamicObjectFromVertex(AAIResource aaiRes, DynamicEntity meObject, TitanVertex vert,
+ Map<String, String> _propertyDataTypeMap, HashMap<String, Object> propertyOverRideHash) {
+
+ for (String attrName : aaiRes.getStringFields()) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), vert.<String>property(attrName).orElse(null));
+ }
+ }
+
+ for (String attrName : aaiRes.getStringListFields()) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), vert.<ArrayList<String>>property(attrName).orElse(null));
+ }
+ }
+
+ // the attrName might need to be converted to camel case!!!
+ for (String attrName : aaiRes.getLongFields()) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+ Long val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.longValue();
+ }
+ } else {
+ val = (Long)vert.<Long>property(attrName).orElse(null);
+ }
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ for (String attrName : aaiRes.getIntFields()) {
+ Integer val = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ for (String attrName : aaiRes.getShortFields()) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+ Short val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.shortValue();
+ }
+ } else {
+ val = (Short)vert.<Short>property(attrName).orElse(null);
+ }
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ for (String attrName : aaiRes.getBooleanFields()) {
+ Boolean val = (Boolean)vert.<Boolean>property(attrName).orElse(null);
+ // This is not ideal, but moxy isn't marshalling these attributes.
+ // TODO: Figure out how to see the default-value from the OXM at startup (or at runtime).
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,aaiRes.getSimpleName());
+ if (val == null && AAIConfig.getDefaultBools().containsKey(dnHypClassName)) {
+ if (AAIConfig.getDefaultBools().get(dnHypClassName).contains(attrName)) {
+ val = false;
+ }
+ }
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Fill prop hash from dynamic object.
+ *
+ * @param aaiRes the aai res
+ * @param meObject the me object
+ * @param propHash the prop hash
+ * @param _propertyDataTypeMap the property data type map
+ * @param aaiExtMap the aai ext map
+ */
+ public void fillPropHashFromDynamicObject(AAIResource aaiRes, DynamicEntity meObject, HashMap<String, Object> propHash,
+ Map<String, String> _propertyDataTypeMap, AAIExtensionMap aaiExtMap) {
+
+ for (String dnHypAttrName : aaiRes.getStringFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ if (propHash.containsKey(dnHypAttrName)) {
+ continue;
+ }
+
+ String val = (String)meObject.get(dnCamAttrName);
+
+ if (val == null && aaiRes.getAutoGenUuidFields().contains(dnHypAttrName)) {
+ // Generate one here
+ val = UUID.randomUUID().toString();
+ }
+
+ if (val != null) {
+ propHash.put(dnHypAttrName, val);
+ }
+ }
+
+ for (String dnHypAttrName : aaiRes.getStringListFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ if (propHash.containsKey(dnHypAttrName)) {
+ continue;
+ }
+
+ @SuppressWarnings("unchecked")
+ ArrayList<String> val = (ArrayList<String>)meObject.get(dnCamAttrName);
+ if (val != null) {
+ propHash.put(dnHypAttrName, val);
+ }
+ }
+
+ // the attrName might need to be converted to camel case!!!
+ for (String dnHypAttrName : aaiRes.getLongFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ if (propHash.containsKey(dnHypAttrName)) {
+ continue;
+ }
+
+ String titanType = _propertyDataTypeMap.get(dnHypAttrName);
+
+ Long val = (Long)meObject.get(dnCamAttrName);
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (val != null) {
+ if (titanType.toLowerCase().contains("int")) {
+ propHash.put(dnHypAttrName, val.intValue());
+ } else {
+ propHash.put(dnHypAttrName, val);
+ }
+ }
+ }
+
+ for (String dnHypAttrName : aaiRes.getIntFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ if (propHash.containsKey(dnHypAttrName)) {
+ continue;
+ }
+ Integer val = (Integer)meObject.get(dnCamAttrName);
+ if (val != null) {
+ propHash.put(dnHypAttrName, val);
+ }
+ }
+
+ for (String dnHypAttrName : aaiRes.getShortFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ if (propHash.containsKey(dnHypAttrName)) {
+ continue;
+ }
+ String titanType = _propertyDataTypeMap.get(dnHypAttrName);
+
+ Short val = (Short)meObject.get(dnCamAttrName);
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (val != null) {
+ if (titanType.toLowerCase().contains("int")) {
+ propHash.put(dnHypAttrName, val.intValue());
+ } else {
+ propHash.put(dnHypAttrName, val);
+ }
+ }
+ }
+
+ for (String dnHypAttrName : aaiRes.getBooleanFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ if (propHash.containsKey(dnHypAttrName)) {
+ continue;
+ }
+ Boolean val = (Boolean)meObject.get(dnCamAttrName);
+ if (val != null) {
+ propHash.put(dnHypAttrName, val);
+ } else {
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,aaiRes.getSimpleName());
+ if (AAIConfig.getDefaultBools().containsKey(dnHypClassName)) {
+ if (AAIConfig.getDefaultBools().get(dnHypClassName).contains(dnHypAttrName)) {
+ propHash.put(dnHypAttrName, false);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the dynamic example object.
+ *
+ * @param childObject the child object
+ * @param aaiRes the aai res
+ * @param singleton the singleton
+ * @return the dynamic example object
+ */
+ public void getDynamicExampleObject(DynamicEntity childObject, AAIResource aaiRes, boolean singleton) {
+ // TODO Auto-generated method stub
+
+ Random rand = new Random();
+ Integer randInt = rand.nextInt(100000);
+ long range = 100000000L;
+ long randLong = (long)(rand.nextDouble()*range);
+ Integer randShrt = rand.nextInt(20000);
+ short randShort = randShrt.shortValue();
+
+ for (String dnHypAttrName : aaiRes.getStringFields()) {
+
+ if (singleton && ("resource-version").equals(dnHypAttrName)) {
+ continue;
+ }
+
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, "example-" + dnHypAttrName + "-val-" + randInt);
+
+ }
+
+ for (String dnHypAttrName : aaiRes.getStringListFields()) {
+ ArrayList<String> exampleList = new ArrayList<String>();
+ exampleList.add("example-" + dnHypAttrName + "-val-" + randInt + "-" + 1);
+ exampleList.add("example-" + dnHypAttrName + "-val-" + randInt + "-" + 2);
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, exampleList);
+ }
+
+ // the attrName might need to be converted to camel case!!!
+ for (String dnHypAttrName : aaiRes.getLongFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, randLong);
+ }
+
+ for (String dnHypAttrName : aaiRes.getIntFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, randInt);
+ }
+
+ for (String dnHypAttrName : aaiRes.getShortFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, randShort);
+ }
+
+ for (String dnHypAttrName : aaiRes.getBooleanFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, Boolean.TRUE);
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/PostResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/PostResource.java
new file mode 100644
index 0000000..5f1514e
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/PostResource.java
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.eelf.configuration.Configuration;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.CaseFormat;
+
+/*
+ * Allows to call POST REST API that AAI supports - currently for edge-tag-query
+ */
+public class PostResource {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAI-TOOLS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ private static final String USAGE_STRING = "Usage: postTool.sh <resource-path> <filename>\n" +
+ "resource-path for a particular resource or query starting after the aai/<version>\n" +
+ "filename is the path to a file which contains the json input for the payload\n" +
+ "for example: postTool.sh search/edge-tag-query /tmp/query-input.json\n";
+
+ /**
+ * The main method.
+ *
+ * @param <T> the generic type
+ * @param args the arguments
+ */
+ public static <T> void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_POSTTOOL_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(PostResource.class.getName());
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+
+ try {
+ if (args.length < 2) {
+ System.out.println("Insufficient arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient arguments");
+ aaiLogger.info(logline, false, "AAI_7403");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7403"), logline, null);
+ System.exit(1);
+ }
+
+ // Assume the config AAI_SERVER_URL has a last slash so remove if
+ // resource-path has it as the first char
+ String path = args[0].replaceFirst("^/", "");
+ Path p = Paths.get(path);
+
+ // currently , it is for edge-taq-query only
+ String query = p.getName(p.getNameCount() - 1).toString();
+ String resourceClass = null;
+ if (query.equals("edge-tag-query"))
+ resourceClass = "org.openecomp.aai.domain.search." +
+ CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, query) + "Request";
+ else {
+ logline.add("msg", "Incorrect resource or query");
+ aaiLogger.info(logline, false, "AAI_7403");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7403"), logline, null);
+ System.exit(1);
+ }
+
+ logline.add("class", resourceClass);
+ logline.add("path", path);
+// System.out.println("class=" + resourceClass);
+// System.out.println("path=" + path);
+
+ @SuppressWarnings("unchecked")
+ T resJson1 = (T)readJsonFile(Class.forName(resourceClass), args[1]);
+
+ String response = RestController.<T>Post(resJson1, FROMAPPID, TRANSID, path);
+ ObjectMapper mapper = new ObjectMapper();
+ Object json = mapper.readValue(response, Object.class);
+
+ System.out.println(" POST succeeded\n");
+ System.out.println("Response = " + mapper.writer().withDefaultPrettyPrinter().writeValueAsString(json));
+ System.out.println("\nDone!!");
+
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+
+ } catch (AAIException e) {
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.exit(1);
+ } catch (Exception e) {
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Gets the single instance of PostResource.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return single instance of PostResource
+ * @throws IllegalAccessException the illegal access exception
+ * @throws InstantiationException the instantiation exception
+ */
+ public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException
+ {
+ return clazz.newInstance();
+ }
+
+ /**
+ * Read json file.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param fName the f name
+ * @return the t
+ * @throws AAIException the AAI exception
+ */
+ public static <T> T readJsonFile( Class<T> clazz, String fName ) throws AAIException
+ {
+ String jsonData = "";
+ BufferedReader br = null;
+ T t;
+
+ try {
+ String line;
+ br = new BufferedReader(new FileReader(fName));
+ while ((line = br.readLine()) != null) {
+ jsonData += line + "\n";
+ }
+ } catch (IOException e) {
+ throw new AAIException("AAI_7403", e, "Error opening json file");
+ } finally {
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ throw new AAIException("AAI_7403", ex, "Error closing json file");
+ }
+ }
+
+ try {
+ t = MapperUtil.readWithDashesAsObjectOf(clazz, jsonData);
+ }
+ catch (Exception je){
+ throw new AAIException("AAI_7403", je, "Error parsing json file");
+ }
+
+ return t;
+
+ }//End readJsonFile()
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/PutActionsNotify.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/PutActionsNotify.java
new file mode 100644
index 0000000..ced9f9d
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/PutActionsNotify.java
@@ -0,0 +1,253 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.JAXBUnmarshaller;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.extensions.ExtensionController;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.domain.yang.Notify;
+import com.att.eelf.configuration.Configuration;
+import com.google.common.base.CaseFormat;
+
+public class PutActionsNotify {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAI-TOOLS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ private static final String USAGE_STRING = "Usage: notifyTool.sh <resource-path> <filename> \n" +
+ "for example 1: putNotify.sh actions/notify /tmp/request.json \n";
+
+ /**
+ * The main method.
+ *
+ * @param <T> the generic type
+ * @param args the arguments
+ */
+ public static <T> void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_PUTTOOL_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(PutActionsNotify.class.getName());
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+
+ try {
+ if (args.length < 2) {
+ System.out.println("Insufficient arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient arguments");
+ aaiLogger.info(logline, true, "0");
+ System.exit(1);
+ }
+
+ // Assume the config AAI_SERVER_URL has a last slash so remove if
+ // resource-path has it as the first char
+ String path = args[0].replaceFirst("^/", "");
+ Path p = Paths.get(path);
+
+ // if the node type has one key
+
+ String resource = p.getName(p.getNameCount() - 1).toString();
+ String resourceClass = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, resource);
+ resourceClass = "org.openecomp.aai.domain.yang." + resourceClass;
+
+ logline.add("class", resourceClass);
+ logline.add("path", path);
+
+ Notify resJson1 = (Notify)readJsonFile(Class.forName(resourceClass), args[1]);
+ RestController.<Notify>Put(resJson1, FROMAPPID, TRANSID, path, false);
+
+ System.out.println(" PUT succeeded\n");
+ System.out.println("\nDone!!");
+
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+
+ } catch (AAIException e) {
+ System.out.println("PUT failed: " + e.getMessage());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println("PUT failed: " + e.toString());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Gets the single instance of PutActionsNotify.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return single instance of PutActionsNotify
+ * @throws IllegalAccessException the illegal access exception
+ * @throws InstantiationException the instantiation exception
+ */
+ public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException
+ {
+ return clazz.newInstance();
+ }
+
+ /**
+ * Read json file.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param fName the f name
+ * @return the t
+ * @throws AAIException the AAI exception
+ */
+ public static <T> T readJsonFile( Class<T> clazz, String fName ) throws AAIException
+ {
+ String jsonData = "";
+ BufferedReader br = null;
+ T t;
+
+ try {
+ String line;
+ br = new BufferedReader(new FileReader(fName));
+ while ((line = br.readLine()) != null) {
+ jsonData += line + "\n";
+ }
+ } catch (IOException e) {
+
+ throw new AAIException("AAI_7403", e, "Error opening json file");
+ } finally {
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+
+ throw new AAIException("AAI_7403", ex, "Error closing json file");
+ }
+ }
+
+ try {
+ t = MapperUtil.readWithDashesAsObjectOf(clazz, jsonData);
+ }
+ catch (Exception je){
+ throw new AAIException("AAI_7403", je, "Error parsing json file");
+ }
+
+ return t;
+
+ }//End readJsonFile()
+
+ /**
+ * Gets the resource version.
+ *
+ * @param <T> the generic type
+ * @param resource the resource
+ * @return the string
+ */
+ public static <T> String GetResourceVersion(T resource)
+ {
+ Field[] fields = resource.getClass().getDeclaredFields();
+ if (fields != null)
+ {
+ for (Field field : fields)
+ {
+ try
+ {
+ field.setAccessible(true);
+ if ( field.getName().equalsIgnoreCase("resourceVersion") )
+ {
+ Object obj = field.get(resource);
+ return (String)obj;
+ }
+
+
+ }
+ catch (Exception e)
+ {
+
+ }
+
+
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the dynamic entity for request.
+ *
+ * @param jaxbContext the jaxb context
+ * @param aaiRes the aai res
+ * @param objectFromRequest the object from request
+ * @param aaiExtMap the aai ext map
+ * @return the dynamic entity for request
+ * @throws JAXBException the JAXB exception
+ */
+ protected static DynamicEntity getDynamicEntityForRequest(DynamicJAXBContext jaxbContext,
+ AAIResource aaiRes,
+ String objectFromRequest,
+ AAIExtensionMap aaiExtMap) throws JAXBException {
+DynamicEntity request = null;
+if (objectFromRequest != null) {
+JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+String dynamicClass = aaiRes.getResourceClassName();
+
+//if (aaiExtMap.getHttpServletRequest().getContentType() == null ||
+//aaiExtMap.getHttpServletRequest().getContentType().equalsIgnoreCase("application/json")) {
+unmarshaller.setProperty("eclipselink.media-type", "application/json");
+unmarshaller.setProperty("eclipselink.json.include-root", false);
+//}
+
+Class<? extends DynamicEntity> resultClass = jaxbContext.newDynamicEntity(dynamicClass).getClass();
+StringReader reader = new StringReader(objectFromRequest);
+request = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(reader), resultClass).getValue();
+}
+return request;
+}
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/PutResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/PutResource.java
new file mode 100644
index 0000000..0309872
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/PutResource.java
@@ -0,0 +1,470 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyManagementException;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+import org.openecomp.aai.logging.LogLine;
+
+import com.att.eelf.configuration.Configuration;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.CaseFormat;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+
+/*
+ * SWGK - 09/03/2015 - Added Generics to Put as well as to Get the object that was created/updated
+ * by Put to get the Object back.
+ */
+public class PutResource {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAI-TOOLS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+
+ private static final String USAGE_STRING = "Usage: putTool.sh <resource-path> <filename> <UpdatingRelationshiplist> <UpdatingChild> <ChildNameList> <SkipIfExists>\n" +
+ "resource-path for a particular resource starting after the aai/<version>\n" +
+ "filename is the path to a file which contains the json input for the payload\n" +
+ "optional UpdatingRelationshiplist setting 1 for updating the relationship list and if setting 0 relationship list will not be updated.\n" +
+ "optional UpdatingChild setting 1 for updating the child(r)en and if setting 0 child(ren) will not be updated.\n" +
+ "optional ChildNameList is a comma-separated child(ren) name list only applicable if UpdatingChild is set to 1.\n" +
+ "optional SkipIfExisting setting 1 to skip the update if resource exists and if setting 0 put will be done.\n" +
+ "for example 1: putTool.sh cloud-infrastructure/oam-networks/oam-network/test-100-oam /tmp/putoam.json\n" +
+ "for example 2: putTool.sh cloud-infrastructure/pservers/pserver/dpa2r04c009-swgk-009 /tmp/pserver.json 0 1 PInterfaces,LagInterfaces\n" +
+ "for example 2: putTool.sh cloud-infrastructure/pservers/pserver/dpa2r04c009-swgk-009 /tmp/pserver.json 0 1 PInterfaces,LagInterfaces 1\n";
+
+ /**
+ * The main method.
+ *
+ * @param <T> the generic type
+ * @param args the arguments
+ */
+ public static <T> void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_PUTTOOL_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(PutResource.class.getName());
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+
+ Boolean bResVersionEnabled = false;
+
+ try
+ {
+ String strEnableResVersion = AAIConfig.get(AAIConstants.AAI_RESVERSION_ENABLEFLAG);
+ if (strEnableResVersion != null && !strEnableResVersion.isEmpty())
+ bResVersionEnabled = Boolean.valueOf(strEnableResVersion);
+ }
+ catch (Exception e) {
+
+ }
+
+ boolean doPutIfExists = true;
+ if (args.length > 5)
+ if (args[5].equals("1"))
+ doPutIfExists = false;
+
+ try {
+ if (args.length < 2) {
+ System.out.println("Insufficient arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient arguments");
+ aaiLogger.info(logline, true, "0");
+ System.exit(1);
+ }
+
+ // Assume the config AAI_SERVER_URL has a last slash so remove if
+ // resource-path has it as the first char
+ String path = args[0].replaceFirst("^/", "");
+ Path p = Paths.get(path);
+
+ // if the node type has one key
+ String resource = p.getName(p.getNameCount() - 2).toString();
+ // if the node type has two keys - this assumes max 2 keys
+ IngestModelMoxyOxm moxyMod = new IngestModelMoxyOxm();
+ DbMaps dbMaps = null;
+ try {
+ ArrayList <String> defaultVerLst = new ArrayList <String> ();
+ defaultVerLst.add( AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP) );
+ moxyMod.init( defaultVerLst, false);
+ // Just make sure we can get DbMaps - don't actually need it until later.
+ dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not get the DbMaps object. ";
+ System.out.println( emsg );
+ aaiLogger.info(logline, false, "AAI_7402");
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402"), logline, ex);
+ System.exit(1);
+ }
+ if (!dbMaps.NodeKeyProps.containsKey(resource))
+ resource = p.getName(p.getNameCount() - 3).toString();
+ String resourceClass = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, resource);
+ resourceClass = "org.openecomp.aai.domain.yang." + resourceClass;
+
+ logline.add("class", resourceClass);
+ logline.add("path", path);
+ System.out.println("class=" + resourceClass);
+ System.out.println("path=" + path);
+
+ RestObject<T> restObj = new RestObject<T>();
+ @SuppressWarnings("unchecked")
+ T t2 = (T)getInstance(Class.forName(resourceClass));
+ restObj.set(t2);
+
+ boolean bExist = true;
+
+ try
+ {
+ if ( !doPutIfExists ) {
+
+ String url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+
+ logline.add("url", url);
+ System.out.println("url=" + url);
+ if ( nodeExists( url) ) {
+ System.out.println("PUT succeeded, the resource exists already in the DB. Skipping the put based on the skipIfExists command line parameter.\n");
+ System.exit(0);
+ }
+
+ }
+ RestController.<T>Get(t2, FROMAPPID, TRANSID, path, restObj, false);
+ t2 = restObj.get();
+ System.out.println(" GET succeeded\n");
+ } catch (AAIException e) {
+ if ( !doPutIfExists ) {
+ System.out.println("GET " + path + " returned " + e.getMessage() + "\n");
+ ErrorObject eo = e.getErrorObject();
+ System.out.println( "details " + eo.getDetails() + "\n");
+
+ }
+ bExist = false;
+ }
+ catch (Exception e1)
+ {
+ if ( !doPutIfExists ) {
+ System.out.println(" GET exception ignored with skipExists parameter\n");
+ e1.printStackTrace();
+ }
+ bExist = false;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ T resJson1 = (T)readJsonFile(Class.forName(resourceClass), args[1]);
+ String resourceUpdateVersion = GetResourceVersion(resJson1);
+
+
+ if (bResVersionEnabled && bExist)
+ {
+
+ String DBresourceVersion = GetResourceVersion(t2);
+ if ( !doPutIfExists ) {
+ System.out.println("PUT succeeded, the resource exists already in the DB. Skipping the put based on the skipIfExists command line parameter.\n");
+ logline.add("dbVersion", DBresourceVersion);
+ logline.add("UpdateVersion", resourceUpdateVersion);
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+ }
+
+ if (resourceUpdateVersion == null || resourceUpdateVersion.isEmpty())
+ {
+ if ( DBresourceVersion != null && !DBresourceVersion.isEmpty())
+ System.out.println("The resource with version = " + DBresourceVersion + " exists already in the DB. Please supply the right resourceVersion in input data file.\n");
+ else
+ System.out.println("The resource exists already in the DB. Please supply the right resourceVersion in input data file.\n");
+
+ logline.add("dbVersion", DBresourceVersion);
+ logline.add("UpdateVersion", resourceUpdateVersion);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+
+ if ( DBresourceVersion != null && !DBresourceVersion.isEmpty() )
+ {
+ if ( resourceUpdateVersion != null && !resourceUpdateVersion.isEmpty() )
+ if (!DBresourceVersion.equals(resourceUpdateVersion))
+ {
+ System.out.println("DB version doesn't match current version. Please get the latest version and modify.\n");
+
+ logline.add("dbVersion", DBresourceVersion);
+ logline.add("UpdateVersion", resourceUpdateVersion);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+ }
+ }
+ else //sanity check
+ {
+ if ( bResVersionEnabled && resourceUpdateVersion != null && !resourceUpdateVersion.isEmpty())
+ {
+ System.out.println("DB doesn't have this resource any more. Please create a new version by taking out the resourceVersion tag from your input resource data file.\n");
+
+ logline.add("UpdateVersion", resourceUpdateVersion);
+ aaiLogger.info(logline, false, "AAI_7403");
+ System.exit(1);
+ }
+
+ }
+
+ if (bExist) //merge
+ {
+ boolean bUpdateChildren = false;
+ boolean bUpdateRL = false;
+
+ if (args.length == 3)
+ {
+ if (args[2].equals("1"))
+ bUpdateRL = true;
+ resJson1 = MergeResource.merge(t2, resJson1, false, bUpdateRL);
+ }
+ else if (args.length == 4)
+ {
+ if (args[2].equals("1"))
+ bUpdateRL = true;
+ if (args[3].equals("1"))
+ bUpdateChildren = true;
+ resJson1 = MergeResource.merge(t2, resJson1, bUpdateChildren, bUpdateRL);
+ }
+ else if (args.length == 5)
+ {
+ if (args[2].equals("1"))
+ bUpdateRL = true;
+ if (args[3].equals("1"))
+ bUpdateChildren = true;
+ String[] strChildArray = args[4].split("\\,");
+ resJson1 = MergeResource.merge(t2, resJson1, bUpdateChildren, strChildArray, bUpdateRL);
+
+ }
+ else
+ resJson1 = MergeResource.merge(t2, resJson1);
+
+ }
+
+ RestController.<T>Put(resJson1, FROMAPPID, TRANSID, path, false);
+
+ System.out.println(" PUT succeeded\n");
+
+ System.out.println("\nDone!!");
+
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+
+ } catch (AAIException e) {
+ if ( !doPutIfExists ) { // ignore 412 failure
+ ErrorObject eo = e.getErrorObject();
+ System.out.println( "ignore 412 AAIException " + e.getMessage() + " errorObject " + eo.getHTTPResponseCode() +
+ " details " + eo.getDetails());
+ if ( e.getMessage().equals("AAI_7116") ) {
+ if ( eo.getDetails().indexOf("status=412") > 0)
+ System.out.println("PUT succeeded, return 412 ignored\n");
+ System.out.println("\nDone!!");
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+ }
+ }
+ System.out.println("PUT failed: " + e.getMessage());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+
+ System.exit(1);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("PUT failed: " + e.toString());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Gets the single instance of PutResource.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return single instance of PutResource
+ * @throws IllegalAccessException the illegal access exception
+ * @throws InstantiationException the instantiation exception
+ */
+ public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException
+ {
+ return clazz.newInstance();
+ }
+
+ /**
+ * Read json file.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param fName the f name
+ * @return the t
+ * @throws AAIException the AAI exception
+ */
+ public static <T> T readJsonFile( Class<T> clazz, String fName ) throws AAIException
+ {
+ String jsonData = "";
+ BufferedReader br = null;
+ T t;
+
+ try {
+ String line;
+ br = new BufferedReader(new FileReader(fName));
+ while ((line = br.readLine()) != null) {
+ jsonData += line + "\n";
+ }
+ } catch (IOException e) {
+
+ throw new AAIException("AAI_7403", e, "Error opening json file");
+ } finally {
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ throw new AAIException("AAI_7403", ex, "Error closing json file");
+ }
+ }
+
+ try {
+ t = MapperUtil.readWithDashesAsObjectOf(clazz, jsonData);
+ }
+ catch (Exception je){
+ throw new AAIException("AAI_7403", je, "Error parsing json file");
+ }
+
+ return t;
+
+ }//End readJsonFile()
+
+ /**
+ * Gets the resource version.
+ *
+ * @param <T> the generic type
+ * @param resource the resource
+ * @return the string
+ */
+ public static <T> String GetResourceVersion(T resource)
+ {
+ Field[] fields = resource.getClass().getDeclaredFields();
+ if (fields != null)
+ {
+ for (Field field : fields)
+ {
+ try
+ {
+ field.setAccessible(true);
+ if ( field.getName().equalsIgnoreCase("resourceVersion") )
+ {
+ Object obj = field.get(resource);
+ return (String)obj;
+ }
+
+
+ }
+ catch (Exception e)
+ {
+
+ }
+
+
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Node exists.
+ *
+ * @param url the url
+ * @return true, if successful
+ * @throws AAIException the AAI exception
+ */
+ public static boolean nodeExists(String url) throws AAIException {
+ try{
+ String useBasicAuth = AAIConfig.get("aai.tools.enableBasicAuth");
+ Client client = null;
+
+ if (useBasicAuth != null && useBasicAuth.equals("true")) {
+ client = HttpsAuthClient.getBasicAuthClient();
+ } else {
+ client = HttpsAuthClient.getTwoWaySSLClient();
+ }
+
+ System.out.println("Getting the resource...: " + url);
+
+ ClientResponse cres;
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true"))
+ {
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", TRANSID)
+ .header("X-FromAppId", FROMAPPID)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .get(ClientResponse.class);
+ }
+
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", TRANSID)
+ .header("X-FromAppId", FROMAPPID)
+ .type("application/json")
+ .get(ClientResponse.class);
+ }
+
+
+
+ if (cres.getStatus() == 404) { // resource not found
+ return false;
+ } else if (cres.getStatus() == 200){
+ return true;
+ } else {
+ System.out.println("Getting the Resource failed: " + cres.getStatus()
+ + ":\n" + cres.getEntity(String.class));
+ return false;
+ }
+ } catch (KeyManagementException e) {
+ throw new AAIException("AAI_7401", e, "Error during GET");
+ } catch (Exception e) {
+ throw new AAIException("AAI_7402", e, "Error during GET");
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java
new file mode 100644
index 0000000..7a8af11
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java
@@ -0,0 +1,234 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.domain.yang.Relationship;
+import com.att.eelf.configuration.Configuration;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+
+
+public class RelationshipPutDel {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAI-TOOLS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static AAILogger aaiLogger = null;
+
+ private static final String USAGE_STRING = "Usage: rshipTool.sh <PUT|DELETE> <resource-path> <filename>\n" +
+ "resource-path for a particular resource starting after the aai/<version>, relationship-list/relationship gets added by script\n" +
+ "filename is the path to a file which contains the json input for the relationship payload" +
+ "for example: relTool.sh PUT cloud-infrastructure/oam-networks/oam-network/test-100-oam /tmp/putrship.json\n";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_RSHIPTOOL_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ aaiLogger = new AAILogger(RelationshipPutDel.class.getName());
+ LogLine logline = new LogLine();
+ LogLine glogline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+ aaiLogger.debug(logline, "Start processing...");
+ String rshipURL, resURL = null;
+ Relationship rship = null;
+
+ try {
+ if ((args.length < 3) || (!args[0].equalsIgnoreCase("PUT") && !args[0].equalsIgnoreCase("DELETE"))) {
+ System.out.println("Insufficient or Invalid arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient or Invalid arguments");
+ aaiLogger.info(logline, true, "0");
+ System.exit(1);
+ }
+
+ rship = readJsonFile(args[2]);
+
+ // Assume the config AAI_SERVER_URL has a last slash so remove if
+ // resource-path has it as the first char
+ resURL = args[1].replaceFirst("^/", "");
+ resURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + resURL;
+ rshipURL = resURL.concat("/relationship-list/relationship");
+
+ logline.add("rshipURL", rshipURL);
+ logline.add("action", args[0]);
+ System.out.println("Resource URL=" + rshipURL);
+
+ PutDelRelationship(aaiLogger, logline, rshipURL, rship, args[0]);
+
+ logline.add("rel", rship.getRelatedTo());
+ System.out.println(args[0] + " Relationship succeeded to: " + rship.getRelatedTo() + "\n");
+
+ GetResource.getNode(aaiLogger, glogline, resURL);
+ System.out.println("\nDone!!");
+
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+
+ } catch (AAIException e) {
+ System.out.println(args[0] + " Relationship PUT/DELETE failed: " + e.getMessage());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println(args[0] + " Relationship PUT/DELETE failed: " + e.toString());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Read json file.
+ *
+ * @param fName the f name
+ * @return the relationship
+ * @throws AAIException the AAI exception
+ */
+ public static Relationship readJsonFile( String fName ) throws AAIException {
+
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "readJsonFile");
+
+ String jsonData = "";
+ BufferedReader br = null;
+ Relationship rship = new Relationship();
+
+ try {
+ String line;
+ br = new BufferedReader(new FileReader(fName));
+ while ((line = br.readLine()) != null) {
+ jsonData += line + "\n";
+ }
+ } catch (IOException e) {
+ throw new AAIException("AAI_7403", e, "Error opening json file");
+ } finally {
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ aaiLogger.info(logline, false, "AAI_7403");
+ throw new AAIException("AAI_7403", ex, "Error closing json file");
+ }
+ }
+
+ try {
+ rship = MapperUtil.readWithDashesAsObjectOf(Relationship.class, jsonData);
+ }
+ catch (Exception je){
+ aaiLogger.info(logline, false, "AAI_7403");
+ throw new AAIException("AAI_7403", je, "Error parsing json file");
+ }
+
+ aaiLogger.info(logline, true, "0");
+ return rship;
+
+ }//End readJsonFile()
+
+
+ /**
+ * Put del relationship.
+ *
+ * @param aaiLogger the aai logger
+ * @param logline the logline
+ * @param rshipURL the rship URL
+ * @param rship the rship
+ * @param action the action
+ * @throws AAIException the AAI exception
+ */
+ public static void PutDelRelationship(AAILogger aaiLogger,
+ LogLine logline,
+ String rshipURL,
+ Relationship rship,
+ String action) throws AAIException{
+ try {
+ String useBasicAuth = AAIConfig.get("aai.tools.enableBasicAuth");
+ Client client = null;
+
+ if (useBasicAuth != null && useBasicAuth.equals("true")) {
+
+ client = HttpsAuthClient.getBasicAuthClient();
+ } else {
+ client = HttpsAuthClient.getTwoWaySSLClient();
+ }
+ ClientResponse cres = null;
+
+ if (action.equalsIgnoreCase("PUT"))
+ cres = client.resource(rshipURL)
+ .header("X-TransactionId", TRANSID)
+ .header("X-FromAppId", FROMAPPID)
+ .accept("application/json")
+ .entity(rship)
+ .put(ClientResponse.class);
+ else
+ cres = client.resource(rshipURL)
+ .header("X-TransactionId", TRANSID)
+ .header("X-FromAppId", FROMAPPID)
+ .accept("application/json")
+ .entity(rship)
+ .delete(ClientResponse.class);
+
+ if (cres.getStatus() == 404) { // resource not found
+ String msg = "Resource does not exist...: " + cres.getStatus()
+ + ":\n" + cres.getEntity(String.class);
+ System.out.println(msg);
+ logline.add("msg", msg);
+ throw new AAIException("AAI_7404", "Resource does not exist");
+ } else if ((action.equalsIgnoreCase("PUT") && cres.getStatus() == 200) ||
+ (action.equalsIgnoreCase("DELETE") && cres.getStatus() == 204)) {
+ String msg = action + " Resource status: " + cres.getStatus();
+ System.out.println(msg);
+ } else {
+ String msg = action + " Resource failed: " + cres.getStatus()
+ + ":\n" + cres.getEntity(String.class);
+ System.out.println(msg);
+ logline.add("msg", msg);
+ throw new AAIException("AAI_7402", "Error during PutDel");
+ }
+ } catch (AAIException e) {
+ throw e;
+ } catch (KeyManagementException e) {
+ throw new AAIException("AAI_7401", "Error during PutDel");
+ } catch (Exception e) {
+ throw new AAIException("AAI_7402", "Error during PutDel");
+ }
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/Request.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/Request.java
new file mode 100644
index 0000000..3b8d937
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/Request.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+import javax.ws.rs.core.UriBuilder;
+
+import org.openecomp.aai.exceptions.AAIException;
+
+public class Request<T> {
+
+ public static final String V2 = "v2";
+ public static final String V3 = "v3";
+ public static final String V4 = "v4";
+ public static final String V5 = "v5";
+ public final String fromAppId;
+ public final String transactionId;
+ public final String path;
+ public final RestObject<T> restObj;
+ public final boolean oldServer;
+ public final String apiVersion;
+
+
+ /**
+ * Instantiates a new request.
+ *
+ * @param builder the builder
+ */
+ public Request(RequestBuilder<T> builder) {
+
+ fromAppId = builder.fromAppId;
+ transactionId = builder.transactionId;
+ restObj = builder.restObj;
+ oldServer = builder.oldServer;
+ apiVersion = builder.apiVersion;
+
+ if (!oldServer) {
+ path = apiVersion + "/" + builder.path;
+ } else {
+ path = builder.path;
+ }
+
+
+ }
+
+ public static class RequestBuilder<T> {
+ private String fromAppId;
+ private String transactionId;
+ private String path;
+ private RestObject<T> restObj;
+ private boolean oldServer;
+ private String apiVersion = Request.V4;
+
+
+ /**
+ * Sets the from app id.
+ *
+ * @param fromAppId the from app id
+ * @return the request builder
+ */
+ public RequestBuilder<T> setFromAppId(String fromAppId) {
+ this.fromAppId = fromAppId;
+ return this;
+ }
+
+ /**
+ * Sets the transaction id.
+ *
+ * @param transactionId the transaction id
+ * @return the request builder
+ */
+ public RequestBuilder<T> setTransactionId(String transactionId) {
+ this.transactionId = transactionId;
+ return this;
+
+ }
+
+ /**
+ * Sets the path.
+ *
+ * @param path the path
+ * @return the request builder
+ */
+ public RequestBuilder<T> setPath(String path) {
+
+ this.path = path;
+ return this;
+
+ }
+
+ /**
+ * Sets the rest obj.
+ *
+ * @param restObj the rest obj
+ * @return the request builder
+ */
+ public RequestBuilder<T> setRestObj(RestObject<T> restObj) {
+ this.restObj = restObj;
+ return this;
+
+ }
+
+ /**
+ * Sets the old server.
+ *
+ * @param oldServer the old server
+ * @return the request builder
+ */
+ public RequestBuilder<T> setOldServer(boolean oldServer) {
+ this.oldServer = oldServer;
+ return this;
+
+ }
+
+ /**
+ * Sets the api version.
+ *
+ * @param apiVersion the api version
+ * @return the request builder
+ */
+ public RequestBuilder<T> setApiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ return this;
+ }
+
+ /**
+ * Builds the.
+ *
+ * @return the request
+ */
+ public Request<T> build() {
+ return new Request<T>(this);
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/RestController.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/RestController.java
new file mode 100644
index 0000000..bcc0a48
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/RestController.java
@@ -0,0 +1,750 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.codehaus.groovy.util.SingleKeyHashMap;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.util.RestObject;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.GenericType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+public class RestController {
+
+ private static AAILogger aaiLogger = new AAILogger(RestController.class.getName());
+ private static LogLine logline = new LogLine();
+ private static final String COMPONENT = "aaiutil";
+
+ private static Client client = null;
+
+ private String restSrvrBaseURL;
+
+ //To do - Come up with helper function that will automatically
+ //generate the REST API path based on path parameter(s) and query parameter(s)!
+ public static final String REST_APIPATH_COMPLEXES = "cloud-infrastructure/complexes";
+ public static final String REST_APIPATH_COMPLEX = "cloud-infrastructure/complexes/complex/";
+ public static final String REST_APIPATH_PSERVERS = "cloud-infrastructure/pservers";
+ public static final String REST_APIPATH_PSERVER = "cloud-infrastructure/pservers/pserver/";
+ public static final String REST_APIPATH_PHYSICALLINKS = "network/physical-links/";
+ public static final String REST_APIPATH_PHYSICALLINK = "network/physical-links/physical-link/";
+ public static final String REST_APIPATH_PINTERFACES = "network/p-interfaces/";
+ public static final String REST_APIPATH_PINTERFACE = "network/p-interfaces/p-interface/";
+ public static final String REST_APIPATH_VPLSPES = "network/vpls-pes/";
+ public static final String REST_APIPATH_VPLSPE = "network/vpls-pes/vpls-pe/";
+ public static final String REST_APIPATH_UPDATE = "actions/update/";
+ public static final String REST_APIPATH_SEARCH = "search/nodes-query?search-node-type=";
+
+ public static final String REST_APIPATH_CLOUDREGION = "cloud-infrastructure/cloud-regions/cloud-region/";
+ public static final String REST_APIPATH_TENANT = "cloud-infrastructure/tenants/tenant/";
+ public static final String REST_APIPATH_VPE = "network/vpes/vpe/";
+ public static final String REST_APIPATH_VIRTUAL_DATA_CENTER = "cloud-infrastructure/virtual-data-centers/virtual-data-center/";
+ public static final String REST_APIPATH_VIRTUAL_DATA_CENTERS = "cloud-infrastructure/virtual-data-centers/";
+ //network/generic-vnfs/generic-vnf/{vnf-id}
+ public static final String REST_APIPATH_GENERIC_VNF = "network/generic-vnfs/generic-vnf/";
+ public static final String REST_APIPATH_GENERIC_VNFS = "network/generic-vnfs";
+ public static final String REST_APIPATH_L3_NETWORK = "network/l3-networks/l3-network/";
+ public static final String REST_APIPATH_L3_NETWORKS = "network/l3-networks";
+
+ public static final String REST_APIPATH_VCE = "network/vces/vce/";
+
+ public static final String REST_APIPATH_SERVICE = "service-design-and-creation/services/service/";
+
+ /**
+ * Inits the rest client.
+ *
+ * @throws AAIException the AAI exception
+ */
+ private static void initRestClient() throws AAIException
+ {
+ if (client == null) {
+ try {
+ String useBasicAuth = AAIConfig.get("aai.tools.enableBasicAuth");
+ //Client client = null;
+
+ if (useBasicAuth != null && useBasicAuth.equals("true")) {
+
+ client = HttpsAuthClient.getBasicAuthClient();
+ } else {
+ client = HttpsAuthClient.getTwoWaySSLClient();
+ }
+ }
+ catch (KeyManagementException e){
+ throw new AAIException("AAI_7117", "KeyManagementException in REST call to DB: " + e.toString());
+ } catch (Exception e) {
+ throw new AAIException("AAI_7117", " Exception in REST call to DB: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * Sets the rest srvr base URL.
+ *
+ * @param baseURL the base URL
+ * @throws AAIException the AAI exception
+ */
+ public void SetRestSrvrBaseURL(String baseURL) throws AAIException
+ {
+ if (baseURL == null)
+ throw new AAIException("AAI_7117", "REST Server base URL cannot be null.");
+ restSrvrBaseURL = baseURL;
+ }
+
+ /**
+ * Gets the rest srvr base URL.
+ *
+ * @return the rest srvr base URL
+ */
+ public String getRestSrvrBaseURL()
+ {
+ return restSrvrBaseURL;
+ }
+
+ /**
+ * To do - optimization and automation. Also make it as generic as possible.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param sourceID the source ID
+ * @param transId the trans id
+ * @param path the path
+ * @param restObject the rest object
+ * @param oldserver the oldserver
+ * @throws AAIException the AAI exception
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> void Get(T t, String sourceID, String transId, String path, RestObject<T> restObject, boolean oldserver) throws AAIException {
+ String methodName = "Get";
+ String url="";
+ transId += ":" + UUID.randomUUID().toString();
+ aaiLogger.debug(logline, methodName + " start");
+
+ restObject.set(t);
+
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+ initRestClient();
+ aaiLogger.debug(logline, url + " for the get REST API");
+
+ ClientResponse cres;
+
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true"))
+ { cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .get(ClientResponse.class);
+ }
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .get(ClientResponse.class);
+ }
+// System.out.println("cres.EntityInputSream()="+cres.getEntityInputStream().toString());
+// System.out.println("cres.tostring()="+cres.toString());
+// System.out.println("CLIENT RESPONSE: "+ cres.getEntity(c));
+
+ if (cres.getStatus() == 200) {
+// System.out.println(methodName + ": url=" + url);
+ t = (T) cres.getEntity(t.getClass());
+ System.out.println("CLASS: " + t.getClass());
+ restObject.set(t);
+ aaiLogger.debug(logline, methodName + "REST api GET was successfull!");
+
+ } else {
+// System.out.println(methodName + ": url=" + url + " failed with status=" + cres.getStatus());
+ throw new AAIException("AAI_7116", methodName +" with status="+cres.getStatus()+", url="+url);
+ }
+
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param requestObj the request obj
+ * @throws AAIException the AAI exception
+ */
+ public static <T> void Get(T t, Request<T> requestObj) throws AAIException {
+ String methodName = "Get";
+ String url="";
+ String transId = requestObj.transactionId;
+ transId += ":" + UUID.randomUUID().toString();
+ aaiLogger.debug(logline, methodName + " start");
+
+ requestObj.restObj.set(t);
+
+ if (requestObj.oldServer)
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + "server/" + requestObj.path;
+ else
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + requestObj.path;
+ initRestClient();
+
+ try {
+ URL urlObj= new URL(url);
+ URI uri = new URI(urlObj.getProtocol(), urlObj.getUserInfo(), urlObj.getHost(), urlObj.getPort(), urlObj.getPath(), urlObj.getQuery(), urlObj.getRef());
+ url = uri.toASCIIString();
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new AAIException("AAI_7116", "bad URL");
+
+ }
+ aaiLogger.debug(logline, url + " for the get REST API");
+ ClientResponse cres;
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true"))
+ {
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", requestObj.fromAppId)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .get(ClientResponse.class);
+ }
+
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", requestObj.fromAppId)
+ .type("application/json")
+ .get(ClientResponse.class);
+ }
+
+
+
+
+// System.out.println("cres.EntityInputSream()="+cres.getEntityInputStream().toString());
+// System.out.println("cres.tostring()="+cres.toString());
+
+ if (cres.getStatus() == 200) {
+// System.out.println(methodName + ": url=" + url);
+ t = (T) cres.getEntity(t.getClass());
+ requestObj.restObj.set(t);
+ aaiLogger.debug(logline, methodName + "REST api GET was successfull!");
+
+ } else {
+// System.out.println(methodName + ": url=" + url + " failed with status=" + cres.getStatus());
+ throw new AAIException("AAI_7116", methodName +" with status="+cres.getStatus()+", url="+url);
+ }
+
+ }
+
+ /**
+ * Put.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param requestObj the request obj
+ * @throws AAIException the AAI exception
+ */
+ public static <T> void Put(T t, Request<T> requestObj) throws AAIException {
+ String methodName = "Put";
+ String url="";
+ String transId = requestObj.transactionId;
+ transId += ":" + UUID.randomUUID().toString();
+ logline.init(COMPONENT, transId, requestObj.fromAppId, methodName);
+ aaiLogger.debug(logline, methodName + " start");
+
+ initRestClient();
+
+ if (requestObj.oldServer)
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + "server/" + requestObj.path;
+ else
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + requestObj.path;
+
+
+ logline.add("path", url);
+
+ try {
+ URL urlObj= new URL(url);
+ URI uri = new URI(urlObj.getProtocol(), urlObj.getUserInfo(), urlObj.getHost(), urlObj.getPort(), urlObj.getPath(), urlObj.getQuery(), urlObj.getRef());
+ url = uri.toASCIIString();
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new AAIException("AAI_7116", "bad URL");
+
+ }
+ ClientResponse cres;
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true")){
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", requestObj.fromAppId)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .entity(t)
+ .put(ClientResponse.class);
+ }
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", requestObj.fromAppId)
+ .type("application/json")
+ .entity(t)
+ .put(ClientResponse.class);
+ }
+
+// System.out.println("cres.tostring()="+cres.toString());
+
+ int statuscode = cres.getStatus();
+ if ( statuscode >= 200 && statuscode <= 299 ) {
+// aaiLogger.debug(logline, methodName+": url=" + url + ", request=" + path);
+ aaiLogger.info(logline, true, "0");
+ } else {
+// System.out.println(methodName + ": with url="+url+ " failed with status="+ cres.getStatus() + ":" + cres.getEntity(String.class));
+ aaiLogger.info(logline, false, "AAI_7116");
+ throw new AAIException("AAI_7116", methodName +" with status="+statuscode+", url="+url);
+ }
+ }
+
+ /**
+ * Multiple Generic Get.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param sourceID the source ID
+ * @param transId the trans id
+ * @param path the path
+ * @param oldserver the oldserver
+ * @return the list
+ * @throws AAIException the AAI exception
+ */
+ public static <T> List<T> Get(T t, String sourceID, String transId, String path, boolean oldserver) throws AAIException {
+ String methodName = "Get";
+ String url="";
+ transId += ":" + UUID.randomUUID().toString();
+ aaiLogger.debug(logline, methodName + " start");
+
+ List<T> list;
+
+ try {
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+ initRestClient();
+ aaiLogger.debug(logline, url + " for the get REST API");
+ ClientResponse cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .type("application/json")
+ .get(ClientResponse.class);
+
+
+ if (cres.getStatus() == 200) {
+ String datainJson = cres.getEntity(String.class);
+ list = mapJsonToObjectList(t, datainJson, t.getClass());
+
+ aaiLogger.debug(logline, methodName + "REST api GET was successfull!");
+ return list;
+
+ } else {
+ System.out.println(methodName + ": url=" + url + " failed with status=" + cres.getStatus());
+ throw new AAIException("AAI_7116", methodName +" with status="+cres.getStatus()+", url="+url);
+ }
+ } catch (AAIException e) {
+ throw new AAIException("AAI_7116", methodName + " with url="+url+ ", Exception: " + e.toString());
+ } catch (Exception e)
+ {
+ throw new AAIException("AAI_7116", methodName + " with url="+url+ ", Exception: " + e.toString());
+
+ }
+
+ }
+
+ /**
+ * Map json to object list.
+ *
+ * @param <T> the generic type
+ * @param typeDef the type def
+ * @param json the json
+ * @param clazz the clazz
+ * @return the list
+ * @throws Exception the exception
+ */
+ private static <T> List<T> mapJsonToObjectList(T typeDef,String json, Class clazz) throws Exception
+ {
+ List<T> list;
+ ObjectMapper mapper = new ObjectMapper();
+ System.out.println(json);
+ TypeFactory t = TypeFactory.defaultInstance();
+ list = mapper.readValue(json, t.constructCollectionType(ArrayList.class,clazz));
+
+ return list;
+ }
+
+ /**
+ * Put.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param sourceID the source ID
+ * @param transId the trans id
+ * @param path the path
+ * @throws AAIException the AAI exception
+ */
+ public static <T> void Put(T t, String sourceID, String transId, String path) throws AAIException {
+ Put( t, sourceID, transId, path, false);
+ }
+
+ /**
+ * Put.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param sourceID the source ID
+ * @param transId the trans id
+ * @param path the path
+ * @param oldserver the oldserver
+ * @throws AAIException the AAI exception
+ */
+ public static <T> void Put(T t, String sourceID, String transId, String path, boolean oldserver) throws AAIException {
+ String methodName = "Put";
+ String url="";
+ transId += ":" + UUID.randomUUID().toString();
+ logline.init(COMPONENT, transId, sourceID, methodName);
+ logline.add("path", path);
+ aaiLogger.debug(logline, methodName + " start");
+
+ initRestClient();
+
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+ ClientResponse cres;
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true")){
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .entity(t)
+ .put(ClientResponse.class);
+ }
+
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .type("application/json")
+ .entity(t)
+ .put(ClientResponse.class);
+
+ }
+ int statuscode = cres.getStatus();
+ if ( statuscode >= 200 && statuscode <= 299 ) {
+ aaiLogger.info(logline, true, "0");
+ } else {
+ aaiLogger.info(logline, false, "AAI_7116");
+ throw new AAIException("AAI_7116", methodName +" with status="+statuscode+", url="+url + ", msg=" + cres.getEntity(String.class));
+ }
+ }
+
+ /**
+ * Delete.
+ *
+ * @param requestObj the request obj
+ * @throws AAIException the AAI exception
+ */
+ public static void Delete(Request requestObj) throws AAIException {
+ String methodName = "Delete";
+
+ String url="";
+ String transId = requestObj.transactionId;
+ transId += ":" + UUID.randomUUID().toString();
+ logline.init(COMPONENT, transId, requestObj.fromAppId, methodName);
+ aaiLogger.debug(logline, methodName + " start");
+
+ initRestClient();
+
+ if (requestObj.oldServer)
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + "servers/" + requestObj.path;
+ else
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + requestObj.path;
+
+
+ logline.add("path", url);
+
+ try {
+ URL urlObj= new URL(url);
+ URI uri = new URI(urlObj.getProtocol(), urlObj.getUserInfo(), urlObj.getHost(), urlObj.getPort(), urlObj.getPath(), urlObj.getQuery(), urlObj.getRef());
+ url = uri.toASCIIString();
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new AAIException("AAI_7116", "bad URL");
+
+ }
+ ClientResponse cres;
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true")){
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", requestObj.fromAppId)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .entity("{}")
+ .delete(ClientResponse.class);
+ }
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", requestObj.fromAppId)
+ .type("application/json")
+ .entity("{}")
+ .delete(ClientResponse.class);
+ }
+// System.out.println("cres.tostring()="+cres.toString());
+
+ if (cres.getStatus() == 204) {
+// aaiLogger.debug(logline, methodName+": url=" + url);
+ aaiLogger.info(logline, true, "0");
+ } else {
+// System.out.println(methodName + ": with url="+url+ " failed with status="+ cres.getStatus() + ":" + cres.getEntity(String.class));
+ aaiLogger.info(logline, false, "AAI_7116");
+ throw new AAIException("AAI_7116", methodName +" with status="+cres.getStatus()+", url="+url);
+ }
+
+ }
+
+ /**
+ * Delete.
+ *
+ * @param sourceID the source ID
+ * @param transId the trans id
+ * @param path the path
+ * @throws AAIException the AAI exception
+ */
+ public static void Delete(String sourceID, String transId, String path) throws AAIException {
+ String methodName = "Delete";
+ String url="";
+ transId += ":" + UUID.randomUUID().toString();
+ logline.init(COMPONENT, transId, sourceID, methodName);
+ aaiLogger.debug(logline, methodName + " start");
+ logline.add("path", path);
+
+ initRestClient();
+ String request = "{}";
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+
+ ClientResponse cres;
+ if(AAIConfig.get("aai.tools.enableBasicAuth").equals("true")){
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue())
+ .type("application/json")
+ .entity(request)
+ .delete(ClientResponse.class);
+ }
+ else{
+ cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .type("application/json")
+ .entity(request)
+ .delete(ClientResponse.class);
+ }
+// System.out.println("cres.tostring()="+cres.toString());
+
+ if (cres.getStatus() == 404) { // resource not found
+ String msg = "Resource does not exist...: " + cres.getStatus()
+ + ":" + cres.getEntity(String.class);
+ //System.out.println("\n" + msg);
+ logline.add("msg", msg );
+ aaiLogger.info(logline, false, "AAI_7404");
+ throw new AAIException("AAI_7404", "Resource does not exist");
+ } else if (cres.getStatus() == 200 || cres.getStatus() == 204){
+ //System.out.println("\nResource " + url + " deleted");
+ logline.add("msg", "Resource " + url + " deleted");
+ aaiLogger.info(logline, true, "0");
+ } else {
+ String msg = "Deleting Resource failed: " + cres.getStatus()
+ + ":" + cres.getEntity(String.class);
+ //System.out.println("\n" + msg);
+ logline.add("msg", msg);
+ aaiLogger.info(logline, false, "AAI_7116");
+ throw new AAIException("AAI_7116", "Error during DELETE");
+ }
+ /*if (cres.getStatus() == 204) {
+// aaiLogger.debug(logline, methodName+": url=" + url);
+ aaiLogger.info(logline, true, "0");
+ } else {
+// System.out.println(methodName + ": with url="+url+ " failed with status="+ cres.getStatus() + ":" + cres.getEntity(String.class));
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ throw new AAIException("AAI_7116", methodName +" with status="+cres.getStatus()+", url="+url);
+ } */
+ }
+
+ /**
+ * Post.
+ *
+ * @param <T> the generic type
+ * @param t the t
+ * @param sourceID the source ID
+ * @param transId the trans id
+ * @param path the path
+ * @return the string
+ * @throws Exception the exception
+ */
+ public static <T> String Post(T t, String sourceID, String transId, String path) throws Exception {
+ String methodName = "Post";
+ String url="";
+ transId += ":" + UUID.randomUUID().toString();
+ logline.init(COMPONENT, transId, sourceID, methodName);
+ logline.add("path", path);
+ aaiLogger.debug(logline, methodName + " start");
+
+ try {
+
+ initRestClient();
+
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + path;
+
+ ClientResponse cres = client.resource(url)
+ .accept("application/json")
+ .header("X-TransactionId", transId)
+ .header("X-FromAppId", sourceID)
+ .type("application/json")
+ .entity(t)
+ .post(ClientResponse.class);
+
+ int statuscode = cres.getStatus();
+ if ( statuscode >= 200 && statuscode <= 299 ) {
+ // aaiLogger.debug(logline, methodName+": url=" + url + ", request=" + path);
+
+ aaiLogger.debug(logline, methodName + "REST api POST was successful!");
+ aaiLogger.info(logline, true, "0");
+ return cres.getEntity(String.class);
+ } else {
+ // System.out.println(methodName + ": with url="+url+ " failed with status="+ cres.getStatus() + ":" + cres.getEntity(String.class));
+ aaiLogger.info(logline, false, "AAI_7116");
+ throw new AAIException("AAI_7116", methodName +" with status="+statuscode+", url="+url + ", msg=" + cres.getEntity(String.class));
+ }
+
+ } catch (AAIException e) {
+ throw new AAIException("AAI_7116", methodName + " with url="+url+ ", Exception: " + e.toString());
+ } catch (Exception e)
+ {
+ throw new AAIException("AAI_7116", methodName + " with url="+url+ ", Exception: " + e.toString());
+
+ }
+ }
+
+
+ /**
+ * Gets the single instance of RestController.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return single instance of RestController
+ * @throws IllegalAccessException the illegal access exception
+ * @throws InstantiationException the instantiation exception
+ */
+ public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException
+ {
+ return clazz.newInstance();
+ }
+
+ /**
+ * Does resource exist.
+ *
+ * @param <T> the generic type
+ * @param resourcePath the resource path
+ * @param resourceClassName the resource class name
+ * @param fromAppId the from app id
+ * @param transId the trans id
+ * @return the t
+ */
+ /*
+ * DoesResourceExist
+ *
+ * To check whether a resource exist or get a copy of the existing version of the resource
+ *
+ * Resourcepath: should contain the qualified resource path (including encoded unique key identifier value),
+ * resourceClassName: is the canonical name of the resource class name,
+ * fromAppId:
+ * transId:
+ *
+ * Will return null (if the resource doesn’t exist) (or)
+ * Will return the specified resource from the Graph.
+ *
+ * Example:
+ * LogicalLink llink = new LogicalLink();
+ * String resourceClassName = llink.getClass().getCanonicalName();
+ * llink = RestController.DoesResourceExist("network/logical-links/logical-link/" + <encoded-link-name>, resourceClassName, fromAppId, transId);
+ */
+ public static <T> T DoesResourceExist(String resourcePath, String resourceClassName, String fromAppId, String transId) {
+ String methodName = "DoesResourceExist";
+ System.out.println(methodName);
+
+ logline.init(COMPONENT, transId, fromAppId, "DoesResourceExist");
+
+ try {
+
+ RestObject<T> restObj = new RestObject<T>();
+ @SuppressWarnings("unchecked")
+ T resourceObj = (T)getInstance(Class.forName(resourceClassName));
+ restObj.set(resourceObj);
+ RestController.<T>Get(resourceObj, fromAppId, transId, resourcePath, restObj, false);
+
+ resourceObj = restObj.get();
+ if (resourceObj != null)
+ return resourceObj;
+
+ } catch (AAIException e) {
+
+ } catch (ClientHandlerException che) {
+
+ }catch (Exception e) {
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/RestObject.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/RestObject.java
new file mode 100644
index 0000000..a1cc2a1
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/RestObject.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+public class RestObject<T> {
+
+ /**
+ * Generic version of the RestObject class.
+ * @param <T> the type of the value being called for the Rest object interface
+ */
+ // T stands for "Type"
+ private T t;
+
+ /**
+ * Sets the.
+ *
+ * @param t the t
+ */
+ public void set(T t) { this.t = t; }
+
+ /**
+ * Gets the.
+ *
+ * @return the t
+ */
+ public T get() { return t; }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/RestURL.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/RestURL.java
new file mode 100644
index 0000000..4707544
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/RestURL.java
@@ -0,0 +1,799 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResourceKey;
+import org.openecomp.aai.domain.model.AAIResourceKeys;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.springframework.web.util.UriUtils;
+
+import com.google.common.base.CaseFormat;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+public class RestURL {
+
+
+ /*
+ * method returns a REST URL for the given node based on its nodetype and key
+ * information
+ * Special cases for REST URLs:
+ * - old URLS for vserver, ipaddress and volume node types for v2/v3
+ * - images, flavor, vnic and l-interface node types will return new url
+ * - nodetypes with multiple keys such as service capability
+ * - nodetypes with multiple keys such as ipaddress where we use one key in the URL
+ * - cvlan-tags and *list nodetypes - have special or no plurals - they get handled via the hash Map
+ *
+ * 3.0 - generate links for v4-v6 as the current version and clean up the default cloud region.
+ * - Ensures that the all links under the default cr will work but still provides non default details
+ */
+
+ /**
+ * Gets the.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @param apiVersion the api version
+ * @param isLegacyVserverUEB the is legacy vserver UEB
+ * @param isCallbackurl the is callbackurl
+ * @return the string
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static String get(TitanTransaction graph, TitanVertex node, String apiVersion, Boolean isLegacyVserverUEB, Boolean isCallbackurl) throws AAIException, UnsupportedEncodingException
+ {
+ String nodeType = node.<String>property("aai-node-type").orElse(null);
+ String url = "";
+ String currentNodeType = nodeType;
+ Boolean noMoreDependentNodes = true;
+ TitanVertex currentNode = node;
+ Boolean oldVServer = false;
+
+ // if the caller supplies an apiVersion we'll use it, otherwise we'll just
+ // reflect back from the called URI
+ if (apiVersion == null) {
+ apiVersion = AAIApiVersion.get();
+ }
+
+ // for v2 and v3 still return old vserver url format
+ if ((apiVersion.equals("v2") || apiVersion.equals("v3")) &&
+ (nodeType.equals("vserver") || nodeType.equals("ipaddress") || nodeType.equals("volume")))
+ oldVServer = true;
+
+ if (! oldVServer) { // aai-unique-key for these will be aspirational one which we cant return
+ String nodeURI = null;
+ if (Boolean.parseBoolean(AAIConfig.get("aai.use.unique.key", "false")))
+ nodeURI = node.<String>property("aai-unique-key").orElse(null);
+
+ if (nodeURI != null && !nodeURI.equals("")) {
+ if (isCallbackurl) {
+ url = AAIConfig.get(AAIConstants.AAI_GLOBAL_CALLBACK_URL) + apiVersion + "/" + nodeURI;
+ return url;
+ } else if(isLegacyVserverUEB || (apiVersion.equals("v2") || apiVersion.equals("v3") || apiVersion.equals("v4"))) {
+ // for v2, v3, v4 do not use the http header server host to return
+ url = AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE) + apiVersion + "/" + nodeURI;
+ return url;
+ } else {
+ url = AAIApiServerURLBase.get() + apiVersion + "/" + nodeURI;
+ return url;
+ }
+ }
+ }
+
+ // TODO
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ // add the url component for the dependent on nodes for the node passed in
+ while (noMoreDependentNodes) {
+ Collection <String> depNodeTypeColl = dbMaps.NodeDependencies.get(currentNodeType);
+ Iterator <String> depNodeTypeListIterator = (Iterator<String>) depNodeTypeColl.iterator();
+ if (!depNodeTypeListIterator.hasNext()) {
+ noMoreDependentNodes = false;
+ break;
+ }
+
+ // Look for IN edges for the current Node and find its Parent - and make it the current Node
+ boolean foundParent = false;
+ Iterator <Edge> inEdges = currentNode.edges(Direction.IN);
+ while( inEdges.hasNext() ){
+ TitanEdge inEdge = (TitanEdge) inEdges.next();
+ Boolean inEdgeIsParent = inEdge.<Boolean>property("isParent").orElse(null);
+ if( inEdgeIsParent != null && inEdgeIsParent ){
+ foundParent = true;
+ currentNode = (TitanVertex) inEdge.otherVertex(currentNode);
+ break;
+ }
+ }
+
+ if (foundParent == false) {
+ break;
+ }
+
+ // find the key(s) and add to the url
+ // first see what type of node the parent is - note some nodes can have one of many kinds of parents
+ String depNodeType = currentNode.<String>property("aai-node-type").orElse(null);
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(depNodeType);
+ Iterator <String> keyPropI = keyProps.iterator();
+
+ String nodeUrl = null;
+ String depNodeTypePlural = dbMaps.NodePlural.get(depNodeType);
+
+ if (oldVServer) { // old server url format
+ if (depNodeType.equals("vserver") || depNodeType.equals("ipaddress") || depNodeType.equals("volume")) // no nodeType
+ nodeUrl = depNodeTypePlural ;
+ else if (depNodeType.equals("tenant")) // no nodeType or plural
+ nodeUrl = "";
+ else // this case doesnt really exist but adding to complete the logic here
+ if (depNodeTypePlural != null)
+ nodeUrl = depNodeTypePlural + "/" + depNodeType + "/";
+ } else {
+ if (depNodeTypePlural != null)
+ nodeUrl = depNodeTypePlural + "/" + depNodeType + "/";
+ }
+
+ while (keyPropI.hasNext()) {
+ Object nodeKey = currentNode.<Object>property(keyPropI.next()).orElse(null);
+ nodeUrl += encodeURL(nodeKey.toString()) + "/";
+ }
+
+ currentNodeType = depNodeType;
+ url = nodeUrl + url;
+ }
+ // use the name space of the highest level of unique node since lots of children node types
+ // are common ex. l-interface is in the path for pserver and vpe
+ String urlNamespace = dbMaps.NodeNamespace.get(currentNodeType) + "/";
+ urlNamespace = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, urlNamespace);
+
+ // add the url component for the node passed in
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(nodeType);
+ Iterator <String> keyPropI = keyProps.iterator();
+
+ String nodeUrl = null;
+ String nodeTypePlural = "";
+ nodeTypePlural = dbMaps.NodePlural.get(nodeType);
+
+ if (oldVServer) {
+ if (nodeTypePlural != null && !nodeTypePlural.equals(""))
+ nodeUrl = nodeTypePlural + "/";
+ } else {
+ if (nodeTypePlural != null && !nodeTypePlural.equals(""))
+ nodeUrl = nodeTypePlural + "/" + nodeType + "/";
+ else
+ nodeUrl = nodeType + "/";
+ }
+
+ if (nodeType.equals("ipaddress")) { // this has 2 keys but API only uses port-or -address in URL
+ String nodeKey = node.<String>property("port-or-interface").orElse(null);
+ nodeUrl += encodeURL(nodeKey) + "/";
+ } else {
+ while (keyPropI.hasNext()) {
+ Object nodeKey = node.<Object>property(keyPropI.next()).orElse(null);
+ nodeUrl += encodeURL(nodeKey.toString()) + "/";
+ }
+ }
+ if (isCallbackurl) {
+ url = AAIConfig.get(AAIConstants.AAI_GLOBAL_CALLBACK_URL) + apiVersion + "/" + urlNamespace + url + nodeUrl;
+ } else if (oldVServer)
+ url = AAIApiServerURLBase.get() + "servers/" + apiVersion + "/" + url + nodeUrl;
+ else {
+ url = AAIApiServerURLBase.get() + apiVersion + "/" + urlNamespace + url + nodeUrl;
+ }
+ return url;
+ }
+
+ /**
+ * Gets the search url.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @param apiVersion the api version
+ * @return the search url
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static String getSearchUrl(TitanTransaction graph, TitanVertex node, String apiVersion) throws AAIException, UnsupportedEncodingException
+ {
+ String nodeType = node.<String>property("aai-node-type").orElse(null);
+ String url = "";
+ String currentNodeType = nodeType;
+ Boolean noMoreDependentNodes = true;
+ TitanVertex currentNode = node;
+ Boolean hasCloudRegion = false;
+
+ // if the caller supplies an apiVersion we'll use it, otherwise we'll just
+ // reflect back from the called URI
+ if (apiVersion == null) {
+ apiVersion = AAIApiVersion.get();
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP));
+
+ // add the url component for the dependent on nodes for the node passed in
+ while (noMoreDependentNodes) {
+ Collection <String> depNodeTypeColl = dbMaps.NodeDependencies.get(currentNodeType);
+ Iterator <String> depNodeTypeListIterator = (Iterator<String>) depNodeTypeColl.iterator();
+ if (!depNodeTypeListIterator.hasNext()) {
+ noMoreDependentNodes = false;
+ break;
+ }
+
+ // Look for IN edges for the current Node and find its Parent - and make it the current Node
+ boolean foundParent = false;
+ Iterator <Edge> inEdges = currentNode.edges(Direction.IN);
+ while( inEdges.hasNext() ){
+ TitanEdge inEdge = (TitanEdge) inEdges.next();
+ Boolean inEdgeIsParent = inEdge.<Boolean>property("isParent").orElse(null);
+ if( inEdgeIsParent != null && inEdgeIsParent ){
+ foundParent = true;
+ currentNode = inEdge.otherVertex(currentNode);
+ break;
+ }
+ }
+
+ if (foundParent == false) {
+ break;
+ }
+
+ // find the key(s) and add to the url
+ // first see what type of node the parent is - note some nodes can have one of many kinds of parents
+ String depNodeType = currentNode.<String>property("aai-node-type").orElse(null);
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(depNodeType);
+ Iterator <String> keyPropI = keyProps.iterator();
+
+ String nodeUrl = null;
+ String depNodeTypePlural = dbMaps.NodePlural.get(depNodeType);
+
+ if (depNodeTypePlural != null)
+ nodeUrl = depNodeTypePlural + "/" + depNodeType + "/";
+
+ while (keyPropI.hasNext()) {
+ Object nodeKey = currentNode.<Object>property(keyPropI.next()).orElse(null);
+ nodeUrl += encodeURL(nodeKey.toString()) + "/";
+ }
+
+ currentNodeType = depNodeType;
+ url = nodeUrl + url;
+ }
+ // use the name space of the highest level of unique node since lots of children node types
+ // are common ex. l-interface is in the path for pserver and vpe
+ String urlNamespace = dbMaps.NodeNamespace.get(currentNodeType) + "/";
+ urlNamespace = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, urlNamespace);
+
+ // add the url component for the node passed in
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(nodeType);
+ Iterator <String> keyPropI = keyProps.iterator();
+
+ String nodeUrl = null;
+ String nodeTypePlural = "";
+ nodeTypePlural = dbMaps.NodePlural.get(nodeType);
+
+ if (nodeTypePlural != null && !nodeTypePlural.equals(""))
+ nodeUrl = nodeTypePlural + "/" + nodeType + "/";
+ else
+ nodeUrl = nodeType + "/";
+
+ if (nodeType.equals("ipaddress")) { // this has 2 keys but API only uses port-or -address in URL
+ String nodeKey = node.<String>property("port-or-interface").orElse(null);
+ nodeUrl += encodeURL(nodeKey) + "/";
+ } else {
+ while (keyPropI.hasNext()) {
+ Object nodeKey = node.<Object>property(keyPropI.next()).orElse(null);
+ nodeUrl += encodeURL(nodeKey.toString()) + "/";
+ }
+ }
+
+ String nodeVersion = dbMaps.NodeVersionInfoMap.get(nodeType);
+ String urlVersion = null;
+ int nodeVerNum = Integer.parseInt(nodeVersion.substring(1));
+ int apiVerNum = Integer.parseInt(apiVersion.substring(1));
+
+ if (nodeVerNum == apiVerNum || nodeVerNum < apiVerNum)
+ urlVersion = apiVersion;
+ else
+ urlVersion = nodeVersion;
+
+ url = AAIApiServerURLBase.get() + urlVersion + "/" + urlNamespace + url + nodeUrl;
+
+ return url;
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @return the string
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static String get(TitanTransaction graph, TitanVertex node) throws AAIException, UnsupportedEncodingException
+ {
+ return get(graph, node, null, false, false);
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @param apiVersion the api version
+ * @return the string
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static String get(TitanTransaction graph, TitanVertex node, String apiVersion) throws AAIException, UnsupportedEncodingException
+ {
+ return get(graph, node, apiVersion, false, false);
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @param apiVersion the api version
+ * @param isLegacyVserverUEB the is legacy vserver UEB
+ * @return the string
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static String get(TitanTransaction graph, TitanVertex node, String apiVersion, Boolean isLegacyVserverUEB) throws AAIException, UnsupportedEncodingException
+ {
+ return get(graph, node, apiVersion, isLegacyVserverUEB, false);
+ }
+
+ /**
+ * Gets the key hashes.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @return the key hashes
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static LinkedHashMap<String, Object> getKeyHashes(TitanTransaction graph, TitanVertex node) throws AAIException, UnsupportedEncodingException
+ {
+ return getKeyHashes(graph, node, null);
+ }
+
+ /**
+ * Encode URL.
+ *
+ * @param nodeKey the node key
+ * @return the string
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static final String encodeURL (String nodeKey) throws UnsupportedEncodingException {
+ return UriUtils.encodePath(nodeKey, "UTF-8").replaceAll("\\+", "%20");
+ }
+
+ /*
+ * method returns a Hash of Hashes for each parents keys for the given node based on its nodetype
+ * Special cases for REST URLs:
+ * - old URLS for vserver, ipaddress and volume node types for v2/v3
+ * - images, flavor, vnic and l-interface node types will return new url
+ * - nodetypes with multiple keys such as service capability
+ * - nodetypes with multiple keys such as ipaddress where we use one key in the URL
+ * - cvlan-tags and *list nodetypes - have special or no plurals - they get handled via the hash Map
+ */
+
+ /**
+ * Gets the key hashes.
+ *
+ * @param graph the graph
+ * @param node the node
+ * @param apiVersion the api version
+ * @return the key hashes
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static LinkedHashMap <String,Object> getKeyHashes(TitanTransaction graph, TitanVertex node, String apiVersion) throws AAIException, UnsupportedEncodingException
+ {
+ String nodeType = node.<String>property("aai-node-type").orElse(null);
+ Boolean noMoreDependentNodes = true;
+ TitanVertex currentNode = node;
+
+ if (apiVersion == null || apiVersion.equals("")) {
+ apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+ }
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(apiVersion);
+
+ // Hash of hashes of keys for each node and its ancestry
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap <String,Object> ();
+
+ // create the hash for the keys for the node passed in
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(nodeType);
+ Iterator <String> keyPropI = keyProps.iterator();
+
+ if (nodeType.equals("ipaddress")) { // this has 2 keys but API only uses port-or -address in URL
+ String nodeKeyValue = node.<String>property("port-or-interface").orElse(null);
+ thisNodeHash.put("port-or-interface", nodeKeyValue);
+ } else {
+ while (keyPropI.hasNext()) {
+ String nodeKeyName = keyPropI.next();
+ Object nodeKeyValue = node.<Object>property(nodeKeyName).orElse(null);
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ nodeKeyName = nodeType + "." + nodeKeyName;
+ }
+ }
+ returnHash.putAll(thisNodeHash);
+
+ // create and add the hashes for the dependent nodes for the node passed in
+ while (noMoreDependentNodes) {
+// Collection <String> depNodeTypeColl = DbRules.NodeDependencies.get(currentNodeType);
+// Iterator <String> depNodeTypeListIterator = (Iterator<String>) depNodeTypeColl.iterator();
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+//
+// if (!depNodeTypeListIterator.hasNext()) {
+// noMoreDependentNodes = false;
+// break;
+// }
+
+ boolean foundParent = false;
+
+ // Look for IN edges for the current Node and find its Parent - and make it the current Node
+ Iterator <Edge> inEdges = currentNode.edges(Direction.IN);
+ while( inEdges.hasNext() ){
+ TitanEdge inEdge = (TitanEdge) inEdges.next();
+ Boolean inEdgeIsParent = inEdge.<Boolean>property("isParent").orElse(null);
+ if( inEdgeIsParent != null && inEdgeIsParent ){
+ currentNode = inEdge.otherVertex(currentNode);
+ foundParent = true;
+ break;
+ }
+ }
+ if (foundParent == false) {
+ break;
+ }
+
+ // find the key(s) and add to the url
+ // first see what type of node the parent is - note some nodes can have one of many kinds of parents
+ String depNodeType = currentNode.<String>property("aai-node-type").orElse(null);
+ keyProps = dbMaps.NodeKeyProps.get(depNodeType);
+ keyPropI = keyProps.iterator();
+
+ while (keyPropI.hasNext()) {
+ String nodeKeyName = keyPropI.next();
+ Object nodeKeyValue = currentNode.<Object>property(nodeKeyName).orElse(null);
+ nodeKeyName = depNodeType + "." + nodeKeyName;
+ // key name will be like tenant.tenant-id
+
+ depNodeHash.put(nodeKeyName, nodeKeyValue);
+ }
+ returnHash.putAll(depNodeHash);
+ }
+
+ return returnHash;
+ }
+
+ /*
+ * method returns a Hash of Hashes for each parents keys for the given node based on its nodeURI
+ * Special cases for REST URLs:
+ * - images, flavor, vnic and l-interface node types will return new url
+ * - nodetypes with multiple keys such as service capability
+ * - nodetypes with multiple keys such as ipaddress where we use one key in the URL
+ * - cvlan-tags and *list nodetypes - have special or no plurals - they get handled via the hash Map
+ */
+
+ /**
+ * Gets the key hashes.
+ *
+ * @param nodeURI the node URI
+ * @return the key hashes
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static LinkedHashMap <String,Object> getKeyHashes(String nodeURI) throws AAIException, UnsupportedEncodingException
+ {
+ return getKeyHashes(nodeURI, null);
+
+ }
+
+ /**
+ * Gets the key hashes.
+ *
+ * @param nodeURI the node URI
+ * @param apiVersion the api version
+ * @return the key hashes
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public static LinkedHashMap <String,Object> getKeyHashes(String nodeURI, String apiVersion) throws AAIException, UnsupportedEncodingException
+ {
+
+ if (apiVersion == null || apiVersion.equals(""))
+ apiVersion = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP);
+
+ DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(apiVersion);
+
+ // Hash of hashes of keys for each node and its ancestry
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap <String,Object> ();
+
+ String path = nodeURI.replaceFirst("^/", "");
+ Path p = Paths.get(path);
+ int index = p.getNameCount() - 2; // index of where we expect the node type to be
+
+ // if the node type has one key
+ String currentNodeType = p.getName(index).toString();
+ // if the node type has two keys - this assumes max 2 keys
+ if (!dbMaps.NodeKeyProps.containsKey(currentNodeType))
+ currentNodeType = p.getName(--index).toString();
+
+ // create the hash for the keys for the node passed in
+ LinkedHashMap <String,Object> thisNodeHash = new LinkedHashMap <String,Object> ();
+ Collection <String> keyProps = dbMaps.NodeKeyProps.get(currentNodeType);
+ Iterator <String> keyPropI = keyProps.iterator();
+
+ if (currentNodeType.equals("ipaddress")) { // this has 2 keys but API only uses port-or -address in URL
+ String nodeKeyValue = p.getName(index + 1).toString();
+ thisNodeHash.put("port-or-interface", nodeKeyValue);
+ } else {
+ int j = 1;
+ while (keyPropI.hasNext()) {
+ String nodeKeyName = currentNodeType + "." + keyPropI.next();
+ String nodeKeyValue = p.getName(index + j++).toString();
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ }
+ }
+ returnHash.putAll(thisNodeHash);
+ if (!currentNodeType.contains("-list"))
+ index -= 3;
+ else
+ index -= 2; // no plural in this case
+
+
+ // create and add the hashes for the dependent nodes for the node passed in
+ LinkedHashMap <String,Object> depNodeHash = new LinkedHashMap <String,Object> ();
+ String depNodeType = null;
+ while (index >= 2) {
+ if (depNodeType == null) depNodeType = p.getName(index).toString();
+ //System.out.println("index=" + index);
+ // if the node type has one key
+ currentNodeType = p.getName(index).toString();
+ // if the node type has two keys - this assumes max 2 keys
+ if (!dbMaps.NodeKeyProps.containsKey(currentNodeType))
+ currentNodeType = p.getName(--index).toString();
+
+ keyProps = dbMaps.NodeKeyProps.get(currentNodeType);
+ keyPropI = keyProps.iterator();
+
+ if (currentNodeType.equals("ipaddress")) { // this has 2 keys but API only uses port-or -address in URL
+ String nodeKeyValue = p.getName(index + 1).toString();
+ depNodeHash.put("port-or-interface", nodeKeyValue);
+ } else {
+ int j = 1;
+ while (keyPropI.hasNext()) {
+ String nodeKeyName = currentNodeType + "." + keyPropI.next();
+ String nodeKeyValue = p.getName(index + j++).toString();
+ depNodeHash.put(nodeKeyName, nodeKeyValue);
+ }
+ }
+
+ if (!currentNodeType.contains("-list"))
+ index -= 3;
+ else
+ index -= 2; // no plural in this case
+ }
+ if (depNodeType != null)
+ returnHash.putAll(depNodeHash);
+
+ return returnHash;
+ }
+
+ /**
+ * Parses the uri.
+ *
+ * @param allKeys the all keys
+ * @param keyList the key list
+ * @param uri the uri
+ * @param aaiExtMap the aai ext map
+ * @return the AAI resource
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public static AAIResource parseUri(HashMap<String, String> allKeys, LinkedHashMap<String,
+ LinkedHashMap<String,Object>> keyList, String uri,
+ AAIExtensionMap aaiExtMap) throws UnsupportedEncodingException, AAIException {
+ List<String> ps = Arrays.asList(uri.split("/"));
+
+ // uri is the entire url including server name and version etc.
+ String apiVersion = ps.get(4).toString();
+ aaiExtMap.setApiVersion(apiVersion);
+
+ AAIResources aaiResources = org.openecomp.aai.ingestModel.IngestModelMoxyOxm.aaiResourceContainer.get(apiVersion);
+
+ String namespace = ps.get(5).toString();
+
+ aaiExtMap.setNamespace(namespace);
+
+ // /vces/vce/{vnf-id}/port-groups/port-group/{port-group-id}/cvlan-tag-entry/cvlan-tag/{cvlan-tag}
+
+ // FullName -> /Vces/Vce/PortGroups/PortGroup/CvlanTagEntry/CvlanTag <-
+
+ String fullResourceName = "/" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, namespace);
+ AAIResources theseResources = new AAIResources();
+
+ StringBuffer thisUri = new StringBuffer();
+
+ // the URI config option in the props file has a trailing slash
+ thisUri.append("/" + namespace);
+
+ boolean firstNode = true;
+
+ AAIResource lastResource = null;
+
+ for (int i = 6; i < ps.size(); i++) {
+
+ AAIResource aaiRes;
+ StringBuffer tmpResourceName = new StringBuffer();
+
+ String p = ps.get(i);
+ String seg = p.toString();
+
+ thisUri.append("/" + seg);
+
+ tmpResourceName.append(fullResourceName);
+
+ if (seg.equals("cvlan-tag")) {
+ seg = "cvlan-tag-entry";
+ }
+ tmpResourceName.append("/" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, seg));
+
+ String tmpResource = tmpResourceName.toString();
+
+ if (aaiResources.getAaiResources().containsKey(tmpResource)) {
+ aaiRes = aaiResources.getAaiResources().get(tmpResource);
+ lastResource = aaiRes;
+ theseResources.getAaiResources().put(tmpResource, aaiRes);
+ fullResourceName = tmpResource;
+ if ("node".equals(aaiRes.getResourceType())) {
+
+ if (firstNode == true) {
+ aaiExtMap.setTopObjectFullResourceName(fullResourceName);
+ firstNode = false;
+ }
+
+ // get the keys, which will be in order and the next path segment(s)
+ AAIResourceKeys keys = aaiRes.getAaiResourceKeys();
+
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+
+ // there might not be another path segment
+ if ( (i + 1) < ps.size()) {
+
+ for (AAIResourceKey rk : keys.getAaiResourceKey()) {
+ String p1 = ps.get(++i);
+ String encodedKey = p1.toString();
+ thisUri.append("/" + encodedKey);
+ String decodedKey = UriUtils.decode(p1.toString(), "UTF-8");
+ subKeyList.put(rk.getKeyName(), decodedKey);
+ }
+ keyList.put(tmpResource, subKeyList);
+ // this is the key
+ allKeys.put(tmpResource, thisUri.toString());
+
+ }
+ } else { // examples sit directly under the container level, should probably be query params!!!
+ if ( (i + 1) < ps.size()) {
+ String p1 = ps.get(i+1);
+ if (p1.toString().equals("example") || p1.toString().equals("singletonExample")) {
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+ subKeyList.put("container|example", p1.toString());
+ keyList.put(tmpResource, subKeyList);
+ }
+ }
+ }
+ } else {
+ if (p.toString().equals("relationship-list")) {
+ LinkedHashMap<String,Object> subKeyList = new LinkedHashMap<String,Object>();
+ subKeyList.put("container|relationship", p.toString());
+ keyList.put(tmpResource, subKeyList);
+ } else if ( p.toString().length() > 0 && !p.toString().equals("example") && !p.toString().equals("singletonExample")
+ && !p.toString().equals("relationship") ) {
+ // this means the URL will break the model, so we bail
+ throw new AAIException("AAI_3001", "bad path");
+ }
+ }
+ }
+ aaiExtMap.setUri(AAIConfig.get("aai.global.callback.url") + apiVersion + thisUri.toString());
+ aaiExtMap.setNotificationUri(AAIConfig.get("aai.global.callback.url") + AAIConfig.get("aai.notification.current.version") + thisUri.toString());
+ aaiExtMap.setFullResourceName(fullResourceName);
+ return lastResource;
+ }
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public static void main (String[] args) throws UnsupportedEncodingException, AAIException {
+
+ String nodeURI = args[0];
+
+ IngestModelMoxyOxm moxyMod = new IngestModelMoxyOxm();
+ try {
+ ArrayList <String> defaultVerLst = new ArrayList <String> ();
+ defaultVerLst.add( AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP) );
+ moxyMod.init( defaultVerLst, false);
+ }
+ catch (Exception ex){
+ String emsg = " ERROR - Could not get the DbMaps object. ";
+ System.out.print(emsg);
+ System.out.println("Exception.getMessage() = [" + ex.getMessage() + "]");
+ System.exit(1);
+ }
+
+ LinkedHashMap <String,Object> returnHash = getKeyHashes(nodeURI);
+
+ Set<String> returnKeySet = returnHash.keySet();
+ Iterator<String> iter = returnKeySet.iterator();
+
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ System.out.println("from url :" + key + ":" + (returnHash.get(key)).toString());
+ }
+
+ TitanTransaction g = AAIGraph.getInstance().getGraph().newTransaction();
+
+ TitanVertex vtx = DbMeth.getUniqueNodeWithDepParams("test", "test", g, "l3-interface-ipv6-address-list", returnHash, "v7");
+ returnHash = getKeyHashes(g, vtx);
+
+ returnKeySet = returnHash.keySet();
+ iter = returnKeySet.iterator();
+
+ while (iter.hasNext()) {
+ String key = (String) iter.next();
+ System.out.println("from vtx: " + key + ":" + (returnHash.get(key)).toString());
+ }
+ g.rollback();
+ System.exit(0);
+ }
+
+}
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java
new file mode 100644
index 0000000..89152ce
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java
@@ -0,0 +1,211 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.UUID;
+
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.openecomp.aai.domain.notificationEvent.NotificationEvent;
+import org.openecomp.aai.exceptions.AAIException;
+
+public class StoreNotificationEvent {
+
+ /**
+ * Instantiates a new store notification event.
+ */
+ public StoreNotificationEvent() {}
+
+ /**
+ * Store event.
+ *
+ * @param eh the eh
+ * @param obj the obj
+ * @throws AAIException the AAI exception
+ */
+ public void storeEvent(NotificationEvent.EventHeader eh, Object obj) throws AAIException {
+
+ if (obj == null) {
+ throw new AAIException("AAI_7350");
+ }
+
+ org.openecomp.aai.domain.notificationEvent.ObjectFactory factory = new org.openecomp.aai.domain.notificationEvent.ObjectFactory();
+
+ org.openecomp.aai.domain.notificationEvent.NotificationEvent ne = factory.createNotificationEvent();
+
+ if (eh.getId() == null) {
+ eh.setId(genDate2() + "-" + UUID.randomUUID().toString());
+ }
+ if (eh.getTimestamp() == null) {
+ eh.setTimestamp(genDate());
+ }
+
+ // there's no default, but i think we want to put this in hbase?
+
+ if (eh.getEntityLink() == null) {
+ eh.setEntityLink("UNK");
+ }
+
+ if (eh.getAction() == null) {
+ eh.setAction("UNK");
+ }
+
+ if (eh.getEventType() == null) {
+ eh.setEventType(AAIConfig.get("aai.notificationEvent.default.eventType", "UNK"));
+ }
+
+ if (eh.getDomain() == null) {
+ eh.setDomain(AAIConfig.get("aai.notificationEvent.default.domain", "UNK"));
+ }
+
+ if (eh.getSourceName() == null) {
+ eh.setSourceName(AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK"));
+ }
+
+ if (eh.getSequenceNumber() == null) {
+ eh.setSequenceNumber(AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK"));
+ }
+
+ if (eh.getSeverity() == null) {
+ eh.setSeverity(AAIConfig.get("aai.notificationEvent.default.severity", "UNK"));
+ }
+
+ if (eh.getVersion() == null) {
+ eh.setVersion(AAIConfig.get("aai.notificationEvent.default.version", "UNK"));
+ }
+
+ ne.setCambriaPartition(AAIConstants.UEB_PUB_PARTITION_AAI);
+ ne.setEventHeader(eh);
+ ne.setEntity(obj);
+
+ try {
+ Exchange message = PhaseInterceptorChain.getCurrentMessage().getExchange();
+ message.put("NOTIFICATION_EVENT", ne);
+ } catch (Exception e) {
+ throw new AAIException("AAI_7350", e);
+ }
+ }
+
+ /**
+ * Store dynamic event.
+ *
+ * @param notificationJaxbContext the notification jaxb context
+ * @param notificationVersion the notification version
+ * @param eventHeader the event header
+ * @param obj the obj
+ * @throws AAIException the AAI exception
+ */
+ public void storeDynamicEvent(DynamicJAXBContext notificationJaxbContext, String notificationVersion, DynamicEntity eventHeader, DynamicEntity obj) throws AAIException {
+
+ if (obj == null) {
+ throw new AAIException("AAI_7350");
+ }
+
+ DynamicEntity notificationEvent = notificationJaxbContext.getDynamicType("inventory.aai.openecomp.org." + notificationVersion + ".NotificationEvent").newDynamicEntity();
+
+ if (eventHeader.get("id") == null) {
+ eventHeader.set("id", genDate2() + "-" + UUID.randomUUID().toString());
+ }
+ if (eventHeader.get("timestamp") == null) {
+ eventHeader.set("timestamp", genDate());
+ }
+
+ // there's no default, but i think we want to put this in hbase?
+
+ if (eventHeader.get("entityLink") == null) {
+ eventHeader.set("entityLink", "UNK");
+ }
+
+ if (eventHeader.get("action") == null) {
+ eventHeader.set("action", "UNK");
+ }
+
+ if (eventHeader.get("eventType") == null) {
+ eventHeader.set("eventType", AAIConfig.get("aai.notificationEvent.default.eventType", "UNK"));
+ }
+
+ if (eventHeader.get("domain") == null) {
+ eventHeader.set("domain", AAIConfig.get("aai.notificationEvent.default.domain", "UNK"));
+ }
+
+ if (eventHeader.get("sourceName") == null) {
+ eventHeader.set("sourceName", AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK"));
+ }
+
+ if (eventHeader.get("sequenceNumber") == null) {
+ eventHeader.set("sequenceNumber", AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK"));
+ }
+
+ if (eventHeader.get("severity") == null) {
+ eventHeader.set("severity", AAIConfig.get("aai.notificationEvent.default.severity", "UNK"));
+ }
+
+ if (eventHeader.get("version") == null) {
+ eventHeader.set("version", AAIConfig.get("aai.notificationEvent.default.version", "UNK"));
+ }
+
+ if (notificationEvent.get("cambriaPartition") == null) {
+ notificationEvent.set("cambriaPartition", AAIConstants.UEB_PUB_PARTITION_AAI);
+ }
+
+ notificationEvent.set("eventHeader", eventHeader);
+ notificationEvent.set("entity", obj);
+
+ try {
+ Exchange message = PhaseInterceptorChain.getCurrentMessage().getExchange();
+ message.put("NOTIFICATION_EVENT", notificationEvent);
+ message.put("NOTIFICATION_EVENT_TYPE", "dynamic");
+ message.put("NOTIFICATION_JAXB_CONTEXT", notificationJaxbContext);
+ } catch (Exception e) {
+ throw new AAIException("AAI_7350", e);
+ }
+ }
+
+ /**
+ * Gen date.
+ *
+ * @return the string
+ */
+ public static String genDate() {
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS");
+ return formatter.format(date);
+ }
+
+ /**
+ * Gen date 2.
+ *
+ * @return the string
+ */
+ public static String genDate2() {
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat("YYYYMMddHHmmss");
+ return formatter.format(date);
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java
new file mode 100644
index 0000000..d3f1d6a
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java
@@ -0,0 +1,264 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.openecomp.aai.exceptions.AAIException;
+import org.slf4j.MDC;
+
+import com.att.eelf.configuration.Configuration;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+
+public class UniquePropertyCheck {
+
+
+ private static final String FROMAPPID = "AAI-UTILS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static final String COMPONENT = "UniquePropertyCheck";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, "uniquePropertyCheck-logback.xml");
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+ EELFLogger logger = EELFManager.getInstance().getLogger(UniquePropertyCheck.class.getSimpleName());
+ MDC.put("logFilenameAppender", UniquePropertyCheck.class.getSimpleName());
+
+ if( args == null || args.length != 1 ){
+ String msg = "usage: UniquePropertyCheck propertyName \n";
+ System.out.println(msg);
+ logAndPrint(logger, msg );
+ System.exit(1);
+ }
+ String propertyName = args[0];
+ TitanTransaction graph = null;
+
+ try {
+ AAIConfig.init(TRANSID, FROMAPPID);
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n");
+ TitanGraph tGraph = TitanFactory.open(AAIConstants.AAI_CONFIG_FILENAME);
+
+ if( tGraph == null ) {
+ logAndPrint(logger, " Error: Could not get TitanGraph ");
+ System.exit(1);
+ }
+
+ graph = tGraph.newTransaction();
+ if( graph == null ){
+ logAndPrint(logger, "could not get graph object in UniquePropertyCheck() \n");
+ System.exit(0);
+ }
+ }
+ catch (AAIException e1) {
+ String msg = "Threw Exception: [" + e1.toString() + "]";
+ logAndPrint(logger, msg);
+ System.exit(0);
+ }
+ catch (Exception e2) {
+ String msg = "Threw Exception: [" + e2.toString() + "]";
+ logAndPrint(logger, msg);
+ System.exit(0);
+ }
+
+ runTheCheckForUniqueness( TRANSID, FROMAPPID, graph, propertyName, logger );
+ System.exit(0);
+
+ }// End main()
+
+
+ /**
+ * Run the check for uniqueness.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param propertyName the property name
+ * @param logger the logger
+ * @return the boolean
+ */
+ public static Boolean runTheCheckForUniqueness( String transId, String fromAppId, TitanTransaction graph,
+ String propertyName, EELFLogger logger ){
+
+ // Note - property can be found in more than one nodetype
+ // our uniqueness constraints are always across the entire db - so this
+ // tool looks across all nodeTypes that the property is found in.
+ Boolean foundDupesFlag = false;
+
+ HashMap <String,String> valuesAndVidHash = new HashMap <String, String> ();
+ HashMap <String,String> dupeHash = new HashMap <String, String> ();
+
+ int propCount = 0;
+ int dupeCount = 0;
+ Iterable <?> vertItr = graph.query().has(propertyName).vertices();
+ Iterator <?> vertItor = vertItr.iterator();
+ while( vertItor.hasNext() ){
+ propCount++;
+ TitanVertex v = (TitanVertex)vertItor.next();
+ String thisVid = v.id().toString();
+ Object val = (v.<Object>property(propertyName)).orElse(null);
+ if( valuesAndVidHash.containsKey(val) ){
+ // We've seen this one before- track it in our dupe hash
+ dupeCount++;
+ if( dupeHash.containsKey(val) ){
+ // This is not the first one being added to the dupe hash for this value
+ String updatedDupeList = dupeHash.get(val) + "|" + thisVid;
+ dupeHash.put(val.toString(), updatedDupeList);
+ }
+ else {
+ // This is the first time we see this value repeating
+ String firstTwoVids = valuesAndVidHash.get(val) + "|" + thisVid;
+ dupeHash.put(val.toString(), firstTwoVids);
+ }
+ }
+ else {
+ valuesAndVidHash.put(val.toString(), thisVid);
+ }
+ }
+
+
+ String info = "\n Found this property [" + propertyName + "] " + propCount + " times in our db.";
+ logAndPrint(logger, info);
+ info = " Found " + dupeCount + " cases of duplicate values for this property.\n\n";
+ logAndPrint(logger, info);
+
+ try {
+ if( ! dupeHash.isEmpty() ){
+ Iterator <?> dupeItr = dupeHash.entrySet().iterator();
+ while( dupeItr.hasNext() ){
+ Map.Entry pair = (Map.Entry) dupeItr.next();
+ String dupeValue = pair.getKey().toString();;
+ String vidsStr = pair.getValue().toString();
+ String[] vidArr = vidsStr.split("\\|");
+ logAndPrint(logger, "\n\n -------------- Found " + vidArr.length
+ + " nodes with " + propertyName + " of this value: [" + dupeValue + "]. Node details: ");
+
+ for( int i = 0; i < vidArr.length; i++ ){
+ String vidString = vidArr[i];
+ Long idLong = Long.valueOf(vidString);
+ TitanVertex tvx = (TitanVertex)graph.getVertex(idLong);
+ showPropertiesAndEdges( TRANSID, FROMAPPID, tvx, logger );
+ }
+ }
+ }
+ }
+ catch( Exception e2 ){
+ logAndPrint(logger, "Threw Exception: [" + e2.toString() + "]");
+ }
+ finally {
+ if( graph != null ){
+ graph.rollback();
+ }
+ }
+
+ return foundDupesFlag;
+
+ }// end of runTheCheckForUniqueness()
+
+
+ /**
+ * Show properties and edges.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @param logger the logger
+ */
+ private static void showPropertiesAndEdges( String transId, String fromAppId, TitanVertex tVert,
+ EELFLogger logger ){
+
+ if( tVert == null ){
+ logAndPrint(logger, "Null node passed to showPropertiesAndEdges.");
+ }
+ else {
+ String nodeType = "";
+ Object ob = tVert.<String>property("aai-node-type");
+ if( ob == null ){
+ nodeType = "null";
+ }
+ else{
+ nodeType = ob.toString();
+ }
+
+ logAndPrint(logger, " AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
+ logAndPrint(logger, " Property Detail: ");
+ Iterator<VertexProperty<Object>> pI = tVert.properties();
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ Object val = tp.value();
+ logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] ");
+ }
+
+ Iterator <Edge> eI = tVert.edges(Direction.BOTH);
+ if( ! eI.hasNext() ){
+ logAndPrint(logger, "No edges were found for this vertex. ");
+ }
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ String lab = ed.label();
+ TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert);
+ if( vtx == null ){
+ logAndPrint(logger, " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
+ }
+ else {
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ String vid = vtx.id().toString();
+ logAndPrint(logger, "Found an edge (" + lab + ") from this vertex to a [" + nType + "] node with VtxId = " + vid);
+ }
+ }
+ }
+ } // End of showPropertiesAndEdges()
+
+
+ /**
+ * Log and print.
+ *
+ * @param logger the logger
+ * @param msg the msg
+ */
+ protected static void logAndPrint(EELFLogger logger, String msg) {
+ System.out.println(msg);
+ logger.info(msg);
+ }
+
+}
+
+
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/util/UpdateResource.java b/ajsc-aai/src/main/java/org/openecomp/aai/util/UpdateResource.java
new file mode 100644
index 0000000..1548cbe
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/util/UpdateResource.java
@@ -0,0 +1,146 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.Properties;
+import java.util.UUID;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.domain.yang.Action;
+import org.openecomp.aai.domain.yang.ActionData;
+import org.openecomp.aai.domain.yang.Update;
+import com.att.eelf.configuration.Configuration;
+
+
+public class UpdateResource {
+
+ private static final String COMPONENT = "aairestctrl";
+ private static final String FROMAPPID = "AAIUPDT";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static final String UPDATE_URL = "actions/update";
+
+ private static final String USAGE_STRING = "Usage: updateTool.sh \n" +
+ "<node type> <update node URI> <property name>:<property value>[,<property name>:<property value]* | \n" +
+ "where update node uri is the URI path for that node \n" +
+ " for ex. ./updateTool.sh pserver cloud-infrastructure/pservers/pserver/XXX prov-status:NEWSTATUS";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+ String nodeType = null;
+ String nodeURI = null;
+ String updValueList = null;
+
+ // Set the logging file properties to be used by EELFManager
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_UPDTOOL_LOGBACK_PROPS);
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+
+ AAILogger aaiLogger = new AAILogger(UpdateResource.class.getName());
+ LogLine logline = new LogLine();
+ logline.init(COMPONENT, TRANSID, FROMAPPID, "main");
+ try {
+ if (args.length < 3) {
+ System.out.println("Nothing to update or Insufficient arguments");
+ System.out.println(USAGE_STRING);
+ logline.add("msg", "Insufficient or Invalid arguments");
+ aaiLogger.info(logline, true, "0");
+ System.exit(1);
+ } else {
+ nodeType = args[0];
+ nodeURI = args[1];
+ updValueList = args[2];
+
+ logline.add("nodeType", nodeType);
+ logline.add("nodeURI", nodeURI);
+ logline.add("updValueList", updValueList);
+
+ update(aaiLogger, logline, nodeType, nodeURI, updValueList);
+ }
+ aaiLogger.info(logline, true, "0");
+ System.exit(0);
+
+ } catch (AAIException e) {
+ System.out.println("Update failed: " + e.getMessage());
+ aaiLogger.error(e.getErrorObject(), logline, e);
+ aaiLogger.info(logline, false, e.getErrorObject().getErrorCodeString());
+ System.exit(1);
+ } catch (Exception e) {
+ System.out.println("Update failed: " + e.toString());
+ aaiLogger.error(ErrorLogHelper.getErrorObject("AAI_7402", e.getMessage()), logline, e);
+ aaiLogger.info(logline, false, "AAI_7402");
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Update.
+ *
+ * @param <T> the generic type
+ * @param aaiLogger the aai logger
+ * @param logline the logline
+ * @param nodeType the node type
+ * @param nodeURI the node URI
+ * @param updValueList the upd value list
+ * @throws AAIException the AAI exception
+ */
+ public static <T> void update(AAILogger aaiLogger, LogLine logline, String nodeType,
+ String nodeURI, String updValueList) throws AAIException {
+ try {
+
+ Update update = new Update();
+ update.setUpdateNodeType(nodeType);
+ update.setUpdateNodeUri(nodeURI);
+
+ Action action = new Action();
+ action.setActionType("replace");
+
+ for (String updValue: updValueList.split(",")) {
+ ActionData data = new ActionData();
+ data.setPropertyName(updValue.substring(0, updValue.indexOf(':')));
+ data.setPropertyValue(updValue.substring(updValue.indexOf(':') + 1));
+ action.getActionData().add(data);
+ }
+
+ update.getAction().add(action);
+
+ System.out.println("updating the resource... ");
+
+ RestController.<Update>Put(update, FROMAPPID, TRANSID, UPDATE_URL);
+ System.out.println("Update Successful");
+ aaiLogger.info(logline, true, "0");
+ } catch (AAIException e) {
+ String msg = "Update failed.";
+ logline.add("msg", msg);
+ System.out.println(msg);
+ throw e;
+ } catch (Exception e) {
+ throw new AAIException("AAI_7402", e, "Error during UPDATE");
+ }
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/LegacyURLTransformer.java b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/LegacyURLTransformer.java
new file mode 100644
index 0000000..2775af0
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/LegacyURLTransformer.java
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.workarounds;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class LegacyURLTransformer {
+
+ /**
+ * Instantiates a new legacy URL transformer.
+ */
+ private LegacyURLTransformer() {
+
+ }
+
+ private static class Helper {
+ private static final LegacyURLTransformer INSTANCE = new LegacyURLTransformer();
+ }
+
+ /**
+ * Gets the single instance of LegacyURLTransformer.
+ *
+ * @return single instance of LegacyURLTransformer
+ */
+ public static LegacyURLTransformer getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ /**
+ * Gets the legacy URL.
+ *
+ * @param url the url
+ * @return the legacy URL
+ * @throws MalformedURLException the malformed URL exception
+ */
+ public URL getLegacyURL(URL url) throws MalformedURLException {
+ String substring = "/aai/(?<version>v\\d+)/cloud-infrastructure/tenants/tenant/(?<tenantKey>.*?)/vservers/vserver/(?<vserverKey>[^/]*?$)";
+ String replacement = "/aai/servers/${version}/${tenantKey}/vservers/${vserverKey}";
+ Pattern p = Pattern.compile(substring);
+ String result = url.toString();
+ Matcher m = p.matcher(result);
+ if (m.find()) {
+ result = m.replaceFirst(replacement);
+
+ }
+ URL resultUrl = new URL(result);
+ return resultUrl;
+
+ }
+
+ /**
+ * Gets the current URL.
+ *
+ * @param url the url
+ * @return the current URL
+ * @throws MalformedURLException the malformed URL exception
+ */
+ public URL getCurrentURL(URL url) throws MalformedURLException {
+ String substring = "/aai/servers/(?<version>v[23])/(?<tenantKey>.*?)/vservers/(?<vserverKey>[^/]*?$)";
+ String replacement = "/aai/${version}/cloud-infrastructure/tenants/tenant/${tenantKey}/vservers/vserver/${vserverKey}";
+ Pattern p = Pattern.compile(substring);
+ String result = url.toString();
+ Matcher m = p.matcher(result);
+ if (m.find()) {
+ result = m.replaceFirst(replacement);
+
+ }
+
+ URL resultUrl = new URL(result);
+ return resultUrl;
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/ModifyOXMProperties.java b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/ModifyOXMProperties.java
new file mode 100644
index 0000000..4f42afb
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/ModifyOXMProperties.java
@@ -0,0 +1,220 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.workarounds;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.CaseFormat;
+
+public class ModifyOXMProperties {
+
+ private static String[] versions = new String[]{"v8"};
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws SAXException the SAX exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws ParserConfigurationException the parser configuration exception
+ * @throws XPathExpressionException the x path expression exception
+ * @throws TransformerException the transformer exception
+ */
+ public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException, TransformerException {
+
+ for (int i = 0; i < versions.length; i++) {
+ process(versions[i]);
+ }
+
+
+
+ }
+
+ /**
+ * Process.
+ *
+ * @param version the version
+ * @throws SAXException the SAX exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws ParserConfigurationException the parser configuration exception
+ * @throws XPathExpressionException the x path expression exception
+ * @throws TransformerException the transformer exception
+ */
+ private static void process(String version) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException, TransformerException {
+
+
+
+ String filepath = "bundleconfig-local/etc/oxm/aai_oxm_" + version + ".xml";
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ docFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+ Document doc = docBuilder.parse(filepath);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ NodeList list = doc.getElementsByTagName("java-type");
+ //Find namespaces - restrict to inventory
+ //XPathExpression expr = xpath.compile("//java-type[java-attributes[count(xml-element[contains(@type, 'aai.openecomp.org')])=count(./xml-element)][count(xml-element) > 1]]/xml-root-element");
+ XPathExpression expr = xpath.compile("//java-type[@name='Inventory']/java-attributes/xml-element/@name");
+ Object result = expr.evaluate(doc, XPathConstants.NODESET);
+ NodeList nodes = (NodeList) result;
+ String[] temp = null;
+ List<String> itemsUnderInventory = new ArrayList<>();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ itemsUnderInventory.add(nodes.item(i).getTextContent());
+ }
+ Map<String, String> namespaces = new HashMap<>();
+
+ itemsUnderInventory.remove("Search");
+ for (String item : itemsUnderInventory) {
+ expr = xpath.compile("//java-type[xml-root-element/@name='" + item + "']");
+ result = expr.evaluate(doc, XPathConstants.NODESET);
+ nodes = (NodeList) result;
+ for (int i = 0; i < nodes.getLength(); i++) {
+ String a = "java-attributes/xml-element/@type[contains(.,'aai.openecomp.org')]";
+ XPathExpression expr2 = xpath.compile(a);
+ Object result2 = expr2.evaluate(nodes.item(i), XPathConstants.NODESET);
+
+ NodeList node2 = (NodeList) result2;
+ for (int j = 0; j < node2.getLength(); j++) {
+ temp = node2.item(j).getTextContent().split("\\.");
+ namespaces.put(temp[temp.length-1], item);
+ }
+ }
+ }
+
+
+
+ //go through plurals
+ expr = xpath.compile("//java-type[java-attributes[count(xml-element) = 1]/xml-element[contains(@type, 'aai.openecomp.org')]]/xml-root-element");
+
+ result = expr.evaluate(doc, XPathConstants.NODESET);
+ nodes = (NodeList) result;
+ List<String> children = new ArrayList<>();
+ for (int i = 0; i < nodes.getLength(); i++) {
+ XPathExpression expr2 = xpath.compile("../java-attributes/xml-element[1]/@type[contains(.,'aai.openecomp.org')]");
+ Object result2 = expr2.evaluate(nodes.item(i), XPathConstants.NODESET);
+
+ NodeList node2 = (NodeList) result2;
+ temp = node2.item(0).getTextContent().split("\\.");
+ String containerName = nodes.item(i).getAttributes().getNamedItem("name").getTextContent();
+ String childrenTuple = containerName + "," + temp[temp.length-1];
+ if (namespaces.containsKey(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL,containerName))) {
+ childrenTuple += "," + namespaces.get(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL,containerName));
+ }
+ children.add(childrenTuple);
+ }
+
+ //match types up with plurals
+ String[] split = null;
+ for (String s : children) {
+ split = s.split(",");
+ expr = xpath.compile("//java-type[@name='"+split[1]+"']/xml-properties");
+ result = expr.evaluate(doc, XPathConstants.NODESET);
+ nodes = (NodeList) result;
+ if (nodes.getLength() > 0) {
+ Element property = null;
+
+ if (!hasChild(nodes.item(0), "name", "container")) {
+
+ property = doc.createElement("xml-property");
+
+ property.setAttribute("name", "container");
+ property.setAttribute("value",split[0]);
+ nodes.item(0).appendChild(property);
+
+ }
+
+ if (split.length == 3) {
+ Element property2 = null;
+ if (!hasChild(nodes.item(0), "name", "namespace")) {
+ property2 = doc.createElement("xml-property");
+ property2.setAttribute("name", "namespace");
+ property2.setAttribute("value",split[2]);
+ nodes.item(0).appendChild(property2);
+ }
+
+ }
+ }
+
+
+ }
+
+ filepath = "bundleconfig-local/etc/oxm/aai_oxm_" + version + ".xml";
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ Transformer transformer = transformerFactory.newTransformer();
+ DOMSource source = new DOMSource(doc);
+ StreamResult file = new StreamResult(new File(filepath));
+ transformer.transform(source, file);
+ }
+
+ /**
+ * Checks for child.
+ *
+ * @param node the node
+ * @param name the name
+ * @param value the value
+ * @return true, if successful
+ */
+ private static boolean hasChild(Node node, String name, String value) {
+ boolean result = false;
+ NodeList list = node.getChildNodes();
+ Node temp = null;
+ for (int i = 0; i < list.getLength(); i++) {
+
+ if (list.item(i).hasAttributes()) {
+ temp = list.item(i).getAttributes().getNamedItem(name);
+ }
+
+ if (temp != null && temp.getTextContent().equals(value)) {
+ result = true;
+ }
+ }
+
+ return result;
+ }
+
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/NamingExceptions.java b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/NamingExceptions.java
new file mode 100644
index 0000000..7ce063e
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/NamingExceptions.java
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.workarounds;
+
+public class NamingExceptions {
+
+ /**
+ * Instantiates a new naming exceptions.
+ */
+ private NamingExceptions() {
+
+ }
+
+ private static class Helper {
+ private static final NamingExceptions INSTANCE = new NamingExceptions();
+ }
+
+ /**
+ * Gets the single instance of NamingExceptions.
+ *
+ * @return single instance of NamingExceptions
+ */
+ public static NamingExceptions getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ /**
+ * Gets the object name.
+ *
+ * @param name the name
+ * @return the object name
+ */
+ public String getObjectName(String name) {
+
+ String result = name;
+
+ if (name.equals("cvlan-tag")) {
+ result = "cvlan-tag-entry";
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets the DB name.
+ *
+ * @param name the name
+ * @return the DB name
+ */
+ public String getDBName(String name) {
+
+ String result = name;
+
+ if (name.equals("cvlan-tag-entry")) {
+ result = "cvlan-tag";
+ }
+
+ return result;
+
+ }
+}
diff --git a/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/RemoveDME2QueryParams.java b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/RemoveDME2QueryParams.java
new file mode 100644
index 0000000..b829639
--- /dev/null
+++ b/ajsc-aai/src/main/java/org/openecomp/aai/workarounds/RemoveDME2QueryParams.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.workarounds;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+public class RemoveDME2QueryParams {
+
+ private final String[] blacklist = {"version", "envContext", "routeOffer"};
+
+
+ /**
+ * Should remove query params.
+ *
+ * @param params the params
+ * @return true, if successful
+ */
+ public boolean shouldRemoveQueryParams(MultivaluedMap<String, String> params) {
+ boolean remove = true;
+
+ for (String param : blacklist) {
+ if (!params.containsKey(param)) {
+ remove = false;
+ break;
+ }
+ }
+
+ return remove;
+
+ }
+
+ /**
+ * Removes the query params.
+ *
+ * @param params the params
+ */
+ public void removeQueryParams(MultivaluedMap<String, String> params) {
+
+
+ for (String param : blacklist) {
+ params.remove(param);
+ }
+
+
+ }
+
+}
diff --git a/ajsc-aai/src/main/resources/docker/Dockerfile b/ajsc-aai/src/main/resources/docker/Dockerfile
new file mode 100644
index 0000000..16a785d
--- /dev/null
+++ b/ajsc-aai/src/main/resources/docker/Dockerfile
@@ -0,0 +1,86 @@
+FROM ubuntu:14.04
+
+ENV HTTP_PROXY ${HTTP_PROXY}
+
+RUN if [ ! -z ${HTTP_PROXY} ]; then echo "Acquire::http::proxy \"${HTTP_PROXY}\";" >> /etc/apt/apt.conf; fi
+RUN if [ ! -z ${HTTP_PROXY} ]; then echo "Acquire::https::proxy \"${HTTP_PROXY}\";" >> /etc/apt/apt.conf; fi
+
+ENV DEBIAN_FRONTEND noninteractive
+
+ENV HTTP_PROXY ${HTTP_PROXY}
+ENV HTTPS_PROXY ${HTTP_PROXY}
+ENV https_proxy ${HTTP_PROXY}
+ENV http_proxy ${HTTP_PROXY}
+
+RUN apt-get update && apt-get install -y software-properties-common
+
+# sudo -E is required to preserve the environment
+# If you remove that line, it will most like freeze at this step
+
+RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && \
+ apt-get update && \
+ apt-get -qq install -y openjdk-8-jre-headless git curl ksh
+
+# Setup JAVA_HOME, this is useful for docker commandline
+ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
+
+# Install Chef
+RUN curl -LO https://packages.chef.io/stable/ubuntu/14.04/chefdk_0.17.17-1_amd64.deb
+RUN dpkg -i chefdk_0.17.17-1_amd64.deb
+RUN rm chefdk_0.17.17-1_amd64.deb
+
+# Add the application folder and common libs to /opt inside container
+# Add the chef script and startup script to docker container
+# Change the permissions to enable execute access
+
+ADD ./opt/app /opt/app
+ADD ./commonLibs/ /opt/app/commonLibs/
+
+ADD init-chef.sh /init-chef.sh
+ADD startup.sh /startup.sh
+ADD aai.sh /etc/profile.d/aai.sh
+
+RUN chmod 755 /init-chef.sh /startup.sh
+RUN chmod 644 /etc/profile.d/aai.sh
+
+# When the container is started this is the entrypoint script
+# that docker will run. Make sure this script doesn't end abruptly
+# If you want the container running even if the main application stops
+# You can run a ever lasting process like tail -f /dev/null
+# Or something like that at the end of the startup script
+# So if the main application you are planning on running fails
+# the docker container keeps on running forever
+
+ENTRYPOINT ./startup.sh
+
+# Expose the ports for outside linux to use
+# 8443 is the important one to be used
+
+EXPOSE 8443
+EXPOSE 8080
+
+# Create the directory structure of aai application resembling the development server
+# hard-coding path to match ajsc version
+
+RUN mkdir /opt/aaihome && \
+ useradd -ms /bin/bash -d /opt/aaihome/aaiadmin aaiadmin && \
+ ln -s /opt/app/${project.artifactId}/${project.version} /opt/app/aai && \
+ chown aaiadmin:aaiadmin /opt/app/aai && \
+ chown -R aaiadmin:aaiadmin /opt/app/${project.artifactId}/${project.version} && \
+ mkdir -p /opt/aai/logroot && \
+ chown -R aaiadmin:aaiadmin /opt/aai/logroot && \
+ ln -s /opt/app/aai/bin scripts && \
+ mkdir /opt/app/aai/extApps && chown -R aaiadmin:aaiadmin /opt/app/aai/extApps && \
+ find /opt/app/aai/bin -name "*.sh" -exec chmod 755 {} +
+
+WORKDIR /var/chef
+
+RUN chown aaiadmin:aaiadmin /startup.sh && \
+ chown -R aaiadmin:aaiadmin /var/chef
+
+RUN mkdir /opt/aai/logroot/AAI && chown aaiadmin:aaiadmin /opt/aai/logroot/AAI
+VOLUME /opt/aai/logroot/AAI
+
+WORKDIR /
+
+USER aaiadmin
diff --git a/ajsc-aai/src/main/resources/docker/Dockerfile.ext b/ajsc-aai/src/main/resources/docker/Dockerfile.ext
new file mode 100644
index 0000000..6beaf58
--- /dev/null
+++ b/ajsc-aai/src/main/resources/docker/Dockerfile.ext
@@ -0,0 +1,76 @@
+FROM ubuntu:14.04
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && apt-get install -y software-properties-common
+
+# sudo -E is required to preserve the environment
+# If you remove that line, it will most like freeze at this step
+
+RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && \
+ apt-get update && \
+ apt-get -qq install -y openjdk-8-jre-headless git curl ksh
+
+# Setup JAVA_HOME, this is useful for docker commandline
+ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
+
+# Install Chef
+RUN curl -LO https://packages.chef.io/stable/ubuntu/14.04/chefdk_0.17.17-1_amd64.deb
+RUN dpkg -i chefdk_0.17.17-1_amd64.deb
+RUN rm chefdk_0.17.17-1_amd64.deb
+
+# Add the application folder and common libs to /opt inside container
+# Add the chef script and startup script to docker container
+# Change the permissions to enable execute access
+
+ADD ./opt/app /opt/app
+ADD ./commonLibs/ /opt/app/commonLibs/
+
+ADD init-chef.sh /init-chef.sh
+ADD startup.sh /startup.sh
+ADD aai.sh /etc/profile.d/aai.sh
+
+RUN chmod 755 /init-chef.sh /startup.sh
+RUN chmod 644 /etc/profile.d/aai.sh
+
+# When the container is started this is the entrypoint script
+# that docker will run. Make sure this script doesn't end abruptly
+# If you want the container running even if the main application stops
+# You can run a ever lasting process like tail -f /dev/null
+# Or something like that at the end of the startup script
+# So if the main application you are planning on running fails
+# the docker container keeps on running forever
+
+ENTRYPOINT ./startup.sh
+
+# Expose the ports for outside linux to use
+# 8443 is the important one to be used
+
+EXPOSE 8443
+EXPOSE 8080
+
+# Create the directory structure of aai application resembling the development server
+# hard-coding path to match ajsc version
+
+RUN mkdir /opt/aaihome && \
+ useradd -ms /bin/bash -d /opt/aaihome/aaiadmin aaiadmin && \
+ ln -s /opt/app/${project.artifactId}/${project.version} /opt/app/aai && \
+ chown aaiadmin:aaiadmin /opt/app/aai && \
+ chown -R aaiadmin:aaiadmin /opt/app/${project.artifactId}/${project.version} && \
+ mkdir -p /opt/aai/logroot && \
+ chown -R aaiadmin:aaiadmin /opt/aai/logroot && \
+ ln -s /opt/app/aai/bin scripts && \
+ mkdir /opt/app/aai/extApps && chown -R aaiadmin:aaiadmin /opt/app/aai/extApps && \
+ find /opt/app/aai/bin -name "*.sh" -exec chmod 755 {} +
+
+WORKDIR /var/chef
+
+RUN chown aaiadmin:aaiadmin /startup.sh && \
+ chown -R aaiadmin:aaiadmin /var/chef
+
+RUN mkdir /opt/aai/logroot/AAI && chown aaiadmin:aaiadmin /opt/aai/logroot/AAI
+VOLUME /opt/aai/logroot/AAI
+
+WORKDIR /
+
+USER aaiadmin
diff --git a/ajsc-aai/src/main/resources/docker/aai.sh b/ajsc-aai/src/main/resources/docker/aai.sh
new file mode 100644
index 0000000..ed93aab
--- /dev/null
+++ b/ajsc-aai/src/main/resources/docker/aai.sh
@@ -0,0 +1,42 @@
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+PROJECT_HOME=/opt/app/aai
+export PROJECT_HOME
+
+JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+export JAVA_HOME
+
+AAIENV=dev
+export AAIENV
+
+PATH=/usr/lib/jvm/java-8-openjdk-amd64:$PATH
+
+PROJECT_OWNER=aaiadmin
+PROJECT_GROUP=aaiadmin
+PROJECT_UNIXHOMEROOT=/opt/aaihome
+export PROJECT_OWNER PROJECT_GROUP PROJECT_UNIXHOMEROOT
+umask 0022
+
+export idns_api_url=
+export idnscred=
+export idnstenant=
+
+
diff --git a/ajsc-aai/src/main/resources/docker/commonLibs/README b/ajsc-aai/src/main/resources/docker/commonLibs/README
new file mode 100644
index 0000000..00e36c0
--- /dev/null
+++ b/ajsc-aai/src/main/resources/docker/commonLibs/README
@@ -0,0 +1 @@
+// this file's presence ensures commonLibs folder is present when image is created \ No newline at end of file
diff --git a/ajsc-aai/src/main/resources/docker/init-chef.sh b/ajsc-aai/src/main/resources/docker/init-chef.sh
new file mode 100644
index 0000000..112b0b3
--- /dev/null
+++ b/ajsc-aai/src/main/resources/docker/init-chef.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+##############################################################################
+# Script to initialize the chef-repo branch and.chef
+#
+##############################################################################
+
+#echo "AAI_CHEF_ENV=${AAI_CHEF_ENV}" >> /etc/environment
+#echo "AAI_CHEF_LOC=${AAI_CHEF_LOC}" >> /etc/environment
+#touch /root/.bash_profile
+chef-solo -c /var/chef/aai-data/chef-config/dev/.knife/solo.rb -j /var/chef/aai-config/cookbooks/runlist-app-server.json -E ${AAI_CHEF_ENV}
+
diff --git a/ajsc-aai/src/main/resources/docker/startup.sh b/ajsc-aai/src/main/resources/docker/startup.sh
new file mode 100644
index 0000000..2d8ea02
--- /dev/null
+++ b/ajsc-aai/src/main/resources/docker/startup.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+##############################################################################
+#
+# AAI Startup Script
+# ------------------
+#
+# Changes to the aai application folder
+# Adds the jar files into the classpath
+# Start the init chef script
+# Start the hbase creation of tables script
+# Then run the java ajsc aai application via com.att.ajsc.runner.Runner
+#
+##############################################################################
+
+cd /opt/app/aai;
+ARG=$1;
+
+CP=$(find extJars/ lib/ -name "*.jar" | sort | uniq | tr '\n' ':');
+COMMONLIBS_PATH=$(find /opt/app/commonLibs -name "*.jar" | tr '\n' ':');
+
+JAVA_OPTS="-XX:MaxPermSize=256m -XX:MaxPermSize=256m -XX:PermSize=32m";
+JAVA_OPTS+=" -Dhttps.protocols=TLSv1.1,TLSv1.2";
+JAVA_OPTS+=" -DSOACLOUD_SERVICE_VERSION=0.0.1";
+JAVA_OPTS+=" -Dlogback.configurationFile=$(pwd)/bundleconfig/etc/logback.xml";
+if [ ! -z "${HTTP_PROXY}" ]; then
+ IFS=':' read -ra NAMES <<< "$HTTP_PROXY"
+ JAVA_OPTS+=" -Dhttp.proxyHost=${NAMES[0]}:${NAMES[1]}";
+ JAVA_OPTS+=" -Dhttp.proxyPort=${NAMES[2]}";
+fi
+JAVA_OPTS+=" -DAJSC_HOME=$(pwd)";
+JAVA_OPTS+=" -DAJSC_CONF_HOME=$(pwd)/bundleconfig/";
+JAVA_OPTS+=" -DAJSC_SHARED_CONFIG=$(pwd)/bundleconfig";
+JAVA_OPTS+=" -Dplatform=NON-PROD";
+JAVA_OPTS+=" -DPid=1306";
+JAVA_OPTS+=" -Xmx512m -Xms512m";
+
+JAVA_ARGS="context=/ port=8080 sslport=8443";
+
+JAVA_RUN_FILE="com.att.ajsc.runner.Runner";
+
+if [ ! -z "$ARG" ] && [ "$ARG" = "simple" ]; then
+ pkill java;
+ java ${JAVA_OPTS} -cp ${CP}${COMMONLIBS_PATH} ${JAVA_RUN_FILE} ${JAVA_ARGS} > /opt/aaihome/aaiadmin/log.out 2>&1 &
+else
+
+ PROTOCOL=${PROTOCOL:-https};
+ GITLAB_CERTNAME=${GITLAB_CERTNAME};
+ GITLAB_USERNAME=${GITLAB_USERNAME};
+ GITLAB_PASSWORD=${GITLAB_PASSWORD};
+
+ docker_giturl=${PROTOCOL}://${GITLAB_USERNAME}:${GITLAB_PASSWORD}@${GITLAB_CERTNAME}/${AAI_REPO_PATH};
+
+ cd /var/chef/
+
+ git clone -b ${docker_gitbranch} --single-branch ${docker_giturl}/aai-config.git && \
+ git clone -b ${docker_gitbranch} --single-branch ${docker_giturl}/aai-data.git
+
+ /init-chef.sh
+
+ sleep 45;
+
+ cd /opt/app/aai;
+
+ ./bin/createDBSchema.sh;
+
+ java ${JAVA_OPTS} -cp ${CP}${COMMONLIBS_PATH} ${JAVA_RUN_FILE} ${JAVA_ARGS} > /opt/aaihome/aaiadmin/log.out 2>&1 &
+
+ sleep 20;
+
+ . /etc/profile.d/aai.sh
+
+ ./bin/install/updateQueryData.sh
+
+ tail -f /dev/null
+fi
diff --git a/ajsc-aai/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context b/ajsc-aai/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context
new file mode 100644
index 0000000..8514196
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/context/default#0.context b/ajsc-aai/src/main/runtime/context/default#0.context
new file mode 100644
index 0000000..d1b5ab4
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json b/ajsc-aai/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json
new file mode 100644
index 0000000..d0954cf
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroRole/ajscadmin.json b/ajsc-aai/src/main/runtime/shiroRole/ajscadmin.json
new file mode 100644
index 0000000..f5e981e
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json b/ajsc-aai/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json
new file mode 100644
index 0000000..2dae9f5
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroRole/contextadmin#default.json b/ajsc-aai/src/main/runtime/shiroRole/contextadmin#default.json
new file mode 100644
index 0000000..5de814e
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroUser/ajsc.json b/ajsc-aai/src/main/runtime/shiroUser/ajsc.json
new file mode 100644
index 0000000..f4c7855
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json b/ajsc-aai/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json
new file mode 100644
index 0000000..cb8d483
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json b/ajsc-aai/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json
new file mode 100644
index 0000000..95d2361
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json b/ajsc-aai/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json
new file mode 100644
index 0000000..2bd5063
--- /dev/null
+++ b/ajsc-aai/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/ajsc-aai/src/main/scripts/PropertyChangeName.sh b/ajsc-aai/src/main/scripts/PropertyChangeName.sh
new file mode 100644
index 0000000..86a2e40
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/PropertyChangeName.sh
@@ -0,0 +1,87 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# This script is used to add a target property name with the same value in the database schema
+# to a vertex which has an existing property. The existing property is not removed.
+#
+# Note also - This script just makes changes to the schema that is currently live.
+# If you were to create a new schema in a brandy-new environment, it would look like
+# whatever the oxm (as of July 2016) told it to look like. So, part of making a
+# change to the db schema should Always first be to make the change in the oxm so that
+# future environments will have the change. This script is just to change existing
+# instances of the schema since schemaGenerator (as of July 2015) does not update things - it
+# just does the initial creation.
+#
+# To use this script, you need to pass four parameters:
+# propertyName -- the name of the property that has the value to be used in the targetProperty
+# targetPropertyName -- the name of the targetProperty
+# targetNodeType -- NA if all propertyName instances in the DB are impacted, otherwise limit the change to this nodeType
+# skipCommit -- true or false. For testing, skips the commit when set to true.
+#
+# Ie. propertyNameChange service-id persona-model-id service-instance true
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+
+if [ "$#" -ne 4 ]; then
+ echo "Illegal number of parameters"
+ echo "usage: $0 propertyName targetPropertyName targetNodeType skipCommit"
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.PropertyNameChange $1 $2 $3 $4
+if [ "$?" -ne "0" ]; then
+ echo "Problem executing propertyNameChange "
+ exit 1
+fi
+
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/aaiadmin.crontab b/ajsc-aai/src/main/scripts/aaiadmin.crontab
new file mode 100644
index 0000000..eb6ba78
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/aaiadmin.crontab
@@ -0,0 +1,25 @@
+#########################################################################
+# Archive and/or delete the AAI logs
+# Arg1: The directory containing the log files
+# Arg2: The number of days after which a log will be archived
+# Arg3: The number of days after which an archived log will be deleted
+##########################################################################
+# application logs includes all subdirectories under PROJECT_HOME/LOGS that have *.log and *.log.<date> log files
+10 00 * * * . /etc/profile.d/aai.sh; ${PROJECT_HOME}/scripts/logcleanup.sh ${PROJECT_HOME}/logs 7 15 >> ${PROJECT_HOME}/logs/misc/logcleanup.log.$(date +\%Y-\%m-\%d) 2>&1
+# tomee logs
+11 00 * * * . /etc/profile.d/aai.sh; ${PROJECT_HOME}/scripts/tomeelogcleanup.sh ${PROJECT_HOME}/servers/aai/logs 7 15 >> ${PROJECT_HOME}/logs/misc/tomeelogcleanup.log.$(date +\%Y-\%m-\%d) 2>&1
+#########################################################################
+# Archive and/or delete the AAI db related out files
+##########################################################################
+# db snapshot .out files
+17 00 * * * . /etc/profile.d/aai.sh; ${PROJECT_HOME}/scripts/dotOutMiddle_cleanup.sh ${PROJECT_HOME}/logs/data/dataSnapshots 5 30 >> ${PROJECT_HOME}/logs/misc/dotOutMiddle_cleanup.log.$(date +\%Y-\%m-\%d) 2>&1
+# db grooming .out files
+19 00 * * * . /etc/profile.d/aai.sh; ${PROJECT_HOME}/scripts/dotOutEnd_cleanup.sh ${PROJECT_HOME}/logs/data/dataGrooming 5 30 >> ${PROJECT_HOME}/logs/misc/dotOutEnd_cleanup.log.$(date +\%Y-\%m-\%d) 2>&1
+########################################################################
+# Run the DataGrooming script
+########################################################################
+10 1,7,13,20 * * * . /etc/profile.d/aai.sh; ${PROJECT_HOME}/scripts/dataGrooming.sh -autoFix -dupeFixOn -dontFixOrphans >> ${PROJECT_HOME}/logs/misc/run_dataGrooming.log.$(date +\%Y-\%m-\%d) 2>&1
+########################################################################
+# Take snapshot of our data
+########################################################################
+45 * * * * . /etc/profile.d/aai.sh; ${PROJECT_HOME}/scripts/dataSnapshot.sh JUST_TAKE_SNAPSHOT >> ${PROJECT_HOME}/logs/misc/run_dataSnapshot.log.$(date +\%Y-\%m-\%d) 2>&1
diff --git a/ajsc-aai/src/main/scripts/addResourceVersionProperty.sh b/ajsc-aai/src/main/scripts/addResourceVersionProperty.sh
new file mode 100644
index 0000000..7c4af8e
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/addResourceVersionProperty.sh
@@ -0,0 +1,55 @@
+#!/bin/ksh
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+#
+# The script invokes the AddResourceVersionProp java class as a one-time (per database instance) migration tool
+# which adds the new property "resource-version" to every node in the db.
+#
+
+echo
+echo `date` " Starting $0"
+
+. /etc/profile.d/aai.sh
+
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.AddResourceVersionProp
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/audit_schema.sh b/ajsc-aai/src/main/scripts/audit_schema.sh
new file mode 100644
index 0000000..52b0545
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/audit_schema.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+if [ -f "/etc/profile.d/aai.sh" ]; then
+ source /etc/profile.d/aai.sh
+else
+ echo "File not found: /etc/profile.d/aai.sh";
+ exit
+fi
+
+JAVA=$JAVA_HOME/bin/java
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME -cp $CLASSPATH org.openecomp.aai.db.schema.ScriptDriver $@
diff --git a/ajsc-aai/src/main/scripts/changePropertyCardinality.sh b/ajsc-aai/src/main/scripts/changePropertyCardinality.sh
new file mode 100644
index 0000000..04fdfee
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/changePropertyCardinality.sh
@@ -0,0 +1,85 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+#
+# This script is used to change the cardinality of an existing database property.
+# It currently just allows you to change TO a SET cardinality with dataType = String.
+# It does not currently let you preserve the data (since we're just doing this for one
+# field which nobody uses yet).
+#
+# Note also - This script just makes changes to the schema that is currently live.
+# If you were to create a new schema in a brandy-new environment, it would look like
+# whatever oxm told it to look like. So, part of making a
+# change to the db schema should Always first be to make the change in oxm so that
+# future environments will have the change. This script is just to change existing
+# instances of the schema since schemaGenerator (as of Jan 2016) does not update things - it
+# just does the initial creation.
+#
+# Boy, this is getting to be a big comment section...
+#
+# To use this script, you need to pass four parameters:
+# propertyName -- the name of the property that you need to change Cardinality on.
+# targetDataType -- whether it's changing or not, you need to give it: For now -- we only allow "String"
+# targetCardinality -- For now -- only accepts "SET". In the future we should support ("SET", "LIST" or "SINGLE")
+# preserveDataFlag -- true or false. For now -- only supports "false"
+#
+# Ie. changePropertyCardinality.sh supplier-release-list String SET false
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+
+if [ "$#" -ne 4 ]; then
+ echo "Illegal number of parameters"
+ echo "usage: $0 propertyName targetDataType targetCardinality preserveDataFlag"
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.ChangePropertyCardinality $1 $2 $3 $4
+if [ "$?" -ne "0" ]; then
+ echo "Problem executing ChangePropertyCardinality "
+ exit 1
+fi
+
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/createDBSchema.sh b/ajsc-aai/src/main/scripts/createDBSchema.sh
new file mode 100644
index 0000000..4d7e410
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/createDBSchema.sh
@@ -0,0 +1,58 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# The script invokes GenTester java class to create the DB schema
+#
+# OPTIONS:
+# GEN_DB_WITH_NO_SCHEMA - use if you want it to create an instance of
+# the graph - but with no schema (this is useful when using the Hbase copyTable to
+# copy our database to different environments).
+# Ie. createDbSchema.sh GEN_DB_WITH_NO_SCHEMA
+#
+# CREATE_HBASE_LOG_TBL - use if you want the Hbase logging table
+# to be checked for existence and created if not found.
+#
+# GEN_DB_WITH_NO_DEFAULT_CR - use if you do NOT want the default cloud
+# region generated automatically. Note - this is moot if you're
+# using GEN_DB_WITH_NO_SCHEMA
+#
+#
+
+echo
+echo `date` " Starting $0"
+
+. /etc/profile.d/aai.sh
+
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.GenTester $1
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/dataGrooming.sh b/ajsc-aai/src/main/scripts/dataGrooming.sh
new file mode 100644
index 0000000..dfa4ea8
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/dataGrooming.sh
@@ -0,0 +1,131 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# The script invokes the dataGrooming java class to run some tests and generate a report and
+# potentially do some auto-deleteing.
+#
+# Here are the allowed Parameters. Note - they are all optional and can be mixed and matched.
+#
+# -f oldFileName (see note below)
+# -autoFix
+# -sleepMinutes nn
+# -edgesOnly
+# -dontFixOrphans
+# -maxFix
+# -skipHostCheck
+# -singleCommits
+# -dupeCheckOff
+# -dupeFixOn
+# -ghost2CheckOff
+# -ghost2FixOn
+#
+# NOTES:
+# -f The name of a previous report can optionally be passed in with the "-f" option.
+# Just the filename -- ie. "dataGrooming.sh -f dataGrooming.201504272106.out"
+# The file will be assumed to be in the directory that it was created in.
+# If a filename is passed, then the "deleteCandidate" vertex-id's and bad edges
+# listed inside that report file will be deleted on this run if they are encountered as
+# bad nodes/edges again.
+#
+# -autoFix If you don't use the "-f" option, you could choose to use "-autofix" which will
+# automatically run the script twice: once to look for problems, then after
+# sleeping for a few minutes, it will re-run with the inital-run's output as
+# an input file.
+#
+# -maxFix When using autoFix, you might want to limit how many 'bad' records get fixed.
+# This is a safeguard against accidently deleting too many records automatically.
+# It has a default value set in AAIConstants: AAI_GROOMING_DEFAULT_MAX_FIX = 15;
+# If there are more than maxFix candidates found -- then none will be deleted (ie.
+# someone needs to look into it)
+#
+# -sleepMinutes When using autoFix, this defines how many minutes we sleep before the second run.
+# It has a default value set in AAIConstants: AAI_GROOMING_DEFAULT_SLEEP_MINUTES = 7;
+# The reason we sleep at all between runs is that our DB is "eventually consistant", so
+# we want to give it time to resolve itself if possible.
+#
+# -edgesOnly Can be used any time you want to limit this tool so it only looks at edges.
+# It runs much more quickly when it's just doing edges and sometimes all our
+# problems are with bad edges so it can be nice to focus on edges only sometimes.
+#
+# -dontFixOrphans Since there can sometimes be a lot of orphan nodes, and they don't
+# harm processing as much as phantom-nodes or bad-edges, it is useful to be
+# able to ignore them when fixing things.
+#
+# -skipHostCheck By default, the grooming tool will check to see that it is running
+# on the host that is the first one in the list found in:
+# aaiconfig.properties aai.primary.filetransfer.serverlist
+# This is so that when run from the cron, it only runs on one machine.
+# This option lets you turn that checking off.
+#
+# -singleCommits By default, the grooming tool will do all of its processing and then do
+# a commit of all the changes at once. This option (maybe could have been named better)
+# is letting the user override the default behavior and do a commit for each
+# individual 'remove" one by one as they are encountered by the grooming logic.
+# NOTE - this only applies when using either the "-f" or "-autoFix" options since
+# those are the only two that make changes to the database.
+#
+# -dupeCheckOff By default, we will check all of our nodes for duplicates. This parameter lets
+# us turn this check off if we don't want to do it for some reason.
+#
+# -dupeFixOn When we're fixing data, by default we will NOT fix duplicates This parameter lets us turn
+# that fixing ON when we are comfortable that it can pick the correct duplicate to preserve.
+#
+# -ghost2CheckOff By default, we will check for the "new" kind of ghost that we saw on
+# Production in early February 2016. This parameter lets us turn this check off if we
+# don't want to do it for some reason.
+#
+# -ghost2FixOn When we're fixing data, by default we will NOT try to fix the "new" ghost nodes.
+# This parameter lets us turn that fixing ON if we want to try to fix them.
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/jetty/webapps/*/webapp/WEB-INF/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.DataGrooming "$@"
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/dataRestoreFromSnapshot.sh b/ajsc-aai/src/main/scripts/dataRestoreFromSnapshot.sh
new file mode 100644
index 0000000..7b045ef
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/dataRestoreFromSnapshot.sh
@@ -0,0 +1,85 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+
+if [ "$#" -ne 1 ]; then
+ echo "Illegal number of parameters"
+ echo "usage: $0 previous_snapshot_filename"
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+#### Step 1) clear out the database
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.DataSnapshot CLEAR_ENTIRE_DATABASE $1
+if [ "$?" -ne "0" ]; then
+ echo "Problem clearing out database."
+ exit 1
+fi
+
+#### Step 2) rebuild the db-schema
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.GenTester GEN_DB_WITH_NO_DEFAULT_CR
+if [ "$?" -ne "0" ]; then
+ echo "Problem rebuilding the schema (SchemaGenerator)."
+ exit 1
+fi
+
+#### Step 3) reload the data from a snapshot file
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.DataSnapshot RELOAD_DATA $1
+if [ "$?" -ne "0" ]; then
+ echo "Problem reloading data into the database."
+ exit 1
+fi
+
+
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/dataSnapshot.sh b/ajsc-aai/src/main/scripts/dataSnapshot.sh
new file mode 100644
index 0000000..054e7f5
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/dataSnapshot.sh
@@ -0,0 +1,59 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# This script invokes the dataSnapshot java class passing an option to tell it to take
+# a snapshot of the database and store it as a single-line XML file.
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.DataSnapshot JUST_TAKE_SNAPSHOT
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/deleteTool.sh b/ajsc-aai/src/main/scripts/deleteTool.sh
new file mode 100644
index 0000000..32437e5
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/deleteTool.sh
@@ -0,0 +1,61 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+
+# The script invokes Deletion java class to delete customer, subs, dvs-switch, service-capability or tenants
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.DeleteResource "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/deobfuscatePW.sh b/ajsc-aai/src/main/scripts/deobfuscatePW.sh
new file mode 100644
index 0000000..918c7d7
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/deobfuscatePW.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+
+# The script invokes the utils.JettyObfuscationConversionCommandLineUtil class to
+# deobfuscate an obfuscated name from aaiconfig property file
+# e.g.
+# ./deobfuscatePW.sh odl.auth.password
+# will return:
+# admin
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ -Dcom.att.eelf.logging.file=default-logback.xml -Dcom.att.eelf.logging.path="$PROJECT_HOME/bundleconfig/etc/appprops/" \
+ org.openecomp.aai.util.AAIConfigCommandLinePropGetter $1
+
+echo `date` " Done $0"
diff --git a/ajsc-aai/src/main/scripts/dotOutEnd_cleanup.sh b/ajsc-aai/src/main/scripts/dotOutEnd_cleanup.sh
new file mode 100644
index 0000000..79ca663
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/dotOutEnd_cleanup.sh
@@ -0,0 +1,81 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script archives/deletes files that end in .out (Ie. dataGrooming.201511111305.out) that sit in our log/data directory structure
+#
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+PROGNAME=$(basename $0)
+LOGDIR=${PROJECT_HOME}/logs
+ZIPDIR=ARCHIVE
+AGEZIP=30
+AGEDELETE=60
+ZIPPER=/bin/gzip
+DATE=$(date +%Y%m%d)
+
+# Get the program arguments
+if [[ $# -lt 3 ]]
+then
+ echo "${PROGNAME}: Arguments are missing. Found $#"
+ exit 1
+fi
+LOGDIR="${1}"
+AGEZIP=$2
+AGEDELETE=$3
+if [[ ! -d $LOGDIR ]]
+then
+ echo "${PROGNAME}: Directory does not exist: ${LOGDIR}"
+ exit 1
+fi
+
+# Create the archive folder, if it does not exist.
+if [[ ! -d ${LOGDIR}/${ZIPDIR} ]]
+then
+ mkdir ${LOGDIR}/${ZIPDIR}
+ if [ $? -ne 0 ]
+ then
+ echo "${PROGNAME}: Failed to create directory: ${LOGDIR}/${ZIPDIR}"
+ exit 1
+ fi
+ chmod 777 ${LOGDIR}/${ZIPDIR}
+fi
+
+# Compress files that are older than AGEZIP days
+find -L ${LOGDIR} -name *.gz -prune -o -mtime +${AGEZIP} -type f -name "*.out" -exec ${ZIPPER} -f {} \;
+find -L ${LOGDIR} -name ${ZIPDIR} -prune -o -type f -name "*.out.gz" -print | while read i; do dirnm=`dirname ${i}`; drn=`basename ${dirnm}`; mkdir -p ${LOGDIR}/${ZIPDIR}/${drn}; echo ${i}; echo ${LOGDIR}/${ZIPDIR}/${drn}; mv ${i} ${LOGDIR}/${ZIPDIR}/${drn}; done
+
+# Delete archive files that are older than AGEDELETE days
+find -L ${LOGDIR}/${ZIPDIR}/* -type f -name "*.gz" -mtime +${AGEDELETE} -exec rm -r {} \;
+
+exit 0
diff --git a/ajsc-aai/src/main/scripts/dotOutMiddle_cleanup.sh b/ajsc-aai/src/main/scripts/dotOutMiddle_cleanup.sh
new file mode 100644
index 0000000..1cc6214
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/dotOutMiddle_cleanup.sh
@@ -0,0 +1,81 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script archives/deletes files that have ".out." in middle of their name (Ie. "dataSnapshot.out.201511102245") that sit
+# in our log/data directory structure
+#
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+PROGNAME=$(basename $0)
+LOGDIR=${PROJECT_HOME}/logs
+ZIPDIR=ARCHIVE
+AGEZIP=30
+AGEDELETE=60
+ZIPPER=/bin/gzip
+DATE=$(date +%Y%m%d)
+
+# Get the program arguments
+if [[ $# -lt 3 ]]
+then
+ echo "${PROGNAME}: Arguments are missing. Found $#"
+ exit 1
+fi
+LOGDIR="${1}"
+AGEZIP=$2
+AGEDELETE=$3
+if [[ ! -d $LOGDIR ]]
+then
+ echo "${PROGNAME}: Directory does not exist: ${LOGDIR}"
+ exit 1
+fi
+
+# Create the archive folder, if it does not exist.
+if [[ ! -d ${LOGDIR}/${ZIPDIR} ]]
+then
+ mkdir ${LOGDIR}/${ZIPDIR}
+ if [ $? -ne 0 ]
+ then
+ echo "${PROGNAME}: Failed to create directory: ${LOGDIR}/${ZIPDIR}"
+ exit 1
+ fi
+ chmod 777 ${LOGDIR}/${ZIPDIR}
+fi
+
+# Compress files that are older than AGEZIP days
+find -L ${LOGDIR} -name *.gz -prune -o -mtime +${AGEZIP} -type f -name "*.out.*" -exec ${ZIPPER} -f {} \;
+find -L ${LOGDIR} -name ${ZIPDIR} -prune -o -type f -name "*.out.*.gz" -print | while read i; do dirnm=`dirname ${i}`; drn=`basename ${dirnm}`; mkdir -p ${LOGDIR}/${ZIPDIR}/${drn}; echo ${i}; echo ${LOGDIR}/${ZIPDIR}/${drn}; mv ${i} ${LOGDIR}/${ZIPDIR}/${drn}; done
+
+# Delete archive files that are older than AGEDELETE days
+find -L ${LOGDIR}/${ZIPDIR}/* -type f -name "*.gz" -mtime +${AGEDELETE} -exec rm -r {} \;
+
+exit 0
diff --git a/ajsc-aai/src/main/scripts/edgeTagger.sh b/ajsc-aai/src/main/scripts/edgeTagger.sh
new file mode 100644
index 0000000..5a120a2
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/edgeTagger.sh
@@ -0,0 +1,96 @@
+#!/bin/ksh
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+#
+# This script is used to synch-up the data in the database with the "edge-tags" definitions found in the DbEdgeRules.java file.
+# It is not needed during normal operation, but if a new tag (really a property) is defined for an edge or if an
+# existing tag is changed, then this script should be run to migrate existing data so that it matches the new
+# definition. Note: it is only dealing with the "tags" defined after position 2. For example, for our existing
+# rules, we have have "isParent" defined in position 2, and then other tags in positions 3, 4 and 5 as
+# mapped in DbEdgeRules.EdgeInfoMap:
+#
+# public static final Map<Integer, String> EdgeInfoMap;
+# static {
+# EdgeInfoMap = new HashMap<Integer, String>();
+# EdgeInfoMap.put(0, "edgeLabel");
+# EdgeInfoMap.put(1, "direction");
+# EdgeInfoMap.put(2, "isParent" );
+# EdgeInfoMap.put(3, "usesResource" );
+# EdgeInfoMap.put(4, "hasDelTarget" );
+# EdgeInfoMap.put(5, "SVC-INFRA" );
+# }
+#
+# -- The map above is used to interpret the data in the DbEdgeRules.EdgeRules map:
+#
+# public static final Multimap<String, String> EdgeRules =
+# new ImmutableSetMultimap.Builder<String, String>()
+# .putAll("availability-zone|complex","groupsResourcesIn,OUT,false,false,false,reverse")
+# .putAll("availability-zone|service-capability","supportsServiceCapability,OUT,false,false,false,false")
+# .putAll("complex|ctag-pool","hasCtagPool,OUT,true,false,false,false")
+# .putAll("complex|l3-network","usesL3Network,OUT,false,false,false,true")
+# etc...
+#
+# -- Valid values for the "tags" can be "true", "false" or "reverse". Read the T-space
+# write-up for a detailed explanation of this...
+#
+#
+# To use this script, You can either pass the parameter, "all" to update all the edge rules, or
+# you can pass the KEY to a single edge rule that you would like to update. NOTE - the
+# key is that first part of each edge rule that looks like, "nodeTypeA|nodeTypeB".
+#
+# Ie. ./edgeTagger.sh "all"
+# or ./edgeTagger.sh "complex|ctag-pool"
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ -Dcom.att.eelf.logging.file=default-logback.xml -Dcom.att.eelf.logging.path="$PROJECT_HOME/bundleconfig/etc/appprops/" \
+ org.openecomp.aai.dbgen.UpdateEdgeTags $1
+if [ "$?" -ne "0" ]; then
+ echo "Problem executing UpdateEdgeTags "
+ exit 1
+fi
+
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/fix_yang_classes.pl b/ajsc-aai/src/main/scripts/fix_yang_classes.pl
new file mode 100644
index 0000000..4e579c9
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/fix_yang_classes.pl
@@ -0,0 +1,64 @@
+#!/usr/bin/perl
+
+use strict;
+
+use Getopt::Std;
+
+my %opts = ();
+
+getopts("n:", \%opts);
+
+my $namespace = '';
+if (!$opts{'n'}) {
+ $namespace = "http://org.openecomp.aai.inventory";
+} else {
+ $namespace = $opts{'n'};
+}
+
+my $has_xml_root_element = 0;
+my $has_a_class = 0;
+my @file = ();
+
+my $added_rel = 0;
+
+while (<>) {
+ 1 while chomp;
+ # we're going to read it again
+
+ my $line = $_;
+ $line =~ s/(protected boolean (inMaint|isClosedLoopDisabled|isBoundToVpn|dhcpEnabled))(\;)/$1 \= false\;/i;
+
+ push @file, $line;
+
+ #if ($_ =~ /^import/ && $added_rel == 0) {
+ # push @file, "import org.openecomp.aai.domain.yang.rel.*;";
+ # $added_rel = 1;
+ #}
+ if ($_ =~ /^\@XmlRootElement/) {
+ $has_xml_root_element = 1;
+ }
+ if ($_ =~ /^public\sclass\s(\S+)\s{/) {
+ $has_a_class = 1;
+ }
+}
+
+if ($has_xml_root_element == 0 && $has_a_class == 1) {
+ my $printed_include = 0;
+ foreach my $line (@file) {
+ if ($line =~ /^import/ && $printed_include == 0) {
+ print "import javax.xml.bind.annotation.XmlRootElement;\n";
+
+ $printed_include++;
+ }
+ if ($line =~ /^public\sclass\s(\S+)\s{/) {
+ my $className = $1;
+ my @parts = $line =~ /([A-Z](?:[A-Z0-9]*(?=$|[A-Z0-9][a-z])|[a-z0-9]*))/g;
+ print "\@XmlRootElement(name = \"" . lc join('-', @parts) . "\", namespace = \"$namespace\")\n";
+ }
+ print "$line\n";
+ }
+} else {
+ foreach my $line (@file) {
+ print "$line\n";
+ }
+}
diff --git a/ajsc-aai/src/main/scripts/forceDeleteTool.sh b/ajsc-aai/src/main/scripts/forceDeleteTool.sh
new file mode 100644
index 0000000..8840c05
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/forceDeleteTool.sh
@@ -0,0 +1,73 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# Usage: forceDeleteTool.sh action dataString
+#
+# The script invokes the ForceDelete java class to either collect data about
+# nodes that may need to be deleted (when passed the COLLECT_DATA action parameter),
+# or to do a delete given a particular vertexId when passed the "DELETE_NODE action parameter.
+#
+# Ie.
+# forceDeleteTool COLLECT_DATA "hypervisor-type|esx,operational-state|operationalState"
+# or
+# forceDeleteTool DELETE_NODE 98789378
+#
+# Note: when collecting data, the dataString looks like: "propertyName1|propertyVal1,propertyName2|propertyVal2"
+# for however many property names, values you are using to identify this one node.
+# When doing the delete - the dataString has to just be the vertexId of the node you want to delete
+#
+
+echo
+echo `date` " Starting $0"
+
+echo " NOTE - if you are deleting data, please run the dataSnapshot.sh script first or "
+echo " at least make a note the details of the node that you are deleting. "
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.ForceDeleteTool $1 "$2"
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/generate.sh b/ajsc-aai/src/main/scripts/generate.sh
new file mode 100644
index 0000000..9ed1c4b
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/generate.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+REV=$1
+SKIP=$2
+LATEST_REV="v8"
+
+export AAIHOME=/media/Users/userid/Documents/MyGit
+
+export script_home=$AAIHOME/src/main/scripts
+
+export YANG_HOME=$AAIHOME/src/main/yang
+
+export REV_HOME=$YANG_HOME/$REV
+
+echo "REV_HOME: " $REV_HOME
+
+cd $REV_HOME
+
+if test "$SKIP" != "POJO"
+then
+ if [ ! -d "$REV_HOME/xsd" ]
+ then
+ mkdir xsd
+ fi
+
+ for i in *.yang
+ do x=`echo $i | cut -d"." -f 1`
+ echo $i " " $x; pyang -f xsd $i > xsd/$x.xsd
+ done
+
+ echo "Calling $script_home/run_FixXSD.sh $REV $AAIHOME"
+# $script_home/run_FixXSD.sh $REV $AAIHOME
+
+ cd $REV_HOME/xsd
+
+ $script_home/make_refs_in_xsd.pl fixedup.xsd > aai${REV}-corrected.xsd
+
+ NAMESPACE="http://org.openecomp.aai.inventory/$REV"
+ echo "Calling xjc";
+ if test "$REV" = "$LATEST_REV"
+ then
+ xjc -p org.openecomp.aai.domain.yang -b ../bindings.xml aai${REV}-corrected.xsd
+ cd org/openecomp/aai/domain/yang
+ else
+ xjc -p org.openecomp.aai.domain.yang.${REV} -b ../bindings.xml aai${REV}-corrected.xsd
+ cd org/openecomp/aai/domain/yang/${REV}
+ fi
+
+ echo "$script_home/fix_yang_classes.pl -n $NAMESPACE $i > $i.new"
+
+ for i in *.java
+ do $script_home/fix_yang_classes.pl -n $NAMESPACE $i > $i.new
+ mv $i $i.bak
+ mv $i.new $i
+ done
+
+ echo
+ if test "$REV" = "$LATEST_REV"
+ then
+ rm -f $AAIHOME/src/main/java/org/openecomp/aai/domain/yang/*.java
+ cp *.java $AAIHOME/src/main/java/org/openecomp/aai/domain/yang
+ else
+ rm -f $AAIHOME/src/main/java/org/openecomp/aai/domain/yang/$REV/*.java
+ cp *.java $AAIHOME/src/main/java/org/openecomp/aai/domain/yang/$REV
+ fi
+fi
+
+if test "$SKIP" != "GEN"
+then
+ $script_home/run_Generator.sh $REV $AAIHOME
+fi
diff --git a/ajsc-aai/src/main/scripts/getTool.sh b/ajsc-aai/src/main/scripts/getTool.sh
new file mode 100644
index 0000000..7d30344
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/getTool.sh
@@ -0,0 +1,61 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes GetResource java class to get all nodes
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.GetResource "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/install/addManualData.sh b/ajsc-aai/src/main/scripts/install/addManualData.sh
new file mode 100644
index 0000000..ec5de93
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/install/addManualData.sh
@@ -0,0 +1,111 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# this script now requires a release parameter.
+# the tool finds and sorts *.txt files within the
+# bundleconfig/etc/scriptdate/addmanualdata/$release directory containing
+# one resource to be added to the graph. The directory contains a second
+# file with the same name, but the extension is .json. This json file
+# is passed to the PutTool as the payload. The parameters passed to the
+# PutTool will have 412 failures ignored. After calling the PutTool, the
+# GetTool is called to include the object put into the graph.
+# this script is run at every installation, logging the manual data applied.
+
+# Returns 0 if the specified string contains the specified substring,
+# otherwise returns 1.
+contains() {
+ string="$1"
+ substring="$2"
+ if test "${string#*$substring}" != "$string"
+ then
+ return 0 # $substring is in $string
+ else
+ return 1 # $substring is not in $string
+ fi
+}
+
+PROGNAME=$(basename $0)
+OUTFILE=$PROJECT_HOME/logs/misc/${PROGNAME}.log.$(date +\%Y-\%m-\%d)
+#OUTFILE=/c/temp/${PROGNAME}.log.$(date +\%Y-\%m-\%d)
+
+TS=$(date "+%Y-%m-%d %H:%M:%S")
+
+CHECK_USER="aaiadmin"
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != $CHECK_USER ]; then
+ echo "You must be $CHECK_USER to run $0. The id used $userid."
+ exit 1
+fi
+
+if [ "$#" -ne 1 ]; then
+ echo "Release parameter is required, e.g. 1610, 1702, etc"
+ echo "usage: $0 release"
+ exit 1
+fi
+
+error_exit () {
+ echo "${PROGNAME}: failed for ${1:-"Unknown error"} on cmd $2 in $3" 1>&2
+ echo "${PROGNAME}: failed for ${1:-"Unknown error"} on cmd $2 in $3" >> $OUTFILE
+# exit ${2:-"1"}
+}
+
+rel="/"$1"/"
+k=0
+
+ls $PROJECT_HOME/bundleconfig/etc/scriptdata/addmanualdata/*/*.txt >/dev/null 2>&1
+if [ $? -ne 0 ]
+then
+echo "No manual data to add for release $1";
+exit 0;
+fi
+
+for filepath in `ls $PROJECT_HOME/bundleconfig/etc/scriptdata/addmanualdata/*/*.txt|sort -f`
+do
+contains $filepath $rel
+if [ $? -eq 0 ]
+then
+jsonfile=${filepath%???}json
+j=0
+while IFS=\n read -r i
+do
+echo "##### Begin putTool for $i ##### from file $filepath" | tee -a $OUTFILE
+resource=`echo $i | tr -d '\r'`
+$PROJECT_HOME/scripts/putTool.sh $resource $jsonfile 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource" $j $filepath
+echo "##### End putTool for $resource #####" | tee -a $OUTFILE
+echo "Begin getTool for $resource" | tee -a $OUTFILE
+$PROJECT_HOME/scripts/getTool.sh $resource >> $OUTFILE 2>&1 || error_exit "$i" $j $filepath
+echo "End getTool for $resource" | tee -a $OUTFILE
+
+j=$(expr "$j" + 1)
+k=$(expr "$k" + 1)
+done < $filepath
+
+fi
+
+done
+if [ $k -eq 0 ]
+then
+echo "No manual data to add for release $1";
+exit 0;
+fi
+
+echo "See output and error file: $OUTFILE"
+
+exit 0
diff --git a/ajsc-aai/src/main/scripts/install/doSchemaMods.sh b/ajsc-aai/src/main/scripts/install/doSchemaMods.sh
new file mode 100644
index 0000000..db9b995
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/install/doSchemaMods.sh
@@ -0,0 +1,102 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# this script now requires a release parameter.
+# the tool finds and sorts *.txt files within the
+# bundleconfig/etc/scriptdate/schemamods/$release directory containing
+# one or more sets of schemaMod.sh parameters
+# this script is run at every installation, logging the schemaMods applied.
+
+# Returns 0 if the specified string contains the specified substring,
+# otherwise returns 1.
+contains() {
+ string="$1"
+ substring="$2"
+ if test "${string#*$substring}" != "$string"
+ then
+ return 0 # $substring is in $string
+ else
+ return 1 # $substring is not in $string
+ fi
+}
+
+PROGNAME=$(basename $0)
+OUTFILE=$PROJECT_HOME/logs/misc/${PROGNAME}.log.$(date +\%Y-\%m-\%d)
+#OUTFILE=/c/temp/${PROGNAME}.log.$(date +\%Y-\%m-\%d)
+
+TS=$(date "+%Y-%m-%d %H:%M:%S")
+
+CHECK_USER="aaiadmin"
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != $CHECK_USER ]; then
+ echo "You must be $CHECK_USER to run $0. The id used $userid."
+ exit 1
+fi
+
+if [ "$#" -ne 1 ]; then
+ echo "Release parameter is required, e.g. 1610, 1702, etc"
+ echo "usage: $0 release"
+ exit 1
+fi
+
+error_exit () {
+ echo "${PROGNAME}: failed for ${1:-"Unknown error"} on cmd $2 in $3" 1>&2
+ echo "${PROGNAME}: failed for ${1:-"Unknown error"} on cmd $2 in $3" >> $OUTFILE
+# exit ${2:-"1"}
+}
+
+rel="/"$1"/"
+k=0
+
+ls $PROJECT_HOME/bundleconfig/etc/scriptdata/schemamods/*/*.txt >/dev/null 2>&1
+if [ $? -ne 0 ]
+then
+echo "No schemaMod to run for release $1";
+exit 0;
+fi
+
+
+for filepath in `ls $PROJECT_HOME/bundleconfig/etc/scriptdata/schemamods/*/*.txt|sort -f`
+do
+contains $filepath $rel
+if [ $? -eq 0 ]
+then
+j=0
+while IFS=\n read -r i
+do
+echo "##### Begin Schema Mods for $i #####" | tee -a $OUTFILE
+$PROJECT_HOME/scripts/schemaMod.sh $i >> $OUTFILE 2>&1 || error_exit "$i" $j $filepath
+echo "##### End Schema Mods for $i #####" | tee -a $OUTFILE
+j=$(expr "$j" + 1)
+k=$(expr "$k" + 1)
+done < $filepath
+
+fi
+#echo "End schemamod for $filepath" | tee -a $OUTFILE
+done
+if [ $k -eq 0 ]
+then
+echo "No schemaMod to run for release $1";
+exit 0;
+fi
+
+echo "See output and error file: $OUTFILE"
+
+exit 0
diff --git a/ajsc-aai/src/main/scripts/install/instutils.sh b/ajsc-aai/src/main/scripts/install/instutils.sh
new file mode 100644
index 0000000..497ba09
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/install/instutils.sh
@@ -0,0 +1,722 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+ECHO=${ECHO:-echo}
+
+q_flags="-qq -k$$"
+
+show_install=${PROJECT_HOME}/install/show_install
+
+############################################################################
+# checkgroup groupname gid
+# checks if group is already in /etc/group and if it has the right gid
+# if it's not there, it adds it
+# gid can be DC if you don't care
+############################################################################
+checkgroup () {
+ ecode=0
+ OFILE=/tmp/group.$$
+ getent group "$1" > $OFILE
+ if [ $? -eq 0 ]
+ then
+ CHECKGID=$( grep "^$1:" $OFILE | cut -f3 -d: 2>/dev/null )
+ CHECKGROUPPRESENT=$( grep "^$1:" $OFILE | cut -f1 -d: 2>/dev/null )
+ CHECKGROUP=$( grep ":$2:" $OFILE | cut -f1 -d: 2>/dev/null )
+ fi
+ if [ "${CHECKGID}" = "" -a "${CHECKGROUP}" = "" ]
+ then
+ ${ECHO} "Adding $1 group ..."
+ if [ "$2" = "DC" ]
+ then
+ groupadd $1
+ else
+ groupadd -g $2 $1
+ fi
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "Cannot add group $1, continuing..."
+ ecode=1
+ fi
+ else
+ if [ "${CHECKGROUPPRESENT}" = "$1" ]
+ then
+ if [ "$2" != "DC" ]
+ then
+ if [ "${CHECKGID}" != "$2" ]
+ then
+ ${ECHO} "ERROR: $1 group added but with wrong gid \"${CHECKGID}\"; should be $2"
+ ecode=1
+ fi
+ if [ "${CHECKGROUP}" != "$1" ]
+ then
+ ${ECHO} "ERROR: wrong group \"${CHECKGROUP}\" for gid $2, group should be $1"
+ ecode=1
+ fi
+ else
+ ${ECHO} "$1 group has already been added"
+ fi
+ fi
+ fi
+ rm -f $OFILE
+ return ${ecode}
+}
+
+############################################################################
+# checkuser username uid homedir shell group
+# checks if the username/uid/homedir/shell combo is already in /etc/passwd
+# if not, it adds it
+# if the login is there and the uid belongs to a different user, it errors
+# if the login is there and the shell is not correct, it errors
+# uid may be DC for don't care
+############################################################################
+checkuser () {
+ ecode=0
+ OFILE=/tmp/user.$$
+ getent passwd $1 > $OFILE
+ if [ $? -eq 0 ]
+ then
+ CHECKUID=$( grep "^$1:" $OFILE | cut -f3 -d: 2>/dev/null )
+ CHECKLOGIN=$( grep ":x:$2:" $OFILE | cut -f1 -d: 2>/dev/null )
+ CHECKLOGINPRESENT=$( grep "^$1:" $OFILE | cut -f1 -d: 2>/dev/null )
+ CHECKSHELL=$( grep "^$1:" $OFILE | cut -f7 -d: 2>/dev/null )
+ CHECKHOME=$( grep "^$1:" $OFILE | cut -f6 -d: 2>/dev/null )
+ fi
+
+ if [ ! -d $3 ]
+ then
+ mkdir -p $3
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "mkdir -p $3 failed"
+ ecode=1
+ fi
+ chmod -R 755 $3
+ fi
+ if [ "${CHECKUID}" = "" -a "${CHECKLOGIN}" = "" ]
+ then
+ ${ECHO} "Adding $1 login ..."
+ if [ "$2" = "DC" ]
+ then
+ useradd -g $5 -d $3 -s $4 -c "$1 LOGIN" -m $1
+ else
+ useradd -u $2 -g $5 -d $3 -s $4 -c "$1 LOGIN" -m $1
+ fi
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "Cannot add $1 login, continuing..."
+ ecode=1
+ fi
+ elif [ "${CHECKLOGINPRESENT}" = "$1" -a "$2" = "DC" -a "${CHECKSHELL}" = "$4" -a "${CHECKHOME}" = "$3" ]
+ then
+ ${ECHO} "The '$1' login has already been added to system with UID ${CHECKUID}."
+
+ elif [ "${CHECKUID}" = "$2" -a "${CHECKLOGIN}" = "$1" -a "${CHECKSHELL}" = "$4" -a "${CHECKHOME}" = "$3" ]
+ then
+ ${ECHO} "The '$1' login has already been added to system."
+ else
+ if [ "$2" != "DC" -a "${CHECKUID}" != "$2" ]
+ then
+ ${ECHO} "ERROR: $1 login added but with wrong uid \"${CHECKUID}\"; should be $2"
+ ecode=1
+ fi
+ if [ "$2" != "DC" -a "${CHECKLOGIN}" != "$1" ]
+ then
+ ${ECHO} "ERROR: wrong login \"${CHECKLOGIN}\" for uid $2, login should be $1"
+ ecode=1
+ fi
+ if [ "${CHECKHOME}" != "$3" ]
+ then
+ ${ECHO} "ERROR: wrong home directory \"${CHECKHOME}\" for login $1, should be $3"
+ ecode=1
+ fi
+ if [ "${CHECKSHELL}" != "$4" ]
+ then
+ ${ECHO} "ERROR: $1 login not set up with $4"
+ ecode=1
+ fi
+ fi
+ rm -f $OFILE
+ return ${ecode}
+}
+
+############################################################################
+# checkhome username homedir action
+# if the user doesn't exist, it errors
+# checks if the username has homedir as its home directory
+# if not and action is null, it modifies it
+# if not and action is mod, it modifies it
+# if not and action is error, it errors
+############################################################################
+checkhome () {
+ ecode=0
+ OFILE=/tmp/user.$$
+ getent passwd $1 > $OFILE
+ if [ $? -eq 0 ]
+ then
+ CHECKUID=$( grep "^$1:" $OFILE | cut -f3 -d: 2>/dev/null )
+ CHECKGID=$( grep "^$1:" $OFILE | cut -f4 -d: 2>/dev/null )
+ CHECKHOME=$( grep "^$1:" $OFILE | cut -f6 -d: 2>/dev/null )
+
+ if [ "${CHECKHOME}" = "$2" ]
+ then
+ if [ ! -d $2 ]
+ then
+ mkdir -p $2
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "mkdir -p $2 failed"
+ ecode=1
+ fi
+ chown ${CHECKUID}:${CHECKGID} $2
+ chmod -R 755 $2
+ fi
+ else
+ # modify the user to set the new home dir and move any current home dir to there
+ usermod -d $2 -m $1
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "usermod -d $2 -m $1 failed"
+ ecode=1
+ fi
+ fi
+ else
+ ${ECHO} "user $1 doesn't exist"
+ ecode=1
+ fi
+
+ rm -f $OFILE
+ return ${ecode}
+}
+
+##################################################################
+#checkloginsforpwds checks /etc/shadow for logins without passwords
+# the first argument is a list of logins to check
+##################################################################
+checkloginsforpwds () {
+ for i in $1
+ do
+ CHECK_LOGIN=$( grep "^${i}:" /etc/shadow | grep "!!" )
+ if [ "${CHECK_LOGIN}" != "" ]
+ then
+ NOPWD="${NOPWD} ${i}"
+ fi
+ done
+
+ if [ "${NOPWD}" != "" ]
+ then
+ ${ECHO} ""
+ ${ECHO} "REMINDER: The following logins must have a passwords assigned to them.\n"
+ ${ECHO} "##############################################################"
+ ${ECHO} " ${NOPWD} "
+ ${ECHO} "##############################################################"
+ ${ECHO} ""
+ ${ECHO} " This must be done by executing the following command:"
+ ${ECHO} ""
+ ${ECHO} " $ passwd <login>"
+ ${ECHO} ""
+ ${ECHO} " After typing the \"passwd\" command you will be prompted for"
+ ${ECHO} " the password for the login."
+ ${ECHO} ""
+ fi
+}
+
+##################################################################
+# checkassignpasswords checks /etc/shadow for logins without passwords
+# and then asks the user to assign one
+# the first argument is a list of logins to check
+##################################################################
+checkassignpasswords () {
+ for i in $1
+ do
+ CHECK_LOGIN=$( grep "^${i}:" /etc/shadow | grep LK )
+ if [ "${CHECK_LOGIN}" != "" ]
+ then
+ ${ECHO} "Please assign a password for the '${i}' login"
+ passwd ${i}
+ ${ECHO}
+ fi
+ done
+}
+
+############################################################################
+# copywithperms origfile destfile owner group perms [save suffix]
+# copies origfile to destfile, giving destfile ownership and permssions
+# from owner, group, and perms. If the sixth argument is "save", the
+# original is saved in the same place with the seventh argument as the
+# suffix. If the seventh arg is null, $$ is used
+############################################################################
+copywithperms () {
+ SAVE=0
+ ECODE=0
+ if [ "$6" = "save" -a -f "$2" ]
+ then
+ if [ "$7" = "" ]
+ then
+ cp $2 $2.$$
+ else
+ cp $2 $2.$7
+ fi
+ fi
+ if [ -f $1 ]
+ then
+ cp $1 $2
+ ECODE=$?
+ chown ${3}:${4} $2
+ chmod $5 $2
+ else
+ ${ECHO} "$1 is not a file. No copy done!"
+ fi
+ return ${ECODE}
+}
+
+############################################################################
+# mkdirwithperms dirname owner group perms ifExist
+# makes directory dirname , giving dirname ownership and permssions
+# from owner, group, and perms.
+# perms can be DC if you don't care
+# ifExist can be rm, error, dontcreate
+############################################################################
+mkdirwithperms () {
+ ECODE=0
+ if [ -f $1 ]
+ then
+ ECODE=1
+ ${ECHO} "$1 exists but is a file. No mkdir done!"
+ elif [ -d $1 ]
+ then
+ if [ "$5" = "rm" ]
+ then
+ rm -rf $1
+ mkdir -p $1
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "mkdir -p $1 failed"
+ ECODE=1
+ fi
+ elif [ "$5" = "error" ]
+ then
+ ECODE=1
+ ${ECHO} "$1 is a directory. No mkdir done!"
+ elif [ "$5" != "dontcreate" ]
+ then
+ mkdir -p $1
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "mkdir -p $1 failed"
+ ECODE=1
+ fi
+ fi
+ else
+ mkdir -p $1
+ if [ "$?" != "0" ]
+ then
+ ${ECHO} "mkdir -p $1 failed"
+ ECODE=1
+ fi
+ fi
+ if [ "${ECODE}" = "0" ]
+ then
+ chown ${2}:${3} $1
+ if [ "$4" != "DC" ]
+ then
+ chmod $4 $1
+ fi
+ fi
+ return ${ECODE}
+}
+
+
+############################################################################
+# chownwithperms owner group file mode
+# changes the ownership and mode for the specified file
+############################################################################
+chownwithperms () {
+ chown ${1}:${2} $3
+ chmod $4 $3
+}
+
+verifywhosrunning () {
+ userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+ if [ "${userid}" != "$1" ]
+ then
+ ${ECHO} "You must be $1 to run $0"
+ exit 1
+ fi
+}
+
+replaceline() {
+
+ name=$1
+ value=$2
+ file=$3
+
+ if [ -z "${file}" ]
+ then
+ ${ECHO} "replaceline: ERROR: insufficient arguments: $1 $2" >&2
+ return 1
+ fi
+
+ if [ -n "$4" ]
+ then
+ ${ECHO} "replaceline: ERROR: too many arguments: $1 $2 $3 $4" >&2
+ return 1
+ fi
+
+ if [ -f ${file} ]
+ then
+ grep -v "^${name}=" ${file} > ${file}.$$
+ ${ECHO} "${name}=${value}" >> ${file}.$$
+ mv -f ${file}.$$ ${file}
+ else
+ ${ECHO} "${name}=${value}" > ${file}
+ fi
+}
+
+replaceline_with_quotes() {
+
+ name=$1
+ value=$2
+ file=$3
+
+ if [ -z "${file}" ]
+ then
+ ${ECHO} "replaceline: ERROR: insufficient arguments: $1 $2" >&2
+ return 1
+ fi
+
+ if [ -n "$4" ]
+ then
+ ${ECHO} "replaceline: ERROR: too many arguments: $1 $2 $3 $4" >&2
+ return 1
+ fi
+
+ if [ -f ${file} ]
+ then
+ grep -v "^${name}=" ${file} > ${file}.$$
+ ${ECHO} "${name}=\"${value}\"" >> ${file}.$$
+ mv -f ${file}.$$ ${file}
+ else
+ ${ECHO} "${name}=\"${value}\"" > ${file}
+ fi
+}
+
+# this deleteline will not actually delete the entry
+# but only delete the value leaving the name=
+# when siteconf.pl went from Boilerplate to Fillin,
+# we changed this because Fillin can handle null values.
+
+deleteline() {
+
+ name=$1
+ file=$2
+
+ if [ -z "${file}" ]
+ then
+ ${ECHO} "deleteline: ERROR: insufficient arguments" >&2
+ return 1
+ fi
+
+ if [ -f ${file} ]
+ then
+ cp ${file} ${file}.$$
+ lno=$( grep -n "^${name}=" ${file} | cut -d: -f1 )
+ if [ "${lno}" != "" ]
+ then
+ sed "${lno}d" ${file} > ${file}.$$
+ fi
+ ${ECHO} "${name}=" >> ${file}.$$
+ mv -f ${file}.$$ ${file}
+ else
+ ${ECHO} "${name}=" > ${file}
+ fi
+}
+
+# dropline will drop the line from the file
+# unlike the deleteline function above
+
+dropline() {
+
+ name=$1
+ file=$2
+
+ if [ -z "${file}" ]
+ then
+ ${ECHO} "dropline: ERROR: insufficient arguments" >&2
+ return 1
+ fi
+
+ if [ -f ${file} ]
+ then
+ grep -v "^${name}=" ${file} > ${file}.$$
+ mv -f ${file}.$$ ${file}
+ fi
+}
+
+pause_install() {
+
+ if [ "${Pause}" = "1" ]
+ then
+ if ${chkyn} -y "Continue with ${Itype}?"
+ then
+ return 0
+ else
+ ${ECHO} "${PNAME}: quitting" >&2
+ exit 1
+ fi
+ fi
+}
+
+get_ITYPE() {
+ ITYPE=$( ${chkyn} -fer ${q_flags} -h\? ${ITYPE:+-D"${ITYPE}"} -H \
+" If you are doing a fresh install, answer 'I' or answer 'U' for upgrade." \
+"Is this a fresh 'install' or 'upgrade' (I or U):${ITYPE:+ [${ITYPE}]}" \
+ '^[IU]$' \
+'*** ERROR *** Entry must be I or U.' )
+}
+
+
+###
+# Change an /etc/group entry to allow a give user to change group into it.
+# arg1 = comma-sep group list (e.g., sylantro,other)
+# arg2 = user
+###
+addUserToGroup()
+{
+ if [ -z "$1" -o -z "$2" ]
+ then
+ ${ECHO} "addUserToGroup failed, need two args, group and user"
+ return 1
+ else
+ usermod -G $1 $2
+ fi
+ return 0
+}
+
+################### BACKUP AND RESTORE METHODS ########################
+################### VARIABLES ##########################
+################### VARIABLES ##########################
+################### VARIABLES ##########################
+################### VARIABLES ##########################
+
+NO_FILE_INDICATOR="__NO_PREVIOUS_FILE__"
+SAVE_SUFFIX=${Project}save
+
+################### SUBROUTINES ##########################
+################### SUBROUTINES ##########################
+################### SUBROUTINES ##########################
+################### SUBROUTINES ##########################
+################### SUBROUTINES ##########################
+
+##############################################################################
+# Purpose: make a backup copy of a file in such a way that the backup
+# won't be lost by re-running your script PLUS give you a predictable name
+# for the most recent back up to use when you roll back.
+#
+# Input:
+# - Arg1 = file to back up
+#
+# Requirement:
+# - Remove $1.save before calling this function or else a copy won't be made.
+# - Make sure to set the value of env value TODAY to use as a suffix.
+#
+# Description:
+# Copy $1 to $1.${SAVE_SUFFIX}.${TODAY}, then link that to $1.save.
+#
+##############################################################################
+make_backup_copy ()
+{
+ if [ -z "${TODAY}" ]
+ then
+ ${ECHO} "make_backup_copy - TODAY variable is unset" >&2
+ return 1
+ fi
+
+ if [ -f $1.${SAVE_SUFFIX}.${TODAY} -a -h $1.save ]
+ then
+ ${ECHO} "Note: backup already exists for $1"
+ else
+ # if existing file doesn't exist, set up for later delete by rollback
+ if [ ! -f $1 -a ! -h $1 ]
+ then
+ ${ECHO} ${NO_FILE_INDICATOR} > $1
+ fi
+ cp -p $1 $1.${SAVE_SUFFIX}.${TODAY}
+ ln -s $1.${SAVE_SUFFIX}.${TODAY} $1.save
+ fi
+}
+
+################################################################################
+# Purpose: Find the actual file that belongs to $1, which can be a symbolic
+# link.
+#
+# Input:
+# - Arg1 = path to file or link
+# - Arg2 = true if you want _SRCFILE to be null if no actual file is
+# found. If Arg2 is NOT true, then _SRCFILE is set to Arg1.
+#
+# Side Effect:
+# Sets value of _SRCFILE variable
+################################################################################
+find_source_file ()
+{
+ if [ -z "$1" ]
+ then
+ ${ECHO} "find_source_file - needs at least one argument" >&2
+ return 1
+ fi
+
+ ls -l $1 > /tmp/tls$$
+ cat /tmp/tls$$ | sed 's/ */ /g' |cut -f11 > /tmp/cuts$$
+ _SRCFILE=$( cat /tmp/cuts$$ )
+
+ if [ "$_SRCFILE" = "" ]
+ then
+ if [ "$2" != "true" ]
+ then
+ _SRCFILE=$1
+ fi
+ fi
+ rm -f /tmp/tls$$ /tmp/cuts$$
+}
+
+#######################################################################
+# Purpose: Expands template file using data in COPT variable.
+# Diffs expanded template against existing file and installs if different.
+# If arg5 = true, sets _config_changes=1 so you know that changes were installed
+#
+# Makes its own backup copy using make_backup_copy.
+# Does install if different using install_if_different.
+#
+# Input:
+# Arg1 = template path without .tmpl extension
+# Arg2 = install path
+# Arg3 = owner and group (e.g., root:other)
+# Arg4 = permissions (e.g., 750)
+# Arg5 = true/false, if expanded file is different than installed .
+# Set _config_changes to 1 if Arg5 is true. Otherwise, don't touch
+# _config_changes
+#
+# Requirement: set COPT to the value of the -c option to siteconf.pl
+#
+# Side Effect: sets _config_changes=1 if changes were installed
+#######################################################################
+install_from_template ()
+{
+ if [ -z "${COPT}" ]
+ then
+ ${ECHO} "install_from_template - COPT is unset" >&2
+ return 1
+ fi
+
+ TMPL=$( basename ${1} )
+ OFILE=/tmp/${TMPL}
+ if [ -f ${1}.tmpl ]
+ then
+
+ ${PROJECT_HOME}/bin/siteconf.pl -t ${1}.tmpl -c ${COPT} -o ${OFILE}
+ install_if_different ${OFILE} ${2} ${3} ${4} ${5}
+
+ else
+ ${ECHO} "install_from_template: ERROR: Missing ${TMPL}.tmpl" >&2
+ fi
+ rm -f ${OFILE}
+}
+
+
+#######################################################################
+# Purpose: Copies source to destination if the two are different.
+# If arg5 = true, sets _config_changes=1 so you know that changes were installed
+#
+# Makes its own backup copy using make_backup_copy.
+#
+# Input:
+# Arg1 = source path
+# Arg2 = install path
+# Arg3 = owner and group (e.g., root:other)
+# Arg4 = permissions (e.g., 750)
+# Arg5 = true/false, if expanded file is different than installed .
+# Set _config_changes to 1 if Arg5 is true. Otherwise, don't touch
+# _config_changes
+#
+# Side Effect: sets _config_changes=1 if changes were installed
+#######################################################################
+install_if_different()
+{
+ # Take backup before changing.
+ # Only change if different.
+ if [ -f ${2} ]
+ then
+ diff ${1} ${2} > /dev/null
+ diffrc=$?
+ if [ "${diffrc}" != "0" ]
+ then
+ ${ECHO} "Installing ${2}"
+ make_backup_copy ${2}
+ mv -f ${1} ${2}
+ chown ${3} ${2}
+ chmod ${4} ${2}
+ if [ "${5}" = "true" ]
+ then
+ _config_changes=1
+ fi
+ fi
+ else
+ # creates backup containing ${NO_FILE_INDICATOR} for rollback removal
+ make_backup_copy ${2}
+ mv -f ${1} ${2}
+ chown ${3} ${2}
+ chmod ${4} ${2}
+ if [ "${5}" = "true" ]
+ then
+ _config_changes=1
+ fi
+ fi
+}
+###################################################################
+# Purpose: rollback a file whose backup was made with make_backup_copy
+#
+# Input:
+# Arg1 is path of installed file. Subroutine will look for ${1}.save
+# Arg2 = true/false, if expanded file is different than installed,
+# set _config_changes to 1 if Arg2 is true. Otherwise, don't touch
+# _config_changes
+#
+# Side Effect: sets _config_changes=1 if changes were rolled back
+###################################################################
+rollback_from_save ()
+{
+ if [ -f ${1}.save -o -h ${1}.save ]
+ then
+ find_source_file ${1}.save false
+ ${ECHO} "rollback_from_save: rolling back to $( basename ${_SRCFILE} )"
+ grep ${NO_FILE_INDICATOR} ${_SRCFILE} > /dev/null
+ if [ $? -eq 0 ]
+ then
+ rm -f ${_SRCFILE} ${1}
+ else
+ mv -f ${_SRCFILE} ${1}
+ fi
+ if [ "${2}" = "true" ]
+ then
+ _config_changes=1
+ fi
+ rm -f ${1}.save
+ fi
+}
diff --git a/ajsc-aai/src/main/scripts/install/updateQueryData.sh b/ajsc-aai/src/main/scripts/install/updateQueryData.sh
new file mode 100644
index 0000000..2968230
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/install/updateQueryData.sh
@@ -0,0 +1,103 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+PROGNAME=$(basename $0)
+OUTFILE=$PROJECT_HOME/logs/misc/${PROGNAME}.log.$(date +\%Y-\%m-\%d)
+#OUTFILE=/c/temp/${PROGNAME}.log.$(date +\%Y-\%m-\%d)
+
+TS=$(date "+%Y-%m-%d %H:%M:%S")
+
+CHECK_USER="aaiadmin"
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != $CHECK_USER ]; then
+ echo "You must be $CHECK_USER to run $0. The id used $userid."
+ exit 1
+fi
+
+error_exit () {
+ echo "${PROGNAME}: failed for ${1:-"Unknown error"} on cmd $2" 1>&2
+ echo "${PROGNAME}: failed for ${1:-"Unknown error"} on cmd $2" >> $OUTFILE
+# exit ${2:-"1"}
+}
+
+j=0
+for filepath in `ls $PROJECT_HOME/bundleconfig/etc/scriptdata/widget-model-json/*.json|sort -f`
+#for filepath in `ls /c/sources/aai/aaigitnew/bundleconfig-local/etc/scriptdata/widget-model-json/*.json|sort -f`
+do
+j=$(expr "$j" + 1)
+filename=$(basename $filepath)
+echo "Begin putTool for widget $filename" | tee -a $OUTFILE
+vers=`grep model-name-version-id $filepath|cut -d':' -f2|cut -d'"' -f2`
+# last parameter will skip put if it exists
+resource=service-design-and-creation/models/model/$vers
+$PROJECT_HOME/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+#/c/sources/aai/aaigitnew/src/main/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+echo "End putTool for widget $filename" | tee -a $OUTFILE
+done
+
+j=0
+for filepath in `ls $PROJECT_HOME/bundleconfig/etc/scriptdata/named-query-json/*.json|sort -f`
+#for filepath in `ls /c/sources/aai/aaigitnew/bundleconfig-local/etc/scriptdata/named-query-json/*.json|sort -f`
+do
+j=$(expr "$j" + 1)
+filename=$(basename $filepath)
+echo "Begin putTool for named-query $filename" | tee -a $OUTFILE
+vers=`grep named-query-uuid $filepath|cut -d':' -f2|cut -d'"' -f2`
+# last parameter will skip put if it exists
+resource=service-design-and-creation/named-queries/named-query/$vers
+$PROJECT_HOME/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+#/c/sources/aai/aaigitnew/src/main/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+echo "End putTool for named-query $filename" | tee -a $OUTFILE
+done
+
+j=0
+for filepath in `ls $PROJECT_HOME/bundleconfig/etc/scriptdata/resource-model-json/*.json|sort -f`
+#for filepath in `ls /c/sources/aai/aaigitnew/bundleconfig-local/etc/scriptdata/resource-model-json/*.json|sort -f`
+do
+j=$(expr "$j" + 1)
+filename=$(basename $filepath)
+echo "Begin putTool for resource model $filename" | tee -a $OUTFILE
+vers=`grep model-name-version-id $filepath|cut -d':' -f2|cut -d'"' -f2`
+# last parameter will skip put if it exists
+resource=service-design-and-creation/models/model/$vers
+$PROJECT_HOME/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+#/c/sources/aai/aaigitnew/src/main/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+echo "End putTool for resource model $filename" | tee -a $OUTFILE
+done
+
+j=0
+for filepath in `ls $PROJECT_HOME/bundleconfig/etc/scriptdata/service-model-json/*.json|sort -f`
+#for filepath in `ls /c/sources/aai/aaigitnew/bundleconfig-local/etc/scriptdata/service-model-json/*.json|sort -f`
+do
+j=$(expr "$j" + 1)
+filename=$(basename $filepath)
+echo "Begin putTool for service model $filename" | tee -a $OUTFILE
+vers=`grep model-name-version-id $filepath|cut -d':' -f2|cut -d'"' -f2`
+# last parameter will skip put if it exists
+resource=service-design-and-creation/models/model/$vers
+$PROJECT_HOME/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+#/c/sources/aai/aaigitnew/src/main/scripts/putTool.sh $resource $filepath 1 0 na 1 >> $OUTFILE 2>&1 || error_exit "$resource $filepath" $j
+echo "End putTool for service model $filename" | tee -a $OUTFILE
+done
+
+echo "$PROGNAME completed ${TS}" | tee -a $OUTFILE
+echo "See output and error file: $OUTFILE"
+
+exit 0
diff --git a/ajsc-aai/src/main/scripts/logcleanup.sh b/ajsc-aai/src/main/scripts/logcleanup.sh
new file mode 100644
index 0000000..36f8124
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/logcleanup.sh
@@ -0,0 +1,80 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script archives/deletes log files
+#
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+PROGNAME=$(basename $0)
+LOGDIR=${PROJECT_HOME}/logs
+ZIPDIR=ARCHIVE
+AGEZIP=30
+AGEDELETE=60
+ZIPPER=/bin/gzip
+DATE=$(date +%Y%m%d)
+
+# Get the program arguments
+if [[ $# -lt 3 ]]
+then
+ echo "${PROGNAME}: Arguments are missing. Found $#"
+ exit 1
+fi
+LOGDIR="${1}"
+AGEZIP=$2
+AGEDELETE=$3
+if [[ ! -d $LOGDIR ]]
+then
+ echo "${PROGNAME}: Directory does not exist: ${LOGDIR}"
+ exit 1
+fi
+
+# Create the archive folder, if it does not exist.
+if [[ ! -d ${LOGDIR}/${ZIPDIR} ]]
+then
+ mkdir ${LOGDIR}/${ZIPDIR}
+ if [ $? -ne 0 ]
+ then
+ echo "${PROGNAME}: Failed to create directory: ${LOGDIR}/${ZIPDIR}"
+ exit 1
+ fi
+ chmod 777 ${LOGDIR}/${ZIPDIR}
+fi
+
+# Compress files that are older than AGEZIP days
+find -L ${LOGDIR} -name *.gz -prune -o -mtime +${AGEZIP} -type f -name "*.log.*" -exec ${ZIPPER} -f {} \;
+find -L ${LOGDIR} -name ${ZIPDIR} -prune -o -type f -name "*.log.*.gz" -print | while read i; do dirnm=`dirname ${i}`; drn=`basename ${dirnm}`; mkdir -p ${LOGDIR}/${ZIPDIR}/${drn}; echo ${i}; echo ${LOGDIR}/${ZIPDIR}/${drn}; mv ${i} ${LOGDIR}/${ZIPDIR}/${drn}; done
+
+# Delete archive files that are older than AGEDELETE days
+find -L ${LOGDIR}/${ZIPDIR}/* -type f -name "*.gz" -mtime +${AGEDELETE} -exec rm -r {} \;
+
+exit 0
diff --git a/ajsc-aai/src/main/scripts/notifyTool.sh b/ajsc-aai/src/main/scripts/notifyTool.sh
new file mode 100644
index 0000000..37be83d
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/notifyTool.sh
@@ -0,0 +1,61 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes PutActionsNotify java class to PUT a actions/notify request for a given JSON payload.
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.PutActionsNotify "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/postTool.sh b/ajsc-aai/src/main/scripts/postTool.sh
new file mode 100644
index 0000000..e02895f
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/postTool.sh
@@ -0,0 +1,61 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes PostResource java class to POST on a resource
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.PostResource "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/putTool.sh b/ajsc-aai/src/main/scripts/putTool.sh
new file mode 100644
index 0000000..369496e
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/putTool.sh
@@ -0,0 +1,61 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes PutResource java class to PUT on a resource
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.PutResource "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/rshipTool.sh b/ajsc-aai/src/main/scripts/rshipTool.sh
new file mode 100644
index 0000000..bf6d585
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/rshipTool.sh
@@ -0,0 +1,75 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes RelationshipputDel java class to PUT/DELETE a relationship
+#
+# sample json file for an oam-network node to put a relationship to a complex
+#{
+# "related-to": "complex",
+# "relationship-data": [ {
+# "relationship-key": "complex.physical-location-id",
+# "relationship-value": "CHCGILCL73W"
+# }]
+#}
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/jetty/webapps/*/webapp/WEB-INF/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.RelationshipPutDel "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/run_ChangeAuthMethod.sh b/ajsc-aai/src/main/scripts/run_ChangeAuthMethod.sh
new file mode 100644
index 0000000..7899db1
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/run_ChangeAuthMethod.sh
@@ -0,0 +1,107 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script to update runner-web.xml to change authentication from basic to 2-way SSL and vice-versa
+#
+
+usage () {
+ echo "=========input error==========="
+ echo " Usage: $0 <action>"
+ echo "usage examples: $0 disable-basic-auth"
+ echo " $0 enable-basic-auth"
+ exit 1
+}
+
+prop_file=$PROJECT_HOME/etc/runner-web.xml
+prop_name='login-config'
+
+update_prop_disable_basic_auth() {
+
+# echo "Updating security-constraint and login-config elements in file $prop_file"
+
+ sec_string=`egrep -i "<security-constraint>" $prop_file | grep "<\!--"`
+ if [ "$?" -eq "1" ]; then
+ sed -i "s/<security-constraint>/<\!-- <security-constraint>/g" $prop_file
+ fi
+
+ config_string=`egrep -i "<\/login-config>" $prop_file | grep "\-->"`
+ if [ "$?" -eq "1" ]; then
+ sed -i "s/<\/login-config>/<\/login-config> -->/g" $prop_file
+ fi
+}
+
+update_prop_enable_basic_auth() {
+
+# echo "Updating security-constraint and login-config elements in file $prop_file"
+
+ sec_string=`egrep -i "<security-constraint>" $prop_file | grep "<\!--"`
+ if [ "$?" -eq "0" ]; then
+ sed -i "s/<\!-- <security-constraint>/<security-constraint>/g" $prop_file
+ fi
+
+ config_string=`egrep -i "<\/login-config>" $prop_file | grep "\-->"`
+ if [ "$?" -eq "0" ]; then
+ sed -i "s/<\/login-config> -->/<\/login-config>/g" $prop_file
+ fi
+}
+
+echo `date` "Running $0... Action:$1"
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+if [ "$#" -ne 1 ]; then
+ usage
+fi
+
+if [ "$1" = "disable-basic-auth" ]; then
+ echo "Updating Authentication Type..."
+ update_prop_disable_basic_auth true
+ echo `date` " Done $0"
+ exit 0
+fi
+
+if [ "$1" = "enable-basic-auth" ]; then
+ echo "Updating Authentication Type..."
+ update_prop_enable_basic_auth true
+ echo `date` " Done $0"
+ exit 0
+fi
+. /etc/profile.d/aai.sh
+
+CLASSPATH=$CLASSPATH:$PROJECT_HOME/extJars/*
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+exit 0
+
diff --git a/ajsc-aai/src/main/scripts/run_DbTestProcessBuilder.sh b/ajsc-aai/src/main/scripts/run_DbTestProcessBuilder.sh
new file mode 100644
index 0000000..8ba3960
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/run_DbTestProcessBuilder.sh
@@ -0,0 +1,49 @@
+#!/bin/ksh
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+#
+# The script invokes DbTestProcessBuilder class to run test methods from property file path passed as an argument
+#
+
+echo `date` " Starting $0"
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.DbTestProcessBuilder "$@"
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/run_FixXSD.sh b/ajsc-aai/src/main/scripts/run_FixXSD.sh
new file mode 100644
index 0000000..3c61c55
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/run_FixXSD.sh
@@ -0,0 +1,67 @@
+#!/bin/ksh
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+#
+# The script invokes GetResource java class to get all nodes
+#
+
+echo
+echo `date` " Starting $0"
+
+REV=$1
+AAIHOME=$2
+echo "AAIHOME: $AAIHOME"
+
+if test "$REV" = ""
+then
+ REV=v6
+fi
+
+. /etc/profile.d/aai.sh
+
+if test "$AAIHOME" = ""
+then
+ AAIHOME=$PROJECT_HOME
+fi
+
+
+for JAR in `ls $AAIHOME/target/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+export REV=$REV
+echo "FixXSD $REV $AAIHOME"
+$JAVA_HOME/bin/java -classpath $CLASSPATH -DAJSC_HOME=$AAIHOME org.openecomp.aai.util.FixXSDNew $REV
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/schemaMod.sh b/ajsc-aai/src/main/scripts/schemaMod.sh
new file mode 100644
index 0000000..f7acc2f
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/schemaMod.sh
@@ -0,0 +1,94 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# This script is used to correct mistakes made in the database schema.
+# It currently just allows you to change either the dataType and/or indexType on properties used by nodes.
+#
+# NOTE - Titan is not elegant in 0.5.3 about making changes to the schema. Bad properties never
+# actually leave the database, they just get renamed and stop getting used. So it is
+# really worthwhile to get indexes and dataTypes correct the first time around.
+# Note also - This script just makes changes to the schema that is currently live.
+# If you were to create a new schema in a brandy-new environment, it would look like
+# whatever oxm told it to look like. So, part of making a
+# change to the db schema should Always first be to make the change in oxm so that
+# future environments will have the change. This script is just to change existing
+# instances of the schema since schemaGenerator (as of June 2015) does not update things - it
+# just does the initial creation.
+#
+# Boy, this is getting to be a big comment section...
+#
+# To use this script, you need to pass four parameters:
+# propertyName -- the name of the property that you need to change either the index or dataType on
+# targetDataType -- whether it's changing or not, you need to give it: String, Integer, Boolean or Long
+# targetIndexInfo -- whether it's changing or not, you need to give it: index, noIndex or uniqueIndex
+# preserveDataFlag -- true or false. The only reason I can think of why you'd ever want to
+# set this to false would be maybe if you were changing to an incompatible dataType so didn't
+# want it to try to use the old data (and fail). But 99% of the time this will just be 'true'.
+#
+# Ie. schemaMod flavor-id String index true
+#
+
+echo
+echo `date` " Starting $0"
+
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+
+if [ "$#" -ne 4 ]; then
+ echo "Illegal number of parameters"
+ echo "usage: $0 propertyName targetDataType targetIndexInfo preserveDataFlag"
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \
+ org.openecomp.aai.dbgen.SchemaMod $1 $2 $3 $4
+if [ "$?" -ne "0" ]; then
+ echo "Problem executing schemaMod "
+ exit 1
+fi
+
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/uniquePropertyCheck.sh b/ajsc-aai/src/main/scripts/uniquePropertyCheck.sh
new file mode 100644
index 0000000..20bd2e3
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/uniquePropertyCheck.sh
@@ -0,0 +1,64 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes UniqueProperty java class to see if the passed property is unique in the db and if
+# not, to display where duplicate values are found.
+#
+# For example: uniquePropertyCheck.sh subscriber-name
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.UniquePropertyCheck "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/updateTool.sh b/ajsc-aai/src/main/scripts/updateTool.sh
new file mode 100644
index 0000000..77faac8
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/updateTool.sh
@@ -0,0 +1,61 @@
+#!/bin/ksh
+#
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+#
+# This script uses the dataSnapshot and SchemaGenerator (via GenTester) java classes to restore
+# data to a database by doing three things:
+# 1) clear out whatever data and schema are currently in the db
+# 2) rebuild the schema (using the SchemaGenerator)
+# 3) reload data from the passed-in datafile (which must found in the dataSnapShots directory and
+# contain an xml view of the db data).
+#
+#
+# The script invokes GetResource java class to get all nodes
+#
+
+echo
+echo `date` " Starting $0"
+
+userid=$( id | cut -f2 -d"(" | cut -f1 -d")" )
+if [ "${userid}" != "aaiadmin" ]; then
+ echo "You must be aaiadmin to run $0. The id used $userid."
+ exit 1
+fi
+
+. /etc/profile.d/aai.sh
+
+for JAR in `ls $PROJECT_HOME/extJars/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+for JAR in `ls $PROJECT_HOME/lib/*.jar`
+do
+ CLASSPATH=$CLASSPATH:$JAR
+done
+
+$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.UpdateResource "$@"
+ret_code=$?
+if [ $ret_code != 0 ]; then
+ echo `date` " Done $0"
+ exit $ret_code
+fi
+
+echo `date` " Done $0"
+exit 0
diff --git a/ajsc-aai/src/main/scripts/yangToJava.sh b/ajsc-aai/src/main/scripts/yangToJava.sh
new file mode 100644
index 0000000..ac10e7d
--- /dev/null
+++ b/ajsc-aai/src/main/scripts/yangToJava.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+#check system vars
+: ${AAI_HOME:?"AAI_HOME must be set. This is typically your git root/aai-webapp/all/src"}
+: ${SCRIPT_HOME:?"SCRIPT_HOME must be set. This is typically your git root/packages/scripts"}
+: ${YANG_OUTPUT:?"YANG_OUTPUT must be set. This should be a temporary directory outside of your git root."}
+: ${REV:?"REV must be set. The format is vX where X is the version you'd like to create."}
+
+usage() {
+ echo "-b [use defaults for all prompts] --help [display help]"
+}
+SKIP=false
+while getopts ":b-" opt; do
+ case $opt in
+ b)
+ echo "skipping prompts"
+ SKIP=true
+ ;;
+ \?)
+ echo "Invalid option: -$OPTARG" >&2
+ usage
+ exit 1
+ ;;
+ -)
+ case "${OPTARG}" in
+ help)
+ usage
+ exit 1
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+
+YANGDIR=$AAI_HOME/main/yang/$REV
+cd $YANGDIR
+
+if [ ! -d "$YANG_OUTPUT/xsd" ]; then
+ mkdir $YANG_OUTPUT/xsd
+fi
+
+for i in *.yang ; do x=`echo $i | cut -d"." -f 1`; echo $i " " $x; pyang -f xsd $i > $YANG_OUTPUT/xsd/$x.xsd; done
+
+cd $AAI_HOME/main/java/
+javac org/openecomp/aai/util/FixXSDNew.java
+java org.openecomp.aai.util.FixXSDNew
+
+rm org/openecomp/aai/util/FixXSDNew.class
+cd $YANG_OUTPUT/xsd
+
+$SCRIPT_HOME/make_refs_in_xsd.pl fixedup.xsd > aai$REV-corrected.xsd
+
+echo "compiling class files..."
+xjc -p org.openecomp.aai.domain.yang -b $AAI_HOME/main/yang/$REV/bindings.xml aai$REV-corrected.xsd
+
+echo "done!"
+cd $YANG_OUTPUT/xsd/org/openecomp/aai/domain/yang/
+
+if [ ! $SKIP = true ]; then
+ read -p "Remove relationship classes? (N/y)" choice
+else
+ choice="N"
+fi
+case "$choice" in
+ y|Y ) echo "removing..."
+ rm -v Relationship*
+ ;;
+ * ) echo "skipping removal"
+ ;;
+esac
+
+echo "fixing yang classes via perl script..."
+for i in *.java; do $SCRIPT_HOME/fix_yang_classes.pl -n "http://org.openecomp.aai.inventory/$REV" $i > $i.new; mv $i $i.bak; mv $i.new $i; done
+
+if [ ! $SKIP = true ]; then
+ read -p "Copy generated classes into git home? (Y/n)" choice
+else
+ choice="Y"
+fi
+case "$choice" in
+ n|N ) echo "classes are at $YANG_OUTPUT";;
+ * ) echo "moving files..."
+ cp -fv *.java $AAI_HOME/main/java/org/openecomp/aai/domain/yang
+ ;;
+esac
+
+echo "generation complete"
+exit 1
+
diff --git a/ajsc-aai/src/main/xjb/bindings.xjb b/ajsc-aai/src/main/xjb/bindings.xjb
new file mode 100644
index 0000000..fec3fe8
--- /dev/null
+++ b/ajsc-aai/src/main/xjb/bindings.xjb
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<jaxb:bindings
+ version="2.1"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <jaxb:bindings scd="x-schema::a" xmlns:a="http://org.openecomp.aai.inventory/v8">
+ <jaxb:schemaBindings>
+ <jaxb:package name="org.openecomp.aai.domain.yang"/>
+ </jaxb:schemaBindings>
+ </jaxb:bindings>
+</jaxb:bindings> \ No newline at end of file
diff --git a/ajsc-aai/src/test/java/bundleconfig-local/etc/appprops/aaiconfig.properties b/ajsc-aai/src/test/java/bundleconfig-local/etc/appprops/aaiconfig.properties
new file mode 100644
index 0000000..5ad8439
--- /dev/null
+++ b/ajsc-aai/src/test/java/bundleconfig-local/etc/appprops/aaiconfig.properties
@@ -0,0 +1,21 @@
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+ecm.auth.password.x=OBF:1igd1i9a1jnb1yte1vv11vu91yt81jk71i6o1idt
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/dbmap/ActionsGraphTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/dbmap/ActionsGraphTest.java
new file mode 100644
index 0000000..dd4d750
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/dbmap/ActionsGraphTest.java
@@ -0,0 +1,2485 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.Matchers.*;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.dbmap.ActionsGraph;
+import org.openecomp.aai.dbmap.GraphHelpersMoxy;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.domain.model.AncestryItem;
+import org.openecomp.aai.domain.model.AncestryItems;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.HttpsAuthClient;
+import org.openecomp.aai.util.RestController;
+import org.openecomp.aai.util.RestObject;
+import org.openecomp.aai.util.RestURL;
+import org.openecomp.aai.util.StoreNotificationEvent;
+
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+
+import static org.mockito.Mockito.*;
+
+import org.powermock.api.mockito.PowerMockito;
+
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.eclipse.persistence.dynamic.DynamicClassLoader;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicHelper;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;
+import org.eclipse.persistence.jaxb.BeanValidationMode;
+import org.eclipse.persistence.jaxb.JAXBContext;
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
+import org.eclipse.persistence.jaxb.metadata.MetadataSource;
+import org.eclipse.persistence.jaxb.metadata.MetadataSourceAdapter;
+import org.eclipse.persistence.jpa.dynamic.JPADynamicTypeBuilder;
+import org.eclipse.persistence.sessions.DatabaseSession;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.eclipse.persistence.sessions.Project;
+import org.eclipse.persistence.sessions.DatabaseLogin;
+import org.eclipse.persistence.sessions.DatabaseSession;
+
+import org.openecomp.aai.domain.yang.GenericVnf;
+import org.openecomp.aai.domain.yang.UpdateNodeKey;
+import com.google.common.collect.ArrayListMultimap;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+@RunWith(PowerMockRunner.class)
+
+@PrepareForTest({DynamicEntity.class, AAIGraph.class, ActionsGraph.class, TitanGraph.class, TitanVertex.class, DbMeth.class,
+ GraphHelpersMoxy.class, RestURL.class, AAIResource.class, AAIExtensionMap.class, DynamicJAXBContext.class,
+ StoreNotificationEvent.class, AAIException.class, RestObject.class, RestController.class,
+ HttpsAuthClient.class, Client.class, ClientResponse.class})
+@SuppressStaticInitializationFor("com.sun.jersey.api.client.ClientResponse")
+@PowerMockIgnore( {"javax.management.*"})
+
+public class ActionsGraphTest {
+
+ //@Rule
+ //public PowerMockRule rule = new PowerMockRule();
+
+ DynamicJAXBContext jaxbContext;
+ static String defaultApiVersion = null;
+ static String latestC25version = "v6";
+
+ private static class SequenceAnswer<T> implements Answer<T> {
+
+
+ private Iterator<T> resultIterator;
+
+ // the last element is always returned once the iterator is exhausted, as with thenReturn()
+ private T last;
+
+ /**
+ * Instantiates a new sequence answer.
+ *
+ * @param results the results
+ */
+ public SequenceAnswer(List<T> results) {
+ this.resultIterator = results.iterator();
+ this.last = results.get(results.size() - 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ //@Override
+ public T answer(InvocationOnMock invocation) throws Throwable {
+ if (resultIterator.hasNext()) {
+ return resultIterator.next();
+ }
+ return last;
+ }
+ }
+
+
+
+ /**
+ * Sets the up before class.
+ *
+ * @throws Exception the exception
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+
+ try {
+ defaultApiVersion = AAIConfig.get("aai.default.api.version");
+ //System.out.println("defaultApiVersion " + defaultApiVersion);
+ } catch ( Exception e) {
+ fail("aaiconfig.properties for aai.default.api.version exception " + e.getMessage());
+ }
+
+ //PowerMockito.mockStatic(IngestModelMoxyOxm.class);
+ //IngestModelMoxyOxm ingestModelMoxyOxmMock = PowerMockito.mock(IngestModelMoxyOxm.class);
+
+ DbMaps dbMaps = new DbMaps();
+
+ dbMaps.NodeProps.put("customer", "global-customer-id");
+ dbMaps.NodeProps.put("customer", "subscriber-name");
+ dbMaps.NodeProps.put("service-subscription", "service-type");
+ dbMaps.NodeProps.put("service-subscription", "temp-ub-sub-account-id");
+ dbMaps.NodeProps.put("cloud-region", "region-owner");
+ dbMaps.NodeProps.put("cloud-region", "cloud-region-id");
+ dbMaps.NodeProps.put("volume-group", "volume-group-id");
+ dbMaps.NodeProps.put("volume-group", "heat-stack-id");
+ dbMaps.NodeProps.put("generic-vnf", "vnf-id");
+ dbMaps.NodeProps.put("generic-vnf", "prov-status");
+ dbMaps.NodeProps.put("vpe", "vnf-id");
+ dbMaps.NodeProps.put("vpe", "prov-status");
+ dbMaps.NodeProps.put("generic-vnf", "something-else");
+
+ dbMaps.PropertyDataTypeMap.put("global-customer-id", "String");
+ dbMaps.PropertyDataTypeMap.put("subscriber-name", "String");
+ dbMaps.PropertyDataTypeMap.put("service-type", "String");
+ dbMaps.PropertyDataTypeMap.put("temp-ub-sub-account-id", "String");
+ dbMaps.PropertyDataTypeMap.put("cloud-owner", "String");
+ dbMaps.PropertyDataTypeMap.put("cloud-region-id", "String");
+ dbMaps.PropertyDataTypeMap.put("volume-group-id", "String");
+ dbMaps.PropertyDataTypeMap.put("heat-stack-id", "String");
+ dbMaps.PropertyDataTypeMap.put("vnf-id", "String");
+ dbMaps.PropertyDataTypeMap.put("prov-status", "String");
+ dbMaps.PropertyDataTypeMap.put("something-else", "String");
+
+ HashMap<String, DbMaps> dbMapsContainerMock = new HashMap<String, DbMaps>();
+ dbMapsContainerMock.put(defaultApiVersion, dbMaps);
+ dbMapsContainerMock.put(latestC25version, dbMaps);
+
+ IngestModelMoxyOxm.dbMapsContainer = dbMapsContainerMock;
+
+ HashMap<String, AAIResources> aaiResourceContainerMock = new HashMap<String, AAIResources>();
+ AAIResources aaiResources = new AAIResources();
+
+ aaiResourceContainerMock.put(defaultApiVersion, aaiResources);
+ IngestModelMoxyOxm.aaiResourceContainer = aaiResourceContainerMock;
+
+ }
+
+ /**
+ * Tear down after class.
+ *
+ * @throws Exception the exception
+ */
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ /**
+ * Sets the up.
+ *
+ * @throws Exception the exception
+ */
+ @Before
+ public void setUp() throws Exception {
+
+ }
+
+ /**
+ * Tear down.
+ *
+ * @throws Exception the exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Test property update with update node key.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked" })
+ @Test
+ public void testPropertyUpdate_withUpdateNodeKey() throws Exception {
+
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("customer");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity keyData1DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+
+ keyData1DynamicEntity.set("keyName", "global-customer-id");
+ keyData1DynamicEntity.set("keyValue", "globalCustomerIdVal");
+ updateNodeKeyList.add(keyData1DynamicEntity);
+
+ DynamicEntity keyData2DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+ keyData2DynamicEntity.set("keyName", "service-subscription");
+ keyData2DynamicEntity.set("keyValue", "serviceTypeVal");
+ //updateNodeKeyList.add(keyData2DynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "subscriber-name");
+ actionDataDynamicEntity.set("propertyValue", "newName");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+ // not dependent
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update with dependent update node key.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testPropertyUpdate_withDependentUpdateNodeKey() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("service-subscription");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity keyData1DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+ keyData1DynamicEntity.set("keyName", "customer.global-customer-id");
+ keyData1DynamicEntity.set("keyValue", "globalCustomerIdVal");
+ updateNodeKeyList.add(keyData1DynamicEntity);
+
+ DynamicEntity keyData2DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+ keyData2DynamicEntity.set("keyName", "service-subscription");
+ keyData2DynamicEntity.set("keyValue", "serviceTypeVal");
+ updateNodeKeyList.add(keyData2DynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "temp-ub-sub-account-id");
+ actionDataDynamicEntity.set("propertyValue", "tempUbSubAccountIdVal");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update with missing cloud region update node key.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testPropertyUpdate_withMissingCloudRegionUpdateNodeKey() throws Exception {
+
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + latestC25version + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + latestC25version + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + latestC25version + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("volume-group");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity keyData1DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+ keyData1DynamicEntity.set("keyName", "volume-group-id");
+ keyData1DynamicEntity.set("keyValue", "volumeGroupIdVal");
+ updateNodeKeyList.add(keyData1DynamicEntity);
+
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "heat-stack-id");
+ actionDataDynamicEntity.set("propertyValue", "heatStackIdVal");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(latestC25version);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update with dependent update node uri.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testPropertyUpdate_withDependentUpdateNodeUri() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("service-subscription");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("business/customers/customer/globalCustomerIdVal/service-subscriptions/service-subscription/serviceTypeVal");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "service-subscription.service-type";
+ String nodeKeyValue = "serviceTypeVal";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+ String depNodeKeyName = "customer.global-customer-id";
+ String depNodeKeyValue = "globalCustomerIdVal";
+ depNodeHash.put(depNodeKeyName, depNodeKeyValue);
+ returnHash.putAll(depNodeHash);
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "temp-ub-sub-account-id");
+ actionDataDynamicEntity.set("propertyValue", "tempUbSubAccountIdVal");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update with missing cloud region dependent update node uri.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testPropertyUpdate_withMissingCloudRegionDependentUpdateNodeUri() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + latestC25version + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + latestC25version + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + latestC25version + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("volume-group");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("cloud-infrastructure/volume-groups/volume-group/volumeGroupIdValue");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "volume-group.volume-group-id";
+ String nodeKeyValue = "volumeGroupIdVal";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+ String depNodeKeyName = "cloud-region.cloud-owner";
+ String depNodeKeyValue = "cloudOwnerVal";
+ String depNodeKeyName1 = "cloud-region.cloud-region-id";
+ String depNodeKeyValue1 = "cloudRegionIdVal";
+ depNodeHash.put(depNodeKeyName, depNodeKeyValue);
+ depNodeHash.put(depNodeKeyName1, depNodeKeyValue1);
+ returnHash.putAll(depNodeHash);
+
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "heat-stack-id");
+ actionDataDynamicEntity.set("propertyValue", "heatStackIdVal");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(latestC25version);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("cloud-region");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update generic vnf prov status PREPRO vwith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_GenericVnfProvStatusPREPROVwithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "prov-status");
+ actionDataDynamicEntity.set("propertyValue", "PREPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update generic vnf prov status XY zwith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_GenericVnfProvStatusXYZwithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("XYZ");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "prov-status");
+ actionDataDynamicEntity.set("propertyValue", "NVTPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update invalid action typewith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_InvalidActionTypewithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "prov-status");
+ actionDataDynamicEntity.set("propertyValue", "PREPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "not-replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+ try {
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+ fail( "expected exception");
+ } catch ( Exception e ) {
+ assertNotNull(e);
+ }
+
+ }
+
+ /**
+ * Test property update udefined propertywith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_UdefinedPropertywithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "x-prov-status");
+ actionDataDynamicEntity.set("propertyValue", "PREPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+ try {
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+ fail( "expected exception");
+ } catch ( Exception e ) {
+ assertNotNull(e);
+ }
+
+ }
+
+ /**
+ * Test property update invalid node typewith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_InvalidNodeTypewithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("x-generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "prov-status");
+ actionDataDynamicEntity.set("propertyValue", "PREPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "not-replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+ try {
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+ fail( "expected exception");
+ } catch ( Exception e ) {
+ assertNotNull(e);
+ }
+
+ }
+
+ /**
+ * Test property update missing node typewith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_MissingNodeTypewithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn(null);
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "prov-status");
+ actionDataDynamicEntity.set("propertyValue", "PREPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "not-replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+ try {
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+ fail( "expected exception");
+ } catch ( Exception e ) {
+ assertNotNull(e);
+ }
+
+ }
+
+ /**
+ * Test property update with key params empty update node key.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked" })
+ @Test
+ public void testPropertyUpdate_withKeyParamsEmptyUpdateNodeKey() throws Exception {
+
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("customer");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity keyData1DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+
+ keyData1DynamicEntity.set("keyName", "global-customer-id");
+ keyData1DynamicEntity.set("keyValue", "globalCustomerIdVal");
+ //updateNodeKeyList.add(keyData1DynamicEntity);
+
+ DynamicEntity keyData2DynamicEntity = dynamicHelper.newDynamicEntity(classNameUpdateNodeKey);
+ keyData2DynamicEntity.set("keyName", "service-subscription");
+ keyData2DynamicEntity.set("keyValue", "serviceTypeVal");
+ //updateNodeKeyList.add(keyData2DynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "subscriber-name");
+ actionDataDynamicEntity.set("propertyValue", "newName");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+ // not dependent
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+ try {
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+ fail( "expected exception");
+ } catch ( Exception e ) {
+ assertNotNull(e);
+ }
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+
+ /**
+ * Test property update generic vnf not prov statuswith update node URI.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_GenericVnfNotProvStatuswithUpdateNodeURI() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "something-else");
+ actionDataDynamicEntity.set("propertyValue", "somethingElseValue");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+ /**
+ * Test property update exception from get vnf.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testPropertyUpdate_exceptionFromGetVnf() throws Exception {
+ String classNameUpdateNodeKey = "inventory.aai.openecomp.org." + defaultApiVersion + ".UpdateNodeKey";
+ String classNameAction = "inventory.aai.openecomp.org." + defaultApiVersion + ".Action";
+ String classNameActionData = "inventory.aai.openecomp.org." + defaultApiVersion + ".ActionData";
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.whenNew(AAIGraph.class).withAnyArguments().thenReturn(graphMock);
+ PowerMockito.whenNew(AAIGraph.class).withNoArguments().thenReturn(graphMock);
+
+ LogLineBuilder llb = new LogLineBuilder();
+
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+
+
+
+ PowerMockito.mockStatic(RestController.class);
+ //PowerMockito.doNothing().when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ //anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+ PowerMockito.doThrow(new AAIException()).when( RestController.class, "Get", Mockito.anyObject(), anyString(),
+ anyString(), anyString(), Mockito.anyObject(), anyBoolean());
+
+ RestObject<GenericVnf> mockRestObject = PowerMockito.mock(RestObject.class);
+ PowerMockito.whenNew(RestObject.class).withNoArguments().thenReturn(mockRestObject);
+ PowerMockito.doNothing().when( mockRestObject).set(isA(GenericVnf.class));
+ GenericVnf genericVnf = new GenericVnf();
+ genericVnf.setEquipmentRole("VRR");
+ genericVnf.setVnfName("vnfNameValue");
+
+ PowerMockito.when(mockRestObject.get()).thenReturn(genericVnf);
+
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ DbMeth dbMethMock = PowerMockito.mock(DbMeth.class);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+
+ when(dynamicEntityMock.<String>get("updateNodeType")).thenReturn("generic-vnf");
+
+ when(dynamicEntityMock.<String>get("updateNodeUri")).thenReturn("network/generic-vnfs/generic-vnf/vnfId");
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> updateNodeKeyClass = dcl.createDynamicClass(classNameUpdateNodeKey);
+ JPADynamicTypeBuilder updateNodeKey = new JPADynamicTypeBuilder(updateNodeKeyClass, null, "D_UPDATE_NODE_KEY");
+ updateNodeKey.addDirectMapping("keyName", String.class, "KEY_NAME");
+ updateNodeKey.addDirectMapping("keyValue", String.class, "KEY_VALUE");
+ DynamicType type = updateNodeKey.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ ArrayList <DynamicEntity> updateNodeKeyList = new ArrayList<DynamicEntity>();
+
+ LinkedHashMap <String,Object> returnHash = new LinkedHashMap<String,Object>();
+
+ HashMap <String,Object> thisNodeHash = new HashMap <String,Object> ();
+ String nodeKeyName = "generic-vnf.vnf-id";
+ String nodeKeyValue = "vnfId";
+ thisNodeHash.put(nodeKeyName, nodeKeyValue);
+ returnHash.putAll(thisNodeHash);
+
+ HashMap <String,Object> depNodeHash = new HashMap <String,Object> ();
+
+ PowerMockito.mockStatic(RestURL.class);
+ //RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ PowerMockito.when(( RestURL.getKeyHashes(anyString()))).thenReturn(returnHash);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("updateNodeKey")).thenReturn(updateNodeKeyList);
+
+ Class<?> actionDataClass = dcl.createDynamicClass(classNameActionData);
+
+ Class<?> actionClass = dcl.createDynamicClass(classNameAction);
+ JPADynamicTypeBuilder action = new JPADynamicTypeBuilder(actionClass, null, "D_ACTION");
+ action.addDirectMapping("actionType", String.class, "ACTION_TYPE");
+ action.addDirectMapping("actionData", ArrayList.class, "ACTION_DATA");
+
+ type = action.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+
+ JPADynamicTypeBuilder actionData = new JPADynamicTypeBuilder(actionDataClass, action.getType(), "D_ACTION_DATA");
+ actionData.addDirectMapping("propertyName", String.class, "PROPERTY_NAME");
+ actionData.addDirectMapping("propertyValue", String.class, "PROPERTY_VALUE");
+
+ type = actionData.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ ArrayList <DynamicEntity> actionDataList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDataDynamicEntity = dynamicHelper.newDynamicEntity(classNameActionData);
+ actionDataDynamicEntity.set("propertyName", "prov-status");
+ actionDataDynamicEntity.set("propertyValue", "NVTPROV");
+ actionDataList.add(actionDataDynamicEntity);
+
+ ArrayList <DynamicEntity> actionList = new ArrayList<DynamicEntity>();
+
+ DynamicEntity actionDynamicEntity = dynamicHelper.newDynamicEntity(classNameAction);
+ actionDynamicEntity.set("actionType", "replace");
+ actionDynamicEntity.set("actionData", actionDataList);
+
+ actionList.add(actionDynamicEntity);
+
+ when(dynamicEntityMock.<List<DynamicEntity>>get("action")).thenReturn(actionList);
+
+ AAIExtensionMap aaiExtensionMapMock = PowerMockito.mock(AAIExtensionMap.class);
+
+ when(aaiExtensionMapMock.getApiVersion()).thenReturn(defaultApiVersion);
+
+ PowerMockito.when(( DbMeth.figureDepNodeTypeForRequest(anyString(), anyString(), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn("customer");
+
+ PowerMockito.when(( DbMeth.getUniqueNodeWithDepParams(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), anyString()))).thenReturn(vMock);
+
+ PowerMockito.when(( DbMeth.patchAaiNode(anyString(), anyString(), isA(TitanTransaction.class), anyString(),
+ isA(HashMap.class), isA(TitanVertex.class), anyString()))).thenReturn(vMock);
+
+
+ ActionsGraph actionsGraph = new ActionsGraph();
+
+ ActionsGraph actionsGraphSpy = PowerMockito.spy(actionsGraph);
+
+ PowerMockito.doReturn("updateNodeURLValue").when(actionsGraphSpy, "setupUEBEventObject",
+ anyString(), anyString(), Mockito.any(TitanTransaction.class), anyString(),
+ Mockito.any(TitanVertex.class), anyString());
+
+ PowerMockito.doNothing().when(actionsGraphSpy, "triggerInstarEquipStatusUpdate",
+ anyString(), anyString(), anyString());
+
+ actionsGraphSpy.propertyUpdate("fromAppId", "transId", dynamicEntityMock, aaiExtensionMapMock);
+
+
+ assertTrue("return from propertyUpdate", true);
+
+ }
+
+
+
+ /**
+ * Test setup UEB event object.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testSetupUEBEventObject() throws Exception{
+ String classNameNotificationEventHeader = "inventory.aai.openecomp.org." + defaultApiVersion + ".NotificationEventHeader";
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ TitanVertex vMock = PowerMockito.mock(TitanVertex.class);
+
+ GraphHelpersMoxy graphHelpersMoxyMock = PowerMockito.mock(GraphHelpersMoxy.class);
+ PowerMockito.whenNew( GraphHelpersMoxy.class).withNoArguments().thenReturn(graphHelpersMoxyMock);
+
+ PowerMockito.when(graphHelpersMoxyMock.isEventEnabled(anyString(), anyString(), anyString())).thenReturn(true);
+
+ AncestryItems ancestryItemsMock = PowerMockito.mock(AncestryItems.class);
+ PowerMockito.whenNew( AncestryItems.class).withNoArguments().thenReturn(ancestryItemsMock);
+
+ AncestryItem ancestryItem = new AncestryItem();
+ AAIResource aaiResource = new AAIResource();
+ aaiResource.setSimpleName("resourceSimpleNameValue");
+ ancestryItem.setAaiResource(aaiResource);
+ LinkedHashMap<String, AncestryItem> map = new LinkedHashMap<String, AncestryItem>();
+ map.put("key", ancestryItem);
+ when (ancestryItemsMock.getAncestryItems()).thenReturn(map);
+
+
+ PowerMockito.mockStatic(RestURL.class);
+ RestURL restURLMock = PowerMockito.mock(RestURL.class);
+
+ AAIResource aaiResourceMock = PowerMockito.mock(AAIResource.class);
+ //AAIResources aaiResourcesMock = PowerMockito.mock(AAIResources.class);
+
+ DynamicJAXBContext dynamicJAXBContextMock = PowerMockito.mock(DynamicJAXBContext.class);
+
+ AAIResources aaiResourcesMock = IngestModelMoxyOxm.aaiResourceContainer.get(defaultApiVersion);
+ aaiResourcesMock.setJaxbContext(dynamicJAXBContextMock);
+
+ StoreNotificationEvent storeNotificationEventMock = PowerMockito.mock(StoreNotificationEvent.class);
+ PowerMockito.whenNew( StoreNotificationEvent.class).withNoArguments().thenReturn(storeNotificationEventMock);
+
+ PowerMockito.doNothing().when( storeNotificationEventMock).storeDynamicEvent(isA(DynamicJAXBContext.class), anyString(), isA(DynamicEntity.class),
+ isA(DynamicEntity.class));
+
+ Project project = new Project(new DatabaseLogin());
+ DatabaseSession databaseSession = project.createDatabaseSession();
+ DynamicHelper dynamicHelper = new DynamicHelper(databaseSession);
+
+ DynamicClassLoader dcl = dynamicHelper.getDynamicClassLoader();
+
+ Class<?> notificationEventHeaderClass = dcl.createDynamicClass(classNameNotificationEventHeader);
+ JPADynamicTypeBuilder notificationEventHeader = new JPADynamicTypeBuilder(notificationEventHeaderClass, null, "D_NOTIFICATION_EVENT_HEADER");
+ notificationEventHeader.addDirectMapping("entityType", String.class, "ENTITY_TYPE");
+ notificationEventHeader.addDirectMapping("action", String.class, "ACTION");
+ notificationEventHeader.addDirectMapping("sourceName", String.class, "SOURCE_NAME");
+ notificationEventHeader.addDirectMapping("version", String.class, "VERSION");
+ notificationEventHeader.addDirectMapping("entityLink", String.class, "ENTITY_LINK");
+ notificationEventHeader.addDirectMapping("topEntityType", String.class, "TOP_ENTITY_TYPE");
+ DynamicType type = notificationEventHeader.getType();
+ dynamicHelper.addTypes(false, false, type);
+
+ DynamicEntity notificationEventHeaderDynamicEntity = dynamicHelper.newDynamicEntity(classNameNotificationEventHeader);
+
+
+
+ //notificationEventHeaderDynamicEntity.
+ PowerMockito.when(graphHelpersMoxyMock.unpackAncestry(isA(TitanTransaction.class), isA(AncestryItems.class), anyString(),
+ isA(DynamicJAXBContext.class), isA(AAIExtensionMap.class))).thenReturn(notificationEventHeaderDynamicEntity);
+
+ PowerMockito.when(dynamicJAXBContextMock.getDynamicType(anyString())).thenReturn(type);
+
+ PowerMockito.when(( RestURL.get(isA(TitanTransaction.class), isA(TitanVertex.class),
+ anyString(), anyBoolean(), anyBoolean()))).thenReturn("updatedNodeURLValue");
+ PowerMockito.when(( RestURL.parseUri(Mockito.any(HashMap.class), Mockito.any(LinkedHashMap.class), anyString(),
+ any(AAIExtensionMap.class)))).thenReturn(aaiResourceMock);
+ ActionsGraph actionsGraph = new ActionsGraph();
+ String nodeUrl = actionsGraph.setupUEBEventObject("fromAppId", "transId", gMock, "updateNodeType", vMock, defaultApiVersion);
+ assertTrue("returned from setupUEBEvent", true);
+ }
+
+ /**
+ * Test trigger instar equip status update.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void testTriggerInstarEquipStatusUpdate() throws Exception {
+ Client mockClient = mock( Client.class );
+ WebResource mockWebResource = mock( WebResource.class );
+ WebResource.Builder mockBuilder = mock( WebResource.Builder.class );
+ PowerMockito.mockStatic(ClientResponse.class);
+ ClientResponse mockClientResponse = mock( ClientResponse.class );
+ ActionsGraph actionsGraph = new ActionsGraph();
+ PowerMockito.mockStatic(HttpsAuthClient.class);
+ HttpsAuthClient mockHttpsAuthClient = PowerMockito.mock(HttpsAuthClient.class);
+ when(mockHttpsAuthClient.getTwoWaySSLClient()).thenReturn(mockClient);
+
+ when(mockClient.resource(anyString())).thenReturn(mockWebResource);
+ when(mockWebResource.header(anyString(), anyString())).thenReturn(mockBuilder);
+ when(mockBuilder.header(anyString(), anyString())).thenReturn(mockBuilder);
+ when(mockBuilder.accept(anyString())).thenReturn(mockBuilder);
+
+ when(mockBuilder.put(eq(ClientResponse.class))).thenReturn(mockClientResponse);
+ when(mockClientResponse.getStatus()).thenReturn(200, 500);
+ // first call returns success
+ String msg= WhiteboxImpl.invokeMethod(actionsGraph, "triggerInstarEquipStatusUpdate",
+ "fromAppId", "transId", "urlValue");
+ assertTrue("return from triggerInstarEquipStatusUpdate", true);
+ // 2nd call generates exception
+ try {
+ msg= WhiteboxImpl.invokeMethod(actionsGraph, "triggerInstarEquipStatusUpdate",
+ "fromAppId", "transId", "urlValue");
+ fail("Exception expected");
+ } catch ( Exception e ) {
+ assertNotNull(e);
+ }
+ }
+
+}
+
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/dbmap/SearchGraphTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/dbmap/SearchGraphTest.java
new file mode 100644
index 0000000..3a8fc5a
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/dbmap/SearchGraphTest.java
@@ -0,0 +1,739 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.dbmap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+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.Direction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.openecomp.aai.dbgen.DbMeth;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.dbmap.SearchGraph;
+import org.openecomp.aai.domain.model.AAIResources;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.ingestModel.DbMaps;
+import org.openecomp.aai.ingestModel.IngestModelMoxyOxm;
+import org.openecomp.aai.util.RestURL;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanGraphQuery;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({AAIGraph.class, TitanGraph.class, DbMeth.class, IngestModelMoxyOxm.class,
+ AAIResources.class, DynamicJAXBContext.class, DynamicEntity.class, VertexProperty.class,
+ RestURL.class, TitanTransaction.class, TitanVertex.class, SearchGraph.class})
+@PowerMockIgnore("javax.management.*")
+public class SearchGraphTest {
+// @Rule
+// public PowerMockRule rule = new PowerMockRule();
+
+ private String fromAppId = "searchGraphId";
+ private String transId = "transId";
+ private String aaiApiVersion = "v8";
+
+ /**
+ * Test run nodes query.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testRunNodesQuery() throws Exception {
+ String targetNodeType = "vserver";
+ String nodePropsValue = "testNodePropsValue";
+ List<String> edgeFilterParams = new ArrayList<String>();
+ edgeFilterParams.add("pserver:EXISTS:hostname:test-pserver-hostname");
+ List<String> filterParams = new ArrayList<String>();
+ filterParams.add("vserver-name2:EXISTS:");
+ String serverNodeURL = "testServerNodeURL";
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph aaiGraphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(aaiGraphMock);
+ TitanGraph titanGraphMock = PowerMockito.mock(TitanGraph.class);
+ when(aaiGraphMock.getGraph()).thenReturn(titanGraphMock);
+ TitanTransaction titanTransactionMock = PowerMockito.mock(TitanTransaction.class);
+ when(titanGraphMock.newTransaction()).thenReturn(titanTransactionMock);
+
+ HashMap<String, DbMaps> dbMapsContainer = new HashMap<String, DbMaps>();
+ DbMaps dbMaps = new DbMaps();
+ dbMaps.NodeProps = ArrayListMultimap.create();
+ dbMaps.NodeProps.put(targetNodeType, nodePropsValue);
+ dbMapsContainer.put(aaiApiVersion, dbMaps);
+ IngestModelMoxyOxm.dbMapsContainer = dbMapsContainer;
+
+ TitanGraphQuery titanGraphQueryMock = PowerMockito.mock(TitanGraphQuery.class);
+ when(titanTransactionMock.query()).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has("aai-node-type", targetNodeType)).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has("vserver-name2")).thenReturn(titanGraphQueryMock);
+ Iterable<TitanVertex> iterableMock =(Iterable<TitanVertex>) PowerMockito.mock(Iterable.class);
+ when(titanGraphQueryMock.vertices()).thenReturn(iterableMock);
+ Iterator<TitanVertex> iteratorTitanVertexMock = (Iterator<TitanVertex>) PowerMockito.mock(Iterator.class);
+ when(iterableMock.iterator()).thenReturn(iteratorTitanVertexMock);
+ when(iteratorTitanVertexMock.hasNext()).thenReturn(true, false);
+ TitanVertex titanVertexMock = PowerMockito.mock(TitanVertex.class);
+ when(iteratorTitanVertexMock.next()).thenReturn(titanVertexMock);
+
+ Iterator<Vertex> iteratorVertexMock = (Iterator<Vertex>) PowerMockito.mock(Iterator.class);
+ when(titanVertexMock.vertices(Direction.BOTH, "runsOnPserver")).thenReturn(iteratorVertexMock);
+ when(iteratorVertexMock.hasNext()).thenReturn(true, false);
+ when(iteratorVertexMock.next()).thenReturn(titanVertexMock);
+
+ VertexProperty<String> vertexPropertyMock = (VertexProperty<String>)PowerMockito.mock(VertexProperty.class);
+ when(titanVertexMock.<String>property("hostname")).thenReturn(vertexPropertyMock);
+ when(vertexPropertyMock.orElse(null)).thenReturn("test-pserver-hostname");
+ when(vertexPropertyMock.equals("test-pserver-hostname")).thenReturn(true);
+
+ PowerMockito.mockStatic(RestURL.class);
+ when(RestURL.getSearchUrl(Mockito.any(TitanTransaction.class), Mockito.any(TitanVertex.class),
+ Mockito.anyString())).thenReturn(serverNodeURL);
+ when(titanVertexMock.<String>property("aai-node-type")).thenReturn(vertexPropertyMock);
+ when(vertexPropertyMock.orElse(null)).thenReturn("pserver");
+
+ PowerMockito.mockStatic(IngestModelMoxyOxm.class);
+ HashMap<String, AAIResources> aaiResourceContainerMock = new HashMap<String, AAIResources>();
+ AAIResources aaiResourcesMock = PowerMockito.mock(AAIResources.class);
+ aaiResourceContainerMock.put("v8", aaiResourcesMock);
+ IngestModelMoxyOxm.aaiResourceContainer = aaiResourceContainerMock;
+ DynamicJAXBContext dynamicJAXBContextMock = PowerMockito.mock(DynamicJAXBContext.class);
+ when(aaiResourcesMock.getJaxbContext()).thenReturn(dynamicJAXBContextMock);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+ when(dynamicJAXBContextMock.newDynamicEntity(Mockito.anyString())).thenReturn(dynamicEntityMock);
+
+ Response respMock = PowerMockito.mock(Response.class);
+ when(respMock.getStatus()).thenReturn(200);
+
+ SearchGraph searchGraph = new SearchGraph();
+ SearchGraph searchGraphSpy = PowerMockito.spy(searchGraph);
+ PowerMockito.doReturn(respMock).when(searchGraphSpy, "getResponseFromDynamicEntity",
+ Mockito.any(DynamicEntity.class), Mockito.any(DynamicJAXBContext.class),
+ Mockito.any(AAIExtensionMap.class));
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+ Response resp = searchGraphSpy.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ assertEquals(200, resp.getStatus());
+ }
+
+ /**
+ * Test run nodes query exception.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testRunNodesQuery_exception() throws Exception {
+ String targetNodeType = "";
+ String nodePropsValue = "testNodePropsValue";
+ List<String> edgeFilterParams = new ArrayList<String>();
+ edgeFilterParams.add("pserver:EXISTS:hostname:test-pserver-hostname");
+ List<String> filterParams = new ArrayList<String>();
+ filterParams.add("vserver-name2:EXISTS:");
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph aaiGraphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(aaiGraphMock);
+ TitanGraph titanGraphMock = PowerMockito.mock(TitanGraph.class);
+ when(aaiGraphMock.getGraph()).thenReturn(titanGraphMock);
+ TitanTransaction titanTransactionMock = PowerMockito.mock(TitanTransaction.class);
+ when(titanGraphMock.newTransaction()).thenReturn(titanTransactionMock);
+
+ HashMap<String, DbMaps> dbMapsContainer = new HashMap<String, DbMaps>();
+ DbMaps dbMaps = new DbMaps();
+ dbMaps.NodeProps = ArrayListMultimap.create();
+ dbMaps.NodeProps.put(targetNodeType, nodePropsValue);
+ dbMapsContainer.put(aaiApiVersion, dbMaps);
+ IngestModelMoxyOxm.dbMapsContainer = dbMapsContainer;
+
+ SearchGraph searchGraph = new SearchGraph();
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+
+ //targetNodeType is empty
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //dbMaps.NodeProps doesn't contain targetNodeType
+ targetNodeType = "vserver";
+ dbMaps.NodeProps.clear();
+ dbMaps.NodeProps.put("pserver", nodePropsValue);
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //filterParams.isEmpty() && edgeFilterParams.isEmpty()
+ dbMaps.NodeProps.clear();
+ dbMaps.NodeProps.put(targetNodeType, nodePropsValue);
+ edgeFilterParams.clear();
+ filterParams.clear();
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //Exception : bad filter passed to node query
+ filterParams.add("vserver-name2");
+ TitanGraphQuery titanGraphQueryMock = PowerMockito.mock(TitanGraphQuery.class);
+ when(titanTransactionMock.query()).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has("aai-node-type", targetNodeType)).thenReturn(titanGraphQueryMock);
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //Exception - FilterType EQUALS - No value passed for filter
+ filterParams.clear();
+ filterParams.add("vserver-name2:EQUALS");
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //Exception - FilterType DOES-NOT-EQUAL - No value passed for filter
+ filterParams.clear();
+ filterParams.add("vserver-name2:DOES-NOT-EQUAL");
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //Exception - bad filterType passed
+ filterParams.clear();
+ filterParams.add("vserver-name2:NOT-EQUAL");
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ when(titanGraphQueryMock.has("vserver-name2")).thenReturn(titanGraphQueryMock);
+ Iterable<TitanVertex> iterableMock =(Iterable<TitanVertex>) PowerMockito.mock(Iterable.class);
+ when(titanGraphQueryMock.vertices()).thenReturn(iterableMock);
+ Iterator<TitanVertex> iteratorTitanVertexMock = (Iterator<TitanVertex>) PowerMockito.mock(Iterator.class);
+ when(iterableMock.iterator()).thenReturn(iteratorTitanVertexMock);
+
+ //Exception - bad filter passed. pieces.length = 3
+ filterParams.clear();
+ filterParams.add("vserver-name2:EXISTS:");
+ edgeFilterParams.clear();
+ edgeFilterParams.add("pserver:EXISTS:hostname");
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ //Exception - filterType - bad filterType passed
+ edgeFilterParams.clear();
+ edgeFilterParams.add("pserver:NOT-EXIST:hostname:test-pserver-hostname");
+ try {
+ searchGraph.runNodesQuery(fromAppId, transId,
+ targetNodeType, edgeFilterParams, filterParams, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ }
+
+ /**
+ * Test run generic query service instance.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testRunGenericQuery_serviceInstance() throws Exception {
+ String startNodeType = "service-instance";
+ String serviceSubscriptionURL = "testServiceSubscriptionURL";
+ String startNodeKey = "service-instance-id";
+ String startNodeValue = "test-service-instance-id";
+ String startNodeKeyParam = "service-instance." + startNodeKey + ":" + startNodeValue;
+
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ TitanGraphQuery titanGraphQueryMock = PowerMockito.mock(TitanGraphQuery.class);
+ when(gMock.query()).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has(startNodeKey, startNodeValue)).thenReturn(titanGraphQueryMock);
+ Iterable<TitanVertex> iterableMock =(Iterable<TitanVertex>) PowerMockito.mock(Iterable.class);
+ when(titanGraphQueryMock.vertices()).thenReturn(iterableMock);
+ Iterator<TitanVertex> iteratorMock = (Iterator<TitanVertex>) PowerMockito.mock(Iterator.class);
+ when(iterableMock.iterator()).thenReturn(iteratorMock);
+ when(iteratorMock.hasNext()).thenReturn(true, false);
+
+ TitanVertex titanVertexMock = PowerMockito.mock(TitanVertex.class);
+ when(iteratorMock.next()).thenReturn(titanVertexMock);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ VertexProperty<String> vertexPropertyMock = (VertexProperty<String>)PowerMockito.mock(VertexProperty.class);
+ when(titanVertexMock.<String>property("aai-node-type")).thenReturn(vertexPropertyMock);
+ when(vertexPropertyMock.orElse(null)).thenReturn(startNodeType);
+
+ when(DbMeth.getUniqueNodeWithDepParams(Mockito.anyString(), Mockito.anyString(),
+ Mockito.any(TitanTransaction.class), Mockito.anyString(), (HashMap<String, Object>)
+ Mockito.anyMapOf(String.class, Object.class), Mockito.anyString())).thenReturn(titanVertexMock);
+
+ PowerMockito.mockStatic(IngestModelMoxyOxm.class);
+ HashMap<String, AAIResources> aaiResourceContainerMock = new HashMap<String, AAIResources>();
+ AAIResources aaiResourcesMock = PowerMockito.mock(AAIResources.class);
+ aaiResourceContainerMock.put("v8", aaiResourcesMock);
+ IngestModelMoxyOxm.aaiResourceContainer = aaiResourceContainerMock;
+ DynamicJAXBContext dynamicJAXBContextMock = PowerMockito.mock(DynamicJAXBContext.class);
+ when(aaiResourcesMock.getJaxbContext()).thenReturn(dynamicJAXBContextMock);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+ when(dynamicJAXBContextMock.newDynamicEntity(Mockito.anyString())).thenReturn(dynamicEntityMock);
+
+ PowerMockito.mockStatic(RestURL.class);
+ when(RestURL.getSearchUrl(Mockito.any(TitanTransaction.class), Mockito.any(TitanVertex.class),
+ Mockito.anyString())).thenReturn(serviceSubscriptionURL);
+
+ Response respMock = PowerMockito.mock(Response.class);
+ when(respMock.getStatus()).thenReturn(200);
+
+ SearchGraph searchGraph = new SearchGraph();
+ SearchGraph searchGraphSpy = PowerMockito.spy(searchGraph);
+ PowerMockito.doReturn(respMock).when(searchGraphSpy, "getResponseFromDynamicEntity", Mockito.any(DynamicEntity.class),
+ Mockito.any(DynamicJAXBContext.class), Mockito.any(AAIExtensionMap.class));
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add(startNodeKeyParam);
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("generic-vnf");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+ Response resp = searchGraphSpy.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ assertEquals(200, resp.getStatus());
+ }
+
+ /**
+ * Test run generic query service instance depth 1 vertex is empty.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testRunGenericQuery_serviceInstance_depth1_vertexIsEmpty() throws Exception {
+ String startNodeType = "service-instance";
+ String startNodeKey = "service-instance-id";
+ String startNodeValue = "test-service-instance-id";
+ String startNodeKeyParam = "service-instance." + startNodeKey + ":" + startNodeValue;
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ TitanGraphQuery titanGraphQueryMock = PowerMockito.mock(TitanGraphQuery.class);
+ when(gMock.query()).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has(startNodeKey, startNodeValue)).thenReturn(titanGraphQueryMock);
+ Iterable<TitanVertex> iterableMock =(Iterable<TitanVertex>) PowerMockito.mock(Iterable.class);
+ when(titanGraphQueryMock.vertices()).thenReturn(iterableMock);
+ Iterator<TitanVertex> iteratorMock = (Iterator<TitanVertex>) PowerMockito.mock(Iterator.class);
+ when(iterableMock.iterator()).thenReturn(iteratorMock);
+ when(iteratorMock.hasNext()).thenReturn(true, false);
+
+ TitanVertex titanVertexMock = PowerMockito.mock(TitanVertex.class);
+ when(iteratorMock.next()).thenReturn(titanVertexMock);
+ GraphTraversalSource graphTraversalSourceMock = PowerMockito.mock(GraphTraversalSource.class);
+ when(titanVertexMock.graph()).thenReturn(gMock);
+ when(gMock.traversal()).thenReturn(graphTraversalSourceMock);
+
+ GraphTraversal graphTraversalMock = PowerMockito.mock(GraphTraversal.class);
+ when(graphTraversalSourceMock.V(titanVertexMock)).thenReturn(graphTraversalMock);
+ when(graphTraversalMock.repeat(Mockito.any(Traversal.class))).thenReturn(graphTraversalMock);
+ when(graphTraversalMock.times(1)).thenReturn(graphTraversalMock);
+
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ SearchGraph searchGraph = new SearchGraph();
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add(startNodeKeyParam);
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("l-interface");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+ Response resp = searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 1, aaiExtMap);
+ assertNull(resp);
+ }
+
+ /**
+ * Test run generic query service instance 6112 exception.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testRunGenericQuery_serviceInstance_6112Exception() throws Exception {
+ String startNodeType = "service-instance";
+ String startNodeKey = "service-instance-id";
+ String startNodeValue = "test-service-instance-id";
+ String startNodeKeyParam = "service-instance." + startNodeKey + ":" + startNodeValue;
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ TitanGraphQuery titanGraphQueryMock = PowerMockito.mock(TitanGraphQuery.class);
+ when(gMock.query()).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has(startNodeKey, startNodeValue)).thenReturn(titanGraphQueryMock);
+ Iterable<TitanVertex> iterableMock =(Iterable<TitanVertex>) PowerMockito.mock(Iterable.class);
+ when(titanGraphQueryMock.vertices()).thenReturn(iterableMock);
+ Iterator<TitanVertex> iteratorMock = (Iterator<TitanVertex>) PowerMockito.mock(Iterator.class);
+ when(iterableMock.iterator()).thenReturn(iteratorMock);
+ when(iteratorMock.hasNext()).thenReturn(true);
+
+ TitanVertex titanVertexMock = PowerMockito.mock(TitanVertex.class);
+ when(iteratorMock.next()).thenReturn(titanVertexMock);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ SearchGraph searchGraph = new SearchGraph();
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add(startNodeKeyParam);
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("generic-vnf");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expectd.");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ }
+
+ /**
+ * Test run generic query service instance 6114 exception.
+ *
+ * @throws Exception the exception
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testRunGenericQuery_serviceInstance_6114Exception() throws Exception {
+ String startNodeType = "service-instance";
+ String startNodeKey = "service-instance-id";
+ String startNodeValue = "test-service-instance-id";
+ String startNodeKeyParam = "service-instance." + startNodeKey + ":" + startNodeValue;
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ TitanGraphQuery titanGraphQueryMock = PowerMockito.mock(TitanGraphQuery.class);
+ when(gMock.query()).thenReturn(titanGraphQueryMock);
+ when(titanGraphQueryMock.has(startNodeKey, startNodeValue)).thenReturn(titanGraphQueryMock);
+ Iterable<TitanVertex> iterableMock =(Iterable<TitanVertex>) PowerMockito.mock(Iterable.class);
+ when(titanGraphQueryMock.vertices()).thenReturn(iterableMock);
+ Iterator<TitanVertex> iteratorMock = (Iterator<TitanVertex>) PowerMockito.mock(Iterator.class);
+ when(iterableMock.iterator()).thenReturn(iteratorMock);
+ when(tMock.newTransaction()).thenReturn(gMock);
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ SearchGraph searchGraph = new SearchGraph();
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add(startNodeKeyParam);
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("generic-vnf");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ }
+
+ /**
+ * Test run generic query service subscription.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testRunGenericQuery_serviceSubscription() throws Exception {
+ String startNodeType = "service-subscription";
+ String serviceSubscriptionURL = "testServiceSubscriptionURL";
+
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-subscription.service-type:test-service-type");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("service-instance");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+
+ PowerMockito.mockStatic(TitanGraph.class);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ TitanVertex titanVertexMock = PowerMockito.mock(TitanVertex.class);
+ @SuppressWarnings("unchecked")
+ VertexProperty<String> vertexPropertyMock = (VertexProperty<String>)PowerMockito.mock(VertexProperty.class);
+ when(titanVertexMock.<String>property("aai-node-type")).thenReturn(vertexPropertyMock);
+ when(vertexPropertyMock.orElse(null)).thenReturn(startNodeType);
+
+ when(DbMeth.getUniqueNodeWithDepParams(Mockito.anyString(), Mockito.anyString(),
+ Mockito.any(TitanTransaction.class), Mockito.anyString(), (HashMap<String, Object>)
+ Mockito.anyMapOf(String.class, Object.class), Mockito.anyString())).thenReturn(titanVertexMock);
+
+ PowerMockito.mockStatic(IngestModelMoxyOxm.class);
+ HashMap<String, AAIResources> aaiResourceContainerMock = new HashMap<String, AAIResources>();
+ AAIResources aaiResourcesMock = PowerMockito.mock(AAIResources.class);
+ aaiResourceContainerMock.put("v8", aaiResourcesMock);
+ IngestModelMoxyOxm.aaiResourceContainer = aaiResourceContainerMock;
+ DynamicJAXBContext dynamicJAXBContextMock = PowerMockito.mock(DynamicJAXBContext.class);
+ when(aaiResourcesMock.getJaxbContext()).thenReturn(dynamicJAXBContextMock);
+
+ DynamicEntity dynamicEntityMock = PowerMockito.mock(DynamicEntity.class);
+ when(dynamicJAXBContextMock.newDynamicEntity(Mockito.anyString())).thenReturn(dynamicEntityMock);
+
+ PowerMockito.mockStatic(RestURL.class);
+ when(RestURL.getSearchUrl(Mockito.any(TitanTransaction.class), Mockito.any(TitanVertex.class),
+ Mockito.anyString())).thenReturn(serviceSubscriptionURL);
+
+// SearchGraph searchGraphMock = PowerMockito.mock(SearchGraph.class);
+ Response respMock = PowerMockito.mock(Response.class);
+ when(respMock.getStatus()).thenReturn(200);
+// PowerMockito.when(SearchGraph.class, "getResponseFromDynamicEntity", Mockito.any(DynamicEntity.class),
+// Mockito.any(DynamicJAXBContext.class), Mockito.any(AAIExtensionMap.class)).thenReturn(respMock);
+ SearchGraph searchGraph = new SearchGraph();
+ SearchGraph searchGraphSpy = PowerMockito.spy(searchGraph);
+ PowerMockito.doReturn(respMock).when(searchGraphSpy, "getResponseFromDynamicEntity", Mockito.any(DynamicEntity.class),
+ Mockito.any(DynamicJAXBContext.class), Mockito.any(AAIExtensionMap.class));
+
+ Response resp = searchGraphSpy.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ assertEquals(200, resp.getStatus());
+ }
+
+ /**
+ * Test run generic query start node not found exception.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testRunGenericQuery_startNodeNotFoundException() throws Exception {
+ String startNodeType = "testStartNodeType";
+
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ when(graphMock.getGraph()).thenReturn(tMock);
+
+ PowerMockito.mockStatic(DbMeth.class);
+ TitanVertex titanVertexMock = PowerMockito.mock(TitanVertex.class);
+ @SuppressWarnings("unchecked")
+ VertexProperty<String> vertexPropertyMock = (VertexProperty<String>)PowerMockito.mock(VertexProperty.class);
+ when(titanVertexMock.<String>property("aai-node-type")).thenReturn(vertexPropertyMock);
+ when(vertexPropertyMock.orElse(null)).thenReturn(startNodeType);
+ when(DbMeth.getUniqueNodeWithDepParams(Mockito.anyString(), Mockito.anyString(),
+ Mockito.any(TitanTransaction.class), Mockito.anyString(), (HashMap<String, Object>)
+ Mockito.anyMapOf(String.class, Object.class), Mockito.anyString())).thenReturn(null);
+
+ Response respMock = PowerMockito.mock(Response.class);
+ when(respMock.getStatus()).thenReturn(200);
+ SearchGraph searchGraph = new SearchGraph();
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-subscription.service-type:test-service-type");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("service-instance");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ aaiExtMap.setApiVersion(aaiApiVersion);
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ }
+
+ /**
+ * Test run generic query exception.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testRunGenericQuery_exception() throws Exception {
+ String startNodeType = "testStartNodeType";
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ when(graphMock.getGraph()).thenReturn(tMock);
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+ SearchGraph searchGraph = new SearchGraph();
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-subscription.service-type:test-service-type");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("service-instance");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ }
+
+ /**
+ * Test run generic query request error.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testRunGenericQuery_requestError() throws Exception {
+ PowerMockito.mockStatic(AAIGraph.class);
+ AAIGraph graphMock = PowerMockito.mock(AAIGraph.class);
+ when(AAIGraph.getInstance()).thenReturn(graphMock);
+ TitanGraph tMock = PowerMockito.mock(TitanGraph.class);
+ when(graphMock.getGraph()).thenReturn(tMock);
+ TitanTransaction gMock = PowerMockito.mock(TitanTransaction.class);
+ when(tMock.newTransaction()).thenReturn(gMock);
+
+ SearchGraph searchGraph = new SearchGraph();
+ String startNodeType = null;
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-subscription.service-type:test-service-type");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("service-instance");
+ AAIExtensionMap aaiExtMap = new AAIExtensionMap();
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ startNodeType = "testStartNodeType";
+ startNodeKeyParams = null;
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-subscription.service-type:test-service-type");
+ includeNodeTypes = null;
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+
+ includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("service-instance");
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 7, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ startNodeKeyParams.add("service-subscription.service-type");
+ try {
+ searchGraph.runGenericQuery(fromAppId, transId, startNodeType, startNodeKeyParams, includeNodeTypes, 0, aaiExtMap);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertNotNull(e);
+ }
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionTest.java
new file mode 100644
index 0000000..e0253d4
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionTest.java
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.exceptions;
+
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.containsString;
+
+import static org.junit.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.logging.ErrorObject;
+
+public class AAIExceptionTest {
+ private static final String code = "4004";
+ private static final String details = "This is a detailed description of the exception.";
+ private static final Throwable cause = new RuntimeException("This is a runtime exception.");
+ private static final Throwable noMessage = new RuntimeException();
+
+ /**
+ * Test constructor with 0 params.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith0Params() throws Exception {
+ AAIException exception = new AAIException();
+ assertEquals(exception, exception);
+ }
+
+ /**
+ * Test constructor with 1 params.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith1Params() throws Exception {
+ AAIException exception = new AAIException(code);
+ assertEquals(exception, exception);
+ }
+
+ /**
+ * Test constructor with 2 params details.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith2ParamsDetails() throws Exception {
+ AAIException exception = new AAIException(code, details);
+ assertEquals(details, exception.getErrorObject().getDetails());
+ }
+
+ /**
+ * Test constructor with 2 params cause.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith2ParamsCause() throws Exception {
+ AAIException exception = new AAIException(code, cause);
+ assertEquals(cause.getMessage(), exception.getErrorObject().getDetails());
+ }
+
+ /**
+ * Test constructor with 2 params null message.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith2ParamsNullMessage() throws Exception {
+ AAIException exception = new AAIException(code, noMessage);
+ assertEquals(noMessage.toString(), exception.getErrorObject().getDetails());
+ }
+
+ /**
+ * Test constructor with 3 params.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith3Params() throws Exception {
+ AAIException exception = new AAIException(code, cause, details);
+ String details = "This is a runtime exception.-This is a detailed description of the exception.";
+ assertEquals(details, exception.getErrorObject().getDetails());
+ }
+
+ /**
+ * Gets the error object test.
+ *
+ * @return the error object test
+ */
+ @Test
+ public void getErrorObjectTest() {
+ AAIException exception = new AAIException();
+ assertEquals(ErrorObject.DefaultErrorObject, exception.getErrorObject());
+ }
+
+ /**
+ * Test constructor with 3 params null message.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith3ParamsNullMessage() throws Exception {
+ AAIException exception = new AAIException(code, noMessage, details);
+ String detailString = new String(noMessage.toString() + "-" + details);
+ assertEquals(detailString, exception.getErrorObject().getDetails());
+ }
+
+ /**
+ * Gets the stack top test.
+ *
+ * @return the stack top test
+ * @throws Exception the exception
+ */
+ @Test
+ public void getStackTopTest() throws Exception {
+ AAIException exception = new AAIException(code, cause);
+ String classname = "org.openecomp.aai.exceptions.AAIExceptionTest";
+ String methodName = "<clinit>";
+ String stackTop = exception.getStackTop();
+ assertThat(stackTop, containsString(classname.trim()));
+ assertThat(stackTop, containsString(methodName.trim()));
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionWithInfoTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionWithInfoTest.java
new file mode 100644
index 0000000..1b2e36d
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/exceptions/AAIExceptionWithInfoTest.java
@@ -0,0 +1,150 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.exceptions;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIExceptionWithInfo;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+public class AAIExceptionWithInfoTest {
+
+
+ private static final HashMap<String, Object> map = new HashMap<String, Object>();
+
+ {
+ map.put("itemInteger", 1);
+ map.put("itemString", "Two");
+ map.put("itemThree", Boolean.TRUE);
+ }
+
+ private static final String info = "An error has occurred.";
+ private static final String code = "4004";
+ private static final String details = "This is a detailed description of the exception.";
+ private static final Throwable cause = new RuntimeException("This is a runtime exception.");
+
+ /**
+ * Test constructor with 2 params.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith2Params() throws Exception {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(map, info);
+
+ assertEquals(map, exception.getInfoHash());
+ assertEquals(info, exception.getInfo());
+ }
+
+ /**
+ * Test constructor with 3 params.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith3Params() throws Exception {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(code, map, info);
+
+ assertEquals(code, exception.getErrorObject().getErrorCode());
+ assertEquals(map, exception.getInfoHash());
+ assertEquals(info, exception.getInfo());
+ }
+
+ /**
+ * Test constructor with 4 params I.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith4ParamsI() throws Exception {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(code, details, map, info);
+
+ assertEquals(code, exception.getErrorObject().getErrorCode());
+ assertEquals(details, exception.getErrorObject().getDetails());
+ assertEquals(map, exception.getInfoHash());
+ assertEquals(info, exception.getInfo());
+ }
+
+ /**
+ * Test constructor with 4 params II.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith4ParamsII() throws Exception {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(code, cause, map, info);
+
+ assertEquals(code, exception.getErrorObject().getErrorCode());
+ assertEquals(cause.getMessage(), exception.getErrorObject().getDetails());
+ assertEquals(map, exception.getInfoHash());
+ assertEquals(info, exception.getInfo());
+ }
+
+ /**
+ * Test constructor with 5 params.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testConstructorWith5Params() throws Exception {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(code, cause, details, map, info);
+
+ assertEquals(code, exception.getErrorObject().getErrorCode());
+ assertEquals(cause.getMessage() + "-" + details, exception.getErrorObject().getDetails());
+ assertEquals(map, exception.getInfoHash());
+ assertEquals(info, exception.getInfo());
+ }
+
+ /**
+ * Test set info hash.
+ */
+ @Test
+ public void testSetInfoHash() {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(map, info);
+
+ HashMap<String, Object> newMap = new HashMap<String, Object>();
+ newMap.put("itemInteger", 2);
+ exception.setInfoHash(newMap);
+
+ assertEquals(newMap, exception.getInfoHash());
+ assertEquals(info, exception.getInfo());
+ }
+
+ /**
+ * Test set info.
+ */
+ @Test
+ public void testSetInfo() {
+ AAIExceptionWithInfo exception = new AAIExceptionWithInfo(map, info);
+
+ String newInfo = "This is updated info.";
+ exception.setInfo(newInfo);
+
+ assertEquals(map, exception.getInfoHash());
+ assertEquals(newInfo, exception.getInfo());
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GraphTraversalTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GraphTraversalTest.java
new file mode 100644
index 0000000..3046848
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GraphTraversalTest.java
@@ -0,0 +1,360 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class GraphTraversalTest {
+
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST")),
+ false);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ /**
+ * Parent query.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void parentQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("physical-location-id", "key1").has("aai-node-type", "complex");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal to normal query",
+ expected.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be complex",
+ "complex",
+ query.getResultType());
+ assertEquals(
+ "result type should be empty",
+ "",
+ query.getParentResultType());
+ assertEquals("dependent",false, query.isDependent());
+
+
+ }
+
+
+ /**
+ * Gets the item affected by default cloud region.
+ *
+ * @return the item affected by default cloud region
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void getItemAffectedByDefaultCloudRegion() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start()
+ .has("cloud-owner", "CR").has("cloud-region-id", "AAI25")
+ .has("aai-node-type", "cloud-region")
+ .out("has")
+ .has("tenant-id", "key1")
+ .out("owns")
+ .has("vserver-id", "key2")
+ .out("hasLInterface")
+ .has("interface-name", "key3");
+ GraphTraversal<Vertex, Vertex> expectedParent = __.<Vertex>start()
+ .has("cloud-owner", "CR").has("cloud-region-id", "AAI25")
+ .has("aai-node-type", "cloud-region")
+ .out("has")
+ .has("tenant-id", "key1")
+ .out("owns")
+ .has("vserver-id", "key2");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for vserver",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be vserver",
+ "vserver",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be l-interface",
+ "l-interface",
+ query.getResultType());
+ assertEquals(
+ "container type should be empty",
+ "",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+
+ /**
+ * Gets the via query param.
+ *
+ * @return the via query param
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void getViaQueryParam() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/tenants/tenant").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("tenant-name", "Tenant1");
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map);
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start()
+ .has("cloud-owner", "CR").has("cloud-region-id", "AAI25")
+ .has("aai-node-type", "cloud-region")
+ .out("has")
+ .has("tenant-name", "Tenant1");
+
+ GraphTraversal<Vertex, Vertex> expectedParent = __.<Vertex>start()
+ .has("cloud-owner", "CR").has("cloud-region-id", "AAI25")
+ .has("aai-node-type", "cloud-region");
+
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for cloud-region",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be cloud-region",
+ "cloud-region",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be tenant",
+ "tenant",
+ query.getResultType());
+ assertEquals(
+ "container type should be empty",
+ "",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+
+ /**
+ * Gets the plural via query param.
+ *
+ * @return the plural via query param
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void getPluralViaQueryParam() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vnfcs").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("prov-status", "up");
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map);
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start()
+ .has("aai-node-type", "vnfc")
+ .has("prov-status", "up");
+
+ GraphTraversal<Vertex, Vertex> expectedParent = __.<Vertex>start()
+ .has("aai-node-type", "vnfc");
+
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "parent result type should be empty",
+ "",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be vnfc",
+ "vnfc",
+ query.getResultType());
+ assertEquals(
+ "container type should be empty",
+ "vnfcs",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+
+ /**
+ * Gets the all query param naming exception.
+ *
+ * @return the all query param naming exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void getAllQueryParamNamingException() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("cvlan-tag", "333");
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map);
+
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2").out("hasCTag")
+ .has("aai-node-type", "cvlan-tag")
+ .has("cvlan-tag", 333);
+ GraphTraversal<Vertex, Vertex> expectedParent = __.<Vertex>start()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be port-group",
+ "port-group",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "container type should be cvlan-tags",
+ "cvlan-tags",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+ /**
+ * Abstract type.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void abstractType() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("vnf/key1").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start()
+ .has("vnf-id", "key1").or(
+ __.has(AAIProperties.NODE_TYPE, "vce"),
+ __.has(AAIProperties.NODE_TYPE, "vpe"),
+ __.has(AAIProperties.NODE_TYPE, "generic-vnf"));
+
+ GraphTraversal<Vertex, Vertex> expectedParent = expected;
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be empty",
+ "",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be vnf",
+ "vnf",
+ query.getResultType());
+
+ assertEquals("dependent",false, query.isDependent());
+
+
+ }
+
+ /**
+ * Non parent abstract type.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void nonParentAbstractType() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key2/vnf/key1").build();
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+
+
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GremlinPipelineTraversalTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GremlinPipelineTraversalTest.java
new file mode 100644
index 0000000..8528fa0
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/GremlinPipelineTraversalTest.java
@@ -0,0 +1,408 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+/*package org.openecomp.aai.parsers.query;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.openecomp.aai.db.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+import com.tinkerpop.gremlin.java.GremlinPipeline;
+import com.tinkerpop.pipes.IdentityPipe;
+
+public class GremlinPipelineTraversalTest {
+
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLINPIPELINE_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v7, new LogLineBuilder("TEST", "TEST")),
+ false);
+
+ private TransactionalGraphEngine dbEnginev6 =
+ new TitanDBEngine(QueryStyle.GREMLINPIPELINE_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v6, new LogLineBuilder("TEST", "TEST")),
+ false);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ @Test
+ public void parentQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V().has("physical-location-id", "key1").has("aai-node-type", "complex");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal to normal query",
+ expected.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be complex",
+ "complex",
+ query.getResultType());
+ assertEquals(
+ "result type should be empty",
+ "",
+ query.getParentResultType());
+ assertEquals("dependent",false, query.isDependent());
+
+
+ }
+
+ @Test
+ public void childQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1/ctag-pools/ctag-pool/key2/key3").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("physical-location-id", "key1").has("aai-node-type", "complex")
+ .out("hasCtagPool")
+ .has("target-pe", "key2").has("availability-zone-name", "key3");
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("physical-location-id", "key1").has("aai-node-type", "complex");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for complex",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be complex",
+ "complex",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be ctag-pool",
+ "ctag-pool",
+ query.getResultType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+ @Test
+ public void namingExceptions() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2").out("hasCTag")
+ .has("cvlan-tag", 655);
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "result type should be port-group",
+ "port-group",
+ query.getParentResultType());
+ assertEquals(
+ "contaner type should be empty",
+ "",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+ @Test
+ public void getAll() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2").out("hasCTag")
+ .has("aai-node-type", "cvlan-tag");
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be port-group",
+ "port-group",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "container type should be cvlan-tags",
+ "cvlan-tags",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+
+ @Test
+ public void getViaQueryParam() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/tenants/tenant").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+
+ .has("tenant-name", "Tenant1");
+
+ .has("tenant-name", "Tenant2");
+
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("cloud-owner", "CR").has("aai-node-type", "cloud-region")
+ .has("cloud-region-id", "AAI25");
+
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for cloud-region",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be cloud-region",
+ "cloud-region",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be tenant",
+ "tenant",
+ query.getResultType());
+ assertEquals(
+ "container type should be empty",
+ "",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+
+ @Test
+ public void getPluralViaQueryParam() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vnfcs").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("prov-status", "up");
+ QueryParser query = dbEnginev6.getQueryBuilder().createQueryFromURI(uri, map);
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("aai-node-type", "vnfc")
+ .has("prov-status", "up");
+
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("aai-node-type", "vnfc");
+
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "parent result type should be empty",
+ "",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be vnfc",
+ "vnfc",
+ query.getResultType());
+ assertEquals(
+ "container type should be empty",
+ "vnfcs",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+
+ @Test
+ public void getAllQueryParamNamingException() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("cvlan-tag", "333");
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map);
+
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2").out("hasCTag")
+ .has("aai-node-type", "cvlan-tag")
+ .has("cvlan-tag", 333);
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").has("aai-node-type", "vce")
+ .out("hasPortGroup")
+ .has("interface-id", "key2");
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be port-group",
+ "port-group",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "container type should be cvlan-tags",
+ "cvlan-tags",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+ @Test
+ public void abstractType() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("vnf/key1").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").or(
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "vce"),
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "vpe"),
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "generic-vnf"));
+
+ GremlinPipeline expectedParent = expected;
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be empty",
+ "",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be vnf",
+ "vnf",
+ query.getResultType());
+
+ assertEquals("dependent",false, query.isDependent());
+
+
+ }
+
+ @Test
+ public void nonParentAbstractType() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key2/vnf/key1").build();
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+
+
+ }
+
+ @Test
+ public void parentAbstractTypeWithNesting() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("vnf/key1/vf-modules/vf-module/key2").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ GremlinPipeline expected = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").or(
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "vce"),
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "vpe"),
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "generic-vnf"))
+ .outE().has("isParent", true).inV().has("vf-module-id", "key2");
+ GremlinPipeline expectedParent = new GremlinPipeline(new IdentityPipe()).V()
+ .has("vnf-id", "key1").or(
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "vce"),
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "vpe"),
+ new GremlinPipeline(new IdentityPipe()).has(AAIProperties.NODE_TYPE, "generic-vnf"));
+ assertEquals(
+ "gremlin query should be " + expected.toString(),
+ expected.toString(),
+ query.getQueryBuilder().getQuery().toString());
+ assertEquals(
+ "parent gremlin query should be equal the query for ",
+ expectedParent.toString(),
+ query.getQueryBuilder().getParentQuery().toString());
+ assertEquals(
+ "result type should be vnf",
+ "vnf",
+ query.getParentResultType());
+ assertEquals(
+ "result type should be vf-module",
+ "vf-module",
+ query.getResultType());
+
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+}
+*/
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyGremlinQueryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyGremlinQueryTest.java
new file mode 100644
index 0000000..3fc6801
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyGremlinQueryTest.java
@@ -0,0 +1,252 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+/*package org.openecomp.aai.parsers.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class LegacyGremlinQueryTest {
+
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLIN_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v7, new LogLineBuilder("TEST", "TEST")),
+ false);
+
+ private TransactionalGraphEngine dbEnginev6 =
+ new TitanDBEngine(QueryStyle.GREMLIN_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v6, new LogLineBuilder("TEST", "TEST")),
+ false);
+
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ @Test
+ public void parentQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ String expected = ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal to normal query",
+ expected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be complex",
+ "complex",
+ query.getResultType());
+ assertEquals("dependent",false, query.isDependent());
+
+
+ }
+
+ @Test
+ public void childQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1/ctag-pools/ctag-pool/key2/key3").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String expected =
+ ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')"
+ + ".out('hasCtagPool')"
+ + ".has('target-pe', 'key2').has('availability-zone-name', 'key3')";
+ String expectedParent =
+ ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for complex",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be ctag-pool",
+ "ctag-pool",
+ query.getResultType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+ @Test
+ public void namingExceptions() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2').out('hasCTag')"
+ + ".has('cvlan-tag', 655)";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "contaner type should be empty",
+ "",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+ @Test
+ public void getAll() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2').out('hasCTag')"
+ + ".has('aai-node-type', 'cvlan-tag')";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "container type should be cvlan-tags",
+ "cvlan-tags",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+
+ }
+
+
+ @Test
+ public void getPluralViaQueryParam() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vnfcs").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("prov-status", "up");
+ QueryParser query = dbEnginev6.getQueryBuilder().createQueryFromURI(uri, map);
+ String expected =
+ ".has('aai-node-type', 'vnfc')"
+ + ".has('prov-status', 'up')";
+
+ String expectedParent =
+ ".has('aai-node-type', 'vnfc')";
+
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be vnfc",
+ "vnfc",
+ query.getResultType());
+ assertEquals(
+ "container type should be empty",
+ "vnfcs",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+
+ @Test
+ public void getAllQueryParamNamingException() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags").build();
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.putSingle("cvlan-tag", "333");
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri, map);
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2').out('hasCTag')"
+ + ".has('aai-node-type', 'cvlan-tag')"
+ + ".has('cvlan-tag', 333)";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+ assertEquals(
+ "container type should be cvlan-tags",
+ "cvlan-tags",
+ query.getContainerType());
+ assertEquals("dependent",true, query.isDependent());
+
+ }
+}
+*/
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyQueryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyQueryTest.java
new file mode 100644
index 0000000..3173cd0
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/LegacyQueryTest.java
@@ -0,0 +1,168 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.xml.bind.JAXBException;
+
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class LegacyQueryTest {
+ private ModelInjestor injestor = ModelInjestor.getInstance();
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLIN_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST")),
+ false);
+ private final Version version = Version.v8;
+ private DynamicJAXBContext context = injestor.getContextForVersion(version);
+
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ /**
+ * Parent query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void parentQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key1").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ String expected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal to normal query",
+ expected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be pserver",
+ "pserver",
+ query.getResultType());
+
+ }
+
+ /**
+ * Child query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void childQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/pservers/pserver/key1/lag-interfaces/lag-interface/key2").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ String expected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')"
+ + ".out('hasLAGInterface')"
+ + ".has('interface-name', 'key2')";
+ String parentExpected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')";
+ assertEquals(
+ "gremlin query should be for node",
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be for parent",
+ parentExpected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be lag-interface",
+ "lag-interface",
+ query.getResultType());
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws JAXBException, UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build();
+
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')"
+ + ".out('hasCTag')"
+ + ".has('cvlan-tag', 655)";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipGremlinQueryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipGremlinQueryTest.java
new file mode 100644
index 0000000..8533040
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipGremlinQueryTest.java
@@ -0,0 +1,649 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+
+public class RelationshipGremlinQueryTest {
+
+ private ModelInjestor injestor = ModelInjestor.getInstance();
+ private LogLineBuilder llBuilder = new LogLineBuilder("TEST", "TEST");
+
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLIN_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, llBuilder),
+ false);
+ private final Version version = Version.v8;
+ private DynamicJAXBContext context = injestor.getContextForVersion(version);
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+
+ /**
+ * Parent query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void parentQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+
+ String content =
+ "{"
+ + "\"related-to\" : \"pserver\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"pserver.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal to normal query",
+ expected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be pserver",
+ "pserver",
+ query.getResultType());
+
+ }
+
+ /**
+ * Child query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void childQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"lag-interface\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"pserver.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected = ".has('hostname', 'key1').has('aai-node-type', 'pserver').out('hasLAGInterface')"
+ + ".has('interface-name', 'key2')";
+ String parentExpected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')";
+ assertEquals(
+ "gremlin query should be for node",
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be for parent",
+ parentExpected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be lag-interface",
+ "lag-interface",
+ query.getResultType());
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String uri = "/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655";
+ String content =
+ "{"
+ + "\"related-to\" : \"cvlan-tag\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"vce.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"port-group.interface-id\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"cvlan-tag.cvlan-tag\","
+ + "\"relationship-value\" : \"655\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2').out('hasCTag')"
+ + ".has('cvlan-tag', 655)";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+
+ }
+
+ /**
+ * Scrambled relationship.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void scrambledRelationship() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"l3-interface-ipv4-address-list\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"l3-interface-ipv4-address-list.l3-interface-ipv4-address\","
+ + "\"relationship-value\" : \"key5\""
+ + "},{"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"l-interface.interface-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "},{"
+ + "\"relationship-key\" : \"vlan.vlan-interface\","
+ + "\"relationship-value\" : \"key4\""
+ + "},{"
+ + "\"relationship-key\" : \"generic-vnf.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "}]"
+ + "}";
+ scrambledRelationshipSpec(content);
+ }
+
+ /**
+ * Reversed relationship.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void reversedRelationship() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"l3-interface-ipv4-address-list\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"l3-interface-ipv4-address-list.l3-interface-ipv4-address\","
+ + "\"relationship-value\" : \"key5\""
+ + "},{"
+ + "\"relationship-key\" : \"vlan.vlan-interface\","
+ + "\"relationship-value\" : \"key4\""
+ + "},{"
+ + "\"relationship-key\" : \"l-interface.interface-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "},{"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"generic-vnf.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "}]"
+ + "}";
+ scrambledRelationshipSpec(content);
+ }
+
+ /**
+ * Ordered ambiguous relationship.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void orderedAmbiguousRelationship() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"l3-interface-ipv4-address-list\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"generic-vnf.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "},{"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"l-interface.interface-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "},{"
+ + "\"relationship-key\" : \"vlan.vlan-interface\","
+ + "\"relationship-value\" : \"key4\""
+ + "},{"
+ + "\"relationship-key\" : \"l3-interface-ipv4-address-list.l3-interface-ipv4-address\","
+ + "\"relationship-value\" : \"key5\""
+ + "}]"
+ + "}";
+ scrambledRelationshipSpec(content);
+ }
+
+ /**
+ * Scrambled relationship spec.
+ *
+ * @param content the content
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ public void scrambledRelationshipSpec(String content) throws JAXBException, UnsupportedEncodingException, AAIException {
+
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'generic-vnf')"
+ + ".out('hasLAGInterface')"
+ + ".has('interface-name', 'key2').out('hasLInterface')"
+ + ".has('interface-name', 'key3').out('hasVlan')"
+ + ".has('vlan-interface', 'key4').out('hasIpAddress')"
+ + ".has('l3-interface-ipv4-address', 'key5')";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'generic-vnf')"
+ + ".out('hasLAGInterface')"
+ + ".has('interface-name', 'key2').out('hasLInterface')"
+ + ".has('interface-name', 'key3').out('hasVlan')"
+ + ".has('vlan-interface', 'key4')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for vlan",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be l3-interface-ipv4-address-list",
+ "l3-interface-ipv4-address-list",
+ query.getResultType());
+
+ }
+
+ /**
+ * Short circuit.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void shortCircuit() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"cvlan-tag\","
+ + "\"related-link\" : \"http://mock-system-name.com:8443/aai/v6/network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"vce.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"port-group.interface-id\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"cvlan-tag.cvlan-tag\","
+ + "\"relationship-value\" : \"655\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2').out('hasCTag')"
+ + ".has('cvlan-tag', 655)";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce')"
+ + ".out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+
+ }
+
+ /**
+ * Double key.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void doubleKey() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String uri = "/service-capabilities/service-capability/key1/key2/cvlan-tags/cvlan-tag/655";
+ String content =
+ "{"
+ + "\"related-to\" : \"ctag-pool\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"complex.physical-location-id\","
+ + "\"relationship-value\" : \"key1\""
+ + " }, { "
+ + "\"relationship-key\" : \"ctag-pool.target-pe\","
+ + " \"relationship-value\" : \"key2\""
+ + " },{"
+ + "\"relationship-key\" : \"ctag-pool.availability-zone-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "}]"
+ + "}";
+
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')"
+ + ".out('hasCtagPool')"
+ + ".has('target-pe', 'key2')"
+ + ".has('availability-zone-name', 'key3')";
+ String expectedParent =
+ ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')";
+
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be ctag-pool",
+ "ctag-pool",
+ query.getResultType());
+
+ }
+
+ /**
+ * Abstract type.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void abstractType() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"vnf\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"vnf.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + " }]"
+ + "}";
+
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('vnf-id', 'key1')"
+ + ".or(_().has('aai-node-type', 'vce'),_().has('aai-node-type', 'vpe'),_().has('aai-node-type', 'generic-vnf'))";
+
+ String expectedParent =
+ ".has('vnf-id', 'key1')"
+ + ".or(_().has('aai-node-type', 'vce'),_().has('aai-node-type', 'vpe'),_().has('aai-node-type', 'generic-vnf'))";
+
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be vnf",
+ "vnf",
+ query.getResultType());
+
+ }
+
+ /**
+ * Invalid node name.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void invalidNodeName() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"l3-interface-ipv4-address-list\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"generic-vnf.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "},{"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"l-infeaterface.interface-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "},{"
+ + "\"relationship-key\" : \"vlan.vlan-interface\","
+ + "\"relationship-value\" : \"key4\""
+ + "},{"
+ + "\"relationship-key\" : \"l3-interface-ipv4-address-list.l3-interface-ipv4-address\","
+ + "\"relationship-value\" : \"key5\""
+ + "}]"
+ + "}";
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3000"));
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ }
+
+ /**
+ * Invalid property name.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void invalidPropertyName() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"l3-interface-ipv4-address-list\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"generic-vnf.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "},{"
+ + "\"relationship-key\" : \"lag-interface.intfdaferface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"l-interface.interface-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "},{"
+ + "\"relationship-key\" : \"vlan.vlan-interface\","
+ + "\"relationship-value\" : \"key4\""
+ + "},{"
+ + "\"relationship-key\" : \"l3-interface-ipv4-address-list.l3-interface-ipv4-address\","
+ + "\"relationship-value\" : \"key5\""
+ + "}]"
+ + "}";
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3000"));
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipQueryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipQueryTest.java
new file mode 100644
index 0000000..40d8913
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/RelationshipQueryTest.java
@@ -0,0 +1,287 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+public class RelationshipQueryTest {
+ private ModelInjestor injestor = ModelInjestor.getInstance();
+ private LogLineBuilder llBuilder = new LogLineBuilder("TEST", "TEST");
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLIN_TRAVERSAL,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, llBuilder),
+ false);
+ private final Version version = Version.v8;
+ private DynamicJAXBContext context = injestor.getContextForVersion(version);
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+
+ /**
+ * Parent query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void parentQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+
+ String content =
+ "{"
+ + "\"related-to\" : \"pserver\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"pserver.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal to normal query",
+ expected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be pserver",
+ "pserver",
+ query.getResultType());
+
+ }
+
+ /**
+ * Child query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Test
+ public void childQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"lag-interface\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"pserver.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+ String expected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver').out('hasLAGInterface')"
+ + ".has('interface-name', 'key2')";
+ String parentExpected =
+ ".has('hostname', 'key1').has('aai-node-type', 'pserver')";
+ assertEquals(
+ "gremlin query should be for node",
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be for parent",
+ parentExpected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be lag-interface",
+ "lag-interface",
+ query.getResultType());
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String uri = "/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655";
+ String content =
+ "{"
+ + "\"related-to\" : \"cvlan-tag\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"vce.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"port-group.interface-id\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"cvlan-tag.cvlan-tag\","
+ + "\"relationship-value\" : \"655\""
+ + "}]"
+ + "}";
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+ String expected =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce').out('hasPortGroup')"
+ + ".has('interface-id', 'key2').out('hasCTag')"
+ + ".has('cvlan-tag', 655)";
+ String expectedParent =
+ ".has('vnf-id', 'key1').has('aai-node-type', 'vce').out('hasPortGroup')"
+ + ".has('interface-id', 'key2')";
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be cvlan-tag",
+ "cvlan-tag",
+ query.getResultType());
+
+ }
+
+ /**
+ * Double key.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void doubleKey() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String uri = "/service-capabilities/service-capability/key1/key2/cvlan-tags/cvlan-tag/655";
+ String content =
+ "{"
+ + "\"related-to\" : \"ctag-pool\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"complex.physical-location-id\","
+ + "\"relationship-value\" : \"key1\""
+ + " }, { "
+ + "\"relationship-key\" : \"ctag-pool.target-pe\","
+ + " \"relationship-value\" : \"key2\""
+ + " },{"
+ + "\"relationship-key\" : \"ctag-pool.availability-zone-name\","
+ + "\"relationship-value\" : \"key3\""
+ + "}]"
+ + "}";
+
+
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String expected =
+ ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')"
+ + ".out('hasCtagPool')"
+ + ".has('target-pe', 'key2')"
+ + ".has('availability-zone-name', 'key3')";
+ String expectedParent =
+ ".has('physical-location-id', 'key1').has('aai-node-type', 'complex')";
+
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be equal the query for port group",
+ expectedParent,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be ctag-pool",
+ "ctag-pool",
+ query.getResultType());
+
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryTest.java
new file mode 100644
index 0000000..a200278
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryTest.java
@@ -0,0 +1,322 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.UnmarshallerProperties;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.IntrospectorFactory;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+public class UniqueRelationshipQueryTest {
+ private ModelInjestor injestor = ModelInjestor.getInstance();
+ private LogLineBuilder llBuilder = new LogLineBuilder("TEST", "TEST");
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLIN_UNIQUE,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, llBuilder),
+ false);
+ private final Version version = Version.v8;
+ private DynamicJAXBContext context = injestor.getContextForVersion(version);
+ private Unmarshaller unmarshaller = null;
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+
+ /**
+ * Setup.
+ *
+ * @throws JAXBException the JAXB exception
+ */
+ @Before
+ public void setup() throws JAXBException {
+ unmarshaller = context.createUnmarshaller();
+ unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
+ unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
+ }
+
+ /**
+ * Parent query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void parentQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+
+ String content =
+ "{"
+ + "\"related-to\" : \"pserver\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"pserver.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}]"
+ + "}";
+
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+ String key = "pserver/key1";
+ GraphTraversal<Vertex, Vertex> expected =
+ __.<Vertex>start().has("aai-unique-key", key);
+ String resultType = "pserver";
+ String containerType = "";
+
+ testSet(query, expected, expected, resultType, containerType);
+
+ }
+
+ /**
+ * Child query.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void childQuery() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"lag-interface\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"pserver.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"lag-interface.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "}]"
+ + "}";
+
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String key = "pserver/key1/lag-interface/key2";
+ GraphTraversal<Vertex, Vertex> expected =
+ __.<Vertex>start().has("aai-unique-key", key);
+ GraphTraversal<Vertex, Vertex> parentExpected =
+ __.<Vertex>start().has("aai-unique-key", "pserver/key1");
+ String resultType = "lag-interface";
+ String containerType = "";
+
+ testSet(query, expected, parentExpected, resultType, containerType);
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String uri = "/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655";
+ String content =
+ "{"
+ + "\"related-to\" : \"cvlan-tag\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"vce.vnf-id\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"port-group.interface-id\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"cvlan-tag.cvlan-tag\","
+ + "\"relationship-value\" : \"655\""
+ + "}]"
+ + "}";
+
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+ String key = "vce/key1/port-group/key2/cvlan-tag/655";
+ GraphTraversal<Vertex, Vertex> expected =
+ __.<Vertex>start().has("aai-unique-key", key);
+ GraphTraversal<Vertex, Vertex> parentExpected =
+ __.<Vertex>start().has("aai-unique-key", "vce/key1/port-group/key2");
+ String resultType = "cvlan-tag";
+ String containerType = "";
+
+ testSet(query, expected, parentExpected, resultType, containerType);
+
+ }
+
+ /**
+ * Double key.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void doubleKey() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String uri = "/service-capabilities/service-capability/key1/key2";
+ String content =
+ "{"
+ + "\"related-to\" : \"service-capability\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"service-capability.service-type\","
+ + "\"relationship-value\" : \"key1\""
+ + " }, { "
+ + "\"relationship-key\" : \"service-capability.vnf-type\","
+ + " \"relationship-value\" : \"key2\""
+ + " }]"
+ + "}";
+
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String key = "service-capability/key1/key2";
+ GraphTraversal<Vertex, Vertex> expected =
+ __.<Vertex>start().has("aai-unique-key", key);
+ GraphTraversal<Vertex, Vertex> parentExpected =
+ __.<Vertex>start().has("aai-unique-key", "service-capability/key1/key2");
+ String resultType = "service-capability";
+ String containerType = "";
+
+ testSet(query, expected, parentExpected, resultType, containerType);
+
+ }
+
+ /**
+ * Short circuit.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void shortCircuit() throws JAXBException, UnsupportedEncodingException, AAIException {
+ String content =
+ "{"
+ + "\"related-to\" : \"cvlan-tag\","
+ + "\"related-link\" : \"http://mock-system-name.com:8443/aai/v6/network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655\","
+ + "\"relationship-data\" : [{"
+ + "\"relationship-key\" : \"vce.hostname\","
+ + "\"relationship-value\" : \"key1\""
+ + "}, {"
+ + "\"relationship-key\" : \"port-group.interface-name\","
+ + "\"relationship-value\" : \"key2\""
+ + "},{"
+ + "\"relationship-key\" : \"cvlan-tag.-name\","
+ + "\"relationship-value\" : \"655\""
+ + "}]"
+ + "}";
+
+ Object obj = context.newDynamicEntity("Relationship");
+
+ DynamicEntity entity = (DynamicEntity)unmarshaller.unmarshal(new StreamSource(new StringReader(content)), obj.getClass()).getValue();
+
+ Introspector wrappedObj = IntrospectorFactory.newInstance(ModelType.MOXY, entity, llBuilder);
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromRelationship(wrappedObj);
+
+ String uri = "network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655";
+ String key = "vce/key1/port-group/key2/cvlan-tag/655";
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("aai-unique-key", key);
+ GraphTraversal<Vertex, Vertex> parentExpected = __.<Vertex>start().has("aai-unique-key", "vce/key1/port-group/key2");
+ String resultType = "cvlan-tag";
+ String containerType = "";
+
+ testSet(query, expected, parentExpected, resultType, containerType);
+
+ }
+
+ /**
+ * Test set.
+ *
+ * @param query the query
+ * @param expected the expected
+ * @param parentExpected the parent expected
+ * @param resultType the result type
+ * @param containerType the container type
+ */
+ public void testSet(QueryParser query, GraphTraversal<Vertex, Vertex> expected, GraphTraversal<Vertex, Vertex> parentExpected, String resultType, String containerType) {
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be " + parentExpected,
+ parentExpected,
+ query.getParentQueryBuilder().getParentQuery());
+ assertEquals(
+ "result type should be " + resultType,
+ resultType,
+ query.getResultType());
+ assertEquals(
+ "container type should be " + containerType,
+ containerType,
+ query.getContainerType());
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueURIQueryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueURIQueryTest.java
new file mode 100644
index 0000000..f108745
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/query/UniqueURIQueryTest.java
@@ -0,0 +1,210 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.query;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class UniqueURIQueryTest {
+ private ModelInjestor injestor = ModelInjestor.getInstance();
+ private TransactionalGraphEngine dbEngine =
+ new TitanDBEngine(QueryStyle.GREMLIN_UNIQUE,
+ LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST")),
+ false);
+ private final Version version = Version.v8;
+ private DynamicJAXBContext context = injestor.getContextForVersion(version);
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+
+ /**
+ * Parent query.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void parentQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1").build();
+ String key = "complex/key1";
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("aai-unique-key", key);
+ String parentResultType = "";
+ String resultType = "complex";
+ String containerType = "";
+
+ testSet(query, expected, expected, parentResultType, resultType, containerType);
+
+ }
+
+ /**
+ * Parent plural query.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void parentPluralQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("aai-node-type", "complex");
+ String parentResultType = "";
+ String resultType = "complex";
+ String containerType = "complexes";
+
+ testSet(query, expected, expected, parentResultType, resultType, containerType);
+
+ }
+
+ /**
+ * Child query.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void childQuery() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("cloud-infrastructure/complexes/complex/key1/ctag-pools/ctag-pool/key2/key3").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String parentKey = "complex/key1";
+ String key = parentKey + "/ctag-pool/key2/key3";
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("aai-unique-key", key);
+ GraphTraversal<Vertex, Vertex> parentExpected = __.<Vertex>start().has("aai-unique-key", parentKey);
+ String parentResultType = "complex";
+ String resultType = "ctag-pool";
+ String containerType = "";
+
+ testSet(query, expected, parentExpected, parentResultType, resultType, containerType);
+
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String parentKey = "vce/key1/port-group/key2";
+ String key = parentKey + "/cvlan-tag/655";
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("aai-unique-key", key);
+ GraphTraversal<Vertex, Vertex> parentExpected = __.<Vertex>start().has("aai-unique-key", parentKey);
+ String parentResultType = "port-group";
+ String resultType = "cvlan-tag";
+ String containerType = "";
+
+ testSet(query, expected, parentExpected, parentResultType, resultType, containerType);
+
+ }
+
+ /**
+ * Gets the all.
+ *
+ * @return the all
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void getAll() throws UnsupportedEncodingException, AAIException {
+ String parentURI = "network/vces/vce/key1/port-groups/port-group/key2";
+ String parentKey = "vce/key1/port-group/key2";
+ URI uri = UriBuilder.fromPath(parentURI + "/cvlan-tags").build();
+ QueryParser query = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ GraphTraversal<Vertex, Vertex> expected = __.<Vertex>start().has("aai-unique-key", parentKey).out("hasCTag").has("aai-node-type", "cvlan-tag");
+ GraphTraversal<Vertex, Vertex> parentExpected = __.<Vertex>start().has("aai-unique-key",parentKey);
+ String parentResultType = "port-group";
+ String resultType = "cvlan-tag";
+ String containerType = "cvlan-tags";
+
+ testSet(query, expected, parentExpected, parentResultType, resultType, containerType);
+
+ }
+
+ /**
+ * Test set.
+ *
+ * @param query the query
+ * @param expected the expected
+ * @param parentExpected the parent expected
+ * @param parentResultType the parent result type
+ * @param resultType the result type
+ * @param containerType the container type
+ */
+ public void testSet(QueryParser query, GraphTraversal<Vertex, Vertex> expected, GraphTraversal<Vertex, Vertex> parentExpected, String parentResultType, String resultType, String containerType) {
+ assertEquals(
+ "gremlin query should be " + expected,
+ expected,
+ query.getQueryBuilder().getQuery());
+ assertEquals(
+ "parent gremlin query should be " + parentExpected,
+ parentExpected,
+ query.getQueryBuilder().getParentQuery());
+ assertEquals(
+ "parent result type should be " + parentResultType,
+ parentResultType,
+ query.getParentResultType());
+ assertEquals(
+ "result type should be " + resultType,
+ resultType,
+ query.getResultType());
+ assertEquals(
+ "container type should be " + containerType,
+ containerType,
+ query.getContainerType());
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIParserTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIParserTest.java
new file mode 100644
index 0000000..44822be
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIParserTest.java
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.xml.bind.JAXBException;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToDBKey;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class URIParserTest {
+
+ private Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST"));
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ /**
+ * Invalid path.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void invalidPath() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/network/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+
+ }
+
+ /**
+ * Invalid path no name space.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void invalidPathNoNameSpace() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3000"));
+
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+
+ }
+
+ /**
+ * Invalid path partial.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void invalidPathPartial() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3000"));
+
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToDBKeyTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToDBKeyTest.java
new file mode 100644
index 0000000..43d0682
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToDBKeyTest.java
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.xml.bind.JAXBException;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToDBKey;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+@PrepareForTest(ModelInjestor.class)
+public class URIToDBKeyTest {
+
+ private Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST"));
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ /**
+ * Uri.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void uri() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+ Object result = parse.getResult();
+
+ String expected = "cloud-region/CR/AAI25/tenant/key1/vserver/key2/l-interface/key3";
+
+ assertEquals("blah", expected, result);
+
+ }
+
+ /**
+ * Uri no version.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void uriNoVersion() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+ Object result = parse.getResult();
+
+ String expected = "cloud-region/CR/AAI25/tenant/key1/vserver/key2/l-interface/key3";
+
+ assertEquals("blah", expected, result);
+
+ }
+
+
+ /**
+ * Bad URI.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void badURI() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interadsfaces/l-interface/key3").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+
+ }
+
+ /**
+ * No valid tokens.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void noValidTokens() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud/blah/blah").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+ }
+
+ /**
+ * Starts with valid namespace.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void startsWithValidNamespace() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+ Object result = parse.getResult();
+
+ String expected = "cloud-region/CR/AAI25/tenant/key1/vserver/key2/l-interface/key3";
+
+ assertEquals("blah", expected, result);
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws IllegalArgumentException, AAIException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build();
+ URIToDBKey parse = new URIToDBKey(loader, uri);
+ Object result = parse.getResult();
+
+ String expected = "vce/key1/port-group/key2/cvlan-tag/655";
+
+ assertEquals("blah", expected, result);
+
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToExtensionInformationTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToExtensionInformationTest.java
new file mode 100644
index 0000000..c875a47
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToExtensionInformationTest.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.xml.bind.JAXBException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToExtensionInformation;
+import org.openecomp.aai.rest.HttpMethod;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class URIToExtensionInformationTest {
+
+ private Loader v8Loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST"));
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+
+ /**
+ * Test spec.
+ *
+ * @param info the info
+ * @param httpMethod the http method
+ * @param namespace the namespace
+ * @param preMethodName the pre method name
+ * @param postMethodName the post method name
+ * @param topLevel the top level
+ */
+ private void testSpec(URIToExtensionInformation info, HttpMethod httpMethod, String namespace, String preMethodName, String postMethodName, String topLevel) {
+
+
+ String namespaceResult = info.getNamespace();
+ String methodNameResult = info.getMethodName(httpMethod, true);
+
+ assertEquals("namespace", namespace, namespaceResult);
+ assertEquals("preprocess method name", preMethodName, methodNameResult);
+ methodNameResult = info.getMethodName(httpMethod, false);
+
+ assertEquals("postprocess method name", postMethodName, methodNameResult);
+
+ String topLevelResult = info.getTopObject();
+
+ assertEquals("topLevel", topLevel, topLevelResult);
+ }
+
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToObjectTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToObjectTest.java
new file mode 100644
index 0000000..721b296
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToObjectTest.java
@@ -0,0 +1,251 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.HashMap;
+
+import javax.xml.bind.JAXBException;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToObject;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+
+public class URIToObjectTest {
+
+ private Version version = Version.v8;
+ private Version currentVersion = Version.v8;
+ private Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, version, new LogLineBuilder("TEST", "TEST"));
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+
+ /**
+ * Uri.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void uri() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ URIToObject parse = new URIToObject(loader, uri);
+ Introspector result = parse.getTopEntity();
+ String expected = "{\"cloud-owner\":\"CR\",\"cloud-region-id\":\"AAI25\",\"tenants\":{\"tenant\":[{\"tenant-id\":\"key1\",\"vservers\":{\"vserver\":[{\"vserver-id\":\"key2\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"key3\"}]}}]}}]}}";
+ String topEntity = "cloud-region";
+ String entity = "l-interface";
+
+ testSet(result.marshal(false), parse, expected, topEntity, entity, currentVersion);
+
+ }
+
+ /**
+ * Uri no version.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void uriNoVersion() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ HashMap<String, Introspector> relatedObjects = new HashMap<>();
+ Introspector tenantObj = this.loader.introspectorFromName("tenant");
+ tenantObj.setValue("tenant-id", "key1");
+ tenantObj.setValue("tenant-name", "name1");
+ relatedObjects.put(tenantObj.getObjectId(), tenantObj);
+ Introspector vserverObj = this.loader.introspectorFromName("vserver");
+ vserverObj.setValue("vserver-id", "key2");
+ vserverObj.setValue("vserver-name", "name2");
+ relatedObjects.put(vserverObj.getObjectId(), vserverObj);
+
+ URIToObject parse = new URIToObject(loader, uri, relatedObjects);
+ Introspector result = parse.getTopEntity();
+ String expected = "{\"cloud-owner\":\"CR\",\"cloud-region-id\":\"AAI25\",\"tenants\":{\"tenant\":[{\"tenant-id\":\"key1\",\"tenant-name\":\"name1\",\"vservers\":{\"vserver\":[{\"vserver-id\":\"key2\",\"vserver-name\":\"name2\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"key3\"}]}}]}}]}}";
+ String topEntity = "cloud-region";
+ String entity = "l-interface";
+
+ testSet(result.marshal(false), parse, expected, topEntity, entity, currentVersion);
+
+
+ }
+
+
+ /**
+ * Bad URI.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void badURI() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interadsfaces/l-interface/key3").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+
+ URIToObject parse = new URIToObject(loader, uri);
+
+ }
+
+ /**
+ * Starts with valid namespace.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void startsWithValidNamespace() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ URIToObject parse = new URIToObject(loader, uri);
+ Introspector result = parse.getTopEntity();
+ String expected = "{\"cloud-owner\":\"CR\",\"cloud-region-id\":\"AAI25\",\"tenants\":{\"tenant\":[{\"tenant-id\":\"key1\",\"vservers\":{\"vserver\":[{\"vserver-id\":\"key2\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"key3\"}]}}]}}]}}";
+ String topEntity = "cloud-region";
+ String entity = "l-interface";
+
+ testSet(result.marshal(false), parse, expected, topEntity, entity, currentVersion);
+
+ }
+
+ /**
+ * Single top level.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Test
+ public void singleTopLevel() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/network/generic-vnfs/generic-vnf/key1").build();
+ URIToObject parse = new URIToObject(loader, uri);
+ Introspector result = parse.getTopEntity();
+ String expected = "{\"vnf-id\":\"key1\"}";
+
+ String topEntity = "generic-vnf";
+ String entity = "generic-vnf";
+
+ testSet(result.marshal(false), parse, expected, topEntity, entity, version);
+
+ }
+
+ /**
+ * Naming exceptions.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void namingExceptions() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/655").build();
+ URIToObject parse = new URIToObject(loader, uri);
+ Introspector result = parse.getTopEntity();
+ String expected = "{\"vnf-id\":\"key1\",\"port-groups\":{\"port-group\":[{\"interface-id\":\"key2\",\"cvlan-tags\":{\"cvlan-tag-entry\":[{\"cvlan-tag\":655}]}}]}}";
+ String topEntity = "vce";
+ String entity = "cvlan-tag";
+
+ testSet(result.marshal(false), parse, expected, topEntity, entity, version);
+
+ }
+
+ /**
+ * No list object.
+ *
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void noListObject() throws IllegalArgumentException, UnsupportedEncodingException, AAIException {
+ URI uri = UriBuilder.fromPath("/aai/v8/network/vpls-pes/vpls-pe/0e6189fd-9257-49b9-a3be-d7ba980ccfc9/lag-interfaces/lag-interface/8ae5aa76-d597-4382-b219-04f266fe5e37/l-interfaces/l-interface/9e141d03-467b-437f-b4eb-b3133ec1e205/l3-interface-ipv4-address-list/8f19f0ea-a81f-488e-8d5c-9b7b53696c11").build();
+ URIToObject parse = new URIToObject(loader, uri);
+ Introspector result = parse.getTopEntity();
+ String topEntity = "vpls-pe";
+ String entity = "l3-interface-ipv4-address-list";
+ String expected = "{\"equipment-name\":\"0e6189fd-9257-49b9-a3be-d7ba980ccfc9\",\"lag-interfaces\":{\"lag-interface\":[{\"interface-name\":\"8ae5aa76-d597-4382-b219-04f266fe5e37\",\"l-interfaces\":{\"l-interface\":[{\"interface-name\":\"9e141d03-467b-437f-b4eb-b3133ec1e205\",\"l3-interface-ipv4-address-list\":[{\"l3-interface-ipv4-address\":\"8f19f0ea-a81f-488e-8d5c-9b7b53696c11\"}]}]}}]}}";
+ testSet(result.marshal(false), parse, expected, topEntity, entity, version);
+
+ }
+
+ /**
+ * Test set.
+ *
+ * @param json the json
+ * @param parse the parse
+ * @param expected the expected
+ * @param topEntity the top entity
+ * @param entity the entity
+ * @param version the version
+ */
+ public void testSet(String json, URIToObject parse, String expected, String topEntity, String entity, Version version) {
+ assertEquals("blah", expected, json);
+
+ assertEquals("top entity", topEntity, parse.getTopEntityName());
+
+ assertEquals("entity", entity, parse.getEntityName());
+
+ assertEquals("entity object", entity, parse.getEntity().getDbName());
+
+ assertEquals("parent list object", 1, parse.getParentList().size());
+
+ assertEquals("object version", version, parse.getObjectVersion());
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToRelationshipObjectTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToRelationshipObjectTest.java
new file mode 100644
index 0000000..ca362ec
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/parsers/uri/URIToRelationshipObjectTest.java
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.parsers.uri;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertTrue;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+
+import javax.xml.bind.JAXBException;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.uri.URIToObject;
+import org.openecomp.aai.parsers.uri.URIToRelationshipObject;
+
+import com.att.aft.dme2.internal.javaxwsrs.core.UriBuilder;
+
+public class URIToRelationshipObjectTest {
+
+ private Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, Version.v8, new LogLineBuilder("TEST", "TEST"));
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Configure.
+ */
+ @BeforeClass
+ public static void configure() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+ }
+
+ /**
+ * Uri.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ @Ignore
+ @Test
+ public void uri() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException, MalformedURLException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ URIToRelationshipObject parse = new URIToRelationshipObject(loader, uri);
+ Introspector result = parse.getResult();
+ String expected = "\\{\"related-to\":\"l-interface\",\"related-link\":\".*?:8443/aai/v8/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3/\",\"relationship-data\":\\[\\{\"relationship-key\":\"tenant.tenant-id\",\"relationship-value\":\"key1\"\\},\\{\"relationship-key\":\"vserver.vserver-id\",\"relationship-value\":\"key2\"\\},\\{\"relationship-key\":\"l-interface.interface-name\",\"relationship-value\":\"key3\"\\}\\]\\}";
+ assertTrue("blah", result.marshal(false).matches(expected));
+
+ }
+
+ /**
+ * Uri no version.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ @Ignore
+ @Test
+ public void uriNoVersion() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException, MalformedURLException {
+ URI uri = UriBuilder.fromPath("/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3").build();
+ URIToRelationshipObject parse = new URIToRelationshipObject(loader, uri);
+ Introspector result = parse.getResult();
+ String expected = "\\{\"related-to\":\"l-interface\",\"related-link\":\".*?:8443/aai/v8/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interfaces/l-interface/key3/\",\"relationship-data\":\\[\\{\"relationship-key\":\"tenant.tenant-id\",\"relationship-value\":\"key1\"\\},\\{\"relationship-key\":\"vserver.vserver-id\",\"relationship-value\":\"key2\"\\},\\{\"relationship-key\":\"l-interface.interface-name\",\"relationship-value\":\"key3\"\\}\\]\\}";
+ assertTrue("blah", result.marshal(false).matches(expected));
+
+
+ }
+
+
+ /**
+ * Double key relationship.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ @Ignore
+ @Test
+ public void doubleKeyRelationship() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException, MalformedURLException {
+ URI uri = UriBuilder.fromPath("/aai/v8/cloud-infrastructure/complexes/complex/key1/ctag-pools/ctag-pool/key2/key3/").build();
+ URIToRelationshipObject parse = new URIToRelationshipObject(loader, uri);
+ Introspector result = parse.getResult();
+ String expected = "\\{\"related-to\":\"ctag-pool\",\"related-link\":\".*?:8443/aai/v8/cloud-infrastructure/complexes/complex/key1/ctag-pools/ctag-pool/key2/key3/\",\"relationship-data\":\\[\\{\"relationship-key\":\"complex.physical-location-id\",\"relationship-value\":\"key1\"\\},\\{\"relationship-key\":\"ctag-pool.target-pe\",\"relationship-value\":\"key2\"\\},\\{\"relationship-key\":\"ctag-pool.availability-zone-name\",\"relationship-value\":\"key3\"\\}\\]\\}";
+ assertTrue("blah", result.marshal(false).matches(expected));
+
+ }
+
+ /**
+ * Uri with non string key.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ */
+ @Ignore
+ @Test
+ public void uriWithNonStringKey() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException, MalformedURLException {
+ URI uri = UriBuilder.fromPath("/aai/v8/network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/144").build();
+ URIToRelationshipObject parse = new URIToRelationshipObject(loader, uri);
+ Introspector result = parse.getResult();
+ String expected = "\\{\"related-to\":\"cvlan-tag\",\"related-link\":\".*?:8443/aai/v8/network/vces/vce/key1/port-groups/port-group/key2/cvlan-tags/cvlan-tag/144/\",\"relationship-data\":\\[\\{\"relationship-key\":\"vce.vnf-id\",\"relationship-value\":\"key1\"\\},\\{\"relationship-key\":\"port-group.interface-id\",\"relationship-value\":\"key2\"\\},\\{\"relationship-key\":\"cvlan-tag.cvlan-tag\",\"relationship-value\":\"144\"\\}\\]\\}";
+ assertTrue("blah", result.marshal(false).matches(expected));
+ }
+
+ /**
+ * Bad URI.
+ *
+ * @throws JAXBException the JAXB exception
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ @Ignore
+ @Test
+ public void badURI() throws JAXBException, AAIException, IllegalArgumentException, UnsupportedEncodingException {
+ URI uri = UriBuilder.fromPath("/aai/" + loader.getVersion() + "/cloud-infrastructure/tenants/tenant/key1/vservers/vserver/key2/l-interadsfaces/l-interface/key3").build();
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage(startsWith("AAI_3001"));
+
+ URIToObject parse = new URIToObject(loader, uri);
+
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/rest/search/SearchProviderTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/rest/search/SearchProviderTest.java
new file mode 100644
index 0000000..b9b8147
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/rest/search/SearchProviderTest.java
@@ -0,0 +1,372 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.search;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.ext.RuntimeDelegate;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.openecomp.aai.dbmap.SearchGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.extensions.AAIExtensionMap;
+import org.openecomp.aai.logging.LogLine;
+import org.openecomp.aai.rest.search.SearchProvider;
+import org.openecomp.aai.util.AAIApiVersion;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+
+
+//@RunWith(PowerMockRunner.class)
+//@PowerMockIgnore( {"javax.management.*"})
+@PrepareForTest({AAIApiVersion.class, SearchGraph.class, SearchProvider.class, ResponseBuilder.class})
+public class SearchProviderTest {
+ //In VM argument, need to pass the following arguments:
+ //-noverify
+ //
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+
+ private String fromAppId = "searchProviderId";
+ private String transId = "transId";
+ private String aaiApiVersion = "v8";
+ private String genericQueryUri = "https://localhost:8443/aai/v8/search" + SearchProvider.GENERIC_QUERY
+ + "?key=service-instance.service-instance-id:test-service-instance-id"
+ + "&start-node-type=service-instance&include=generic-vnf&depth=0";
+ private String nodeQueryUri = "https://localhost:8443/aai/v8/search" + SearchProvider.NODES_QUERY
+ + "?search-node-type=vserver&filter=vserver-name2:EXISTS:"
+ + "&edge-filter=pserver:EXISTS:hostname:test-hostname";
+
+
+ /**
+ * Sets the up.
+ */
+ @Before
+ public void setUp() {
+ RuntimeDelegate.setInstance(runtimeDelegate);
+ }
+
+ @Mock
+ private RuntimeDelegate runtimeDelegate;
+
+ class MockSearchProvider extends SearchProvider {
+ @Override
+ protected String getFromAppId(HttpHeaders headers, LogLine logline) throws AAIException {
+ return fromAppId;
+ }
+ @Override
+ protected String getTransId(HttpHeaders headers, LogLine logline) throws AAIException {
+ return transId;
+ }
+
+ @Override
+ protected String genDate() {
+ return null;
+ }
+ @Override
+ protected String genDate(LogLine logline) {
+ return null;
+ }
+ @Override
+ public void logTransaction( String appId, String tId, String action,
+ String input, String rqstTm, String respTm, String request, Response response, LogLine logline) {
+ }
+ }
+
+ class MockResponse extends Response {
+
+ @Override
+ public Object getEntity() {
+ return null;
+ }
+
+ @Override
+ public int getStatus() {
+ return 200;
+ }
+
+ @Override
+ public MultivaluedMap<String, Object> getMetadata() {
+ return null;
+ }
+ }
+
+
+
+ /**
+ * Test get generic query response.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetGenericQueryResponse() throws Exception {
+ PowerMockito.mockStatic(AAIApiVersion.class);
+ when(AAIApiVersion.get()).thenReturn(aaiApiVersion);
+
+ SearchGraph mockSearchGraph = Mockito.mock(SearchGraph.class);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenReturn(mockSearchGraph);
+ Response mockResp = new MockResponse();
+
+ when(mockSearchGraph.runGenericQuery(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyListOf(String.class),
+ Mockito.anyListOf(String.class), Mockito.anyInt(), Mockito.any(AAIExtensionMap.class)))
+ .thenReturn(mockResp);
+
+ HttpHeaders headers = Mockito.mock(HttpHeaders.class);
+ List<MediaType> mediaTypeList = new ArrayList<MediaType>();
+ mediaTypeList.add(MediaType.APPLICATION_JSON_TYPE);
+ when(headers.getAcceptableMediaTypes()).thenReturn(mediaTypeList);
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-instance.service-instance-id:test-service-instance-id");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("generic-vnf");
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setRequestURI(genericQueryUri);
+ MockSearchProvider mockSearchProvider = new MockSearchProvider();
+ Response resp = mockSearchProvider.getGenericQueryResponse(headers, req,
+ "service-instance", startNodeKeyParams, includeNodeTypes,
+ 0);
+ assertEquals(200, resp.getStatus());
+ }
+
+
+ /**
+ * Test get generic query response AAI exception.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetGenericQueryResponse_AAIException() throws Exception {
+ PowerMockito.mockStatic(AAIApiVersion.class);
+ when(AAIApiVersion.get()).thenReturn(aaiApiVersion);
+
+ SearchGraph mockSearchGraph = Mockito.mock(SearchGraph.class);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenReturn(mockSearchGraph);
+
+ Response response = Mockito.mock(Response.class);
+ when(response.getStatus()).thenReturn(500);
+ ResponseBuilder responseBuilder = Mockito.mock(ResponseBuilder.class);
+ when(runtimeDelegate.createResponseBuilder()).thenReturn(responseBuilder);
+ when((responseBuilder).status(Response.Status.INTERNAL_SERVER_ERROR)).thenReturn(responseBuilder);
+ when((responseBuilder).entity(Mockito.anyObject())).thenReturn(responseBuilder);
+ when((responseBuilder).build()).thenReturn(response);
+ when(mockSearchGraph.runGenericQuery(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyListOf(String.class),
+ Mockito.anyListOf(String.class), Mockito.anyInt(), Mockito.any(AAIExtensionMap.class)))
+ .thenThrow(new AAIException());
+
+ HttpHeaders headers = Mockito.mock(HttpHeaders.class);
+ List<MediaType> mediaTypeList = new ArrayList<MediaType>();
+ mediaTypeList.add(MediaType.APPLICATION_JSON_TYPE);
+ when(headers.getAcceptableMediaTypes()).thenReturn(mediaTypeList);
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-instance.service-instance-id:test-service-instance-id");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("generic-vnf");
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setRequestURI(genericQueryUri);
+ MockSearchProvider mockSearchProvider = new MockSearchProvider();
+ Response resp = mockSearchProvider.getGenericQueryResponse(headers, req,
+ "service-instance", startNodeKeyParams, includeNodeTypes,
+ 0);
+ assertEquals(500, resp.getStatus());
+ }
+
+ /**
+ * Test get generic query response exception.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetGenericQueryResponse_Exception() throws Exception {
+ PowerMockito.mockStatic(AAIApiVersion.class);
+ when(AAIApiVersion.get()).thenReturn(aaiApiVersion);
+
+ SearchGraph mockSearchGraph = Mockito.mock(SearchGraph.class);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenReturn(mockSearchGraph);
+
+ Response response = Mockito.mock(Response.class);
+ when(response.getStatus()).thenReturn(500);
+ ResponseBuilder responseBuilder = Mockito.mock(ResponseBuilder.class);
+ when(runtimeDelegate.createResponseBuilder()).thenReturn(responseBuilder);
+ when((responseBuilder).status(Response.Status.INTERNAL_SERVER_ERROR)).thenReturn(responseBuilder);
+ when((responseBuilder).entity(Mockito.anyObject())).thenReturn(responseBuilder);
+ when((responseBuilder).build()).thenReturn(response);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenThrow(new Exception());
+
+ HttpHeaders headers = Mockito.mock(HttpHeaders.class);
+ List<MediaType> mediaTypeList = new ArrayList<MediaType>();
+ mediaTypeList.add(MediaType.APPLICATION_JSON_TYPE);
+ when(headers.getAcceptableMediaTypes()).thenReturn(mediaTypeList);
+ List<String> startNodeKeyParams = new ArrayList<String>();
+ startNodeKeyParams.add("service-instance.service-instance-id:test-service-instance-id");
+ List<String> includeNodeTypes = new ArrayList<String>();
+ includeNodeTypes.add("generic-vnf");
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setRequestURI(genericQueryUri);
+ MockSearchProvider mockSearchProvider = new MockSearchProvider();
+ Response resp = mockSearchProvider.getGenericQueryResponse(headers, req,
+ "service-instance", startNodeKeyParams, includeNodeTypes,
+ 0);
+ assertEquals(500, resp.getStatus());
+ }
+
+ /**
+ * Test get nodes query response.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetNodesQueryResponse() throws Exception {
+ PowerMockito.mockStatic(AAIApiVersion.class);
+ when(AAIApiVersion.get()).thenReturn(aaiApiVersion);
+
+ SearchGraph mockSearchGraph = Mockito.mock(SearchGraph.class);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenReturn(mockSearchGraph);
+ Response mockResp = new MockResponse();
+ when(mockSearchGraph.runNodesQuery(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyListOf(String.class),
+ Mockito.anyListOf(String.class), Mockito.any(AAIExtensionMap.class)))
+ .thenReturn(mockResp);
+
+ HttpHeaders headers = Mockito.mock(HttpHeaders.class);
+ List<MediaType> mediaTypeList = new ArrayList<MediaType>();
+ mediaTypeList.add(MediaType.APPLICATION_JSON_TYPE);
+ when(headers.getAcceptableMediaTypes()).thenReturn(mediaTypeList);
+ List<String> searchNodeTypes = new ArrayList<String>();
+ searchNodeTypes.add("vserver");
+ List<String> edgeFilterList = new ArrayList<String>();
+ edgeFilterList.add("pserver:EXISTS");
+ edgeFilterList.add("hostname:test-hostname");
+ List<String> filterList = new ArrayList<String>();
+ filterList.add("vserver-name2:EXISTS:");
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setRequestURI(nodeQueryUri);
+ MockSearchProvider mockSearchProvider = new MockSearchProvider();
+ Response resp = mockSearchProvider.getNodesQueryResponse(headers, req ,
+ "vserver", edgeFilterList,
+ filterList);
+ assertEquals(200, resp.getStatus());
+ }
+
+ /**
+ * Test get nodes query response AAI exception.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetNodesQueryResponse_AAIException() throws Exception {
+ PowerMockito.mockStatic(AAIApiVersion.class);
+ when(AAIApiVersion.get()).thenReturn(aaiApiVersion);
+
+ SearchGraph mockSearchGraph = Mockito.mock(SearchGraph.class);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenReturn(mockSearchGraph);
+ Response response = Mockito.mock(Response.class);
+ when(response.getStatus()).thenReturn(500);
+ ResponseBuilder responseBuilder = Mockito.mock(ResponseBuilder.class);
+ when(runtimeDelegate.createResponseBuilder()).thenReturn(responseBuilder);
+ when((responseBuilder).status(Response.Status.INTERNAL_SERVER_ERROR)).thenReturn(responseBuilder);
+ when((responseBuilder).entity(Mockito.anyObject())).thenReturn(responseBuilder);
+ when((responseBuilder).build()).thenReturn(response);
+ when(mockSearchGraph.runNodesQuery(Mockito.anyString(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyListOf(String.class),
+ Mockito.anyListOf(String.class), Mockito.any(AAIExtensionMap.class)))
+ .thenThrow(new AAIException());
+
+ HttpHeaders headers = Mockito.mock(HttpHeaders.class);
+ List<MediaType> mediaTypeList = new ArrayList<MediaType>();
+ mediaTypeList.add(MediaType.APPLICATION_JSON_TYPE);
+ when(headers.getAcceptableMediaTypes()).thenReturn(mediaTypeList);
+ List<String> searchNodeTypes = new ArrayList<String>();
+ searchNodeTypes.add("vserver");
+ List<String> edgeFilterList = new ArrayList<String>();
+ edgeFilterList.add("pserver:EXISTS");
+ edgeFilterList.add("hostname:test-hostname");
+ List<String> filterList = new ArrayList<String>();
+ filterList.add("vserver-name2:EXISTS:");
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setRequestURI(nodeQueryUri);
+ MockSearchProvider mockSearchProvider = new MockSearchProvider();
+ Response resp = mockSearchProvider.getNodesQueryResponse(headers, req ,
+ "vserver", edgeFilterList,
+ filterList);
+ assertEquals(500, resp.getStatus());
+ }
+
+ /**
+ * Test get nodes query response exception.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetNodesQueryResponse_Exception() throws Exception {
+ PowerMockito.mockStatic(AAIApiVersion.class);
+ when(AAIApiVersion.get()).thenReturn(aaiApiVersion);
+
+ SearchGraph mockSearchGraph = Mockito.mock(SearchGraph.class);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenReturn(mockSearchGraph);
+ Response response = Mockito.mock(Response.class);
+ when(response.getStatus()).thenReturn(500);
+ ResponseBuilder responseBuilder = Mockito.mock(ResponseBuilder.class);
+ when(runtimeDelegate.createResponseBuilder()).thenReturn(responseBuilder);
+ when((responseBuilder).status(Response.Status.INTERNAL_SERVER_ERROR)).thenReturn(responseBuilder);
+ when((responseBuilder).entity(Mockito.anyObject())).thenReturn(responseBuilder);
+ when((responseBuilder).build()).thenReturn(response);
+ PowerMockito.whenNew(SearchGraph.class).withNoArguments().thenThrow(new Exception());
+
+ HttpHeaders headers = Mockito.mock(HttpHeaders.class);
+ List<MediaType> mediaTypeList = new ArrayList<MediaType>();
+ mediaTypeList.add(MediaType.APPLICATION_JSON_TYPE);
+ when(headers.getAcceptableMediaTypes()).thenReturn(mediaTypeList);
+ List<String> searchNodeTypes = new ArrayList<String>();
+ searchNodeTypes.add("vserver");
+ List<String> edgeFilterList = new ArrayList<String>();
+ edgeFilterList.add("pserver:EXISTS");
+ edgeFilterList.add("hostname:test-hostname");
+ List<String> filterList = new ArrayList<String>();
+ filterList.add("vserver-name2:EXISTS:");
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setRequestURI(nodeQueryUri);
+ MockSearchProvider mockSearchProvider = new MockSearchProvider();
+ Response resp = mockSearchProvider.getNodesQueryResponse(headers, req , "vserver",
+ edgeFilterList, filterList);
+ assertEquals(500, resp.getStatus());
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/rest/util/ValidateEncodingTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/rest/util/ValidateEncodingTest.java
new file mode 100644
index 0000000..db07bbb
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/rest/util/ValidateEncodingTest.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.rest.util;
+
+import static org.junit.Assert.*;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.openecomp.aai.rest.util.ValidateEncoding;
+
+public class ValidateEncodingTest {
+
+
+ @Test
+ public void badPath() throws UnsupportedEncodingException {
+ String badPath = "/aai/v6/network/vces/vce/blahh::blach/others/other/jklfea{}";
+ UriInfo mockUriInfo = getMockUriInfo(badPath, new MultivaluedHashMap<String, String>());
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertEquals(false, validator.validate(mockUriInfo));
+ }
+ @Ignore
+ @Test
+ public void goodPath() throws UnsupportedEncodingException {
+ String goodPath = "/aai/v6/network/vces/vce/blahh%3A%3Ablach/others/other/jklfea%7B%7D";
+ UriInfo mockUriInfo = getMockUriInfo(goodPath, new MultivaluedHashMap<String, String>());
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertEquals(true, validator.validate(mockUriInfo));
+ }
+ @Ignore
+ @Test
+ public void badQueryParamsKey() throws UnsupportedEncodingException {
+ MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
+ map.putSingle("blahblah", "test");
+ map.putSingle("blahblah", "test2");
+ map.putSingle("bad::bad", "test3");
+ UriInfo mockUriInfo = getMockUriInfo("", map);
+
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertEquals(false, validator.validate(mockUriInfo));
+
+ }
+ @Ignore
+ @Test
+ public void badQueryParamsValue() throws UnsupportedEncodingException {
+ MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
+ map.putSingle("blahblah", "test");
+ map.putSingle("blahblah", "test//:2");
+ map.putSingle("badbad", "test3");
+ UriInfo mockUriInfo = getMockUriInfo("", map);
+
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertEquals(false, validator.validate(mockUriInfo));
+ }
+ @Ignore
+ @Test
+ public void goodQueryParams() throws UnsupportedEncodingException {
+ MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
+ map.putSingle("blahblah", "test");
+ map.putSingle("blahblah", "test2");
+ map.putSingle("badbad", "~test%2F%2F%3A3");
+ UriInfo mockUriInfo = getMockUriInfo("", map);
+
+ ValidateEncoding validator = ValidateEncoding.getInstance();
+
+ assertEquals(true, validator.validate(mockUriInfo));
+ }
+
+ private UriInfo getMockUriInfo(String path, MultivaluedMap<String, String> map) {
+ UriInfo mockUriInfo = Mockito.mock(UriInfo.class);
+ Mockito.when(mockUriInfo.getPath(false)).thenReturn(path);
+ Mockito.when(mockUriInfo.getQueryParameters(false)).thenReturn(map);
+
+ return mockUriInfo;
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/schema/db/AuditOXMTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/schema/db/AuditOXMTest.java
new file mode 100644
index 0000000..5e93080
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/schema/db/AuditOXMTest.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.schema.db;
+
+import java.io.IOException;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.db.schema.AuditDoc;
+import org.openecomp.aai.db.schema.AuditOXM;
+import org.openecomp.aai.db.schema.Auditor;
+import org.openecomp.aai.db.schema.AuditorFactory;
+import org.openecomp.aai.introspection.Version;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+@Ignore("not ready for testing")
+public class AuditOXMTest {
+
+ /**
+ * Before.
+ */
+ @BeforeClass
+ public static void before() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+
+ }
+
+
+ /**
+ * Gets the graph audit.
+ *
+ * @return the graph audit
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ @Test
+ public void getGraphAudit() throws JsonGenerationException, JsonMappingException, IOException {
+ TitanGraph graph = TitanFactory.open("bundleconfig-local/etc/appprops/aaiconfig.properties");
+ Auditor a = AuditorFactory.getGraphAuditor(graph);
+ AuditDoc doc = a.getAuditDoc();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(doc);
+ System.out.println(json);
+
+ }
+
+ /**
+ * Gets the audit.
+ *
+ * @return the audit
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ @Test
+ public void getAudit() throws JsonGenerationException, JsonMappingException, IOException {
+ AuditOXM oxm = new AuditOXM(Version.v8);
+
+ AuditDoc doc = oxm.getAuditDoc();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(doc);
+ System.out.println(json);
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/schema/db/ManageSchemaTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/schema/db/ManageSchemaTest.java
new file mode 100644
index 0000000..6a1d0cd
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/schema/db/ManageSchemaTest.java
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.schema.db;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.db.schema.DBIndex;
+import org.openecomp.aai.db.schema.ManageTitanSchema;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.schema.TitanManagement;
+
+@Ignore("not ready yet")
+public class ManageSchemaTest {
+
+ private TitanGraph graph = null;
+ @BeforeClass
+ public static void before() {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local");
+
+ }
+
+ @Before
+ public void beforeTest() {
+ //graph = TitanFactory.open("src/test/resources/inmemory_titan.properties");
+ graph = TitanFactory.open("bundleconfig-local/etc/appprops/aaiconfig.properties");
+ }
+
+ /*
+ @Test
+ public void populateEmptyGraph() {
+ ManageTitanSchema schema = new ManageTitanSchema(graph);
+ schema.buildSchema();
+ }
+
+ @Test
+ public void modifyIndex() {
+ ManageTitanSchema schema = new ManageTitanSchema(graph);
+ schema.buildSchema();
+ Vertex v = graph.addVertex();
+ v.setProperty("aai-node-type", "pserver");
+ v.setProperty("hostname", "test1");
+ v.setProperty("internet-topology", "test2");
+ graph.commit();
+ DBIndex index = new DBIndex();
+ index.setName("internet-topology");
+ index.setUnique(false);
+ schema.updateIndex(index);
+
+ }
+ */
+ @Test
+ public void closeRunningInstances() {
+
+ TitanManagement mgmt = graph.openManagement();
+ Set<String> instances = mgmt.getOpenInstances();
+
+ for (String instance : instances) {
+
+ if (!instance.contains("(current)")) {
+ mgmt.forceCloseInstance(instance);
+ }
+ }
+ mgmt.commit();
+
+ graph.close();
+
+ }
+ @Test
+ public void addNewIndex() throws JsonParseException, JsonMappingException, IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ String content = " {\r\n" +
+ " \"name\" : \"equipment-name\",\r\n" +
+ " \"unique\" : false,\r\n" +
+ " \"properties\" : [ {\r\n" +
+ " \"name\" : \"equipment-name\",\r\n" +
+ " \"cardinality\" : \"SINGLE\",\r\n" +
+ " \"typeClass\" : \"java.lang.String\"\r\n" +
+ " } ]\r\n" +
+ " }";
+ DBIndex index = mapper.readValue(content, DBIndex.class);
+ ManageTitanSchema schema = new ManageTitanSchema(graph);
+ TitanManagement mgmt = graph.openManagement();
+ Set<String> instances = mgmt.getOpenInstances();
+ System.out.println(instances);
+ schema.updateIndex(index);
+
+ graph.close();
+
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/serialization/db/DBSerializerMaxRetryTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/serialization/db/DBSerializerMaxRetryTest.java
new file mode 100644
index 0000000..c8e5ec3
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/serialization/db/DBSerializerMaxRetryTest.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.serialization.db;
+
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.logging.AAILogger;
+import org.openecomp.aai.logging.LogLineBuilder;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanException;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({QueryParser.class, TransactionalGraphEngine.class, TitanGraph.class, TitanTransaction.class, LoaderFactory.class, AAILogger.class, DBSerializer.class})
+public class DBSerializerMaxRetryTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /**
+ * Test.
+ *
+ * @throws Exception the exception
+ */
+ @Ignore
+ @Test
+ public void test() throws Exception {
+
+ QueryParser mockQuery = PowerMockito.mock(QueryParser.class);
+ PowerMockito.when(mockQuery.isDependent()).thenReturn(true);
+
+ TransactionalGraphEngine mockEngine = PowerMockito.mock(TransactionalGraphEngine.class);
+ PowerMockito.when(mockEngine.getQueryEngine()).thenThrow(new TitanException("mock error"));
+
+ TitanGraph mockGraph = PowerMockito.mock(TitanGraph.class);
+ PowerMockito.when(mockEngine.getGraph()).thenReturn(mockGraph);
+ TitanTransaction mockGraphTrans = PowerMockito.mock(TitanTransaction.class);
+ PowerMockito.when(mockGraph.newTransaction()).thenReturn(mockGraphTrans);
+
+ LogLineBuilder llb = new LogLineBuilder();
+ AAILogger mockLogger = PowerMockito.mock(AAILogger.class);
+
+ PowerMockito.whenNew(AAILogger.class).withAnyArguments().thenReturn(mockLogger);
+
+ PowerMockito.mockStatic(LoaderFactory.class);
+
+ DBSerializer dbs = new DBSerializer(mockEngine, mockGraph, null, null, llb);
+
+ thrown.expect(AAIException.class);
+ thrown.expectMessage("AAI_6134");
+ dbs.serializeToDb(null, null, mockQuery, null);
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiServerURLBaseTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiServerURLBaseTest.java
new file mode 100644
index 0000000..b016c7a
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiServerURLBaseTest.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openecomp.aai.util.AAIApiServerURLBase;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import static org.mockito.Mockito.*;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+@PrepareForTest({PhaseInterceptorChain.class, AAIConfig.class})
+
+public class AAIApiServerURLBaseTest {
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+ /**
+ * Test get hostname.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetHostname() throws Exception {
+ PowerMockito.mockStatic(PhaseInterceptorChain.class);
+ Map <String, List<String>> hm = new HashMap<String, List<String>>();
+ List<String> host = new ArrayList<String>();
+ host.add("my-localhost");
+ hm.put("host", host);
+
+ Message outMessage = new MessageImpl();
+ outMessage.put(Message.PROTOCOL_HEADERS, hm);
+
+ when(PhaseInterceptorChain.getCurrentMessage()).thenReturn(outMessage);
+ assertEquals("https://my-localhost/aai/", AAIApiServerURLBase.get());
+ }
+
+ /**
+ * Test get with null hostname.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetWithNullHostname() throws Exception {
+ PowerMockito.mockStatic(AAIConfig.class);
+ String defaultHostname = "default-name";
+ when(AAIConfig.get(AAIConstants.AAI_SERVER_URL_BASE)).thenReturn(defaultHostname);
+ assertEquals(defaultHostname, AAIApiServerURLBase.get());
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiVersionTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiVersionTest.java
new file mode 100644
index 0000000..89f56de
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIApiVersionTest.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.*;
+
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openecomp.aai.util.AAIApiVersion;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import static org.mockito.Mockito.*;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+@PrepareForTest({PhaseInterceptorChain.class, AAIConfig.class})
+
+public class AAIApiVersionTest {
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static { PowerMockAgent.initializeIfNeeded();}
+
+ /**
+ * Test get version.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetVersion() throws Exception {
+ PowerMockito.mockStatic(PhaseInterceptorChain.class);
+ Message outMessage = new MessageImpl();
+ String msg = "/v2/";
+ outMessage.put(Message.REQUEST_URI, msg);
+ when(PhaseInterceptorChain.getCurrentMessage()).thenReturn(outMessage);
+ assertEquals("v2", AAIApiVersion.get());
+ }
+
+ /**
+ * Test get with null version.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testGetWithNullVersion() throws Exception {
+ PowerMockito.mockStatic(AAIConfig.class);
+ String defaultURI = "default-v2";
+ when(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP, AAIConstants.AAI_DEFAULT_API_VERSION)).thenReturn(defaultURI);
+ assertEquals(defaultURI, AAIApiVersion.get());
+ }
+
+ /**
+ * Test incorrect version pattern.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testIncorrectVersionPattern() throws Exception {
+ PowerMockito.mockStatic(PhaseInterceptorChain.class);
+ PowerMockito.mockStatic(AAIConfig.class);
+ Message outMessage = new MessageImpl();
+ String msg = "2.0.1";
+ String defaultURI = "default-v2";
+ outMessage.put(Message.REQUEST_URI, msg);
+ when(PhaseInterceptorChain.getCurrentMessage()).thenReturn(outMessage);
+ when(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP, AAIConstants.AAI_DEFAULT_API_VERSION)).thenReturn(defaultURI);
+ assertEquals(defaultURI, AAIApiVersion.get());
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIAppServletContextListenerTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIAppServletContextListenerTest.java
new file mode 100644
index 0000000..05bb288
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIAppServletContextListenerTest.java
@@ -0,0 +1,179 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletContextEvent;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIAppServletContextListener;
+import org.openecomp.aai.util.AAIConfig;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.PatternLayout;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+@PrepareForTest({AAIGraph.class, AAIConfig.class, ErrorLogHelper.class})
+public class AAIAppServletContextListenerTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+ private ServletContextEvent arg;
+ private AAIAppServletContextListener listener;
+
+ /**
+ * Initialize.
+ */
+ @Before
+ @PrepareForTest({AAIGraph.class, AAIConfig.class, ErrorLogHelper.class})
+ public void initialize(){
+ arg = PowerMockito.mock(ServletContextEvent.class);
+ PowerMockito.mockStatic(AAIGraph.class);
+ PowerMockito.mockStatic(AAIConfig.class);
+ PowerMockito.mockStatic(ErrorLogHelper.class);
+
+ listener = new AAIAppServletContextListener();
+ configureLog();
+ }
+
+ /**
+ * Test contextDestroyed.
+ */
+ @Test
+ @Ignore
+ public void testContextDestroyed(){
+ listener.contextDestroyed(arg);
+ assertTrue(logContains(Level.DEBUG, "AAI Server shutdown"));
+ assertTrue(logContains(Level.INFO, "AAI graph shutdown"));
+ }
+
+ /**
+ * Test contextInitialized.
+ */
+ @Test
+ @Ignore
+ public void testContextInitialized(){
+ listener.contextInitialized(arg);
+ assertTrue(logContains(Level.DEBUG, "Loading aaiconfig.properties"));
+ assertTrue(logContains(Level.DEBUG, "Loading error.properties"));
+ assertTrue(logContains(Level.DEBUG, "Loading graph database"));
+ assertTrue(logContains(Level.INFO, "AAI Server initialization"));
+ }
+
+
+ /**
+ * Helper method to check if a String appears in the desired log level.
+ *
+ * @param level Log level to use
+ * @param expected String to search for
+ * @return True if search String is found, false otherwise
+ */
+ private boolean logContains(Level level, String expected) {
+ String actual[] = RecordingAppender.messages();
+ for (String log : actual) {
+ if (log.contains(level.toString()) && log.contains(expected))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set logging level, and initialize log-appender.
+ */
+ private void configureLog() {
+ Logger rootLogger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+ rootLogger.setLevel(Level.DEBUG);
+ rootLogger.detachAndStopAllAppenders();
+ rootLogger.addAppender(RecordingAppender.appender(new PatternLayout()));
+ }
+
+}
+
+
+/**
+ * Appender class that appends log messages to a String List when some logging event occurs
+ */
+class RecordingAppender extends AppenderBase<ILoggingEvent> {
+ private static List<String> messages = new ArrayList<String>();
+ private static RecordingAppender appender = new RecordingAppender();
+ private PatternLayout patternLayout;
+
+ private RecordingAppender() {
+ super();
+ }
+
+ /**
+ * @param patternLayout Pattern to format log message
+ * @return Current appender
+ */
+ public static RecordingAppender appender(PatternLayout patternLayout) {
+ appender.patternLayout = patternLayout;
+ appender.clear();
+ return appender;
+ }
+
+ @Override
+ protected void append(ILoggingEvent event) {
+ messages.add(patternLayout.doLayout(event));
+ }
+
+ public void close() {}
+
+ public boolean requiresLayout() {
+ return false;
+ }
+
+ /**
+ * @return Return logs as a String array
+ */
+ public static String[] messages() {
+ return (String[]) messages.toArray(new String[messages.size()]);
+ }
+
+ /**
+ * Clear the message container
+ */
+ private void clear() {
+ messages.clear();
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIConfigPasswordDecodingTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIConfigPasswordDecodingTest.java
new file mode 100644
index 0000000..d5e5923
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIConfigPasswordDecodingTest.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.util.AAIConfig;
+
+public class AAIConfigPasswordDecodingTest {
+
+ /**
+ * Configure.
+ *
+ * @throws AAIException the AAI exception
+ */
+ @BeforeClass
+ public static void configure() throws AAIException {
+ System.setProperty("AJSC_HOME", ".");
+ System.setProperty("BUNDLECONFIG_DIR", "src/test/java/bundleconfig-local"); //fake prop file for testing
+ AAIConfig.init();
+ }
+
+ /**
+ * Password check.
+ *
+ * @throws AAIException the AAI exception
+ */
+ @Ignore
+ @Test
+ public void passwordCheck() throws AAIException {
+ assertEquals("password", "aaiuser123", AAIConfig.get("ecm.auth.password"));
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIPrimaryHostTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIPrimaryHostTest.java
new file mode 100644
index 0000000..5454aac
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIPrimaryHostTest.java
@@ -0,0 +1,203 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIPrimaryHost;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+@PrepareForTest({InetAddress.class, AAIPrimaryHost.class})
+public class AAIPrimaryHostTest {
+
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+
+ AAIPrimaryHost obj = null;
+ private static final String transId = UUID.randomUUID().toString();
+ private static final String fromAppId = "AAIPrimaryHostTest";
+
+ /**
+ * Initialize.
+ */
+ @Before
+ public void initialize(){
+ partialSetupForAAIConfig();
+ obj = new AAIPrimaryHost(transId, fromAppId);
+
+ }
+
+ /**
+ * Test do commandwith failure.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testDoCommandwithFailure() throws Exception {
+ List<String> myCommands = new ArrayList<String>();
+ String command = "some-command";
+ myCommands.add(command);
+ try {
+ obj.doCommand(myCommands);
+ }
+ catch (Exception e){
+ assertTrue(e.getMessage().contains("Cannot run program \"some-command\""));
+ }
+ }
+
+ /**
+ * Test am I primary with random key name.
+ */
+ @Test
+ public void testAmIPrimary_withRandomKeyName(){
+ assertTrue("If key isn't found in the config file, log exception and return true.", obj.amIPrimary("randomName"));
+ }
+
+ /**
+ * Test am I primary with DEFAUL T CHEC K for localhost.
+ */
+ @Test
+ public void testAmIPrimary_with_DEFAULT_CHECK_for_localhost(){
+ assertTrue("localhost name should not be in the server list", obj.amIPrimary(new String("aai.primary.filetransfer.")));
+ }
+
+
+ /**
+ * Test am I primary with DEFAUL T CHEC K for valid host echo success.
+ */
+ @Test
+ public void testAmIPrimary_with_DEFAULT_CHECK_for_valid_host_echo_success(){
+ mockIP();
+ obj = getTestObject(true, "");
+ assertTrue("host name should exist in the server list in echo success", obj.amIPrimary(new String("aai.primary.filetransfer.")));
+ }
+
+ /**
+ * Test which is primary when missingconfig properties.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testWhichIsPrimaryWhenMissingconfigProperties() throws Exception {
+ assertEquals(null, obj.whichIsPrimary("checkName"));
+ }
+
+ /**
+ * Test which is primary.
+ *
+ * @throws Exception the exception
+ */
+ @Test
+ public void testWhichIsPrimary() throws Exception {
+ AAIPrimaryHost primaryHost = getTestObject(true, "primaryHost");
+ assertEquals("primaryHost", primaryHost.whichIsPrimary("aai.primary.filetransfer."));
+ }
+
+
+
+ /**
+ * Mock IP.
+ */
+ public void mockIP(){
+
+ PowerMockito.mockStatic(InetAddress.class);
+ InetAddress dummyInetAddress = null;
+ try {
+ Mockito.when(InetAddress.getLocalHost()).thenReturn(dummyInetAddress);
+ Mockito.when(dummyInetAddress.getHostAddress()).thenReturn("localhost");
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Gets the test object.
+ *
+ * @param echoStatus the echo status
+ * @param host the host
+ * @return the test object
+ */
+ public AAIPrimaryHost getTestObject(final boolean echoStatus, final String host){
+ return new AAIPrimaryHost(transId, fromAppId){
+ @Override
+ public boolean amIPrimaryUsingEcho( String hostname, String aaiPrimaryCheck, String aaiServerList) {
+ return echoStatus;
+ }
+
+ @Override
+ public String whichIsPrimaryUsingEcho( String aaiPrimaryCheck, String aaiServerList) {
+ return "primaryHost";
+ }
+
+ };
+ }
+
+
+ static void setFinalStatic(Field field, Object newValue) throws Exception {
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(null, newValue);
+ }
+
+ /**
+ * Partial setup for AAI config.
+ */
+ public void partialSetupForAAIConfig(){
+ try {
+ setFinalStatic(AAIConfig.class.getDeclaredField("GlobalPropFileName"), "src/test/resources/test_aaiconfig.properties");
+ }
+ catch (Exception e) {fail();}
+
+ AAIConfig.reloadConfig();
+ }
+
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIRSyncUtilityTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIRSyncUtilityTest.java
new file mode 100644
index 0000000..71ab75f
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIRSyncUtilityTest.java
@@ -0,0 +1,216 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIRSyncUtility;
+
+
+public class AAIRSyncUtilityTest {
+
+ AAIRSyncUtility syncUtil;
+ AAIRSyncUtility syncUtilOmitDoCommand;
+ AAIConfig aaiConfig;
+ String hostName;
+ String transId = UUID.randomUUID().toString();
+
+ /**
+ * Initialize.
+ */
+ @Before
+ public void initialize(){
+ syncUtil = new AAIRSyncUtility();
+
+ syncUtilOmitDoCommand = new AAIRSyncUtility(){
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int doCommand(List<String> command) throws Exception
+ {
+ return 1;
+ }
+ };
+
+ partialSetupForAAIConfig();
+
+ InetAddress ip = null;
+ try {
+ ip = InetAddress.getLocalHost();
+ } catch (UnknownHostException e2) {
+ e2.printStackTrace();
+ }
+ hostName = ip.getHostName();
+ }
+
+
+ /**
+ * Test sendRsync.
+ */
+ @Ignore
+ @Test
+ public void testSendRsyncCommand(){
+ syncUtilOmitDoCommand.sendRsyncCommand(transId, "RandomFileName");
+ //TODO write codes to check what is being logged
+ }
+
+ /**
+ * Test getHost.
+ */
+ @Test
+ public void testGetHost(){
+
+ String returnedHost = null;
+ Method getHostMethod = makePublic("getHost");
+ try {
+ returnedHost = (String)getHostMethod.invoke(syncUtil, null);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+
+ assertEquals("Host name didn't match", returnedHost, hostName);
+ }
+
+ /**
+ * Test getRemoteHostList.
+ */
+ @Test
+ public void testGetRemoteHostList(){
+ String localHost = "host_local";
+ String remoteHost1 = "hostR1";
+ String remoteHost2 = "hostR2";
+ ArrayList<String> remotes = new ArrayList<String>();
+ remotes.add(remoteHost1);
+ remotes.add(remoteHost2);
+
+ StringTokenizer stTokenizer = new StringTokenizer(remoteHost1+"\r"+remoteHost2+"\r"+localHost);
+
+ Method m = makePublic("getRemoteHostList");
+ try {
+ assertEquals("Remote host missing", remotes, m.invoke(syncUtil, stTokenizer, localHost));
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Test doCommand.
+ */
+ @Test
+ public void testDoCommand(){
+
+ assertTrue("Don't have execute permissions", Files.isExecutable(new File(".").toPath()));
+
+ List<String> commands = new ArrayList<String>();
+ commands.add("ping");
+ commands.add("google.com");
+ try {
+ assertEquals("Failed to execute commands", 1, syncUtilOmitDoCommand.doCommand(commands));
+ } catch (Exception e) {
+ fail("Failed to execute a command");
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Test doCommand with null.
+ */
+ @Test
+ public void testDoCommand_withNull(){
+ assertTrue("Don't have execute permissions", Files.isExecutable(new File(".").toPath()));
+ try {
+ assertEquals("This should be unreachable", 1, syncUtil.doCommand(null));
+ } catch (Exception e) {
+ assertTrue("Expecting an NPE from ProcessBuilder", e instanceof NullPointerException);
+ }
+
+ }
+
+
+ /**
+ * Helper method to covert access type of a method from private to public .
+ *
+ * @param privateMethodName Method which is private originally
+ * @return method object with 'access type = 'public'
+ */
+ public Method makePublic(String privateMethodName){
+ Method targetMethod = null;
+ try {
+ if (privateMethodName.equals("getHost"))
+ targetMethod = AAIRSyncUtility.class.getDeclaredMethod(privateMethodName, null);
+ else if (privateMethodName.equals("getRemoteHostList"))
+ targetMethod = AAIRSyncUtility.class.getDeclaredMethod(privateMethodName, StringTokenizer.class, String.class);
+ } catch (NoSuchMethodException | SecurityException e) {
+ e.printStackTrace();
+ }
+ targetMethod.setAccessible(true);
+ return targetMethod;
+ }
+
+ /**
+ * Helper method to load aai config from test configuration file
+ * This requires that the 'test_aaiconfig.properties' file is available
+ */
+ static void setFinalStatic(Field field, Object newValue) throws Exception {
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(null, newValue);
+ }
+
+ /**
+ * Helper method to setup AAIConfig for test.
+ */
+ public void partialSetupForAAIConfig(){
+ try {
+ setFinalStatic(AAIConfig.class.getDeclaredField("GlobalPropFileName"), "src/test/resources/test_aaiconfig.properties");
+ }
+ catch (SecurityException e) {fail();}
+ catch (NoSuchFieldException e) {fail();}
+ catch (Exception e) {fail();}
+
+ AAIConfig.reloadConfig();
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAITxnLogTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAITxnLogTest.java
new file mode 100644
index 0000000..8929e33
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAITxnLogTest.java
@@ -0,0 +1,362 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.openecomp.aai.domain.notificationEvent.NotificationEvent;
+import org.openecomp.aai.domain.translog.TransactionLogEntries;
+import org.openecomp.aai.domain.translog.TransactionLogEntry;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAITxnLog;
+import org.openecomp.aai.util.PojoUtils;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+
+@PrepareForTest({HBaseConfiguration.class, Configuration.class,
+ HTable.class, Result.class, ResultScanner.class, Scan.class,
+ Get.class, NotificationEvent.class,
+ NotificationEvent.EventHeader.class, PojoUtils.class, AAITxnLog.class})
+
+public class AAITxnLogTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+ AAITxnLog aaiTnxLog;
+ Configuration config;
+ HTable htable;
+ Result result;
+ ResultScanner resScanner;
+ Scan scan;
+ Get g;
+ NotificationEvent notif;
+ NotificationEvent.EventHeader ehNotif;
+ PojoUtils pu;
+
+ boolean hasNotifEvent = true;
+ final String notifPayload = "A random payload";
+ final String notifID = "1";
+ final String notifEntityLink = "nLink";
+ final String notifAction = "nAction";
+ final String notifStatus = "nStatus";
+ final String notifTopic = "nTopic";
+
+ final String tid = "tidVal";
+ final String status = "statusVal";
+ final String rqstTm = "rqstTmVal";
+ final String respTm = "respTmVal";
+ final String srcId = "srcIdVal";
+ final String rsrcId = "rsrcIdVal";
+ final String rsrcType = "rsrcTypeVal";
+ final String rqstBuf = "rqstBufVal";
+ final String respBuf = "respBufVal";
+
+
+ /**
+ * Initialize.
+ */
+ @Before
+ public void initialize(){
+ partialSetupForAAIConfig();
+ PowerMockito.mockStatic(HBaseConfiguration.class);
+ config = PowerMockito.mock(Configuration.class);
+ htable = PowerMockito.mock(HTable.class);
+ result = PowerMockito.mock(Result.class);
+ resScanner = PowerMockito.mock(ResultScanner.class);
+ scan = PowerMockito.mock(Scan.class);
+ g = PowerMockito.mock(Get.class);
+ notif = PowerMockito.mock(NotificationEvent.class);
+ ehNotif = PowerMockito.mock(NotificationEvent.EventHeader.class);
+ pu = PowerMockito.mock(PojoUtils.class);
+
+
+ mockNotificationEvent();
+
+ Mockito.when(HBaseConfiguration.create()).thenReturn(config);
+ aaiTnxLog = new AAITxnLog(tid, srcId);
+
+ try {
+ PowerMockito.whenNew(HTable.class).withAnyArguments().thenReturn(htable);
+ PowerMockito.whenNew(Get.class).withAnyArguments().thenReturn(g);
+ PowerMockito.whenNew(PojoUtils.class).withAnyArguments().thenReturn(pu);
+ PowerMockito.whenNew(Scan.class).withAnyArguments().thenReturn(scan);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ mockResult();
+
+ try {
+ PowerMockito.when(htable.get(g)).thenReturn(result);
+ PowerMockito.when(htable.getScanner(scan)).thenReturn(resScanner);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Method to test 'put' operation without a notification event.
+ */
+ @Test
+ public void testPut_withoutNotifEvent(){
+ String htid = aaiTnxLog.put(tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf);
+ try {
+ TransactionLogEntry tle = aaiTnxLog.get(htid);
+ hasNotifEvent = false;
+ validateTransactionLogEntry(tle);
+ } catch (AAIException e) {
+ fail("Cant read back data from htable");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Method to test 'put' operation with a notification event.
+ */
+ @Test
+ public void testPut_withNotifEvent(){
+ hasNotifEvent = true;
+ String htid = aaiTnxLog.put(tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf, hasNotifEvent, notif);
+ try {
+ TransactionLogEntry tle = aaiTnxLog.get(htid);
+ validateTransactionLogEntry(tle);
+ } catch (AAIException e) {
+ fail("Cant read back data from htable");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Method to test 'scan' over an empty htable.
+ */
+ @Test
+ public void testScan_withEmptyHTable(){
+ String key = tid;
+ List<String> res = aaiTnxLog.scan(key);
+ assertTrue("Scan output should be empty", res.size() == 0 );
+ }
+
+ /**
+ * Method to test 'scan' operation.
+ */
+ @Test
+ public void testScan(){
+ try {
+ PowerMockito.when(resScanner.next()).thenReturn(result).thenReturn(null);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ List<String> res = aaiTnxLog.scan(tid);
+ assertTrue("Scan output should not be empty", res.size()==1);
+ assertTrue("Did not find entry in 'scan'", res.get(0).equals(result.toString()));
+ }
+
+ /**
+ * Method to test 'scanFiltered' with an empty htable.
+ */
+ @Test
+ public void testScanFiltered_withEmptyHTable(){
+ aaiTnxLog.put(tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf, true, new NotificationEvent());
+ TransactionLogEntries tles = aaiTnxLog.scanFiltered(0, 100, null, null, null, null, null);
+ assertTrue ("scanFilstered output should be empty", tles.getTransactionLogEntries().size() == 0);
+ }
+
+ /**
+ * Method to test 'scanFiltered' operation.
+ */
+ @Test
+ public void testScanFiltered(){
+ try {
+ PowerMockito.when(resScanner.next()).thenReturn(result).thenReturn(null);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ aaiTnxLog.put(tid, status, rqstTm, respTm, srcId, rsrcId, rsrcType, rqstBuf, respBuf, true, new NotificationEvent());
+ TransactionLogEntries tles = aaiTnxLog.scanFiltered(0, 100, null, null, null, null, null);
+ assertFalse ("scanFilstered output should not be empty", tles.getTransactionLogEntries().size() == 0);
+ validateTransactionLogEntry(tles.getTransactionLogEntries().get(0));
+ }
+
+ /**
+ * Helper method to validate the contents of a TransactionalLogEntry.
+ *
+ * @param tle TransactionalLogEntry to compare against
+ */
+ public void validateTransactionLogEntry(TransactionLogEntry tle){
+ String pre = "validateTransactionLogEntry: ";
+ String post = " didn't match";
+ assertEquals(pre + "tid" + post, tle.getTransactionLogEntryId(), tid);
+ assertEquals(pre + "status" + post, tle.getStatus(), status);
+ assertEquals(pre + "rqstDate" + post, tle.getRqstDate(), rqstTm);
+ assertEquals(pre + "respDate" + post, tle.getRespDate(), respTm);
+ assertEquals(pre + "srcId" + post, tle.getSourceId(), srcId);
+ assertEquals(pre + "rsrcId" + post, tle.getResourceId(), rsrcId);
+ assertEquals(pre + "rqstBuf" + post, tle.getRqstBuf(), rqstBuf);
+ assertEquals(pre + "respBuf" + post, tle.getrespBuf(), respBuf);
+ if ( hasNotifEvent){
+ assertEquals(pre + "notifPayload" + post, tle.getNotificationPayload(), notifPayload);
+ assertEquals(pre + "notifStatus" + post, tle.getNotificationStatus(), notifStatus);
+ assertEquals(pre + "notifID" + post, tle.getNotificationId(), notifID);
+ assertEquals(pre + "notifTopic" + post, tle.getNotificationTopic(), notifTopic);
+ assertEquals(pre + "notifEntityLink" + post, tle.getNotificationEntityLink(), notifEntityLink);
+ assertEquals(pre + "notifAction" + post, tle.getNotificationAction(), notifAction);
+ }
+ }
+
+
+
+ /**
+ * Helper method to mock PojoUtils.
+ */
+ public void mockPojoUtils(){
+
+ try {
+ PowerMockito.when(pu.getJsonFromObject(notif)).thenReturn(notifPayload);
+ } catch (JsonGenerationException e) {e.printStackTrace();}
+ catch (JsonMappingException e) {e.printStackTrace();}
+ catch (IOException e) {e.printStackTrace(); }
+ }
+
+
+
+ /**
+ * Helper method to mock a notification event handler.
+ */
+ public void mockNotifEventHandler(){
+ PowerMockito.when(ehNotif.getId()).thenReturn(notifID);
+ PowerMockito.when(ehNotif.getEntityLink()).thenReturn(notifEntityLink);
+ PowerMockito.when(ehNotif.getAction()).thenReturn(notifAction);
+ PowerMockito.when(ehNotif.getStatus()).thenReturn(notifStatus);
+ }
+
+ /**
+ * Helper method to mock a notification event.
+ */
+ public void mockNotificationEvent(){
+ mockPojoUtils();
+ mockNotifEventHandler();
+ PowerMockito.when(notif.getEventHeader()).thenReturn(ehNotif);
+ PowerMockito.when(notif.getEventHeader().getEventType()).thenReturn(null);
+ PowerMockito.when(notif.getEventHeader().getStatus()).thenReturn(null);
+ }
+
+
+ /**
+ * Helper method to build a mock-Result.
+ */
+ public void mockResult(){
+ PowerMockito.when(result.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("tid"))).thenReturn(Bytes.toBytes(tid));
+ PowerMockito.when(result.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("status"))).thenReturn(Bytes.toBytes(status));
+ PowerMockito.when(result.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("rqstDate"))).thenReturn(Bytes.toBytes(rqstTm));
+ PowerMockito.when(result.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("respDate"))).thenReturn(Bytes.toBytes(respTm));
+ PowerMockito.when(result.getValue(Bytes.toBytes("transaction"),Bytes.toBytes("sourceId"))).thenReturn(Bytes.toBytes(srcId));
+
+ PowerMockito.when(result.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceId"))).thenReturn(Bytes.toBytes(rsrcId));
+ PowerMockito.when(result.getValue(Bytes.toBytes("resource"),Bytes.toBytes("resourceType"))).thenReturn(Bytes.toBytes(rsrcType));
+
+ PowerMockito.when(result.getValue(Bytes.toBytes("payload"),Bytes.toBytes("rqstBuf"))).thenReturn(Bytes.toBytes(rqstBuf));
+ PowerMockito.when(result.getValue(Bytes.toBytes("payload"),Bytes.toBytes("respBuf"))).thenReturn(Bytes.toBytes(respBuf));
+
+ PowerMockito.when(result.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationPayload"))).thenReturn(Bytes.toBytes(notifPayload));
+ PowerMockito.when(result.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationStatus"))).thenReturn(Bytes.toBytes(notifStatus));
+ PowerMockito.when(result.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationId"))).thenReturn(Bytes.toBytes(notifID));
+ PowerMockito.when(result.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationTopic"))).thenReturn(Bytes.toBytes(notifTopic));
+ PowerMockito.when(result.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationEntityLink"))).thenReturn(Bytes.toBytes(notifEntityLink));
+ PowerMockito.when(result.getValue(Bytes.toBytes("notification"),Bytes.toBytes("notificationAction"))).thenReturn(Bytes.toBytes(notifAction));
+ }
+
+
+ /**
+ * Helper method to load aai config from test configuration file
+ * This requires that the 'test_aaiconfig.properties' file is available
+ */
+
+ static void setFinalStatic(Field field, Object newValue) throws Exception {
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(null, newValue);
+ }
+
+ /**
+ * Partial setup for AAI config.
+ */
+ public void partialSetupForAAIConfig(){
+
+ try {
+ setFinalStatic(AAIConfig.class.getDeclaredField("GlobalPropFileName"), "src/test/resources/test_aaiconfig.properties");
+ }
+ catch (SecurityException e) {fail();}
+ catch (NoSuchFieldException e) {fail();}
+ catch (Exception e) {fail();}
+
+ AAIConfig.reloadConfig();
+ }
+
+ /**
+ * Helper method to set the file name of aaiconfig.properties file
+ *
+ * @param field Private static filed for update
+ * @param newValue New value to be used
+ * @throws Exception the exception
+ */
+ public void modifyFinalStatic(Field field, Object newValue) throws Exception {
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(null, newValue);
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIUtilsTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIUtilsTest.java
new file mode 100644
index 0000000..5b2d1c4
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/AAIUtilsTest.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openecomp.aai.util.AAIUtils;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+public class AAIUtilsTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+
+ AAIUtils testObj;
+
+ /**
+ * Initialize.
+ */
+ @Before
+ public void initialize(){
+ testObj = new AAIUtils();
+ }
+
+ /**
+ * Test nullCheck with null.
+ */
+ @Test
+ public void testNullCheck_withNull(){
+ List<String> newList = null;
+ assertNotNull("method nullCheck should not return null", AAIUtils.nullCheck(newList));
+ }
+
+ /**
+ * Test nullCheck with a List.
+ */
+ @Test
+ public void testNullCheck_withList(){
+ List<String> newList = new ArrayList<String>();
+ newList.add("testString");
+ assertNotNull("method nullCheck failed for a List", AAIUtils.nullCheck(newList));
+ }
+
+ /**
+ * Test genDate using a past and a future date.
+ */
+ @Test
+ public void testGenDate(){
+
+ Date d1 = new Date(0);
+
+ DateFormat formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
+ formatter.setLenient(false);
+
+ Date d2 = null;
+
+ try {
+ d2 = formatter.parse(AAIUtils.genDate());
+ } catch (ParseException e) {
+ fail("Date parsing exception");
+ e.printStackTrace();
+ }
+
+ try {
+ TimeUnit.SECONDS.sleep(1);
+ } catch (InterruptedException e1) {}
+
+ Date d3 = new Date();
+
+ assertTrue("Generated date is not after a past date", d2.after(d1));
+ assertTrue("Generated date is not before a future date", d2.before(d3));
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/CNNameTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/CNNameTest.java
new file mode 100644
index 0000000..5ba1701
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/CNNameTest.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.openecomp.aai.util.CNName;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import ch.qos.logback.access.spi.IAccessEvent;
+
+@PowerMockIgnore("javax.security.auth.x500.X500Principal")
+@PrepareForTest({IAccessEvent.class, HttpServletRequest.class, X509Certificate.class})
+public class CNNameTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+
+ IAccessEvent mockAccEvent;
+ HttpServletRequest mockHttpServletRequest;
+ CNName cnname;
+ X509Certificate cert;
+
+ /**
+ * Initialize.
+ */
+ @Before
+ public void initialize(){
+ mockAccEvent = Mockito.mock(IAccessEvent.class);
+ mockHttpServletRequest = Mockito.mock(HttpServletRequest.class);
+ cert = Mockito.mock(X509Certificate.class);
+ }
+
+
+ /**
+ * Test 'convert' when there is no AccessConverter.
+ */
+ @Test
+ public void testConvert_withoutAccessConverter(){
+ cnname = getTestObj(false);
+ assertTrue("Conversion failed with no AccessConverter", "INACTIVE_HEADER_CONV".equals(cnname.convert(mockAccEvent)));
+ }
+
+ /**
+ * Test 'convert' with no CipherSuite.
+ */
+ @Test
+ public void testConvert_withNullCipherSuite(){
+ setupForCipherSuite(null);
+ assertTrue("Conversion failed for a null CipherSuite", "-".equals(cnname.convert(mockAccEvent)));
+ }
+
+
+ /**
+ * Test 'convert' with a non-null CipherSuite.
+ */
+ @Test
+ public void testConvert_withNotNullCipherSuite(){
+
+ setupForCipherSuite("StrRepOfAValidSuite");
+
+ final X500Principal principal = new X500Principal("CN=AnAI, OU=DOX, O=BWS, C=CA");
+
+ Mockito.when(cert.getSubjectX500Principal()).thenReturn(principal);
+
+ final X509Certificate[] certChain = {cert};
+
+ when(mockHttpServletRequest.getAttribute("javax.servlet.request.X509Certificate")).thenReturn(certChain);
+
+ assertTrue("Conversion failed for a valid CipherSuite", principal.toString().equals(cnname.convert(mockAccEvent)));
+ }
+
+
+ /**
+ * Helper method to mock IAccessEvent and HttpServletRequest.
+ *
+ * @param suite CipherSuite to be used in current test
+ */
+ private void setupForCipherSuite(String suite){
+ cnname = getTestObj(true);
+ when(mockAccEvent.getRequest()).thenReturn(mockHttpServletRequest);
+ when(mockHttpServletRequest.getAttribute("javax.servlet.request.cipher_suite")).thenReturn(suite);
+ }
+
+
+ /**
+ * Helper method to create a CNName object with overridden 'start status' .
+ *
+ * @param instanceStarted Start status to be used
+ * @return CNName object to test
+ */
+ private CNName getTestObj(final boolean instanceStarted){
+ return new CNName(){
+ @Override
+ public boolean isStarted(){
+ return instanceStarted;
+ }
+ };
+ }
+}
+
+
+
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/CustomLogPatternLayoutTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/CustomLogPatternLayoutTest.java
new file mode 100644
index 0000000..aa946b0
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/CustomLogPatternLayoutTest.java
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.openecomp.aai.util.CNName;
+import org.openecomp.aai.util.CustomLogPatternLayout;
+
+public class CustomLogPatternLayoutTest {
+
+ /**
+ * Test null when defaultConverterMap doesn't have corresponding entry.
+ */
+ @Test
+ public void testNull(){
+ String s = CustomLogPatternLayout.defaultConverterMap.get("z");
+ assertFalse("Entry not found for key 'z'", CNName.class.getName().equals(s));
+ }
+
+ /**
+ * Test defaultConverterMap when valid entry exists.
+ */
+ @Test
+ public void testEntryFor_Z(){
+ CustomLogPatternLayout layout = new CustomLogPatternLayout();
+ String s = CustomLogPatternLayout.defaultConverterMap.get("z");
+ assertTrue("Entry not found for key 'z'", CNName.class.getName().equals(s));
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/DataConversionHelperTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/DataConversionHelperTest.java
new file mode 100644
index 0000000..9df8900
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/DataConversionHelperTest.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openecomp.aai.util.DataConversionHelper;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+public class DataConversionHelperTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ static {
+ PowerMockAgent.initializeIfNeeded();
+ }
+
+ /**
+ * Test convertIPVersionNumToString with value "4".
+ */
+ @Test
+ public void testConvertIPVersionNumToString_withNum4(){
+ assertEquals(DataConversionHelper.IPVERSION_IPV4, DataConversionHelper.convertIPVersionNumToString("4"));
+ }
+
+ /**
+ * Test convertIPVersionNumToString with value "6".
+ */
+ @Test
+ public void testConvertIPVersionNumToString_withNum6(){
+ assertEquals(DataConversionHelper.IPVERSION_IPV6, DataConversionHelper.convertIPVersionNumToString("6"));
+ }
+
+ /**
+ * Test convertIPVersionNumToString with a value other than "4" or "6".
+ */
+ @Test
+ public void testConvertIPVersionNumToString_withAThirdNumber(){
+ assertEquals(DataConversionHelper.IPVERSION_UNKNOWN, DataConversionHelper.convertIPVersionNumToString("-1"));
+ }
+
+ /**
+ * Test convertIPVersionStringToNum with "v4".
+ */
+ @Test
+ public void testConvertIPVersionStringToNum_withV4(){
+ assertEquals("4", DataConversionHelper.convertIPVersionStringToNum(DataConversionHelper.IPVERSION_IPV4));
+ }
+
+ /**
+ * Test convertIPVersionStringToNum with "v6".
+ */
+ @Test
+ public void testConvertIPVersionStringToNum_withV6(){
+ assertEquals("6", DataConversionHelper.convertIPVersionStringToNum(DataConversionHelper.IPVERSION_IPV6));
+ }
+
+ /**
+ * Test convertIPVersionStringToNum with an illegal version.
+ */
+ @Test
+ public void testConvertIPVersionStringToNum_withRandomString(){
+ assertEquals("0", DataConversionHelper.convertIPVersionStringToNum("test string"));
+ }
+
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestConfig.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestConfig.java
new file mode 100644
index 0000000..4f84519
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestConfig.java
@@ -0,0 +1,303 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.TimerTask;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Timer;
+import java.net.InetAddress;
+
+public class DbTestConfig {
+
+ public static final String AUDIT_FILESEP = (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator");
+ public static final String AUDIT_HOME = (System.getProperty("audit.home") == null) ? AUDIT_FILESEP + "opt" + AUDIT_FILESEP + "audit" : System.getProperty("audit.home");
+ public static final String AuditPropFilename = "c:\\tmp\\auditConfig.prop";
+ public static final String AUDIT_CONFIG_CHECKINGTIME = "audit.config.checktime";
+ public static final String AUDIT_NODENAME = "localhost";
+ public static final String AUDIT_DEBUG = "audit.config.debug";
+
+ private static Properties serverProps;
+ private static boolean propsInitialized = false;
+ private static boolean timerSet = false;
+ private static Timer timer = null;
+
+ private static String propFile = null;
+
+ /**
+ * Inits the.
+ *
+ * @param propertyFile the property file
+ */
+ public synchronized static void init(String propertyFile) {
+ propFile = propertyFile;
+ init();
+ }
+
+ /**
+ * Inits the.
+ */
+ public synchronized static void init() {
+ System.out.println("Initializing Config");
+
+ DbTestConfig.getConfigFile();
+ DbTestConfig.reloadConfig();
+
+ if ( propFile == null)
+ propFile = AuditPropFilename;
+ TimerTask task = null;
+ task = new DbTestFileWatcher ( new File(propFile)) {
+ protected void onChange( File file ) {
+ // here we implement the onChange
+ DbTestConfig.reloadConfig();
+ }
+ };
+
+ if (!timerSet) {
+ timerSet = true;
+ // repeat the check every second
+ timer = new Timer();
+ String fwi = DbTestConfig.get(AUDIT_CONFIG_CHECKINGTIME);
+ timer.schedule( task , new Date(), Integer.parseInt(fwi) );
+ System.out.println("Config Watcher Interval=" + fwi);
+
+ System.out.println("File" + propFile+" Loaded!");
+ }
+
+ }
+
+ /**
+ * Cleanup.
+ */
+ public static void cleanup() {
+ timer.cancel();
+ }
+
+ /**
+ * Gets the config file.
+ *
+ * @return the config file
+ */
+ public static String getConfigFile() {
+ return propFile;
+ }
+
+ /**
+ * Reload config.
+ */
+ public synchronized static void reloadConfig() {
+
+ String propFileName = propFile;
+
+ Properties newServerProps = null;
+
+ System.out.println("Reloading config from "+propFileName);
+
+ try {
+ InputStream is = new FileInputStream(propFileName);
+ newServerProps = new Properties();
+ newServerProps.load(is);
+ propsInitialized = true;
+
+ serverProps = newServerProps;
+ if (get(AUDIT_DEBUG).equals("on")) {
+ serverProps.list(System.out);
+ }
+ newServerProps = null;
+
+ } catch (FileNotFoundException fnfe) {
+ System.out.println("AuditConfig: " + propFileName + ". FileNotFoundException: "+fnfe.getMessage());
+ } catch (IOException e) {
+ System.out.println("AuditConfig: " + propFileName + ". IOException: "+e.getMessage());
+ }
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param key the key
+ * @param defaultValue the default value
+ * @return the string
+ */
+ public static String get(String key, String defaultValue) {
+ String result = defaultValue;
+ try {
+ result = get (key);
+ }
+ catch ( Exception a ) {
+ }
+ return result;
+ }
+
+ /**
+ * Gets the.
+ *
+ * @param key the key
+ * @return the string
+ */
+ public static String get(String key) {
+ String response = null;
+
+ if (key.equals(AUDIT_NODENAME)) {
+ // Get this from InetAddress rather than the properties file
+ String nodeName = getNodeName();
+ if (nodeName != null) {
+ return nodeName;
+ }
+ // else get from property file
+ }
+
+ if (!propsInitialized || (serverProps == null)) {
+ reloadConfig();
+ }
+ if (!serverProps.containsKey(key)) {
+ System.out.println( "Property key "+key+" cannot be found");
+ } else {
+ response = serverProps.getProperty(key);
+ if (response == null || response.isEmpty()) {
+ System.out.println("Property key "+key+" is null or empty");
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Gets the int.
+ *
+ * @param key the key
+ * @return the int
+ */
+ public static int getInt(String key) {
+ return Integer.valueOf(DbTestConfig.get(key));
+ }
+
+ /**
+ * Gets the server props.
+ *
+ * @return the server props
+ */
+ public static Properties getServerProps() {
+ return serverProps;
+ }
+
+ /**
+ * Gets the node name.
+ *
+ * @return the node name
+ */
+ public static String getNodeName() {
+ try {
+ InetAddress ip = InetAddress.getLocalHost();
+ if (ip != null) {
+ String hostname = ip.getHostName();
+ if (hostname != null) {
+ return hostname;
+ }
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * Extracts a specific property key subset from the known properties.
+ * The prefix may be removed from the keys in the resulting dictionary,
+ * or it may be kept. In the latter case, exact matches on the prefix
+ * will also be copied into the resulting dictionary.
+ *
+ * @param prefix is the key prefix to filter the properties by.
+ * @param keepPrefix if true, the key prefix is kept in the resulting
+ * dictionary. As side-effect, a key that matches the prefix exactly
+ * will also be copied. If false, the resulting dictionary's keys are
+ * shortened by the prefix. An exact prefix match will not be copied,
+ * as it would result in an empty string key.
+ * @return a property dictionary matching the filter key. May be
+ * an empty dictionary, if no prefix matches were found.
+ *
+ * @see #getProperty( String ) is used to assemble matches
+ */
+ public static Properties matchingSubset(String prefix, boolean keepPrefix) {
+ Properties result = new Properties();
+
+ // sanity check
+ if (prefix == null || prefix.length() == 0) {
+ return result;
+ }
+
+ String prefixMatch; // match prefix strings with this
+ String prefixSelf; // match self with this
+ if (prefix.charAt(prefix.length() - 1) != '.') {
+ // prefix does not end in a dot
+ prefixSelf = prefix;
+ prefixMatch = prefix + '.';
+ } else {
+ // prefix does end in one dot, remove for exact matches
+ prefixSelf = prefix.substring(0, prefix.length() - 1);
+ prefixMatch = prefix;
+ }
+ // POSTCONDITION: prefixMatch and prefixSelf are initialized!
+
+ // now add all matches into the resulting properties.
+ // Remark 1: #propertyNames() will contain the System properties!
+ // Remark 2: We need to give priority to System properties. This is done
+ // automatically by calling this class's getProperty method.
+ String key;
+ for (Enumeration e = serverProps.keys(); e.hasMoreElements(); ) {
+ key = (String) e.nextElement();
+
+ if (keepPrefix) {
+ // keep full prefix in result, also copy direct matches
+ if (key.startsWith(prefixMatch) || key.equals(prefixSelf)) {
+ result.setProperty(key, serverProps.getProperty(key));
+ }
+ } else {
+ // remove full prefix in result, dont copy direct matches
+ if (key.startsWith(prefixMatch)) {
+ result.setProperty(key.substring(prefixMatch.length()), serverProps.getProperty(key));
+ }
+ }
+ }
+
+ // done
+ return result;
+ }
+
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+ DbTestConfig.init( );
+
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestFileWatcher.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestFileWatcher.java
new file mode 100644
index 0000000..05a4cfe
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestFileWatcher.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.util.*;
+import java.io.*;
+
+public abstract class DbTestFileWatcher extends TimerTask {
+ private long timeStamp;
+ private File file;
+
+ /**
+ * Instantiates a new db test file watcher.
+ *
+ * @param file the file
+ */
+ public DbTestFileWatcher( File file ) {
+ this.file = file;
+ this.timeStamp = file.lastModified();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void run() {
+ long timeStamp = file.lastModified();
+
+ if( (timeStamp - this.timeStamp) > 500 ) {
+ this.timeStamp = timeStamp;
+ onChange(file);
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * On change.
+ *
+ * @param file the file
+ */
+ protected abstract void onChange( File file );
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestGetFileTime.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestGetFileTime.java
new file mode 100644
index 0000000..d56a4d2
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestGetFileTime.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+
+public class DbTestGetFileTime {
+
+
+ /**
+ * Creates the file return time.
+ *
+ * @param path the path
+ * @return the file time
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public FileTime createFileReturnTime( String path) throws IOException {
+ File file = new File(path);
+ if(!file.exists()) {
+ file.createNewFile();
+ }
+ Path p = Paths.get(file.getAbsolutePath());
+ BasicFileAttributes view
+ = Files.getFileAttributeView(p, BasicFileAttributeView.class)
+ .readAttributes();
+ FileTime fileTime=view.creationTime();
+ // also available view.lastAccessTine and view.lastModifiedTime
+ return fileTime;
+ }
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestProcessBuilder.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestProcessBuilder.java
new file mode 100644
index 0000000..8d8ebe0
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/DbTestProcessBuilder.java
@@ -0,0 +1,218 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.attribute.FileTime;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+public class DbTestProcessBuilder {
+ ///public static Logger clog = Logger.getLogger("auditConsole");
+ //public static Logger alog = Logger.getLogger("auditLog");
+
+ /**
+ * Start audit process non blocking.
+ *
+ * @param wait the wait
+ * @param cmds the cmds
+ * @param dir the dir
+ */
+ public void startAuditProcessNonBlocking(final long wait, final String cmds[], final String dir) {
+
+ final ProcessBuilder pb = new ProcessBuilder(cmds).redirectErrorStream(true).directory(new File(dir));
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ //System.out.println( "sleeping seconds " + wait + " cmds " + Arrays.toString(cmds));
+ Thread.sleep(wait*1000);
+ //System.out.println( "returned from sleep");
+ final Process p = pb.start();
+ //System.out.println( "returned from pb.start");
+ final InputStream is = p.getInputStream();
+ final BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+ final InputStreamReader isr = new InputStreamReader(is);
+ final BufferedReader br = new BufferedReader(isr);
+//clog.debug("Output of running " + Arrays.toString(cmds) + " is:");
+ System.out.println("Output of running is:" );
+ String line;
+ while ((line = br.readLine()) != null ) {
+ System.out.println(line);
+ }
+ System.out.println("stderr of running is:" );
+
+ while ((line = stdError.readLine()) != null ) {
+ System.out.println(line);
+ }
+
+ } catch (IOException ie) {
+
+ } catch (InterruptedException itre) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }).start();
+
+ }
+
+
+ private final ScheduledExecutorService auditProcessScheduler =
+ Executors.newScheduledThreadPool(10);
+
+ /**
+ * Run W command every X seconds for Y minutes.
+ *
+ * @param w the w
+ * @param x the x
+ * @param y the y
+ * @param runningDir the running dir
+ */
+ public void runWCommandEveryXSecondsForYMinutes(String[] w, int x, int y, final String runningDir) {
+ final String[] c1 = w;
+ final Runnable audit = new Runnable() {
+ public void run() {
+//clog.debug("checkpoint "+(new Date()).toString());
+ DbTestProcessBuilder a1 = new DbTestProcessBuilder();
+ a1.startAuditProcessNonBlocking(1, c1, "/tmp");
+ }
+ };
+
+ final ScheduledFuture<?> auditHandle =
+ auditProcessScheduler.scheduleAtFixedRate(audit, 0, x, TimeUnit.SECONDS);
+ auditProcessScheduler.schedule(new Runnable() {
+ public void run() {
+ auditHandle.cancel(true);
+ }
+ }, y * 60, TimeUnit.SECONDS);
+ }
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ @SuppressWarnings({ "null", "static-access" })
+ public static void main(String args[]) {
+ String props = "NA";
+ if (args.length > 0) {
+ System.out.println( "DbTestProcessBuilder called with " + args.length + " arguments, " + args[0]);
+ props = args[0].trim();
+ } else {
+ System.out.print("usage: DbTestProcessBuilder <auditConfig.prop path\n");
+ return;
+ }
+ DbTestConfig.init(props);
+ String ail = DbTestConfig.get("audit.list");
+ String path = DbTestConfig.get("audit.path");
+ final String runningDir = DbTestConfig.get("audit.runningdir");
+ try {
+ DbTestGetFileTime getFileTime = new DbTestGetFileTime();
+ FileTime fileTime = getFileTime.createFileReturnTime( path );
+ System.out.println(path + " creation time :"
+ + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss")
+ .format(fileTime.toMillis()) + " runningDir " + runningDir);
+ } catch ( IOException io ) {
+ System.out.println( "IOException getting creation time " + path + " message " + io.getMessage());
+ io.printStackTrace();
+ }
+
+ List<String> items = Arrays.asList(ail.split("\\s*,\\s*"));
+ for (String ai: items) {
+ if (!DbTestConfig.get("audit.task."+ai+".status").startsWith("a")) {
+ continue;
+ }
+//clog.debug("***audit item = " + ai + " Starting***");
+
+ String w1 = DbTestConfig.get("audit.task."+ai+".cmd");
+ String[] w2 = w1.split("\\s*,\\s*");
+ System.out.print( "task items are : " + Arrays.toString(w2));
+ // append the audit item name as the prefix of the audit directory name
+ /*final int N = w2.length;
+ w2 = Arrays.copyOf(w2, N+1);
+ w2[N-2] = "\"-Dp=" + DbTestConfig.get("audit.task.odl.output.dir")+ai + "\"";
+//clog.debug("***java -D:"+w2[N-2]);
+ //w2[N] = "\""+DbTestConfig.get("audit.task.odl.output.dir")+ai+"\"";
+ w2[N] = "\""+DbTestConfig.get("audit.task.odl.output.dir")+ai+"\"";
+ */
+ DbTestProcessBuilder apb = new DbTestProcessBuilder();
+
+ String ts1 = DbTestConfig.get("audit.task."+ai+".schedule");
+ String[] ts2 = ts1.split("\\s*,\\s*");
+ // note ts2[0] is the wait-before time, and it is not being used right now. We start with ts2[1]
+ apb.runWCommandEveryXSecondsForYMinutes(w2,Integer.parseInt(ts2[1]),Integer.parseInt(ts2[2]), runningDir);
+//clog.debug("***audit item = " + ai + " started***");
+ System.out.println( "started test " + ai);
+
+ /*
+ int ct = 0;
+
+ while (true) try {
+ if (DbTestConfig.get("jcl").startsWith("q")) {
+ System.out.println("***Audit Main Program exiting...");
+ System.exit(0);
+ }
+
+ Thread.currentThread().sleep(1000);
+ if (ct < 10) {
+ ct++;
+ } else {
+ //clog.debug(AuditConfig.get("jcl").charAt(0));
+ ct=0;
+ }
+
+ } catch (InterruptedException ie) {
+
+ } */
+ }
+ int ct = 0;
+
+ while (true) try {
+ if (DbTestConfig.get("jcl").startsWith("q")) {
+ System.out.println("***Audit Main Program exiting...");
+ System.exit(0);
+ }
+
+ Thread.currentThread().sleep(1000);
+ if (ct < 10) {
+ ct++;
+ } else {
+ //clog.debug(AuditConfig.get("jcl").charAt(0));
+ ct=0;
+ }
+
+ } catch (InterruptedException ie) {
+
+ }
+
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/DeleteResourceTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/DeleteResourceTest.java
new file mode 100644
index 0000000..efe4a41
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/DeleteResourceTest.java
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+
+
+import static org.junit.Assert.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+
+import static org.junit.Assert.assertTrue;
+
+import static org.junit.Assert.fail;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.aai.util.DeleteResource;
+import org.openecomp.aai.domain.yang.PhysicalLink;
+
+
+
+public class DeleteResourceTest {
+
+
+
+ /**
+ * Test getInstance.
+ */
+
+ @Test
+
+ public void testGetInstance(){
+
+ Object obj = null;
+
+ try {
+
+ obj = DeleteResource.getInstance(DeleteResource.class);
+
+ } catch (IllegalAccessException | InstantiationException e) {
+
+ e.printStackTrace();
+
+ }
+
+ assertTrue("Didn't get right instance", obj instanceof DeleteResource);
+
+ }
+
+
+
+ /**
+ * Test GetResourceVersion.
+ */
+ @Ignore
+ @Test
+
+ public void testGetResourceVersion(){
+
+ String version = "aVersion";
+
+ PhysicalLink plink = new PhysicalLink();
+
+ plink.setResourceVersion(version);
+
+ assertEquals("Versions didn't match", version, DeleteResource.GetResourceVersion(plink));
+
+ }
+
+
+
+ /**
+ * Test null in GetResourceVersion.
+ */
+
+ @Test
+
+ public void testGetResourceVersion_withNull(){
+
+ PhysicalLink plink = new PhysicalLink();
+
+ assertEquals("Versions didn't match", null, DeleteResource.GetResourceVersion(plink));
+
+ }
+
+
+
+}
+
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/HbaseSaltPrefixerTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/HbaseSaltPrefixerTest.java
new file mode 100644
index 0000000..ff1b53b
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/HbaseSaltPrefixerTest.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.openecomp.aai.util.HbaseSaltPrefixer;
+
+public class HbaseSaltPrefixerTest {
+
+ /**
+ * Test.
+ */
+ @Test
+ public void test() {
+ String key = "imakey";
+ String saltedKey = HbaseSaltPrefixer.getInstance().prependSalt(key);
+ assertTrue(saltedKey.equals("0-imakey"));
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtilTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtilTest.java
new file mode 100644
index 0000000..39fec9b
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtilTest.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.util;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.openecomp.aai.util.JettyObfuscationConversionCommandLineUtil;
+
+
+public class JettyObfuscationConversionCommandLineUtilTest {
+ private final ByteArrayOutputStream testOut = new ByteArrayOutputStream();
+
+ /**
+ * Test.
+ */
+ @Test
+ public void test() {
+ //setup, this will catch main's print statements for evaluation
+ System.setOut(new PrintStream(testOut));
+
+ /* ------ TEST OBFUSCATION ----*/
+ JettyObfuscationConversionCommandLineUtil.main(new String[]{"-e", "hello world"});
+ /*
+ * testOut was also catching any logging statements which interfered with result checking.
+ * This regex business was the workaround - it tries to find the expected value in
+ * the results and asserts against that.
+ */
+ String obfResult = testOut.toString();
+ String obfExpected = "OBF:1thf1ugo1x151wfw1ylz11tr1ymf1wg21x1h1uh21th7";
+ Pattern obfExpectPat = Pattern.compile(obfExpected);
+ Matcher obfMatch = obfExpectPat.matcher(obfResult);
+ assertTrue(obfMatch.find());
+
+ testOut.reset(); //clear out previous result
+
+ /* ------ TEST DEOBFUSCATION ----- */
+ JettyObfuscationConversionCommandLineUtil.main(new String[]{"-d", obfExpected});
+ String deobfResult = testOut.toString();
+ String deobfExpected = "hello world";
+ Pattern deobfExpectPat = Pattern.compile(deobfExpected);
+ Matcher deobfMatch = deobfExpectPat.matcher(deobfResult);
+ assertTrue(deobfMatch.find());
+
+ //clean up, resets to stdout
+ System.setOut(null);
+ }
+
+}
diff --git a/ajsc-aai/src/test/java/org/openecomp/aai/workarounds/RemoveDME2QueryParamsTest.java b/ajsc-aai/src/test/java/org/openecomp/aai/workarounds/RemoveDME2QueryParamsTest.java
new file mode 100644
index 0000000..80bcef8
--- /dev/null
+++ b/ajsc-aai/src/test/java/org/openecomp/aai/workarounds/RemoveDME2QueryParamsTest.java
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.workarounds;
+
+import static org.junit.Assert.*;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openecomp.aai.workarounds.RemoveDME2QueryParams;
+
+public class RemoveDME2QueryParamsTest {
+
+ private MultivaluedMap<String, String> hasParams;
+ private MultivaluedMap<String, String> doesNotHaveParams;
+ private RemoveDME2QueryParams removeParams = new RemoveDME2QueryParams();
+
+ /**
+ * Setup.
+ */
+ @Before
+ public void setup() {
+ hasParams = new MultivaluedHashMap<>();
+ doesNotHaveParams = new MultivaluedHashMap<>();
+
+ hasParams.add("version", "1");
+ hasParams.add("envContext", "DEV");
+ hasParams.add("routeOffer", "INT1");
+ hasParams.add("test1", "peppermints");
+ hasParams.add("test2", "amber");
+
+ doesNotHaveParams.add("version", "1");
+ doesNotHaveParams.add("envContext", "DEV");
+ doesNotHaveParams.add("test1", "peppermints");
+ doesNotHaveParams.add("test2", "amber");
+
+ }
+
+ /**
+ * Test removal.
+ */
+ @Test
+ public void testRemoval() {
+
+ if (removeParams.shouldRemoveQueryParams(hasParams)) {
+ removeParams.removeQueryParams(hasParams);
+ }
+
+ assertEquals("no version", false, hasParams.containsKey("version"));
+ assertEquals("no envContext", false, hasParams.containsKey("envContext"));
+ assertEquals("no routeOffer", false, hasParams.containsKey("routeOffer"));
+ assertEquals("has test1", true, hasParams.containsKey("test1"));
+ assertEquals("has test2", true, hasParams.containsKey("test2"));
+
+ }
+
+ /**
+ * Should not remove.
+ */
+ @Test
+ public void shouldNotRemove() {
+
+ if (removeParams.shouldRemoveQueryParams(doesNotHaveParams)) {
+ removeParams.removeQueryParams(doesNotHaveParams);
+ }
+
+ assertEquals("no version", true, doesNotHaveParams.containsKey("version"));
+ assertEquals("no envContext", true, doesNotHaveParams.containsKey("envContext"));
+ assertEquals("has test1", true, doesNotHaveParams.containsKey("test1"));
+ assertEquals("has test2", true, doesNotHaveParams.containsKey("test2"));
+ }
+}
diff --git a/ajsc-aai/src/test/resources/inmemory_titan.properties b/ajsc-aai/src/test/resources/inmemory_titan.properties
new file mode 100644
index 0000000..46695d6
--- /dev/null
+++ b/ajsc-aai/src/test/resources/inmemory_titan.properties
@@ -0,0 +1,21 @@
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+storage.backend=inmemory
diff --git a/ajsc-aai/src/test/resources/log4j.properties b/ajsc-aai/src/test/resources/log4j.properties
new file mode 100644
index 0000000..2e68f61
--- /dev/null
+++ b/ajsc-aai/src/test/resources/log4j.properties
@@ -0,0 +1,3 @@
+log4j.logger.org.apache.zookeeper=WARN
+log4j.logger.org.apache.hadoop.hbase.zookeeper=WARN
+log4j.logger.org.apache.hadoop.hbase.client=WARN \ No newline at end of file
diff --git a/ajsc-aai/src/test/resources/logback.xml b/ajsc-aai/src/test/resources/logback.xml
new file mode 100644
index 0000000..7f167f1
--- /dev/null
+++ b/ajsc-aai/src/test/resources/logback.xml
@@ -0,0 +1,288 @@
+<!--
+ ============LICENSE_START=======================================================
+ org.openecomp.aai
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+ <contextName>${module.ajsc.namespace.name}</contextName>
+ <jmxConfigurator />
+ <property name="logDirectory" value="${AJSC_HOME}/logs" />
+
+ <!-- Example evaluator filter applied against console appender -->
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> -->
+ <level>ERROR</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n
+ </pattern>
+ </encoder>
+ </appender>
+
+ <appender name="METRIC"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/metric.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/metric.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <!-- <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy> -->
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="DEBUG"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>DEBUG</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/debug.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/debug.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <!-- <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>-->
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="ERROR"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>WARN</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/rest/error.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/error.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <!-- <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>-->
+ <encoder>
+ <!-- <pattern>"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n"</pattern> -->
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="AUDIT"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator>
+ <matcher>
+ <Name>audit</Name>
+ <!-- filter out odd numbered statements -->
+ <regex>co\=aairest</regex>
+ </matcher>
+ <expression>level == INFO &amp;&amp; audit.matches(formattedMessage)</expression>
+ </evaluator>
+ <OnMatch>ACCEPT</OnMatch>
+ <OnMismatch>DENY</OnMismatch>
+ </filter>
+ <file>${logDirectory}/rest/audit.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/metric.log.%d{yyyy-MM-dd}</fileNamePattern>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%m%n</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="auditLogs"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ </filter>
+ <file>${logDirectory}/rest/audit.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/audit-${lrmRVer}-${lrmRO}-${Pid}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ </rollingPolicy>
+ <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy>
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+
+ <appender name="perfLogs"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ </filter>
+ <file>${logDirectory}/rest/perform.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/rest/perform-${lrmRVer}-${lrmRO}-${Pid}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ </rollingPolicy>
+ <!-- <triggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+ <maxFileSize>5MB</maxFileSize>
+ </triggeringPolicy> -->
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+
+ <!-- Spring related loggers -->
+ <logger name="org.springframework" level="WARN" />
+ <logger name="org.springframework.beans" level="WARN" />
+ <logger name="org.springframework.web" level="WARN" />
+ <logger name="com.blog.spring.jms" level="WARN" />
+
+ <!-- AJSC Services (bootstrap services) -->
+ <logger name="ajsc" level="WARN" />
+ <logger name="ajsc.RouteMgmtService" level="WARN" />
+ <logger name="ajsc.ComputeService" level="WARN" />
+ <logger name="ajsc.VandelayService" level="WARN" />
+ <logger name="ajsc.FilePersistenceService" level="WARN" />
+ <logger name="ajsc.UserDefinedJarService" level="WARN" />
+ <logger name="ajsc.UserDefinedBeansDefService" level="WARN" />
+ <logger name="ajsc.LoggingConfigurationService" level="WARN" />
+
+ <!-- AJSC related loggers (DME2 Registration, csi logging, restlet, servlet
+ logging) -->
+ <logger name="ajsc.utils" level="WARN" />
+ <logger name="ajsc.utils.DME2Helper" level="WARN" />
+ <logger name="ajsc.filters" level="WARN" />
+ <logger name="ajsc.beans.interceptors" level="WARN" />
+ <logger name="ajsc.restlet" level="WARN" />
+ <logger name="ajsc.servlet" level="WARN" />
+ <logger name="com.att.ajsc" level="WARN" />
+ <logger name="com.att.ajsc.csi.logging" level="WARN" />
+ <logger name="com.att.ajsc.filemonitor" level="WARN" />
+
+ <!-- Other Loggers that may help troubleshoot -->
+ <logger name="net.sf" level="WARN" />
+ <logger name="org.apache.commons.httpclient" level="WARN" />
+ <logger name="org.apache.commons" level="WARN" />
+ <logger name="org.apache.coyote" level="WARN" />
+ <logger name="org.apache.jasper" level="WARN" />
+
+ <!-- Camel Related Loggers (including restlet/servlet/jaxrs/cxf logging.
+ May aid in troubleshooting) -->
+ <logger name="org.apache.camel" level="WARN" />
+ <logger name="org.apache.cxf" level="WARN" />
+ <logger name="org.apache.camel.processor.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.jaxrs.interceptor" level="WARN" />
+ <logger name="org.apache.cxf.service" level="WARN" />
+ <logger name="org.restlet" level="WARN" />
+ <logger name="org.apache.camel.component.restlet" level="WARN" />
+
+ <!-- logback internals logging -->
+ <logger name="ch.qos.logback.classic" level="INFO" />
+ <logger name="ch.qos.logback.core" level="INFO" />
+
+ <!-- logback jms appenders & loggers definition starts here -->
+
+<!-- <if condition='property("JMS_BROKER").contains("WMQ")'>
+ <then>
+ <appender name="Audit-Record-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName" value="${JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME}" />
+ <param name="ProviderURL" value="${JMS_WMQ_PROVIDER_URL}" />
+ <param name="DestinationName" value="${JMS_WMQ_AUDIT_DESTINATION_NAME}" />
+ <param name="ConnectionFactoryName" value="${JMS_WMQ_CONNECTION_FACTORY_NAME}" />
+ </appender>
+ <appender name="Performance-Tracker-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName" value="${JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME}" />
+ <param name="ProviderURL" value="${JMS_WMQ_PROVIDER_URL}" />
+ <param name="DestinationName" value="${JMS_WMQ_PERF_DESTINATION_NAME}" />
+ <param name="ConnectionFactoryName" value="${JMS_WMQ_CONNECTION_FACTORY_NAME}" />
+ </appender>
+ </then>
+ <else> --> <!-- logback jms appenders definition starts here -->
+<!-- <appender name="Audit-Record-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName"
+ value="com.tibco.tibjms.naming.TibjmsInitialContextFactory" />
+ <param name="ProviderURL" value="${JMS_TIBCO_PROVIDER_URL}" />
+ <param name="userName" value="${JMS_LOGGER_USER_NAME}" />
+ <param name="password" value="${JMS_LOGGER_PASSWORD}" />
+ <QueueBindingName>${JMS_LOGGER_AUDIT_QUEUE_BINDING}
+ </QueueBindingName>
+ </appender>
+ <appender name="Performance-Tracker-Queue" class="ajsc.JMSQueueAppender">
+ <param name="InitialContextFactoryName"
+ value="com.tibco.tibjms.naming.TibjmsInitialContextFactory" />
+ <param name="ProviderURL" value="${JMS_TIBCO_PROVIDER_URL}" />
+ <param name="userName" value="${JMS_LOGGER_USER_NAME}" />
+ <param name="password" value="${JMS_LOGGER_PASSWORD}" />
+ <QueueBindingName>${JMS_LOGGER_PERF_QUEUE_BINDING}
+ </QueueBindingName>
+ </appender>
+ </else>
+ </if> -->
+
+ <appender name="ASYNC-audit" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <discardingThreshold>0</discardingThreshold>
+ <appender-ref ref="Audit-Record-Queue" />
+ </appender>
+
+ <appender name="ASYNC-perf" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>1000</queueSize>
+ <discardingThreshold>0</discardingThreshold>
+ <appender-ref ref="Performance-Tracker-Queue" />
+ </appender>
+
+ <!--
+ <logger name="AuditRecord" level="INFO" additivity="FALSE">
+ <appender-ref ref="ASYNC-audit" />
+ <appender-ref ref="auditLogs" />
+ </logger>
+ <logger name="AuditRecord_DirectCall" level="INFO" additivity="FALSE">
+ <appender-ref ref="ASYNC-audit" />
+ <appender-ref ref="auditLogs" />
+ </logger>
+ <logger name="PerfTrackerRecord" level="INFO" additivity="FALSE">
+ <appender-ref ref="ASYNC-perf" />
+ <appender-ref ref="perfLogs" />
+ </logger>
+ -->
+
+ <logger name="org.openecomp.aai" level="INFO" />
+
+ <logger name="org.apache" level="WARN" />
+ <logger name="org.zookeeper" level="WARN" />
+ <logger name="com.thinkaurelius" level="WARN" />
+
+ <root level="WARN">
+ <appender-ref ref="DEBUG" />
+ <appender-ref ref="ERROR" />
+ <appender-ref ref="METRIC" />
+ <appender-ref ref="AUDIT" />
+ </root>
+
+</configuration>
diff --git a/ajsc-aai/src/test/resources/test_aaiconfig.properties b/ajsc-aai/src/test/resources/test_aaiconfig.properties
new file mode 100644
index 0000000..8d0859f
--- /dev/null
+++ b/ajsc-aai/src/test/resources/test_aaiconfig.properties
@@ -0,0 +1,94 @@
+###
+# ============LICENSE_START=======================================================
+# org.openecomp.aai
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+####################################################################
+# REMEMBER TO THINK ABOUT ENVIRONMENTAL DIFFERENCES AND CHANGE THE
+# TEMPLATE AND *ALL* DATAFILES
+####################################################################
+
+aai.config.checktime=1000
+
+# this could come from siteconfig.pl?
+aai.config.nodename=AutomaticallyOverwritten
+
+aai.logging.hbase.interceptor=true
+aai.logging.hbase.enabled=true
+aai.logging.hbase.logrequest=true
+aai.logging.hbase.logresponse=true
+
+aai.logging.trace.enabled=true
+aai.logging.trace.logrequest=false
+aai.logging.trace.logresponse=false
+
+aai.auth.cspcookies_on=false
+aai.server.url.base=https://localhost:8443/aai/
+aai.server.url=https://localhost:8443/aai/v8/
+aai.truststore.filename=aai_keystore
+aai.truststore.passwd.x=70c87528c88dcd9f9c2558d30e817868
+aai.keystore.filename=aai-client-cert.p12
+aai.keystore.passwd.x=70c87528c88dcd9f9c2558d30e817868
+
+# the following parameters are not reloaded automatically and require a manual bounce
+storage.backend=hbase
+storage.hostname=localhost
+#schema.default=none
+storage.lock.wait-time=300
+storage.hbase.table=aaigraph-dev1.dev
+storage.hbase.ext.zookeeper.znode.parent=/hbase-unsecure
+# Setting db-cache to false ensure the fastest propagation of changes across servers
+cache.db-cache = false
+#cache.db-cache-clean-wait = 20
+#cache.db-cache-time = 180000
+#cache.db-cache-size = 0.5
+
+# for transaction log
+hbase.table.name=aailogging-dev1.dev
+hbase.table.timestamp.format=YYYYMMdd-HH:mm:ss:SSS
+hbase.zookeeper.quorum=localhost
+hbase.zookeeper.property.clientPort=2181
+hbase.zookeeper.znode.parent=/hbase-unsecure
+
+# single primary server
+aai.primary.filetransfer.serverlist=localhost
+aai.primary.filetransfer.primarycheck=echo:8443/aai/util/echo
+aai.primary.filetransfer.pingtimeout=5000
+aai.primary.filetransfer.pingcount=5
+
+
+#rsync properties
+aai.rsync.command=rsync
+aai.rsync.options.list=-v|-t
+aai.rsync.remote.user=aaiadmin
+aai.rsync.enabled=y
+
+aai.notification.current.version=v8
+aai.notificationEvent.default.status=UNPROCESSED
+aai.notificationEvent.default.eventType=AAI-EVENT
+aai.notificationEvent.default.domain=devINT1
+aai.notificationEvent.default.sourceName=aai
+aai.notificationEvent.default.sequenceNumber=0
+aai.notificationEvent.default.severity=NORMAL
+aai.notificationEvent.default.version=v8
+# This one lets us enable/disable resource-version checking on updates/deletes
+aai.resourceversion.enableflag=true
+aai.logging.maxStackTraceEntries=10
+aai.default.api.version=v8
+
+
diff --git a/annotations/.gitignore b/annotations/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/annotations/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/annotations/pom.xml b/annotations/pom.xml
new file mode 100644
index 0000000..92cf2a0
--- /dev/null
+++ b/annotations/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>aai-service</artifactId>
+ <version>${openecomp.release}</version>
+ </parent>
+ <artifactId>annotations</artifactId>
+ <name>annotations</name>
+ <packaging>jar</packaging>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-core</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jsonschema2pojo</groupId>
+ <artifactId>jsonschema2pojo-maven-plugin</artifactId>
+ <version>0.4.13</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-codegen-plugin</artifactId>
+ <version>${cxf.version}</version>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase/>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <configuration>
+ <skip>true</skip></configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+<executions>
+ <execution>
+ <id>make-assembly-ajsc-arch-parent</id>
+ <phase></phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>gmaven-ajsc-arch-parent</id>
+ <phase/>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/annotations/src/main/java/org/openecomp/aai/annotations/Metadata.java b/annotations/src/main/java/org/openecomp/aai/annotations/Metadata.java
new file mode 100644
index 0000000..f2a38de
--- /dev/null
+++ b/annotations/src/main/java/org/openecomp/aai/annotations/Metadata.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.aai.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
+public @interface Metadata {
+
+ boolean isKey() default false;
+ String description() default "";
+ String nameProps() default "";
+ String indexedProps() default "";
+ String dependentOn() default "";
+ String container() default "";
+ String namespace() default "";
+ String defaultValue() default "";
+ String searchable() default "";
+ String uniqueProps() default "";
+ String extendsFrom() default "";
+ String isAbstract() default "";
+ String alternateKeys1() default "";
+
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..299fc03
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>ajsc-archetype-parent</artifactId>
+ <groupId>com.att.ajsc</groupId>
+ <version>2.0.0</version>
+ </parent>
+ <groupId>org.openecomp.aai.aai-service</groupId>
+ <artifactId>aai-service</artifactId>
+ <version>${openecomp.release}</version>
+ <name>aai</name>
+ <packaging>pom</packaging>
+ <modules>
+ <module>aai-schema</module>
+ <module>annotations</module>
+ <module>ajsc-aai</module>
+ </modules>
+ <properties>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <module.ajsc.namespace.name>ActiveAndAvailableInventory-CloudNetwork</module.ajsc.namespace.name>
+ <module.ajsc.namespace.version>v1</module.ajsc.namespace.version>
+ <openecomp.release>1.0.0</openecomp.release>
+ <docker.nexusurl>${docker_nexusurl}</docker.nexusurl>
+ <ajscRuntimeVersion>2.0.0</ajscRuntimeVersion>
+
+ <!-- This will be the Absolute Root of the Project and should contain NO
+ Versioning -->
+ <absoluteDistFilesRoot>/opt/app/ajsc-aai</absoluteDistFilesRoot>
+
+ <!-- For Versioning upon installation, add /${openecomp.release} to distFilesRoot.
+ For NO Versioning, leave as is -->
+ <!-- example: /appl/${project.artifactId}/${openecomp.release}. Also, add
+ ${openecomp.release} to ${runAjscHome} for running locally. -->
+ <distFilesRoot>/opt/app/ajsc-aai/${openecomp.release}</distFilesRoot>
+ <aaiAppHome>${basedir}/ajsc-aai</aaiAppHome>
+ <runAjscHome>${aaiAppHome}/target/swm/package/nix/dist_files${distFilesRoot}</runAjscHome>
+
+ <!-- For SOA Cloud Installation -->
+ <installOwnerUser>aaiadmin</installOwnerUser>
+ <installOwnerGroup>aaiadmin</installOwnerGroup>
+ <ownerManagementGroup>org.openecomp.aai.dev</ownerManagementGroup>
+
+ <!-- Port Selection. A value of 0 will allow for dynamic port selection.
+ For local testing, you may choose to hardcode this value to something like
+ 8080 -->
+ <serverPort>8080</serverPort>
+ <sslport>8443</sslport>
+
+ <testRouteOffer>workstation</testRouteOffer>
+ <testEnv>DEV</testEnv>
+
+ <!-- For using CXF with Maven -->
+ <cxf.version>3.0.4</cxf.version>
+ </properties>
+
+ <!-- The standard build tasks for this project are inherited from the parent.
+ Please do not override the build tasks. However tasks and/or profiles can
+ be included here as well as additional dependencies for your service. Any
+ runtime or compile scope dependencies will be copied to the INSTALLATION_PATH/extJars
+ folder and will be made available on the AJSC classpath for your service.
+ Please, NOTE: DME2 and CSM related dependencies are EXTERNALIZED within the
+ CSI environment. Therefore, they are provided within this project as "provided"
+ dependencies. In order for the AJSC to run properly, locally, the CSM and
+ DME2 dependencies will be copied into the target/commonLibs folder and will
+ be made available to the classpath of the AJSC through the use of the system
+ property, "AJSC_EXTERNAL_LIB_FOLDERS". This system property needs to be set
+ in the "runAjsc" maven profile within the pom.xml (and, is defaulted to do
+ so). -->
+ <dependencies>
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.aft</groupId>
+ <artifactId>dme2</artifactId>
+ <version>3.1.200</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-core</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <profiles>
+ <profile>
+ <id>jenkins-properties</id>
+ <activation>
+ <os>
+ <family>unix</family>
+ </os>
+ </activation>
+ </profile>
+ <profile>
+ <id>runAjsc</id>
+ <build>
+ <defaultGoal>initialize</defaultGoal>
+ <plugins>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <id>run ajsc</id>
+ <phase>initialize</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ <configuration>
+ <!-- In order to better mimic a SOA cloud installation of AJSC (and
+ to help eliminate Maven/Eclipse/AJSC classpath issues that may be difficult
+ to diagnose), within this profile used to run locally, we are NOT including
+ project dependencies. These will be loaded by AJSC from $AJSC_HOME/extJars.
+ The only jar needed to run AJSC is the ajsc-runner.jar, and therefore is
+ the only dependency required by this profile to run locally. -->
+ <includeProjectDependencies>false</includeProjectDependencies>
+ <includePluginDependencies>true</includePluginDependencies>
+ <executable>java</executable>
+ <mainClass>com.att.ajsc.runner.Runner</mainClass>
+ <executableDependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ </executableDependency>
+
+ <environmentVariables>
+ <AJSC_HOME>${runAjscHome}</AJSC_HOME>
+ </environmentVariables>
+ <additionalClasspathElements>
+ <additionalClasspathElement>${runAjscHome}/extJars/logback-access-1.1.7.jar</additionalClasspathElement>
+ <additionalClasspathElement>${runAjscHome}/extJars/logback-core-1.1.7.jar</additionalClasspathElement>
+ <additionalClasspathElement>${runAjscHome}/extJars/aai-custom.jar</additionalClasspathElement>
+ </additionalClasspathElements>
+
+ <!-- Main AJSC System Properties below (necessary for proper startup) -->
+ <systemProperties>
+ <systemProperty>
+ <key>AJSC_HOME</key>
+ <value>${runAjscHome}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AFT_HOME</key>
+ <value>${runAjscHome}/bundleconfig/</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AJSC_CONF_HOME</key>
+ <value>${aaiAppHome}/bundleconfig-local</value>
+ </systemProperty>
+ <systemProperty>
+ <key>logback.configurationFile</key>
+ <value>${aaiAppHome}/ajsc-shared-config/etc/logback.xml</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AJSC_SHARED_CONFIG</key>
+ <value>${aaiAppHome}/ajsc-shared-config</value>
+ </systemProperty>
+ <systemProperty>
+ <key>file.separator</key>
+ <value>/</value>
+ </systemProperty>
+
+ <!-- Please, NOTE: The following 2 system properties will normally
+ be set within the sys-props.properties file once deployed to a node. We are
+ setting them HERE to run locally to make more efficient use of maven variable
+ replacement for ${basedir} -->
+ <!-- AJSC_EXTERNAL_LIB_FOLDERS represents the particular jars that
+ will be externalized on a CSI node. This includes dme2 and csm related artifact. -->
+ <sysproperty>
+ <key>AJSC_EXTERNAL_LIB_FOLDERS</key>
+ <value>${aaiAppHome}/target/commonLibs</value>
+ </sysproperty>
+ <!-- AJSC_EXTERNAL_PROPERTIES_FOLDERS represents the particular
+ files that may need to be added to the classpath. These files will be externalized
+ on a CSI node. This includes dme2 and csm related artifact (such as csm-config-app.properties).
+ Failure to have these files on the classpath may result in errors thrown
+ by csm framework. -->
+ <sysproperty>
+ <key>AJSC_EXTERNAL_PROPERTIES_FOLDERS</key>
+ <value>${aaiAppHome}/ajsc-shared-config/etc</value>
+ </sysproperty>
+
+ <systemProperty>
+ <key>AJSC_SERVICE_NAMESPACE</key>
+ <value>${module.ajsc.namespace.name}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>AJSC_SERVICE_VERSION</key>
+ <value>${module.ajsc.namespace.version}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>SOACLOUD_SERVICE_VERSION</key>
+ <value>${project.version}</value>
+ </systemProperty>
+ <systemProperty>
+ <key>server.port</key>
+ <value>${serverPort}</value>
+ </systemProperty>
+ </systemProperties>
+
+ <!-- Command Line Arguments to add to the java command. Here, you
+ can specify the port as well as the Context you want your service to run
+ in. Use context=/ to run in an unnamed Context (Root Context). The default
+ configuration of the AJSC is to run under the / Context. Setting the port
+ here can aid during the development phase of your service. However, you can
+ leave this argument out entirely, and the AJSC will default to using an Ephemeral
+ port. -->
+ <arguments>
+ <argument>context=/</argument>
+ <argument>port=${serverPort}</argument>
+ <argument>sslport=${sslport}</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>java</executable>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>com.att.ajsc</groupId>
+ <artifactId>ajsc-runner</artifactId>
+ <version>${ajscRuntimeVersion}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+ <build>
+ <plugins>
+ <!-- license plugin -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>license-maven-plugin</artifactId>
+ <version>1.10</version>
+ <configuration>
+ <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage>
+ <licenseName>apache_v2</licenseName>
+ <inceptionYear>2017</inceptionYear>
+ <organizationName>AT&amp;T Intellectual Property. All rights reserved.</organizationName>
+ <projectName>org.openecomp.aai</projectName>
+ <canUpdateCopyright>true</canUpdateCopyright>
+ <canUpdateDescription>true</canUpdateDescription>
+ <canUpdateLicense>true</canUpdateLicense>
+ <emptyLineAfterHeader>true</emptyLineAfterHeader>
+ <processStartTag>============LICENSE_START=======================================================</processStartTag>
+ <processEndTag>============LICENSE_END=========================================================</processEndTag>
+ <sectionDelimiter>================================================================================</sectionDelimiter>
+ <includes>
+ <include>**/*.java</include>
+ <include>**/*.ksh</include>
+ <include>**/*.sh</include>
+ <include>**/*.ftl</include>
+ <include>**/*.xsd</include>
+ <include>**/*.xjb</include>
+ <include>**/aai*.xml</include>
+ <include>**/*logback*.xml</include>
+ <include>**/*aaiconfig*.properties</include>
+ <include>**/*titan*.properties</include>
+ </includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>first</id>
+ <goals>
+ <goal>update-file-header</goal>
+ </goals>
+ <phase>process-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>sonar-maven-plugin</artifactId>
+ <version>3.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.6</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-webdav-jackrabbit</artifactId>
+ <version>2.10</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+</build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.4</version>
+ <configuration>
+ <failOnError>false</failOnError>
+ <doclet>org.umlgraph.doclet.UmlGraphDoc</doclet>
+ <docletArtifact>
+ <groupId>org.umlgraph</groupId>
+ <artifactId>umlgraph</artifactId>
+ <version>5.6</version>
+ </docletArtifact>
+ <additionalparam>-views</additionalparam>
+ <useStandardDocletOptions>true</useStandardDocletOptions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+<distributionManagement>
+ <site>
+ <id>aai-javadoc</id>
+ <url>dav:https://${docker.nexusurl}/repository/aai-javadoc/${openecomp.release}/</url>
+ </site>
+</distributionManagement>
+</project>
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..76ce1f1
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,128 @@
+# OpenECOMP AAI
+
+---
+---
+
+# Introduction
+
+OpenECOMP AAI is delivered with **3 Docker containers**, 1 hosting the **database** (Hbase), 1 hosting the AAI Model Loader micro-service and 1 hosting the AAI Service. This readme only covers the AAI Service and not the AAI Model Loader.
+
+For demo app use case the three containers run on the same VM. Configuration and deployment of hbase for any other use cases should be evaluated and updated accordingly.
+
+# Compiling AAI
+
+AAI can be compiled easily with a `mvn clean install -DskipTests`. Integration tests are started by omitting the skipTests flag `mvn clean install`
+
+The following profiles should be set up in the settings.xml file:
+
+ <profile>
+ <id>nexus</id>
+ <repositories>
+ <repository>
+ <id>repository.jboss.org-public</id>
+ <name>JBoss.org Maven repository</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public</url>
+ </repository>
+ <repository>
+ <id>global maven repo</id>
+ <url>http://repo1.maven.org/maven2/</url>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>always</updatePolicy>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>always</updatePolicy>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>maven-restlet</id>
+ <name>Public online Restlet repository</name>
+ <url>http://maven.restlet.com</url>
+ </repository>
+ </repositories>
+ </profile>
+
+ <profile>
+ <id>eelf</id>
+ <!-- Enable snapshots for the built in central repo to direct -->
+ <!-- all requests to nexus via the mirror -->
+ <repositories>
+ <repository>
+ <id>repo2</id>
+ <url>http://repo2.maven.org/maven2/com/att/eelf/</url>
+ <releases>
+ <enabled>true</enabled>
+ <!-- <updatePolicy>always</updatePolicy> <updatePolicy>never</updatePolicy>
+ <updatePolicy>daily</updatePolicy>
+ <updatePolicy>interval:in minutes</updatePolicy> -->
+ <updatePolicy>never</updatePolicy>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>always</updatePolicy>
+ <!-- <updatePolicy>always</updatePolicy> <updatePolicy>never</updatePolicy>
+ <updatePolicy>daily</updatePolicy> <updatePolicy>interval:30</updatePolicy> -->
+ </snapshots>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repo2</id>
+ <url>http://repo2.maven.org/maven2/com/att/eelf/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+ </profile>
+
+in the profiles section and also specified as an activeProfile in the activeProfiles section.
+
+ <activeProfiles>
+ <activeProfile>nexus</activeProfile>
+ <activeProfile>eelf</activeProfile>
+ </activeProfiles>
+
+
+# Starting AAI
+
+In a developer local environment using the following: mvn -N -P runAjsc
+
+# Accessing AAI APIs
+
+Most of the AAI features within OpenECOMP are triggered by using **RESTful interfaces**. AAI is configured on this release with HTTPS only using Basic Authentication. Two way SSL using client certificates should be considered and used for non demo use case deployments.
+
+The MSO APIs are configured to accept requests having a **basic auth. header** set with various **username and password** depending on which client is triggering the request. The realm.properties contains the credentials for the OpenECOMP components and these should be changed as appropriate.
+
+All API endpoints are exposed on port **8443**.
+
+##### Example API endpoints in the first open source release
+
+http://aai.api.simpledemo.openecomp.org:8443/v8/cloud-infrastructure/pservers/pserver/<pserver-id>
+
+The easy way to trigger these endpoints is to use a RESTful client or automation framework. HTTP GET/PUT/DELETE are supported for most resource endpoints. More information on the REST interface can be found in the AAI Service REST API specification.
+
+# Configuring AAI
+
+The Docker containers use a Chef based configuration file (JSON) in order to provision AAI basic configuration for the demo app use case set up.
+
+# Logging
+
+EELF framework is used for **specific logs** (audit, metric and error logs). They are tracking inter component logs (request and response) and allow to follow a complete flow through the AAI subsystem
+
+EELF logs are located at the following location on the AAI Service container:
+
+- /opt/app/aai/logs (each module has its own folder)
+
+AJSC Jetty logs can be found under /opt/app/aai/logs/ajsc-jetty.
+The REST interface logs can be found under /opt/app/aai/logs/rest.
+
+# Testing AAI Functionalities
+Any RESTful client such as SoapUI may be configured and setup to use for testing AAI requests.
+
+
+
diff --git a/version.properties b/version.properties
new file mode 100644
index 0000000..18b2af6
--- /dev/null
+++ b/version.properties
@@ -0,0 +1,16 @@
+###########################################################
+# Versioning variables
+# Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... )
+# because they are used in Jenkins, whose plug-in doesn't support
+
+major_version=1702
+minor_version=0
+load_number=0
+release_revision=0
+
+base_version=${major_version}.${minor_version}.${load_number}
+
+# Release must be completed with GIT information # in Jenkins
+release_version=${base_version}-${release_revision}
+snapshot_version=${base_version}-SNAPSHOT
+