aboutsummaryrefslogtreecommitdiffstats
path: root/ajsc-aai/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'ajsc-aai/src/main/java')
-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
255 files changed, 63016 insertions, 0 deletions
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);
+ }
+
+
+ }
+
+}