From 4c790f64daf7822de00405140d17e08f296a642f Mon Sep 17 00:00:00 2001 From: Steve Smokowski Date: Thu, 9 Feb 2017 15:27:43 -0500 Subject: Initial OpenECOMP A&AI commit Change-Id: I8b06519995d9dc0f220b80a6d9a71865b23e4edb Signed-off-by: Steve Smokowski --- .../openecomp/aai/ajsc_aai/JaxrsUserService.java | 54 + .../ajsc_aai/filemonitor/ServicePropertiesMap.java | 127 + .../ajsc_aai/util/ServicePropertiesMapBean.java | 37 + .../org/openecomp/aai/audit/ListEndpoints.java | 249 ++ .../main/java/org/openecomp/aai/auth/AAIAuth.java | 61 + .../java/org/openecomp/aai/db/AAIProperties.java | 35 + .../java/org/openecomp/aai/db/schema/AuditDoc.java | 89 + .../java/org/openecomp/aai/db/schema/AuditOXM.java | 241 ++ .../org/openecomp/aai/db/schema/AuditTitan.java | 127 + .../java/org/openecomp/aai/db/schema/Auditor.java | 58 + .../openecomp/aai/db/schema/AuditorFactory.java | 48 + .../org/openecomp/aai/db/schema/CompareByName.java | 36 + .../java/org/openecomp/aai/db/schema/DBIndex.java | 105 + .../org/openecomp/aai/db/schema/DBProperty.java | 86 + .../org/openecomp/aai/db/schema/EdgeProperty.java | 70 + .../openecomp/aai/db/schema/ManageTitanSchema.java | 329 ++ .../java/org/openecomp/aai/db/schema/Named.java | 31 + .../org/openecomp/aai/db/schema/ScriptDriver.java | 95 + .../aai/dbgen/AddResourceVersionProp.java | 126 + .../aai/dbgen/ChangePropertyCardinality.java | 307 ++ .../java/org/openecomp/aai/dbgen/DataGrooming.java | 2184 +++++++++++ .../java/org/openecomp/aai/dbgen/DataSnapshot.java | 257 ++ .../java/org/openecomp/aai/dbgen/DbEdgeGroup.java | 525 +++ .../main/java/org/openecomp/aai/dbgen/DbMeth.java | 3964 ++++++++++++++++++++ .../org/openecomp/aai/dbgen/DbSearchWithTags.java | 771 ++++ .../org/openecomp/aai/dbgen/ForceDeleteTool.java | 209 ++ .../java/org/openecomp/aai/dbgen/GenTester.java | 175 + .../openecomp/aai/dbgen/ModelBasedProcessing.java | 3490 +++++++++++++++++ .../openecomp/aai/dbgen/PropertyNameChange.java | 321 ++ .../java/org/openecomp/aai/dbgen/ResultSet.java | 124 + .../org/openecomp/aai/dbgen/SchemaGenerator.java | 433 +++ .../java/org/openecomp/aai/dbgen/SchemaMod.java | 456 +++ .../org/openecomp/aai/dbgen/UpdateEdgeTags.java | 255 ++ .../java/org/openecomp/aai/dbmap/AAIGraph.java | 142 + .../java/org/openecomp/aai/dbmap/ActionsGraph.java | 418 +++ .../org/openecomp/aai/dbmap/GraphHelpersMoxy.java | 2136 +++++++++++ .../org/openecomp/aai/dbmap/RelationshipGraph.java | 299 ++ .../java/org/openecomp/aai/dbmap/SearchGraph.java | 1475 ++++++++ .../org/openecomp/aai/dbmodel/DbEdgeRules.java | 300 ++ .../java/org/openecomp/aai/dbmodel/RestRules.java | 274 ++ .../aai/dmaap/AAIDmaapEventJMSConsumer.java | 127 + .../aai/dmaap/AAIDmaapEventJMSProducer.java | 43 + .../org/openecomp/aai/dmaap/AAIDmaapPublisher.java | 54 + .../aai/dmaap/aaiWorkload/consumer/AAIClient.java | 164 + .../aaiWorkload/consumer/AAIWorkloadConsumer.java | 207 + .../consumer/AAIWorkloadEventProcessor.java | 340 ++ .../consumer/AAIWorkloadEventStatus.java | 25 + .../openecomp/aai/domain/model/AAIResource.java | 675 ++++ .../openecomp/aai/domain/model/AAIResourceKey.java | 103 + .../aai/domain/model/AAIResourceKeys.java | 40 + .../openecomp/aai/domain/model/AAIResources.java | 86 + .../openecomp/aai/domain/model/AncestryItem.java | 107 + .../openecomp/aai/domain/model/AncestryItems.java | 40 + .../notificationEvent/NotificationEvent.java | 564 +++ .../domain/notificationEvent/ObjectFactory.java | 77 + .../domain/responseMessage/AAIResponseMessage.java | 125 + .../responseMessage/AAIResponseMessageData.java | 78 + .../responseMessage/AAIResponseMessageDatum.java | 81 + .../responseMessage/AAIResponseMessages.java | 118 + .../aai/domain/responseMessage/package-info.java | 32 + .../aai/domain/restPolicyException/Fault.java | 382 ++ .../domain/restPolicyException/ObjectFactory.java | 95 + .../restPolicyException/PolicyException.java | 134 + .../domain/restPolicyException/RESTResponse.java | 86 + .../domain/restPolicyException/RequestError.java | 87 + .../aai/domain/restResponseInfo/Info.java | 385 ++ .../aai/domain/restResponseInfo/ObjectFactory.java | 95 + .../aai/domain/restServiceException/Fault.java | 382 ++ .../domain/restServiceException/ObjectFactory.java | 95 + .../domain/restServiceException/RESTResponse.java | 86 + .../domain/restServiceException/RequestError.java | 86 + .../restServiceException/ServiceException.java | 134 + .../aai/domain/search/IncludeNodeFilter.java | 127 + .../openecomp/aai/domain/search/InventoryItem.java | 197 + .../aai/domain/search/InventoryItemData.java | 155 + .../openecomp/aai/domain/search/ObjectFactory.java | 106 + .../aai/domain/search/SecondaryFilter.java | 183 + .../aai/domain/search/StartNodeFilter.java | 155 + .../aai/domain/search/TaggedInventoryItemList.java | 96 + .../openecomp/aai/domain/search/package-info.java | 29 + .../aai/domain/translog/TransactionLogEntries.java | 131 + .../aai/domain/translog/TransactionLogEntry.java | 438 +++ .../org/openecomp/aai/exceptions/AAIException.java | 164 + .../aai/exceptions/AAIExceptionWithInfo.java | 134 + .../openecomp/aai/extensions/AAIExtensionMap.java | 880 +++++ .../aai/extensions/ExtensionController.java | 168 + .../aai/ingestModel/ConvertXmlToJsonMoxyOxm.java | 111 + .../aai/ingestModel/CreateWidgetModels.java | 164 + .../java/org/openecomp/aai/ingestModel/DbMaps.java | 64 + .../aai/ingestModel/IngestModelListener.java | 85 + .../aai/ingestModel/IngestModelMoxyOxm.java | 988 +++++ .../aai/interceptors/AAILogJAXRSInInterceptor.java | 302 ++ .../interceptors/AAILogJAXRSOutInterceptor.java | 647 ++++ .../openecomp/aai/introspection/Introspector.java | 459 +++ .../aai/introspection/IntrospectorFactory.java | 67 + .../aai/introspection/IntrospectorWalker.java | 147 + .../openecomp/aai/introspection/JSONStrategy.java | 363 ++ .../org/openecomp/aai/introspection/Loader.java | 116 + .../openecomp/aai/introspection/LoaderFactory.java | 46 + .../aai/introspection/MarshallerProperties.java | 139 + .../openecomp/aai/introspection/ModelInjestor.java | 171 + .../org/openecomp/aai/introspection/ModelType.java | 25 + .../openecomp/aai/introspection/MoxyLoader.java | 134 + .../openecomp/aai/introspection/MoxyStrategy.java | 355 ++ .../openecomp/aai/introspection/PojoInjestor.java | 63 + .../openecomp/aai/introspection/PojoLoader.java | 128 + .../openecomp/aai/introspection/PojoStrategy.java | 383 ++ .../org/openecomp/aai/introspection/Version.java | 25 + .../org/openecomp/aai/introspection/Wanderer.java | 75 + .../aai/introspection/generator/CreateExample.java | 167 + .../aai/introspection/tools/CreateUUID.java | 48 + .../aai/introspection/tools/DefaultFields.java | 48 + .../openecomp/aai/introspection/tools/Error.java | 25 + .../aai/introspection/tools/InjectKeysFromURI.java | 70 + .../introspection/tools/IntrospectorValidator.java | 278 ++ .../openecomp/aai/introspection/tools/Issue.java | 144 + .../aai/introspection/tools/IssueResolver.java | 33 + .../aai/introspection/tools/Severity.java | 27 + .../java/org/openecomp/aai/logging/AAILogger.java | 492 +++ .../org/openecomp/aai/logging/ErrorLogHelper.java | 587 +++ .../org/openecomp/aai/logging/ErrorObject.java | 328 ++ .../java/org/openecomp/aai/logging/LogLine.java | 488 +++ .../org/openecomp/aai/logging/LogLineBuilder.java | 64 + .../aai/parsers/query/LegacyQueryParser.java | 163 + .../openecomp/aai/parsers/query/QueryParser.java | 148 + .../aai/parsers/query/QueryParserStrategy.java | 86 + .../aai/parsers/query/RelationshipQueryParser.java | 72 + .../aai/parsers/query/TraversalStrategy.java | 76 + .../query/UniqueRelationshipQueryParser.java | 58 + .../aai/parsers/query/UniqueStrategy.java | 75 + .../aai/parsers/query/UniqueURIQueryParser.java | 169 + .../parsers/relationship/RelationshipToURI.java | 217 ++ .../org/openecomp/aai/parsers/uri/Parsable.java | 71 + .../org/openecomp/aai/parsers/uri/URIParser.java | 272 ++ .../org/openecomp/aai/parsers/uri/URIToDBKey.java | 127 + .../aai/parsers/uri/URIToExtensionInformation.java | 170 + .../org/openecomp/aai/parsers/uri/URIToObject.java | 224 ++ .../aai/parsers/uri/URIToRelationshipObject.java | 166 + .../aai/query/builder/GraphTraversalBuilder.java | 275 ++ .../aai/query/builder/GremlinPipelineBuilder.java | 215 ++ .../query/builder/GremlinPipelineTraversal.java | 77 + .../aai/query/builder/GremlinQueryBuilder.java | 273 ++ .../aai/query/builder/GremlinTraversal.java | 102 + .../openecomp/aai/query/builder/GremlinUnique.java | 102 + .../openecomp/aai/query/builder/QueryBuilder.java | 221 ++ .../aai/query/builder/TraversalQuery.java | 102 + .../org/openecomp/aai/rest/BulkAddConsumer.java | 412 ++ .../aai/rest/CustomJacksonJaxBJsonProvider.java | 71 + .../org/openecomp/aai/rest/ExampleConsumer.java | 111 + .../org/openecomp/aai/rest/ExceptionHandler.java | 132 + .../java/org/openecomp/aai/rest/HttpMethod.java | 33 + .../org/openecomp/aai/rest/LegacyMoxyConsumer.java | 593 +++ .../java/org/openecomp/aai/rest/MediaType.java | 66 + .../main/java/org/openecomp/aai/rest/RESTAPI.java | 391 ++ .../java/org/openecomp/aai/rest/RestProviders.java | 666 ++++ .../aai/rest/URLFromVertexIdConsumer.java | 126 + .../org/openecomp/aai/rest/VertexIdConsumer.java | 144 + .../aai/rest/actions/ActionsProvider.java | 275 ++ .../java/org/openecomp/aai/rest/db/DBRequest.java | 218 ++ .../java/org/openecomp/aai/rest/db/HttpEntry.java | 584 +++ .../search/ModelAndNamedQueryRestProvider.java | 219 ++ .../openecomp/aai/rest/search/SearchProvider.java | 241 ++ .../aai/rest/translog/TransLogRestProvider.java | 284 ++ .../openecomp/aai/rest/ueb/NotificationEvent.java | 97 + .../openecomp/aai/rest/ueb/UEBNotification.java | 173 + .../org/openecomp/aai/rest/util/EchoResponse.java | 149 + .../openecomp/aai/rest/util/ValidateEncoding.java | 160 + .../aai/serialization/db/DBSerializer.java | 1418 +++++++ .../aai/serialization/db/DeleteSemantic.java | 40 + .../openecomp/aai/serialization/db/EdgeRule.java | 202 + .../openecomp/aai/serialization/db/EdgeRules.java | 310 ++ .../openecomp/aai/serialization/db/EdgeType.java | 26 + .../aai/serialization/db/GraphSingleton.java | 81 + .../aai/serialization/db/MultiplicityRule.java | 28 + .../aai/serialization/db/TitanGraphSingleton.java | 74 + .../aai/serialization/engines/QueryStyle.java | 25 + .../aai/serialization/engines/TitanDBEngine.java | 107 + .../engines/TransactionalGraphEngine.java | 166 + .../engines/query/GraphTraversalQueryEngine.java | 165 + .../engines/query/GremlinPipelineQueryEngine.java | 186 + .../engines/query/GremlinQueryEngine.java | 176 + .../serialization/engines/query/QueryEngine.java | 98 + .../org/openecomp/aai/tasks/ScheduledTasks.java | 159 + .../aai/testing/GenerateFitNesseTests.java | 134 + .../org/openecomp/aai/testing/GenerationTest.java | 77 + .../aai/testing/InjectResourceVersion.java | 132 + .../org/openecomp/aai/testing/LocateEndPoints.java | 579 +++ .../java/org/openecomp/aai/testing/OXMTest.java | 63 + .../org/openecomp/aai/testing/PopulateObject.java | 232 ++ .../openecomp/aai/testing/TestDataGenerator.java | 66 + .../org/openecomp/aai/testing/UpdateObject.java | 205 + .../aai/testsuitegeneration/AbstractWriter.java | 491 +++ .../testsuitegeneration/AddNamedPropWildcard.java | 96 + .../aai/testsuitegeneration/FMObject.java | 148 + .../testsuitegeneration/FitNesseJUnitWriter.java | 141 + .../testsuitegeneration/RelationshipWriter.java | 405 ++ .../aai/testsuitegeneration/TestSuite.java | 441 +++ .../aai/testsuitegeneration/TestSuiteWriter.java | 375 ++ .../testsuitegeneration/child_test_content_txt.ftl | 33 + .../aai/testsuitegeneration/empty_context_txt.ftl | 21 + .../end_point_suite_content_txt.ftl | 32 + .../aai/testsuitegeneration/junit_class_java.ftl | 33 + .../aai/testsuitegeneration/properties_xml.ftl | 48 + .../recursive_teardown_content_txt.ftl | 29 + .../relationship_content_txt.ftl | 37 + .../relationship_single_content_txt.ftl | 36 + .../relationship_single_reversed_content_txt.ftl | 36 + .../remove_children_content_txt.ftl | 25 + .../static_page_content_txt.ftl | 21 + .../version_suite_content_txt.ftl | 31 + .../openecomp/aai/util/AAIApiServerURLBase.java | 79 + .../java/org/openecomp/aai/util/AAIApiVersion.java | 73 + .../aai/util/AAIAppServletContextListener.java | 119 + .../java/org/openecomp/aai/util/AAIConfig.java | 320 ++ .../aai/util/AAIConfigCommandLinePropGetter.java | 66 + .../java/org/openecomp/aai/util/AAIConstants.java | 113 + .../org/openecomp/aai/util/AAIPrimaryHost.java | 444 +++ .../org/openecomp/aai/util/AAIRSyncUtility.java | 224 ++ .../java/org/openecomp/aai/util/AAITxnLog.java | 563 +++ .../main/java/org/openecomp/aai/util/AAIUtils.java | 54 + .../main/java/org/openecomp/aai/util/CNName.java | 94 + .../openecomp/aai/util/CustomLogPatternLayout.java | 28 + .../aai/util/CustomLogPatternLayoutEncoder.java | 40 + .../java/org/openecomp/aai/util/DME2RestFlag.java | 55 + .../openecomp/aai/util/DataConversionHelper.java | 63 + .../org/openecomp/aai/util/DeleteResource.java | 302 ++ .../main/java/org/openecomp/aai/util/Entity.java | 196 + .../java/org/openecomp/aai/util/EntityList.java | 114 + .../java/org/openecomp/aai/util/FileWatcher.java | 59 + .../openecomp/aai/util/GenerateMethodMapper.java | 141 + .../java/org/openecomp/aai/util/GenerateXsd.java | 1491 ++++++++ .../java/org/openecomp/aai/util/GetResource.java | 161 + .../org/openecomp/aai/util/HbaseSaltPrefixer.java | 60 + .../org/openecomp/aai/util/HttpsAuthClient.java | 175 + .../aai/util/HttpsAuthExternalClient.java | 151 + .../JettyObfuscationConversionCommandLineUtil.java | 98 + .../java/org/openecomp/aai/util/KeyValueList.java | 138 + .../java/org/openecomp/aai/util/MapperUtil.java | 116 + .../java/org/openecomp/aai/util/MergeResource.java | 205 + .../java/org/openecomp/aai/util/PojoUtils.java | 990 +++++ .../java/org/openecomp/aai/util/PostResource.java | 186 + .../org/openecomp/aai/util/PutActionsNotify.java | 253 ++ .../java/org/openecomp/aai/util/PutResource.java | 470 +++ .../org/openecomp/aai/util/RelationshipPutDel.java | 234 ++ .../main/java/org/openecomp/aai/util/Request.java | 160 + .../org/openecomp/aai/util/RestController.java | 750 ++++ .../java/org/openecomp/aai/util/RestObject.java | 46 + .../main/java/org/openecomp/aai/util/RestURL.java | 799 ++++ .../openecomp/aai/util/StoreNotificationEvent.java | 211 ++ .../openecomp/aai/util/UniquePropertyCheck.java | 264 ++ .../org/openecomp/aai/util/UpdateResource.java | 146 + .../aai/workarounds/LegacyURLTransformer.java | 96 + .../aai/workarounds/ModifyOXMProperties.java | 220 ++ .../aai/workarounds/NamingExceptions.java | 79 + .../aai/workarounds/RemoveDME2QueryParams.java | 65 + 255 files changed, 63016 insertions(+) create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/audit/ListEndpoints.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/auth/AAIAuth.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/AAIProperties.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditDoc.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditOXM.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditTitan.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Auditor.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/AuditorFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/CompareByName.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBIndex.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/DBProperty.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/EdgeProperty.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ManageTitanSchema.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/Named.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataGrooming.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbEdgeGroup.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbMeth.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/DbSearchWithTags.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/GenTester.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ModelBasedProcessing.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/ResultSet.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaGenerator.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmap/AAIGraph.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmap/ActionsGraph.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmap/GraphHelpersMoxy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmap/RelationshipGraph.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmap/SearchGraph.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/DbEdgeRules.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dbmodel/RestRules.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/AAIDmaapPublisher.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIClient.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventProcessor.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/dmaap/aaiWorkload/consumer/AAIWorkloadEventStatus.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKey.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResourceKeys.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AAIResources.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItem.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/model/AncestryItems.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/NotificationEvent.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/notificationEvent/ObjectFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessage.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageData.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessageDatum.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/AAIResponseMessages.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/responseMessage/package-info.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/Fault.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/ObjectFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/PolicyException.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RESTResponse.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restPolicyException/RequestError.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/Info.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restResponseInfo/ObjectFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/Fault.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ObjectFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RESTResponse.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/RequestError.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/restServiceException/ServiceException.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/IncludeNodeFilter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItem.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/InventoryItemData.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/ObjectFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/SecondaryFilter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/StartNodeFilter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/TaggedInventoryItemList.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/search/package-info.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntries.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/domain/translog/TransactionLogEntry.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIException.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/exceptions/AAIExceptionWithInfo.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/extensions/ExtensionController.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/ConvertXmlToJsonMoxyOxm.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/CreateWidgetModels.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/DbMaps.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelListener.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/ingestModel/IngestModelMoxyOxm.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/Introspector.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/IntrospectorWalker.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/JSONStrategy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/Loader.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/LoaderFactory.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/MarshallerProperties.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelInjestor.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/ModelType.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyLoader.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/MoxyStrategy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoInjestor.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoLoader.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/PojoStrategy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/Version.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/Wanderer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/generator/CreateExample.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/CreateUUID.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/DefaultFields.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Error.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/InjectKeysFromURI.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IntrospectorValidator.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Issue.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/IssueResolver.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/introspection/tools/Severity.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/logging/AAILogger.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorLogHelper.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/logging/ErrorObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/logging/LogLineBuilder.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/LegacyQueryParser.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParser.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/QueryParserStrategy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/RelationshipQueryParser.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/TraversalStrategy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueRelationshipQueryParser.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueStrategy.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/query/UniqueURIQueryParser.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/relationship/RelationshipToURI.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/Parsable.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIParser.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToDBKey.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToExtensionInformation.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/parsers/uri/URIToRelationshipObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GraphTraversalBuilder.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineBuilder.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinPipelineTraversal.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinQueryBuilder.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinTraversal.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/GremlinUnique.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/QueryBuilder.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/query/builder/TraversalQuery.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/CustomJacksonJaxBJsonProvider.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/HttpMethod.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/MediaType.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/RESTAPI.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/RestProviders.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/actions/ActionsProvider.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/db/DBRequest.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/translog/TransLogRestProvider.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DBSerializer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/DeleteSemantic.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRule.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/EdgeType.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/GraphSingleton.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/MultiplicityRule.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/db/TitanGraphSingleton.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/QueryStyle.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TitanDBEngine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GraphTraversalQueryEngine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinPipelineQueryEngine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/GremlinQueryEngine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/serialization/engines/query/QueryEngine.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/tasks/ScheduledTasks.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerateFitNesseTests.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/GenerationTest.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/InjectResourceVersion.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/LocateEndPoints.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/OXMTest.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/PopulateObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/TestDataGenerator.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testing/UpdateObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AbstractWriter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/AddNamedPropWildcard.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FMObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/FitNesseJUnitWriter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/RelationshipWriter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuite.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/TestSuiteWriter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/child_test_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/empty_context_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/end_point_suite_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/junit_class_java.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/properties_xml.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/recursive_teardown_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/relationship_single_reversed_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/remove_children_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/static_page_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/testsuitegeneration/version_suite_content_txt.ftl create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiServerURLBase.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIApiVersion.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfig.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConfigCommandLinePropGetter.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIConstants.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIPrimaryHost.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIRSyncUtility.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAITxnLog.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/AAIUtils.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/CNName.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayout.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/CustomLogPatternLayoutEncoder.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/DME2RestFlag.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/DataConversionHelper.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/DeleteResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/Entity.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/EntityList.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/FileWatcher.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/GenerateXsd.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/GetResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/HbaseSaltPrefixer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/HttpsAuthExternalClient.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/KeyValueList.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/MapperUtil.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/MergeResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/PojoUtils.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/PostResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/PutActionsNotify.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/PutResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/Request.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/RestController.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/RestObject.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/RestURL.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/util/UpdateResource.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/workarounds/LegacyURLTransformer.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/workarounds/ModifyOXMProperties.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/workarounds/NamingExceptions.java create mode 100644 ajsc-aai/src/main/java/org/openecomp/aai/workarounds/RemoveDME2QueryParams.java (limited to 'ajsc-aai/src/main/java') 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 userIdToNameMap; + static { + userIdToNameMap = new HashMap(); + 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> mapOfMaps = new HashMap>(); + 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> typeRef = new TypeReference>() {}; + HashMap propMap = om.readValue(file, typeRef); + HashMap lcasePropMap = new HashMap(); + 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 propMap = new HashMap((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 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 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 endpoints = new ArrayList<>(); + + private Map endpointToLogicalName = new HashMap(); + + 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 getLogicalNames() { + + return endpointToLogicalName; + + } + + /** + * Gets the endpoints. + * + * @return the endpoints + */ + public List getEndpoints() { + + return this.getEndpoints(""); + + } + + /** + * Gets the endpoints. + * + * @param filterOut the filter out + * @return the endpoints + */ + public List getEndpoints(String filterOut) { + List 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 properties; + private List indexes; + private List edgeLabels; + + /** + * Gets the properties. + * + * @return the properties + */ + public List getProperties() { + return properties; + } + + /** + * Sets the properties. + * + * @param properties the new properties + */ + public void setProperties(List properties) { + this.properties = properties; + } + + /** + * Gets the indexes. + * + * @return the indexes + */ + public List getIndexes() { + return indexes; + } + + /** + * Sets the indexes. + * + * @param indexes the new indexes + */ + public void setIndexes(List indexes) { + this.indexes = indexes; + } + + /** + * Gets the edge labels. + * + * @return the edge labels + */ + @JsonProperty("edge-labels") + public List getEdgeLabels() { + return edgeLabels; + } + + /** + * Sets the edge labels. + * + * @param edgeLabels the new edge labels + */ + public void setEdgeLabels(List 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 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 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 getAllObjects(Version version) { + String fileName = AAIConstants.AAI_HOME_ETC_OXM + "aai_oxm_" + version.toString() + ".xml"; + Set 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 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 unique = Arrays.asList(uniqueProps.split(",")); + List indexed = temp.getIndexedProperties(); + List keys = temp.getKeys(); + + for (String prop : indexed) { + DBIndex dbIndex = new DBIndex(); + LinkedHashSet 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 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 edgeRules = DbEdgeRules.EdgeRules; + for (String key : edgeRules.keySet()) { + Collection 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 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 iterable = mgmt.getRelationTypes(PropertyKey.class); + Iterator 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 iterable = mgmt.getGraphIndexes(Vertex.class); + Iterator titanIndexes = iterable.iterator(); + TitanGraphIndex titanIndex = null; + while (titanIndexes.hasNext()) { + titanIndex = titanIndexes.next(); + if (titanIndex.isCompositeIndex()) { + DBIndex index = new DBIndex(); + LinkedHashSet 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 iterable = mgmt.getRelationTypes(EdgeLabel.class); + Iterator 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 properties = new HashMap<>(); + protected Map indexes = new HashMap<>(); + protected Map edgeLabels = new HashMap<>(); + + /** + * Gets the audit doc. + * + * @return the audit doc + */ + public AuditDoc getAuditDoc() { + AuditDoc doc = new AuditDoc(); + List propertyList = new ArrayList<>(); + List indexList = new ArrayList<>(); + List 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{ + + /** + * {@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 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 getProperties() { + return properties; + } + + /** + * Sets the properties. + * + * @param properties the new properties + */ + public void setProperties(LinkedHashSet 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 aaiProperties; + private List aaiIndexes; + private List 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 props = index.getProperties(); + boolean isChanged = false; + boolean isNew = false; + List 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 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 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 verts = null; + verts= graph.query().vertices(); + Iterator 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 verts = null; + verts= graph.query().has(retiredName).vertices(); + Iterator 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 defaultVerLst = new ArrayList (); + 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 deleteCandidateList = new ArrayList(); + 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(); + } + + 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 errArr = new ArrayList(); + int totalNodeCount = 0; + HashMap misMatchedHash = new HashMap(); + HashMap orphanNodeHash = new HashMap(); + HashMap missingDepNodeHash = new HashMap(); + HashMap oneArmedEdgeHash = new HashMap(); + HashMap emptyVertexHash = new HashMap(); + HashMap ghostNodeHash = new HashMap(); + ArrayList dupeGroups = new ArrayList(); + + + DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + + Iterator 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 keyProps = DbMeth.getNodeKeyPropNames(TRANSID, FROMAPPID, nType, version); + // Get the types of nodes that this nodetype depends on for uniqueness (if any) + ArrayList depNodeTypes = DbMeth.getDepNodeTypes(TRANSID, FROMAPPID, nType, version); + + // Loop through all the nodes of this Node type + int lastShownForNt = 0; + ArrayList tmpList = new ArrayList (); + 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 secondGetList = new ArrayList (); + // ----------------------------------------------------------------------- + // 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 propHashWithKeys = new HashMap(); + Iterator keyPropI = keyProps.iterator(); + while (keyPropI.hasNext()) { + String propName = keyPropI.next(); + String propVal = ""; + Object obj = thisVtx.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 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 tmpListSec = new ArrayList (); + tmpListSec = DbMeth.getConnectedChildren(TRANSID, FROMAPPID, g, parentVtx, nType ) ; + Iterator 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 tmpDupeGroups = checkAndProcessDupes( + TRANSID, FROMAPPID, g, version, + nType, secondGetList, dupeFixOn, + deleteCandidateList, singleCommits, dupeGroups, dbMaps); + Iterator 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 vertList = new ArrayList(); + Iterable vIt3 = g.query().vertices(); + Iterator 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 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 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.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.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 entry : ghostNodeHash + .entrySet()) { + String vid = entry.getKey(); + bw.write("DeleteCandidate: Phantom Vid = [" + vid + "]\n"); + cleanupCandidateCount++; + } + for (Map.Entry entry : orphanNodeHash + .entrySet()) { + String vid = entry.getKey(); + bw.write("DeleteCandidate: OrphanDepNode Vid = [" + vid + "]\n"); + if (!dontFixOrphansFlag) { + cleanupCandidateCount++; + } + } + for (Map.Entry entry : oneArmedEdgeHash.entrySet()) { + String eid = entry.getKey(); + bw.write("DeleteCandidate: Bad EDGE Edge-id = [" + eid + "]\n"); + cleanupCandidateCount++; + } + for (Map.Entry 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 entry : ghostNodeHash + .entrySet()) { + try { + String vid = entry.getKey(); + bw.write("\n ==> Phantom Vid = " + vid + "\n"); + ArrayList 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 entry : orphanNodeHash + .entrySet()) { + try { + String vid = entry.getKey(); + bw.write("\n> Orphan Node Vid = " + vid + "\n"); + ArrayList 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 entry : missingDepNodeHash + .entrySet()) { + try { + String vid = entry.getKey(); + bw.write("\n> Missing edge to Dependent Node (but has edges) Vid = " + + vid + "\n"); + ArrayList 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 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> pI = thisE.properties(); + while (pI.hasNext()) { + Property 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 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 idArr = new ArrayList(); + 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 vtxIterator = graph.vertices(longVertId); + TitanVertex vtx = null; + if (vtxIterator.hasNext()) { + vtx = (TitanVertex)vtxIterator.next(); + } + ArrayList 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 entry : misMatchedHash.entrySet()) { + String msg = entry.getValue(); + bw.write("MixedMsg = " + msg + "\n"); + } + + bw.write("\n ------------- Got these errors while processing: \n"); + Iterator 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 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.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 keyProps = DbMeth.getNodeKeyPropNames(TRANSID, + FROMAPPID, nType, "junkversion"); + Iterator keyPropI = keyProps.iterator(); + while (keyPropI.hasNext()) { + String propName = keyPropI.next(); + Object ob = v.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 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 delList = new ArrayList(); + 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 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.property("aai-node-type").orElse(null); + if (obj != null) { + vtxANodeType = obj.toString(); + } + obj = vtxB.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 keyProps = DbMeth.getNodeKeyPropNames(transId, + fromAppId, vtxANodeType, ver); + Iterator keyPropI = keyProps.iterator(); + while (keyPropI.hasNext()) { + String propName = keyPropI.next(); + String vtxAKeyPropVal = ""; + obj = vtxA.property(propName).orElse(null); + if (obj != null) { + vtxAKeyPropVal = obj.toString(); + } + String vtxBKeyPropVal = ""; + obj = vtxB.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 vtxIdsConn2A = new ArrayList(); + ArrayList vtxIdsConn2B = new ArrayList(); + HashMap nodeTypesConn2A = new HashMap(); + HashMap nodeTypesConn2B = new HashMap(); + + ArrayList vertListA = DbMeth.getConnectedNodes("transId", + "fromAppId", g, "", emptyHash, vtxA, ver, false); + if (vertListA != null) { + Iterator iter = vertListA.iterator(); + while (iter.hasNext()) { + TitanVertex tvCon = iter.next(); + String conVid = tvCon.id().toString(); + String nt = ""; + obj = tvCon.property("aai-node-type").orElse(null); + if (obj != null) { + nt = obj.toString(); + } + nodeTypesConn2A.put(nt, conVid); + vtxIdsConn2A.add(conVid); + } + } + + ArrayList vertListB = DbMeth.getConnectedNodes("transId", + "fromAppId", g, "", emptyHash, vtxB, ver, false); + if (vertListB != null) { + Iterator iter = vertListB.iterator(); + while (iter.hasNext()) { + TitanVertex tvCon = iter.next(); + String conVid = tvCon.id().toString(); + String nt = ""; + obj = tvCon.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 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 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 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 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 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 checkAndProcessDupes(String transId, + String fromAppId, TitanTransaction g, String version, String nType, + ArrayList passedVertList, Boolean dupeFixOn, + ArrayList deleteCandidateList, Boolean singleCommits, + ArrayList alreadyFoundDupeGroups, DbMaps dbMaps ) { + + ArrayList returnList = new ArrayList(); + ArrayList checkVertList = new ArrayList(); + ArrayList alreadyFoundDupeVidArr = new ArrayList(); + Boolean noFilterList = true; + Iterator 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 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> vertsGroupedByParentHash = groupVertsByDepNodes( + transId, fromAppId, g, version, nType, + checkVertList, dbMaps); + for (Map.Entry> entry : vertsGroupedByParentHash + .entrySet()) { + ArrayList 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> groupVertsByDepNodes( + String transId, String fromAppId, TitanTransaction g, String version, + String nType, ArrayList 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> retHash = new HashMap>(); + 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 depNodeTypeL = new ArrayList(); + Collection depNTColl = dbMaps.NodeDependencies.get(nType); + Iterator 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 emptyHash = new HashMap(); + Iterator iter = passedVertList.iterator(); + while (iter.hasNext()) { + TitanVertex thisVert = iter.next(); + ArrayList connectedVList = DbMeth + .getConnectedNodes("transId", "fromAppId", g, "", + emptyHash, thisVert, "v3", false); + Iterator connIter = connectedVList.iterator(); + while (connIter.hasNext()) { + TitanVertex tvCon = connIter.next(); + String conNt = ""; + Object obj = tvCon.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 vList = new ArrayList(); + 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 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 idArr = new ArrayList(); + 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 getNodeJustUsingKeyParams( String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap keyPropsHash, String apiVersion ) throws AAIException{ + + ArrayList retVertList = new ArrayList (); + + // 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 kName = new ArrayList(); + ArrayList kVal = new ArrayList(); + 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 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 vidToNodeTypeInDbHash = new HashMap (); + HashMap nodeTypeInReqHash = new HashMap (); + HashMap vidToEdgeInDbHash = new HashMap (); + HashMap vidToTargetVertexHash = new HashMap (); + + //------------------------------------------------------------------------------------------------------------ + // 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 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.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 targetConnectedToVertList = new ArrayList(); + 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 > propList = ((ArrayList>)relatedNodesMultiMap.get(rel2Nt)); + while (i < propList.size()) { + HashMap propFilterHash = (HashMap) 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.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.property("aai-node-type").orElse(null); + String msg3 = "We will DELETE existing DB-edge to vids = "; + for( Map.Entry 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 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 edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey); + Iterator 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 cousinVidToEdgeInDbHash = new HashMap (); + String startVertNT = startVert.property("aai-node-type").orElse(null); + String startVertVid = startVert.id().toString(); + DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(apiVersion); + Collection 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 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 propFilterHash = (HashMap)((ArrayList) relatedNodesMultiMap.get(rel2Nt)).get(0); + TitanVertex otherEndVert = DbMeth.getUniqueNodeWithDepParams( transId, fromAppId, graph, rel2Nt, propFilterHash, apiVersion ); + String otherNT = otherEndVert.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 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 depNTColl = dbMaps.NodeDependencies.get(otherNT); + Iterator 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 vidToNodeTypeHash, + HashMap 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 qResult = startVert.query().has("isParent",false).vertices(); + Iterator 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.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 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 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 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 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 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 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 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 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 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.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.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 nodeAltKey1PropsHash = new HashMap(); + Collection altKey1Props = getNodeAltKey1PropNames(transId, fromAppId, nodeType, apiVersion); + if( altKey1Props != null ){ + Iterator 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 nodeKeyPropsHash = new HashMap(); + Collection keyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion); + Iterator 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.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.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.property("aai-created-ts").orElse(null); + if( tmpOb != null ){ + existingCreateTs = (long) tmpOb; + } + + String msg = "UPDATE vertex of type = [" + nodeType + "] "; + if( useDepNode ){ + String depNType = depNodeVal.property("aai-node-type").orElse(null); + HashMap 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 propCol = dbMaps.NodeProps.get(nodeType); + Iterator 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 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 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 currentData = new ArrayList (); + if( patchOnly ){ + // When patching - gotta know what's already in the db + Iterator> 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.property("aai-node-type").orElse(null); + HashMap 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 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 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 currentData = new ArrayList (); + 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 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 keyProps = new ArrayList (); + 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 nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType); + Iterator 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 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 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 altKey1Props = new ArrayList (); + 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 nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType); + Iterator 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 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 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.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.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 kName = new ArrayList(); + ArrayList kVal = new ArrayList(); + + Collection keyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion); + Iterator 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 altKey1Props = getNodeAltKey1PropNames(transId, fromAppId, nodeType, apiVersion); + Iterator 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 onlyKeysHash = new HashMap(); + + Collection onlyKeyProps = getNodeKeyPropNames(transId, fromAppId, nodeType, apiVersion); + + Iterator onlyKeyPropsI = onlyKeyProps.iterator(); + + while( onlyKeyPropsI.hasNext() ){ + String keyName = onlyKeyPropsI.next(); + onlyKeysHash.put(keyName, keyPropsHash.get(keyName)); + } + + propsAndValuesForMsg = onlyKeysHash.toString() + " combined with a Dependent [" + depNodeVal.property("aai-node-type").orElse(null) + "] node."; + ArrayList 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.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 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 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 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 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 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 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 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 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 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 getThisNodeTypeParams(String transId, String fromAppId, String targetNodeType, + HashMap 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 returnHash = new HashMap (); + Iterator >it = passedHash.entrySet().iterator(); + while( it.hasNext() ){ + Map.Entry pairs = (Map.Entry)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 getThisNodeTypeParams(String transId, String fromAppId, String targetNodeType, + HashMap 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 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 depNodeTypeL = new ArrayList (); + if( !DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){ + // This is a good-ole nodeType + Collection depNTColl = dbMaps.NodeDependencies.get(nodeType); + Iterator ntItr = depNTColl.iterator(); + while( ntItr.hasNext() ){ + depNodeTypeL.add(ntItr.next()); + } + } + else { + // The passed-in nodeType must really be a nodeTypeCategory + Collection nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType); + Iterator 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 depNTColl = dbMaps.NodeDependencies.get(nodeType); + Iterator 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 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 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 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 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 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 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 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 >it = requestParamHash.entrySet().iterator(); + while( it.hasNext() ){ + Map.Entry pairs = (Map.Entry)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 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 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 conNodeList = getConnectedNodes( transId, fromAppId, graph, nodeType, propFilterHash, startNodeVal, apiVersion, false ); + Iterator conVIter = conNodeList.iterator(); + while( conVIter.hasNext() ){ + TitanVertex connectedVert = conVIter.next(); + boolean isFirstOne = true; + Iterator 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.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 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 + * @throws AAIException the AAI exception + */ + public static ArrayList getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap 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 + * @throws AAIException the AAI exception + */ + public static ArrayList getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap 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 returnVertList = new ArrayList(); + 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 kName = new ArrayList(); + ArrayList kVal = new ArrayList(); + int i = -1; + Collection 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 getNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap 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 + * @throws AAIException the AAI exception + */ + public static ArrayList 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 childList = new ArrayList (); + 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.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 + * @throws AAIException the AAI exception + */ + public static ArrayList getConnectedNodes( String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap 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.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 excludeVidList = new 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.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 returnVertList = new ArrayList(); + Iterable qResult = null; + Iterator 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.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.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 getConnectedNodes(String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap 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 getConnectedNodes(String transId, String fromAppId, TitanTransaction graph, String nodeType, + HashMap 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 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 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 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.property("aai-node-type").orElse(null); + String inV_NType = inV.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 nodeKeyPropsHash = getNodeKeyPropHash(transId, fromAppId, graph, outV); + ArrayList resultList = new ArrayList(); + 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 nodeKeyPropsHash = getNodeKeyPropHash(transId, fromAppId, graph, inV); + ArrayList resultList = new ArrayList(); + 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 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.property("aai-node-type").orElse(null); + String targetNodeType = toVtx.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 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.property("aai-node-type").orElse(null); + String targetNodeType = targetVert.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 edRuleColl = DbEdgeRules.EdgeRules.get(fwdRuleKey); + Iterator 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 edRuleColl = DbEdgeRules.EdgeRules.get(revRuleKey); + Iterator 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 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 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 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 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 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 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.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 nodeKeyPropsHash = new HashMap(); + Collection keyProps = dbMaps.NodeKeyProps.get(nType); + Iterator keyPropI = keyProps.iterator(); + while( keyPropI.hasNext() ){ + String propName = keyPropI.next(); + Object value = (Object) vtx.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 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.property("aai-node-type").orElse(null); + HashMap nodeNamePropsHash = new HashMap(); + Collection keyProps = DbMeth.getNodeNameProps(transId, fromAppId, nType, apiVersion); + Iterator keyPropI = keyProps.iterator(); + while( keyPropI.hasNext() ){ + String propName = keyPropI.next(); + Object value = (Object) vtx.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 ); + } + + + /** + *
+	 *  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!
+	 *  
. + * + * @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.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.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 eI = thisVtx.edges(Direction.IN); + boolean onlyHasParent = false; + Edge temp = null; + if( eI != null && eI.hasNext() ){ + temp = eI.next(); + Boolean isParent = temp.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 eI = thisVtx.edges(Direction.BOTH); + while( eI.hasNext() ){ + TitanEdge ed = (TitanEdge) eI.next(); + TitanVertex otherVtx = (TitanVertex) ed.otherVertex(thisVtx); + String nodeTypeA = otherVtx.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 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 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.property("isParent").orElse(null); + if( otherVtxAChild == null ){ + otherVtxAChild = false; + } + + Boolean otherVtxADeleteTarget = ed.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.property("aai-node-type").orElse(null); + String resVers = otherVtx.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 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 edges = graph.edges(Direction.BOTH); + graph.tx().commit(); + Edge edge = null; + while (edges.hasNext()) { + edge = edges.next(); + edges.remove(); + } + graph.tx().commit(); + Iterator 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 showAllEdgesForNode( String transId, String fromAppId, TitanVertex tVert ){ + + ArrayList retArr = new ArrayList (); + Iterator 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.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 showPropertiesForNode( String transId, String fromAppId, TitanVertex tVert ){ + + ArrayList retArr = new ArrayList (); + if( tVert == null ){ + retArr.add("null Node object passed to showPropertiesForNode()\n"); + } + else { + String nodeType = ""; + //String datType = ""; + Object ob = tVert.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> pI = tVert.properties(); + while( pI.hasNext() ){ + VertexProperty 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 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 nameProps = new ArrayList (); + 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 nTypeCatCol = DbEdgeRules.NodeTypeCategory.get(nodeType); + Iterator 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 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 retEdgePropPutMap = new HashMap (); + + 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 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 edRuleColl = DbEdgeRules.EdgeRules.get(edgeRuleKey); + Iterator 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 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 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.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.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.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 propHashWithKeys = new HashMap(); + Collection 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 keyPropI = keyProps.iterator(); + while( keyPropI.hasNext() ){ + String propName = keyPropI.next(); + String propVal = ""; + Object ob = v.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 vertList2 = getNodes( transId, fromAppId, graph, nType, propHashWithKeys, false, version, true ); + Iterator 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 + * @throws AAIException the AAI exception + */ + public static HashMap identifyTopNodeSet( String transId, String fromAppId, TitanTransaction graph, + String edgeTag, String topNodeType, HashMap initialFilterHash, int maxLevels ) + throws AAIException { + + + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "identifyInitialNodeSet"); + + HashMap topVertHash = new HashMap (); + 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 initFilterTweakedHash = new HashMap (); + + HashMap initFilterHashUpper = new HashMap (); + HashMap initFilterHashLower = new HashMap (); + 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 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 startVertHash = new HashMap(); + Iterator 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 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 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 + * @throws AAIException the AAI exception + */ + public static HashMap 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 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 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 + * @throws AAIException the AAI exception + */ + public static HashMap 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 targetVertHash = new HashMap (); + + 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.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 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.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 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 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.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 nodeList = new 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 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.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 nodeList = new ArrayList (); + while( vertI != null && vertI.hasNext() ){ + TitanVertex tmpVert = (TitanVertex) vertI.next(); + String nodeType = tmpVert.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.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.property("aai-node-type").orElse(null); + + Iterator> pI = resSet.vert.properties(); + String propsStr = ""; + while( pI.hasNext() ){ + VertexProperty 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 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 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.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 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 verts = (Iterable) tgQ.vertices(); + Iterator vertItor = verts.iterator(); + while( vertItor.hasNext() ){ + resCount++; + TitanVertex v = (TitanVertex)vertItor.next(); + Iterator> pI = v.properties(); + System.out.println("\n\n>>> Found Vertex with VertexId = " + v.id() + ", properties: "); + while( pI.hasNext() ){ + VertexProperty tp = pI.next(); + System.out.println(" [" + tp.key() + "|" + tp.value() + "] "); + } + + try { + ArrayList 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 getStartNodesAndModels( String transId, String fromAppId, TitanTransaction graph, + String passedModelNameVersionId, + String passedModelId, + String passedModelName, + String passedTopNodeType, + ArrayList > 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 startVertInfo = new HashMap (); + 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.property("model-id").orElse(null); + String calcModVer = modVtx.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 modelVtxList = getModelsUsingName(transId, fromAppId, graph, passedModelName); + ArrayList startVtxList = new ArrayList (); + // 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)).property("model-id").orElse(null); + String calcModVer = (modelVtxList.get(i)).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.property("persona-model-id").orElse(null); + String tmpModVers = tmpStartVert.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 modelNameVersionIds2Check = new ArrayList (); + 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 (); // 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.property("persona-model-version").orElse(null); + String personaModId = startVtx.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 queryByModel( String transId, String fromAppId, TitanTransaction graph, + String modelNameVersionId, + String modelId, + String modelName, + String topNodeType, + ArrayList > 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 > 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 resultList = new ArrayList (); + TimeLimiter limiter = new SimpleTimeLimiter(); + try { + resultList = limiter.callWithTimeout(new Callable >() { + public ArrayList 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 queryByModel_Timed( String transId, String fromAppId, TitanTransaction graph, + String modelNameVersionId, + String modelId, + String modelName, + String topNodeType, + ArrayList > startNodeFilterArrayOfHashes, + String apiVer ) + throws AAIException{ + + DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + + + + ArrayList resultArray = new ArrayList (); + 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 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 distinctModelsHash = new HashMap (); + // For distinctModelsHash: key = modelTypeVersionId, val= modelVertex + String startNodeType = ""; + if( topNodeType != null && !topNodeType.equals("") ){ + startNodeType = topNodeType; + } + + Set snKeySet = startNode2ModelHash.keySet(); + Iterator 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 > validNextStepHash = new HashMap >(); + // validNextStepHash: key = modelNameVerId, value = nextStepMap + Set keySet = distinctModelsHash.keySet(); + Iterator modelIterator = keySet.iterator(); + while( modelIterator.hasNext() ){ + String modKey = (String) modelIterator.next(); + TitanVertex modelVtx = (TitanVertex)distinctModelsHash.get(modKey); + Multimap 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 failedPersonaCheckVids = new ArrayList (); + HashMap firstStepInfoHash = new HashMap (); + // 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 vtxIterator = graph.vertices(vtxKey); + TitanVertex tmpVtx = (TitanVertex)vtxIterator.next(); + String thisVtxModelUUID = startNode2ModelHash.get(vtxKey); + TitanVertex modelVtx = (TitanVertex)distinctModelsHash.get(thisVtxModelUUID); + String modId = modelVtx.property("model-id").orElse(null); + String modVersion = modelVtx.property("model-version").orElse(null); + String personaModId = tmpVtx.property("persona-model-id").orElse(null); + String personaModVersion = tmpVtx.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 vtxIterator = graph.vertices(topNodeVtxId); + TitanVertex tmpStartVtx = (TitanVertex)vtxIterator.next(); + String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId); + String modelTypeNameVerId = startNode2ModelHash.get(topNodeVtxId); + Multimap validNextStepMap = validNextStepHash.get(modelTypeNameVerId); + + ArrayList vidsTraversed = new ArrayList (); + HashMap emptyDelKeyHash = new HashMap (); + HashMap emptyNQElementHash = new HashMap (); // 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 runDeleteByModel( String transId, String fromAppId, TitanTransaction graph, + String modelNameVersionId, String topNodeTypeVal, HashMap startNodeFilterHash, String apiVer, String resVersion ) + throws AAIException{ + + HashMap retHash = new HashMap (); + 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 propHash0 = new HashMap(); + 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.property("persona-model-id").orElse(null); + String startVertPersonaModVersion = startVtx.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.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.property("model-id").orElse(null); + chkFirstNodePersonaModelVersion = modelVtx.property("model-version").orElse(null); + personaData = "," + chkFirstNodePersonaModelId + "," + chkFirstNodePersonaModelVersion; + } + + // Get the deleteKeyHash for this model + String incomingTrail = ""; + HashMap currentHash = new HashMap (); + HashMap modConHash = new HashMap (); + ArrayList vidsTraversed = new ArrayList (); + HashMap 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 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.property("persona-model-id").orElse(null); + String startVertPersonaModVersion = startVtx.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 validNextStepMap = genTopoMap4Model(transId, fromAppId, graph, + modelVtx, modelNameVersionId, dbMaps ); + + logline.add("TopoMap", validNextStepMap.toString() ); + + // Collect the data + String elementLocationTrail = topNType + personaData; + vidsTraversed = new ArrayList (); + HashMap emptyHash = new HashMap (); + + // 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 deleteAsNeededFromResultSet( String transId, String fromAppId, TitanTransaction graph, + ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, HashMap hashSoFar ) + throws AAIException + { + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "deleteAsNeededFromResultSet"); + HashMap retHash = new HashMap (); + 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.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 retArr = DbMeth.showPropertiesForNode(transId, fromAppId, thisVtx); + //for( String info : retArr ){ System.out.println(info); } + // --- DEBUG ---- + } + } + + // Now call this routine for the sub-resultSets + List subResultSetList = resSet.getSubResultSet(); + Iterator 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 queryByNamedQuery( String transId, String fromAppId, TitanTransaction graph, + String namedQueryUuid, + ArrayList > 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 > 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 resultList = new ArrayList (); + TimeLimiter limiter = new SimpleTimeLimiter(); + try { + resultList = limiter.callWithTimeout(new Callable >() { + public ArrayList 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 queryByNamedQuery_Timed( String transId, String fromAppId, TitanTransaction graph, + String namedQueryUuid, + ArrayList > 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 propHash0 = new HashMap(); + 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 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 validNextStepMap = genTopoMap4NamedQ(transId, fromAppId, graph, queryVtx, namedQueryUuid); + + ArrayList startVertList = new ArrayList (); + 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 cleanHash = new HashMap (); + HashMap tmpHash = startNodeFilterArrayOfHashes.get(0); + Set propKeySet = tmpHash.keySet(); + Iterator 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 resSetList = new ArrayList (); + for( int i = 0; i < startVertList.size(); i++ ){ + TitanVertex startVtx = startVertList.get(i); + // Collect the data + String elementLocationTrail = topNType; + ArrayList vidsTraversed = new ArrayList (); + HashMap emptyDelKeyHash = new HashMap (); // Does not apply to Named Queries + + // Get the mapping of namedQuery elements to our widget topology for this namedQuery + String incomingTrail = ""; + HashMap currentHash = new HashMap (); + + HashMap namedQueryElementHash = collectNQElementHash( transId, fromAppId, graph, + firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0 ); + + vidsTraversed = new ArrayList (); + 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 collapsedResSetList = new ArrayList (); + 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 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 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 colResultSet = new ArrayList (); + + if( resSetVal.getDoNotOutputFlag().equals("true") ){ + // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets + ArrayList subResList = (ArrayList) resSetVal.getSubResultSet(); + for( int k = 0; k < subResList.size(); k++ ){ + ArrayList 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 newSubSet = new ArrayList (); + ArrayList subResList = (ArrayList) colResultSet.get(i).getSubResultSet(); + for( int n = 0; n < subResList.size(); n++ ){ + ArrayList 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 validNextStepMap, + ArrayList vidsTraversed, + int levelCounter, + HashMap delKeyHash, // only applies when collecting data using the default model for delete + HashMap 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 propHash = new HashMap(); + 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.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.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 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 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 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 validNextStepHashSet = new HashSet (); + Iterator ntcItr = validNextStepColl.iterator(); + while( ntcItr.hasNext() ){ + String targetStepStr = ntcItr.next(); + validNextStepHashSet.add(targetStepStr); + } + + ArrayList tmpVidsTraversedList = new ArrayList (); + tmpVidsTraversedList.addAll(vidsTraversed); + tmpVidsTraversedList.add(thisVid); + + Iterator 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 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 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 initialEmptyMap = ArrayListMultimap.create(); + ArrayList vidsTraversed = new ArrayList (); + + 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.property("model-id").orElse(null); + String firstModelVersion = modelVertex.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 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 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 getModConstraintHash( TitanVertex modelElementVtx, HashMap 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.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 thisHash = new HashMap (); + if( currentHash != null ){ + thisHash.putAll(currentHash); + } + + int count = 0; + ArrayList modelConstraintArray = new ArrayList (); + 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.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.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.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.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.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 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 altPropHash = new HashMap (); + + if( namedQueryElementVertex == null ){ + String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() "; + throw new AAIException("AAI_6114", msg); + } + + ArrayList propCollectList = new ArrayList (); + Iterator > vpI = namedQueryElementVertex.properties("property-collect-list"); + while( vpI.hasNext() ){ + VertexProperty 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 propCollList = makeSureItsAnArrayList( vpOb ); + if( propCollList != null ){ + for( int i = 0; i < propCollList.size(); i++ ){ + String thisPropName = propCollList.get(i); + Object instanceVal = instanceVertex.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 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.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.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.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.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 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 retHash = new HashMap (); + + GraphTraversal 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 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.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.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.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 propCollectList = new ArrayList (); + Iterator > vpI = relLookupVtx.properties("property-collect-list"); + while( vpI.hasNext() ){ + VertexProperty 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 propCList = makeSureItsAnArrayList( vpOb ); + if( propCList != null ){ + for( int i = 0; i < propCList.size(); i++ ){ + String thisPropName = propCList.get(i); + propCollectList.add(thisPropName); + } + } + } + ***/ + + ArrayList propCollectList = new ArrayList (); + Iterator > 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.property(srcProp).orElse(null); + if( valFromInstance == null ){ + valFromInstance = ""; + } + + HashMap propHash = new HashMap (); + propHash.put(targetProp, valFromInstance); + ArrayList 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.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 collectNQElementHash( String transId, String fromAppId, TitanTransaction graph, + TitanVertex thisLevelVertex, String incomingTrail, + HashMap currentHash, ArrayList vidsTraversed, + int levelCounter ) throws AAIException { + + levelCounter++; + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "collectNQElementHash"); + + HashMap thisHash = new HashMap (); + 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.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 elementHash = new HashMap(); + + String connectToType = tmpVert.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 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 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 collectDeleteKeyHash( String transId, String fromAppId, TitanTransaction graph, + TitanVertex thisLevelVertex, String incomingTrail, + HashMap currentHash, ArrayList vidsTraversed, + int levelCounter, DbMaps dbMaps, HashMap modConstraintHash, + String overRideModelId, String overRideModelVersion ) + throws AAIException { + + levelCounter++; + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "collectDeleteKeyHash"); + + HashMap thisHash = new HashMap (); + 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 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 linkagePtList = thisLevelVertex.property("linkage-points").orElse(null); + Object objVal = thisLevelVertex.property("linkage-points").orElse(null); + ArrayList 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.property("new-data-del-flag").orElse(null); + + HashSet 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.property("model-id").orElse(null); + String subModelFirstVersion = thisElementsModelVtx.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.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.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.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.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 elementHash = new HashMap(); + + String connectToType = tmpVert.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.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 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 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 getLinkageConnectNodeTypes( ArrayList 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 linkPtSet = new HashSet (); + + 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 collectTopology4Model( String transId, String fromAppId, TitanTransaction graph, + TitanVertex thisLevelVertex, String incomingTrail, + Multimap currentMap, ArrayList vidsTraversed, + int levelCounter, DbMaps dbMaps, HashMap modConstraintHash, + String overRideModelId, String overRideModelVersion ) + throws AAIException { + + levelCounter++; + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "collectTopology4Model"); + + Multimap 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 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.property("model-id").orElse(null); + subModelFirstVersion = thisElementsModelVtx.property("model-version").orElse(null); + modInfo4Trail = "," + subModelFirstModId + "," + subModelFirstVersion; + String modelUuid = thisElementsModelVtx.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 elementHash = new HashMap(); + + String connectToType = tmpVert.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.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 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 linkagePtList = elVert.property("linkage-points").orElse(null); + Object objVal = elVert.property("linkage-points").orElse(null); + ArrayList 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 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 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 collectTopology4LinkagePoint( String transId, String fromAppId, + String linkagePointStr, String incomingTrail, Multimap currentMap, DbMaps dbMaps ) + throws AAIException { + + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "collectTopology4LinkagePoint"); + + Multimap 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 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 retElementHash = new HashMap(); + + if( constrElemSetVtx == null ){ + String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx "; + throw new AAIException("AAI_6125", msg); + } + + String constrNodeType = constrElemSetVtx.property("aai-node-type").orElse(null); + String constrElemSetUuid = constrElemSetVtx.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 choiceSetVertArray = new ArrayList(); + + 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.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.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 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 initialEmptyMap = ArrayListMultimap.create(); + ArrayList vidsTraversed = new ArrayList (); + + 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 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 collectTopology4NamedQ( String transId, String fromAppId, TitanTransaction graph, + TitanVertex thisLevelVertex, String incomingTrail, + Multimap currentMap, ArrayList vidsTraversed, int levelCounter ) + throws AAIException { + + levelCounter++; + LogLine logline = new LogLine(); + logline.init("aaidbgen", transId, fromAppId, "collectTopology4NamedQ"); + + Multimap 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 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.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.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.property("model-id").orElse(null); + String modelVer = modVtx.property("model-version").orElse(null); + TitanVertex relatedTopElementModelVtx = getTopElementForSvcOrResModel( modVtx ); + TitanVertex relatedModelVtx = getModelThatElementRepresents( relatedTopElementModelVtx, elementTrail ); + thisElementNodeType = relatedModelVtx.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 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.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 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 retVtxArr = new ArrayList (); + 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 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 retArr = new ArrayList (); + + 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.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.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.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 propHash = new HashMap(); + 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 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 propHash = new HashMap(); + 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 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 makeSureItsAnArrayList( Object objVal ){ + // We're sometimes getting a String back on db properties that should be ArrayList + // Need to translate them into ArrayLists sometimes... + + ArrayList retArrList = new ArrayList(); + if( objVal != null ){ + String className = objVal.getClass().getSimpleName(); + if( className.equals("ArrayList") ){ + retArrList = (ArrayList)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.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 overrideHash = resSet.getPropertyOverRideHash(); + if( overrideHash != null && !overrideHash.isEmpty() ){ + for( Map.Entry entry : overrideHash.entrySet() ){ + String propName = entry.getKey(); + Object propVal = entry.getValue(); + propsStr = propsStr + " [" + propName + " = " + propVal + "]"; + } + } + else { + Iterator> pI = resSet.vert.properties(); + while( pI.hasNext() ){ + VertexProperty 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 extraPropHash = resSet.getExtraPropertyHash(); + if( extraPropHash != null && !extraPropHash.isEmpty() ){ + for( Map.Entry 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 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 verts = null; + int vtxCount = 0; + String label; + long longId; + + int propertyCount; + + Iterator> titanProperties = null; + + VertexProperty tmpProperty = null; + Object origVal; + Object targetVal; + + if ( targetNodeType.equals("NA")) { + verts= graph.query().has(propName).vertices(); + Iterator 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 retArr = DbMeth.showPropertiesForNode("junkTransId", "junkFromAppId", tmpVtx); + //for( String info : retArr ){ System.out.println(info); } + + origVal = tmpVtx.property(propName).orElse(null); + targetVal = tmpVtx.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.property(targetPropName).orElse(null); + origVal = v.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.property(propName).orElse(null) != null ) { + propVal = v.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 subResultSet; + String propertyLimitDesc; + HashMap propertyOverRideHash; + HashMap extraPropertyHash; + + /** + * Instantiates a new result set. + */ + public ResultSet(){ + this.vert = null; + this.newDataDelFlag = ""; + this.doNotOutputFlag = ""; + this.locationInModelSubGraph = ""; + this.subResultSet = new ArrayList (); + this.propertyLimitDesc = ""; + this.propertyOverRideHash = new HashMap (); + this.extraPropertyHash = new HashMap (); + } + + /** + * Gets the vert. + * + * @return the vert + */ + public TitanVertex getVert(){ + return this.vert; + } + + /** + * Gets the sub result set. + * + * @return the sub result set + */ + public ArrayList 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 getPropertyOverRideHash(){ + return this.propertyOverRideHash; + } + + /** + * Gets the extra property hash. + * + * @return the extra property hash + */ + public HashMap 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 labelHash = new HashMap(); + Iterator 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 labelInfoColl = DbEdgeRules.EdgeRules.get(lKey); + Iterator 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 defaultVerLst = new ArrayList (); + 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 propertyIsIndexed = new HashMap(); + HashMap propertyIsUnique = new HashMap(); + + Iterator 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 indexInfoColl = dbMaps.NodeMapIndexedProps.get(iKey); + Iterator 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 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 uniqueIndexInfoColl = dbMaps.NodeMapUniqueProps.get(uiKey); + Iterator 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" -- 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")){ + dType = String.class; + cardinality = "SET"; + } + else if(dataTypeStr.equals("Set")){ + 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 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 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") + && !targetDataType.equals("Integer") && !targetDataType.equals("Long") + && !targetDataType.equals("Boolean")) { + String emsg = "Unsupported targetDataType. We only support String, Set, 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 apiVersions = new ArrayList(); + 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")) { + 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")) { + 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 alreadySeenVals = new ArrayList(); + 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 retArr = + // DbMeth.showPropertiesForNode("junkTransId", "junkFromAppId", + // tmpVtx); + // for( String info : retArr ){ System.out.println(info); } + + Object origVal = tmpVtx. 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. 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> pI = tVert.properties(); + while (pI.hasNext()) { + VertexProperty tp = pI.next(); + Object val = tp.value(); + logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] "); + } + + Iterator 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. 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 edgeRuleHash = new HashMap (); + HashMap edgeRulesFullHash = new HashMap (); + HashMap edgeRuleLabelToKeyHash = new HashMap (); + ArrayList labelMapsToMultipleKeys = new 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 edgeRulesIterator = DbEdgeRules.EdgeRules.keySet().iterator(); + while( edgeRulesIterator.hasNext() ){ + String ruleKey = edgeRulesIterator.next(); + Collection edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey); + Iterator 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 edRuleColl = DbEdgeRules.EdgeRules.get(edgeRuleKeyVal); + Iterator 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.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.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 edgeTagPropHash = DbMeth.getEdgeTagPropPutHash(TRANSID, FROMAPPID, derivedEdgeKey); + for( Map.Entry 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 propHash = new HashMap(); + + 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 keyHash = new HashMap(); + LinkedHashMap depNodeKeyHash = new LinkedHashMap(); + 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 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 returnHash = RestURL.getKeyHashes(updateNodeURI); + Set returnKeySet = returnHash.keySet(); + Iterator 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 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 actionDataList = action.get("actionData"); + Collection 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 allKeys = new HashMap(); + LinkedHashMap> keyList = new LinkedHashMap>(); + 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 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 restObjGenericVnf = new RestObject(); + 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. 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> lookupHashMapList, HashMap 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 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> exceptionList = new HashMap>(); + + String[] chunks = aaiExtMap.getFullResourceName().split("/"); + + String keyString = ""; + if (chunks.length > 0) { + HashMap thisResourceKeys = lookupHashMapList.get(aaiExtMap.getFullResourceName()); + + for (Map.Entry ent : thisResourceKeys.entrySet()) { + keyString += ent.getKey() + "=" + ent.getValue() + " "; + } + } + + for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) { + ArrayList templateVars = new ArrayList(); + + templateVars.add("PUT " + aaiRes.getSimpleName()); + templateVars.add(keyString); + List keys = new ArrayList(); + 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> lookupHashMapList, + HashMap 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> lookupHashMapList, + HashMap 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 vertices = new ArrayList(); + 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 returnList = new ArrayList(); + 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> lookupHashMapList, + HashMap 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> lookupHashMapList, + HashMap 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> lookupHashMapList, HashMap 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 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> lookupHashMapList, HashMap 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 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 childResHash = children.getAaiResources(); + + for (Map.Entry 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 dynamicEntityList = new ArrayList(); + + 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 childResHash = children.getAaiResources(); + + for (Map.Entry 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 dynamicEntityList = new ArrayList(); + + 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 allKeys, HashMap> 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 propHash = new HashMap(); + + // 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 children = aaiRes.getChildren().getAaiResources(); + + if (aaiRes.getRecurseToResource() != null) { + AAIResource recurseToResource = aaiRes.getRecurseToResource(); + children.put(recurseToResource.getFullName(), recurseToResource); + } + + for (Entry 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 objList = meObject + .get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, aaiChildRes.getSimpleName())); + doCheckpoint("PUT_OBJECT_PRE_GET_CONNECTED_NODES", aaiExtMap); + List 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.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> lookupHashMapList, + HashMap 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 childResHash = children.getAaiResources(); + if (aaiRes.getRecurseToResource() != null) { + AAIResource recurseToResource = aaiRes.getRecurseToResource(); + childResHash.put(recurseToResource.getFullName(), recurseToResource); + } + for (Map.Entry 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 vertices = new ArrayList(); + if (parentVertex == null) { + vertices = DbMeth.getNodes(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), + g, titanDnHypResourceType, new HashMap(), true, + aaiChildRes.getApiVersion()); + } else { + vertices = DbMeth.getConnectedChildren(aaiExtMap.getTransId(), aaiExtMap.getFromAppId(), g, parentVertex, titanDnHypResourceType); + } + doCheckpoint("GET_OBJECTS_POST_GET_NODES", aaiExtMap); + List childDynamicEntityList = new ArrayList(); + + 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 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 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 childList = new ArrayList(); + // 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 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> lookupHashMapList, + HashMap 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 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 keyPropHash = new HashMap(); + + 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 ancestryHash = ancestry.getAncestryItems(); + String apiVersion = AAIConfig.get("aai.notification.current.version", "v7"); + + DynamicEntity outsideObject = null; + + for (Map.Entry 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 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 cList = new ArrayList(); + 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 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 gcList = new ArrayList(); + + 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 requiredProps, + HashMap propHash) throws AAIException { + ArrayList missingFields = new ArrayList(); + ArrayList emptyFields = new ArrayList(); + + 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 propFilterHash = new HashMap(); + 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 propFilterHash) throws AAIException { + + for( DynamicEntity relData: (List)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 vidToNodeTypeHash = new HashMap (); + HashMap vidToVertexHash = new HashMap (); + + 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 listOfRelationships = new ArrayList(); + + 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 entry : vidToVertexHash.entrySet() ){ + + List relationshipDataList = new ArrayList(); + List relatedToPropertyList = new ArrayList(); + + 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 nodeKeyPropsHash = RestURL.getKeyHashes(g, relNode, AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + Iterator >keyIterator = nodeKeyPropsHash.entrySet().iterator(); + while( keyIterator.hasNext() ){ + DynamicEntity relationshipData = relationshipDataType.newDynamicEntity(); + Map.Entry pair = (Map.Entry)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 nodeNamePropsHash = DbMeth.getNodeNamePropHash(transId, fromAppId, g, relNode, AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + Iterator >nameIterator = nodeNamePropsHash.entrySet().iterator(); + while( nameIterator.hasNext() ){ + DynamicEntity relatedToProperty = relatedToPropertyType.newDynamicEntity(); + Map.Entry pair = (Map.Entry)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 relListTmp = relationshipList.get("relationship"); + for( DynamicEntity rel: relListTmp) { + HashMap propFilterHash = new HashMap(); + 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 propFilterHash = new HashMap(); + 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 startNodeKeyParams, + List 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 propHash = new HashMap(); + 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 ver = new HashSet (); + + 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 resultDataList = new ArrayList(); + for (Vertex thisNode: ver){ + String nodeType = thisNode.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 edgeFilterParams, + List 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 (); + edgeFilterParams = new ArrayList (); + } + else { + if( !filterParams.isEmpty()) + logline.add("filterParams", "[" + filterParams.toString() + "]"); + if( !edgeFilterParams.isEmpty()) + logline.add("edgeFilterParams", "[" + edgeFilterParams.toString() + "]"); + } + + Collection resultSetVertices = new ArrayList (); + 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) 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 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.property(propName).orElse(null) != null && relatedToVertex.property(propName).equals(propValue)) + resultSetVertices.add(targetNodeVertex); + } + } else if (filterType.equals("DOES-NOT-EXIST")) { + // check for matching property + if (relatedToVertex.property(propName).orElse(null) != null && !relatedToVertex.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 resultDataList = new ArrayList(); + for (TitanVertex thisNode: resultSetVertices){ + resCount++; + String nodeType = thisNode.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 includeNodeTypes, + ResultSet resultSet, + int invItemCount, + int levelCount ) + throws UnsupportedEncodingException, AAIException { + + ArrayList retArr = new ArrayList (); + 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.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.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 indexProperties = dbMaps.NodeMapIndexedProps.get(nt); + + ArrayList itemDataList = new ArrayList(); + + Iterator> pI = node.properties(); + + ArrayList defB = new ArrayList(); + + if (AAIConfig.getDefaultBools().containsKey(nt)) { + for (String db : AAIConfig.getDefaultBools().get(nt)) { + defB.add(db); + } + } + + while( pI.hasNext() ){ + VertexProperty 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 listItr = resultSet.getSubResultSet().listIterator(); + ArrayList inventoryItemList = new ArrayList(); + + 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 til = new ArrayList(); + 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 edRuleColl = DbEdgeRules.EdgeRules.get(targetNodeType + "|" + nodeType); + Iterator 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 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 namedQueryLookupHash = new HashMap(); + + 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 namedQueryVertices = DbMeth.getNodes(transId, fromAppId, g, "named-query", namedQueryLookupHash, false); + + for (TitanVertex vert : namedQueryVertices) { + namedQueryUuid = vert.property("named-query-uuid").orElse(null); + // there should only be one, we'll pick the first if not + break; + } + } + + ArrayList> startNodeFilterHash = new ArrayList>(); + + mapInstanceFilters((DynamicEntity)modelAndNamedQuerySearch.get("instanceFilters"), + startNodeFilterHash, jaxbContext); + + ArrayList resultSet = ModelBasedProcessing.queryByNamedQuery(transId, fromAppId, g, + namedQueryUuid, startNodeFilterHash, aaiExtMap.getApiVersion() ); + + inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems"); + + HashMap objectToVertMap = new HashMap(); + ArrayList 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 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 modelQueryLookupHash = new HashMap(); + + 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 modelVertices = DbMeth.getNodes(transId, fromAppId, g, "model", modelQueryLookupHash, false); + for (TitanVertex vert : modelVertices) { + modelNameVersionId = vert.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 > startNodeFilterHash = new ArrayList< HashMap >(); + + String resourceVersion = mapInstanceFilters((DynamicEntity)modelAndNamedQuerySearch.get("instanceFilters"), + startNodeFilterHash, jaxbContext); + + if (isDelete) { + + ArrayList resultSet = ModelBasedProcessing.queryByModel(transId, fromAppId, g, + modelNameVersionId, modelId, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion() ); + + new ArrayList(); + + HashMap objectToVertMap = new HashMap(); + ArrayList invItemList = unpackResultSet(g, resultSet, jaxbContext, aaiResources, objectToVertMap, aaiExtMap); + + ResultSet rs = resultSet.get(0); + + TitanVertex firstVert = rs.getVert(); + String restURL = RestURL.get(g, firstVert); + + HashMap delResult = ModelBasedProcessing.runDeleteByModel( transId, fromAppId, g, + modelNameVersionId, topNodeType, startNodeFilterHash.get(0), aaiExtMap.getApiVersion(), resourceVersion ); + + String resultStr = ""; + for (Map.Entry 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 newInvItemList = new ArrayList(); + 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 = 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(); + HashMap objectToVertMap = new HashMap(); + ArrayList 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.property("availability-zone-name").toString(); + logline.add("availability-zone-name", avZoVtx.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.property("hypervisor-type") != null) { + zone.set("hypervisorType", avZoVtx.property("hypervisor-type").orElse(null)); + } + if (avZoVtx.property("operational-state") != null) { + zone.set("operationalState", (avZoVtx.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.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.property("switch-name") != null) { + dvs.set("switchName", swVtx.property("switch-name").orElse(null)); + } + if (swVtx.property("vcenter-url") != null) { + dvs.set("vcenterUrl", swVtx.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.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.property("network-name") != null) { + oam.set("networkName", oamVtx.property("network-name").orElse(null)); + } + + Object cvt = oamVtx.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.property("ipv4-oam-gateway-address") != null) { + oam.set("ipv4OamGatewayAddress", oamVtx.property("ipv4-oam-gateway-address").orElse(null)); + } + Object len = oamVtx.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> startNodeFilterHash, DynamicJAXBContext jaxbContext) { + + if (instanceFilters == null || !instanceFilters.isSet("instanceFilter")) { + return null; + } + @SuppressWarnings("unchecked") + List instanceFilter = (ArrayList)instanceFilters.get("instanceFilter"); + String resourceVersion = null; + + for (DynamicEntity instFilt : instanceFilter) { + List any = instFilt.get("any"); + HashMap thisNodeFilterHash = new HashMap(); + 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 includeTheseVertices, HashMap 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 invItemList = new ArrayList(); + DynamicEntity inventoryItems = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".InventoryResponseItems"); + DynamicEntity subInventoryResponseItems = invResultItem.get("inventoryResponseItems"); + List 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 unpackResultSet(TitanTransaction g, ArrayList resultSetList, + DynamicJAXBContext jaxbContext, + AAIResources aaiResources, + HashMap objectToVertMap, + AAIExtensionMap aaiExtMap) throws AAIException { + + ArrayList resultList = new ArrayList(); + + 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.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 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 extraProperties = resultSet.getExtraPropertyHash(); + + DynamicEntity extraPropertiesEntity = jaxbContext.newDynamicEntity("inventory.aai.openecomp.org." + aaiExtMap.getApiVersion() + ".ExtraProperties"); + + List extraPropsList = new ArrayList(); + + for (Map.Entry 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 emptyPropertyOverRideHash = new HashMap(); + 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 keysAndNamesPropHash = new HashMap(); + 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 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.property("persona-model-id").orElse(null); + String personaModelVersion = (String)vert.property("persona-model-version").orElse(null); + + if ( (personaModelId != null && personaModelVersion != null) + && (personaModelId.length() > 0 && personaModelVersion.length() > 0) ) { + HashMap modelLookupHash = new HashMap(); + + modelLookupHash.put("model-id", personaModelId); + modelLookupHash.put("model-version", personaModelVersion); + + TitanVertex modelVert = DbMeth.getUniqueNode(aaiExtMap.getTransId(), + aaiExtMap.getFromAppId(), g, "model", modelLookupHash, null); + + modelName = modelVert.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 subResultSet = resultSet.getSubResultSet(); + if (subResultSet != null) { + ArrayList 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 EdgeInfoMap; + static { + EdgeInfoMap = new HashMap(); + 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 EdgeRules = new ImmutableSetMultimap.Builder() + .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 DefaultDeleteScope = new ImmutableSetMultimap.Builder() + .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 NodeTypeCategory = new ImmutableSetMultimap.Builder() + .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 NodeTypeCatMap; + static { + NodeTypeCatMap = new HashMap(); + 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 ReservedPropNames; + static { + ReservedPropNames = new HashMap(); + 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 CanBeRecursiveNT; + static { + CanBeRecursiveNT = new HashMap(); + 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 ResourceMap = + new ImmutableSetMultimap.Builder() + .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 ChildMap = + new ImmutableSetMultimap.Builder() + .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 resRuleColl = ResourceMap.get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, resource)); + Iterator 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 childRuleColl = ChildMap.get(resource); + Iterator 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 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 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 process(String eventMessage) { + + LogLine logline = new LogLine(); + logline.init(COMPONENT, this.transId, fromAppId, "process(String eventMessage)"); + + Pair 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 statusPair) throws JSONException, FileNotFoundException, IOException { + + LogLine logline = new LogLine(); + logline.init(COMPONENT, this.transId, fromAppId, "publishStatusResponse(Pair 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 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 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 statusPair(AAIWorkloadEventStatus status, String msg) { + if (msg == null) { + msg = ""; + } + return new Pair(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 PropertyDataTypeMap; + private Multimap NodeMapIndexedProps; + private Multimap NodeAltKey1Props; + private Multimap NodeDependencies; + private Multimap NodeKeyProps; + private Multimap NodeReqProps; + private Multimap NodeNameProps; + private Multimap NodeUniqueProps; + + // if new dataTypes are added - make sure to update getAllFields() method below + private ArrayList stringFields; + private ArrayList stringListFields; + private ArrayList longFields; + private ArrayList intFields; + private ArrayList shortFields; + private ArrayList booleanFields; + + private ArrayList requiredFields; + private ArrayList orderedFields; + private AAIResource recurseToResource; + private boolean allowDirectWrite; + private boolean allowDirectRead; + private ArrayList 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 getPropertyDataTypeMap() { + return PropertyDataTypeMap; + } + + /** + * Sets the property data type map. + * + * @param propertyDataTypeMap the property data type map + */ + public void setPropertyDataTypeMap(Map propertyDataTypeMap) { + PropertyDataTypeMap = propertyDataTypeMap; + } + + /** + * Gets the node map indexed props. + * + * @return the node map indexed props + */ + public Multimap getNodeMapIndexedProps() { + return NodeMapIndexedProps; + } + + /** + * Sets the node map indexed props. + * + * @param nodeMapIndexedProps the node map indexed props + */ + public void setNodeMapIndexedProps(Multimap nodeMapIndexedProps) { + NodeMapIndexedProps = nodeMapIndexedProps; + } + + /** + * Gets the node key props. + * + * @return the node key props + */ + public Multimap getNodeKeyProps() { + return NodeKeyProps; + } + + /** + * Sets the node key props. + * + * @param nodeKeyProps the node key props + */ + public void setNodeKeyProps(Multimap nodeKeyProps) { + this.NodeKeyProps = nodeKeyProps; + } + + /** + * Gets the node name props. + * + * @return the node name props + */ + public Multimap getNodeNameProps() { + return NodeNameProps; + } + + /** + * Sets the node name props. + * + * @param nodeNameProps the node name props + */ + public void setNodeNameProps(Multimap nodeNameProps) { + + NodeNameProps = nodeNameProps; + } + + /** + * Gets the node unique props. + * + * @return the node unique props + */ + public Multimap getNodeUniqueProps() { + return NodeUniqueProps; + } + + /** + * Sets the node unique props. + * + * @param nodeUniqueProps the node unique props + */ + public void setNodeUniqueProps(Multimap nodeUniqueProps) { + NodeUniqueProps = nodeUniqueProps; + } + + /** + * Gets the node req props. + * + * @return the node req props + */ + public Multimap getNodeReqProps() { + return NodeReqProps; + } + + /** + * Sets the node req props. + * + * @param nodeReqProps the node req props + */ + public void setNodeReqProps(Multimap 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 getStringFields() { + if (this.stringFields == null) { + this.stringFields = new ArrayList(); + } + return this.stringFields; + } + + /** + * Sets the string fields. + * + * @param stringFields the new string fields + */ + public void setStringFields(ArrayList stringFields) { + this.stringFields = stringFields; + } + + /** + * Gets the string list fields. + * + * @return the string list fields + */ + public ArrayList getStringListFields() { + if (this.stringListFields == null) { + this.stringListFields = new ArrayList(); + } + return this.stringListFields; + } + + /** + * Sets the string list fields. + * + * @param stringListFields the new string list fields + */ + public void setStringListFields(ArrayList stringListFields) { + this.stringListFields = stringListFields; + } + + /** + * Gets the long fields. + * + * @return the long fields + */ + public ArrayList getLongFields() { + if (this.longFields == null) { + this.longFields = new ArrayList(); + } + return longFields; + } + + /** + * Sets the long fields. + * + * @param longFields the new long fields + */ + public void setLongFields(ArrayList longFields) { + this.longFields = longFields; + } + + /** + * Gets the int fields. + * + * @return the int fields + */ + public ArrayList getIntFields() { + if (this.intFields == null) { + this.intFields = new ArrayList(); + } + return intFields; + } + + /** + * Sets the int fields. + * + * @param intFields the new int fields + */ + public void setIntFields(ArrayList intFields) { + this.intFields = intFields; + } + + /** + * Gets the short fields. + * + * @return the short fields + */ + public ArrayList getShortFields() { + if (this.shortFields == null) { + this.shortFields = new ArrayList(); + } + return shortFields; + } + + /** + * Sets the short fields. + * + * @param shortFields the new short fields + */ + public void setShortFields(ArrayList shortFields) { + this.shortFields = shortFields; + } + + /** + * Gets the boolean fields. + * + * @return the boolean fields + */ + public ArrayList getBooleanFields() { + if (this.booleanFields == null) { + this.booleanFields = new ArrayList(); + } + return booleanFields; + } + + /** + * Sets the boolean fields. + * + * @param booleanFields the new boolean fields + */ + public void setBooleanFields(ArrayList booleanFields) { + this.booleanFields = booleanFields; + } + + /** + * Gets the required fields. + * + * @return the required fields + */ + public ArrayList getRequiredFields() { + if (this.requiredFields == null) { + this.requiredFields = new ArrayList(); + } + return requiredFields; + } + + /** + * Sets the required fields. + * + * @param requiredFields the new required fields + */ + public void setRequiredFields(ArrayList requiredFields) { + this.requiredFields = requiredFields; + } + + /** + * Gets the ordered fields. + * + * @return the ordered fields + */ + public ArrayList getOrderedFields() { + if (this.orderedFields == null) { + this.orderedFields = new ArrayList(); + } + return this.orderedFields; + } + + /** + * Gets the all fields. + * + * @return the all fields + */ + public ArrayList getAllFields() { + + ArrayList allFields = new ArrayList(); + 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 _dbRulesNodeAltKey1Props) { + this.NodeAltKey1Props = _dbRulesNodeAltKey1Props; + } + + /** + * Gets the node alt key 1 props. + * + * @return the node alt key 1 props + */ + public Multimap getNodeAltKey1Props() { + return this.NodeAltKey1Props; + } + + /** + * Sets the node dependencies. + * + * @param _dbRulesNodeDependencies the db rules node dependencies + */ + public void setNodeDependencies(Multimap _dbRulesNodeDependencies) { + this.NodeDependencies = _dbRulesNodeDependencies; + } + + /** + * Gets the node dependencies. + * + * @return the node dependencies + */ + public Multimap 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 getAutoGenUuidFields() { + if (this.autoGenUuidFields == null) { + this.autoGenUuidFields = new ArrayList(); + } + 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; + + /** + * Gets the aai resource key. + * + * @return the aai resource key + */ + public List getAaiResourceKey() { + if (aaiResourceKey == null) { + aaiResourceKey = new ArrayList(); + } + 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 aaiResources; + private HashMap resourceLookup; + + + /** + * Gets the aai resources. + * + * @return the aai resources + */ + public HashMap getAaiResources() { + if (aaiResources == null) { + aaiResources = new HashMap(); + } + 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 getResourceLookup() { + if (resourceLookup == null) { + resourceLookup = new HashMap(); + } + return resourceLookup; + } + + /** + * Sets the resource lookup. + * + * @param resourceLookup the resource lookup + */ + public void setResourceLookup(HashMap 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 ancestryItems; + + /** + * Gets the ancestry items. + * + * @return the ancestry items + */ + public LinkedHashMap getAncestryItems() { + if (ancestryItems == null) { + ancestryItems = new LinkedHashMap(); + } + 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="cambria.partition" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="event-header" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="timestamp" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="source-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="domain" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="sequence-number" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="severity" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="event-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="version" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="action" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="top-entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="entity-link" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="status" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <any processContents='lax' namespace='##other' minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="timestamp" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="source-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="domain" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="sequence-number" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="severity" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="event-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="version" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="action" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="top-entity-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="entity-link" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *         <element name="status" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @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 http://java.sun.com/xml/jaxb +// 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. + *

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 http://java.sun.com/xml/jaxb +//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; + @XmlAnyElement(lax = true) + protected List any; + + /** + * Gets the AAI response message datum. + * + * @return the AAI response message datum + */ + public List getAAIResponseMessageDatum() { + if (aaiResponseMessageDatum == null) { + aaiResponseMessageDatum = new ArrayList(); + } + return this.aaiResponseMessageDatum; + } + + /** + * Gets the any. + * + * @return the any + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +//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; + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="flavor" maxOccurs="unbounded" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="flavor-id" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="flavor-name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                   <element name="flavor-vcpus" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ *                   <element name="flavor-ram" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ *                   <element name="flavor-disk" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ *                   <element name="flavor-ephemeral" type="{http://www.w3.org/2001/XMLSchema}short" minOccurs="0"/>
+ *                   <element name="flavor-swap" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *                   <element name="flavor-is-public" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ *                   <element name="flavor-selflink" type="{urn:ietf:params:xml:ns:yang:ietf-inet-types}uri" minOccurs="0"/>
+ *                   <element name="flavor-disabled" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ *                   <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *                   <element ref="{http://org.openecomp.aai.inventory/v8}relationship-list" minOccurs="0"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + @XmlAnyElement(lax = true) + protected List any; + + /** + * Gets the AAI response message. + * + * @return the AAI response message + */ + public List getAAIResponseMessage() { + if (aaiResponseMessage == null) { + aaiResponseMessage = new ArrayList(); + } + return this.aaiResponseMessage; + } + + /** + * Gets the any. + * + * @return the any + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="requestError">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="policyException">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="variables">
+ *                               <complexType>
+ *                                 <complexContent>
+ *                                   <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                                     <sequence>
+ *                                       <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *                                     </sequence>
+ *                                   </restriction>
+ *                                 </complexContent>
+ *                               </complexType>
+ *                             </element>
+ *                           </sequence>
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="policyException">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="variables">
+     *                     <complexType>
+     *                       <complexContent>
+     *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                           <sequence>
+     *                             <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+     *                           </sequence>
+     *                         </restriction>
+     *                       </complexContent>
+     *                     </complexType>
+     *                   </element>
+     *                 </sequence>
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="variables">
+         *           <complexType>
+         *             <complexContent>
+         *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *                 <sequence>
+         *                   <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+         *                 </sequence>
+         *               </restriction>
+         *             </complexContent>
+         *           </complexType>
+         *         </element>
+         *       </sequence>
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+             * <complexType>
+             *   <complexContent>
+             *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+             *       <sequence>
+             *         <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+             *       </sequence>
+             *     </restriction>
+             *   </complexContent>
+             * </complexType>
+             * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "variable" + }) + public static class Variables { + + protected List variable; + + /** + * Gets the value of the variable property. + * + *

+ * 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 set method for the variable property. + * + *

+ * For example, to add a new item, do as follows: + *

+                 *    getVariable().add(newItem);
+                 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * @return the variable + */ + public List getVariable() { + if (variable == null) { + variable = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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. + *

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 variables = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new HashMap(); + + /** + * 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 getVariables() { + return variables; + } + + /** + * Sets the variables. + * + * @param variables The variables + */ + @JsonProperty("variables") + public void setVariables(List variables) { + this.variables = variables; + } + + /** + * Gets the additional properties. + * + * @return the additional properties + */ + @JsonAnyGetter + public Map 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 additionalProperties = new HashMap(); + + /** + * 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 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 additionalProperties = new HashMap(); + + /** + * 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 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="responseMessages" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="responseMessage" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="variables">
+ *                               <complexType>
+ *                                 <complexContent>
+ *                                   <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                                     <sequence>
+ *                                       <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *                                     </sequence>
+ *                                   </restriction>
+ *                                 </complexContent>
+ *                               </complexType>
+ *                             </element>
+ *                           </sequence>
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="responseMessage" maxOccurs="unbounded" minOccurs="0">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="variables">
+     *                     <complexType>
+     *                       <complexContent>
+     *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                           <sequence>
+     *                             <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+     *                           </sequence>
+     *                         </restriction>
+     *                       </complexContent>
+     *                     </complexType>
+     *                   </element>
+     *                 </sequence>
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "responseMessage" + }) + public static class ResponseMessages { + + protected List responseMessage; + + /** + * Gets the value of the responseMessage property. + * + *

+ * 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 set method for the responseMessage property. + * + *

+ * For example, to add a new item, do as follows: + *

+         *    getResponseMessage().add(newItem);
+         * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Info.ResponseMessages.ResponseMessage } + * + * @return the response message + */ + public List getResponseMessage() { + if (responseMessage == null) { + responseMessage = new ArrayList(); + } + return this.responseMessage; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="variables">
+         *           <complexType>
+         *             <complexContent>
+         *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *                 <sequence>
+         *                   <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+         *                 </sequence>
+         *               </restriction>
+         *             </complexContent>
+         *           </complexType>
+         *         </element>
+         *       </sequence>
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+             * <complexType>
+             *   <complexContent>
+             *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+             *       <sequence>
+             *         <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+             *       </sequence>
+             *     </restriction>
+             *   </complexContent>
+             * </complexType>
+             * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "variable" + }) + public static class Variables { + + protected List variable; + + /** + * Gets the value of the variable property. + * + *

+ * 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 set method for the variable property. + * + *

+ * For example, to add a new item, do as follows: + *

+                 *    getVariable().add(newItem);
+                 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * @return the variable + */ + public List getVariable() { + if (variable == null) { + variable = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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. + *

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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="requestError">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="serviceException">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="variables">
+ *                               <complexType>
+ *                                 <complexContent>
+ *                                   <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                                     <sequence>
+ *                                       <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *                                     </sequence>
+ *                                   </restriction>
+ *                                 </complexContent>
+ *                               </complexType>
+ *                             </element>
+ *                           </sequence>
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <sequence>
+     *         <element name="serviceException">
+     *           <complexType>
+     *             <complexContent>
+     *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 <sequence>
+     *                   <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+     *                   <element name="variables">
+     *                     <complexType>
+     *                       <complexContent>
+     *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                           <sequence>
+     *                             <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+     *                           </sequence>
+     *                         </restriction>
+     *                       </complexContent>
+     *                     </complexType>
+     *                   </element>
+     *                 </sequence>
+     *               </restriction>
+     *             </complexContent>
+     *           </complexType>
+     *         </element>
+     *       </sequence>
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
+     * 
+ * + * + */ + @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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+         * <complexType>
+         *   <complexContent>
+         *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       <sequence>
+         *         <element name="messageId" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+         *         <element name="variables">
+         *           <complexType>
+         *             <complexContent>
+         *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *                 <sequence>
+         *                   <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+         *                 </sequence>
+         *               </restriction>
+         *             </complexContent>
+         *           </complexType>
+         *         </element>
+         *       </sequence>
+         *     </restriction>
+         *   </complexContent>
+         * </complexType>
+         * 
+ * + * + */ + @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; + } + + + /** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+             * <complexType>
+             *   <complexContent>
+             *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+             *       <sequence>
+             *         <element name="variable" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+             *       </sequence>
+             *     </restriction>
+             *   </complexContent>
+             * </complexType>
+             * 
+ * + * + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "variable" + }) + public static class Variables { + + protected List variable; + + /** + * Gets the value of the variable property. + * + *

+ * 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 set method for the variable property. + * + *

+ * For example, to add a new item, do as follows: + *

+                 *    getVariable().add(newItem);
+                 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * @return the variable + */ + public List getVariable() { + if (variable == null) { + variable = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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. + *

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 additionalProperties = new HashMap(); + + /** + * 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 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 additionalProperties = new HashMap(); + + /** + * 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 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 variables = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new HashMap(); + + /** + * 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 getVariables() { + return variables; + } + + /** + * Sets the variables. + * + * @param variables The variables + */ + @JsonProperty("variables") + public void setVariables(List variables) { + this.variables = variables; + } + + /** + * Gets the additional properties. + * + * @return the additional properties + */ + @JsonAnyGetter + public Map 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="include-node-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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 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. + * + *

+ * 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 set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Object } + * {@link Element } + * + * @return the any + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for inventory-item complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="inventory-item">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="inventory-item-type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="inventory-item-link" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="inventory-item-data" maxOccurs="unbounded" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <element name="tagged-inventory-item-list" type="{http://org.openecomp.aai.inventory/v8}tagged-inventory-item-list" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + @XmlElement(name = "tagged-inventory-item-list") + protected List 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. + * + *

+ * 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 set method for the inventoryItemData property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getInventoryItemData().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link InventoryItemData } + * + * @return the inventory item data + */ + public List getInventoryItemData() { + if (inventoryItemData == null) { + inventoryItemData = new ArrayList(); + } + return this.inventoryItemData; + } + + /** + * Gets the value of the taggedInventoryItemList property. + * + *

+ * 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 set method for the taggedInventoryItemList property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getTaggedInventoryItemList().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link TaggedInventoryItemList } + * + * @return the tagged inventory item list + */ + public List getTaggedInventoryItemList() { + if (taggedInventoryItemList == null) { + taggedInventoryItemList = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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 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. + * + *

+ * 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 set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Object } + * {@link Element } + * + * @return the any + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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. + *

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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="filter-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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 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. + * + *

+ * 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 set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Object } + * {@link Element } + * + * @return the any + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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 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. + * + *

+ * 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 set method for the any property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAny().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Object } + * {@link Element } + * + * @return the any + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for tagged-inventory-item-list complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="tagged-inventory-item-list">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="inventory-item" type="{http://org.openecomp.aai.inventory/v8}inventory-item" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "tagged-inventory-item-list", propOrder = { + "inventoryItem" +}) +public class TaggedInventoryItemList { + + @XmlElement(name = "inventory-item") + protected List inventoryItem; + + /** + * Gets the value of the inventoryItem property. + * + *

+ * 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 set method for the inventoryItem property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getInventoryItem().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link InventoryItem } + * + * @return the inventory item + */ + public List getInventoryItem() { + if (inventoryItem == null) { + inventoryItem = new ArrayList(); + } + 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 http://java.sun.com/xml/jaxb +// 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 http://java.sun.com/xml/jaxb +// 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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="update" minOccurs="0">
+ *           <complexType>
+ *             <complexContent>
+ *               <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 <sequence>
+ *                   <element name="update-node-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                   <element name="update-node-key" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="key-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="key-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *                           </sequence>
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <element name="action" maxOccurs="unbounded" minOccurs="0">
+ *                     <complexType>
+ *                       <complexContent>
+ *                         <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           <sequence>
+ *                             <element name="action-type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                             <element name="action-data" maxOccurs="unbounded" minOccurs="0">
+ *                               <complexType>
+ *                                 <complexContent>
+ *                                   <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                                     <sequence>
+ *                                       <element name="property-name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                                       <element name="property-value" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *                                       <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *                                     </sequence>
+ *                                   </restriction>
+ *                                 </complexContent>
+ *                               </complexType>
+ *                             </element>
+ *                             <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *                           </sequence>
+ *                         </restriction>
+ *                       </complexContent>
+ *                     </complexType>
+ *                   </element>
+ *                   <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *                 </sequence>
+ *               </restriction>
+ *             </complexContent>
+ *           </complexType>
+ *         </element>
+ *         <any processContents='lax' namespace='##other' maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "transactionLogEntries" +}) +@XmlRootElement(name = "transaction-log-entries", namespace = "http://org.openecomp.aai.inventory") +public class TransactionLogEntries { + + protected List transactionLogEntries; + + /** + * Gets the transaction log entries. + * + * @return the transaction log entries + */ + public List getTransactionLogEntries() { + if (transactionLogEntries == null) { + transactionLogEntries = new ArrayList(); + } + 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 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 getTemplateVars() { + return templateVars; + } + + /** + * Sets the template vars. + * + * @param templateVars the new template vars + */ + public void setTemplateVars(List 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 infoHash; + String info; + + /** + * Instantiates a new AAI exception with info. + * + * @param infoHash the info hash + * @param info the info + */ + public AAIExceptionWithInfo(HashMap 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 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 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 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 infoHash, String info) { + super(code, cause, details); + setInfoHash(infoHash); + setInfo(info); + } + + /** + * Gets the info hash. + * + * @return the info hash + */ + public HashMap getInfoHash() { + return infoHash; + } + + /** + * Sets the info hash. + * + * @param infoHash the info hash + */ + public void setInfoHash(HashMap 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 (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 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 lookupHashMap; + private HashMap> precheckAddedList; + private AAIResponseMessages precheckResponseMessages; + private HashMap topology; + private HashMap 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 _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 getTemplateVars() { + if (this.templateVars == null) { + this.templateVars = new ArrayList(); + } + 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 getLookupHashMap() { + if (this.lookupHashMap == null) { + this.lookupHashMap = new HashMap(); + } + return this.lookupHashMap; + } + + /** + * Sets the lookup hash map. + * + * @param lookupHashMap the lookup hash map + */ + public void setLookupHashMap(HashMap lookupHashMap) { + this.lookupHashMap = lookupHashMap; + } + + /** + * Gets the precheck added list. + * + * @return the precheck added list + */ + public HashMap> getPrecheckAddedList() { + if (this.precheckAddedList == null) { + this.precheckAddedList = new HashMap>(); + } + return precheckAddedList; + } + + /** + * Sets the precheck added list. + * + * @param precheckAddedList the precheck added list + */ + public void setPrecheckAddedList(HashMap> 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 getTopology() { + if (this.topology == null) { + this.topology = new HashMap(); + } + return topology; + } + + /** + * Gets the vertex cache. + * + * @return the vertex cache + */ + public HashMap getVertexCache() { + if (this.vertexCache == null) { + this.vertexCache = new HashMap(); + } + 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 apiVersions = new ArrayList(); + apiVersions.add(_apiVersion); + final IngestModelMoxyOxm m = new IngestModelMoxyOxm(); + m.init(apiVersions, false); + + DynamicJAXBContext jaxbContext = IngestModelMoxyOxm.aaiResourceContainer.get(_apiVersion).getJaxbContext(); + + JAXBUnmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + + Class 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 apiVersions = new ArrayList(); + 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 processedWidgets = new ArrayList(); + for (Map.Entry 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 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 NodeAltKey1Props = ArrayListMultimap.create(); + + public Multimap NodeDependencies = ArrayListMultimap.create(); + + public Multimap NodeNameProps = ArrayListMultimap.create(); + + public Multimap NodeMapIndexedProps = ArrayListMultimap.create(); + + public Multimap NodeMapUniqueProps = ArrayListMultimap.create(); + + public Map EdgeInfoMap = new LinkedHashMap(); + + public Map ReservedPropNames = new HashMap(); + + // from AAIResources + public Multimap NodeProps = ArrayListMultimap.create(); + + public Multimap NodeKeyProps = ArrayListMultimap.create(); + + public Map NodePlural = new HashMap(); + + public Map NodeNamespace = new HashMap(); + + public Map PropertyVersionInfoMap = new HashMap(); + + public Map NodeVersionInfoMap = new HashMap(); + + public Map PropertyDataTypeMap = new HashMap(); + + } 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 addIngestModelListener 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 apiVersions = new ArrayList(); + 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 aaiResourceContainer; + + public static HashMap dbMapsContainer; + + private static HashMap timers = new HashMap(); + + /** + * 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 apiVersions = new ArrayList(); + apiVersions.add(_apiVersion); + final IngestModelMoxyOxm m = new IngestModelMoxyOxm(); + m.init(apiVersions, false); + + ArrayList endpoints = new ArrayList(); + + for (Map.Entry ent: aaiResourceContainer.entrySet()) { + + AAIResources aaiResources = ent.getValue(); + DynamicJAXBContext jaxbContext = aaiResources.getJaxbContext(); + for (Map.Entry 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 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 apiVersions, Boolean setTimer) throws Exception { + + aaiResourceContainer = new HashMap(); + dbMapsContainer = new HashMap(); + + 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 ent: aaiResourceContainer.entrySet()) { + String apiVersion = ent.getKey(); + AAIResources aaiResources = ent.getValue(); + + DbMaps dbMap = dbMapsContainer.get(apiVersion); + + for (Map.Entry 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 properties = new HashMap(); + 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 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 dbfList = cd3.getPrimaryKeyFields(); + ArrayList keyFields = new ArrayList(); + + if (dbfList != null) { + for (DatabaseField dbf : dbfList) { + String name = dbf.getName(); + name = name.substring(0, name.indexOf('/')); + keyFields.add(name); + } + } + Vector 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> itemKeyList = new LinkedHashMap>(); + + aaiRes.setApiVersion(apiVersion); + itemKeyList.put(hypName, new ArrayList()); + 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) fromCommaSeparatedString(propMap.get("nameProps").toString())); + + if (propMap.containsKey("indexedProps")) + dbMaps.NodeMapIndexedProps.putAll(nodeType, + (Iterable) fromCommaSeparatedString(propMap.get("indexedProps").toString())); + + if (propMap.containsKey("dependentOn")) + dbMaps.NodeDependencies.putAll(nodeType, + (Iterable) fromCommaSeparatedString(propMap.get("dependentOn").toString())); + + if (propMap.containsKey("alternateKeys1")) + dbMaps.NodeAltKey1Props.putAll(nodeType, + (Iterable) fromCommaSeparatedString(propMap.get("alternateKeys1").toString())); + + if (propMap.containsKey("uniqueProps")) + dbMaps.NodeMapUniqueProps.putAll(nodeType, + (Iterable) fromCommaSeparatedString(propMap.get("uniqueProps").toString())); + + // build EdgeInfoMap + if (propMap.containsKey("edgeInfo")) { + int i = 0; + Iterable edgeInfoIterable = (Iterable) fromCommaSeparatedString(propMap.get("edgeInfo").toString()); + Iterator 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 keyList = new ArrayList(); + 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)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"); + else if (!dbMaps.PropertyDataTypeMap.get(propName).equals("Set")) + 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 apiVersionsList = (ArrayList) 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 nodeTypeIterator = dbMaps.NodeProps.keySet().iterator(); + while( nodeTypeIterator.hasNext() ){ + String nType = nodeTypeIterator.next(); + if (!dbMaps.NodeVersionInfoMap.containsKey(nType)) { + dbMaps.NodeVersionInfoMap.put(nType, apiVersion); + } + Collection nodePropsForType = dbMaps.NodeProps.get(nType); + Iterator 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 the generic type + * @param c the c + * @return the list + */ + private > List asSortedList(Collection c) { + List list = new ArrayList(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 fromCommaSeparatedString( String string ) { + Iterable split = Splitter.on( "," ).omitEmptyStrings().trimResults().split( string ); + return split; + } + + /** + * Pretty print map. + * + * @param map the map + * @return the string + */ + public String prettyPrintMap(Multimap 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 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> headersList = CastUtils.cast((Map)message.get(Message.PROTOCOL_HEADERS)); + String transId = ""; + String fromAppId = null; + List 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 txList = new ArrayList(); + 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 fa = headersList.get("X-FromAppId"); + if (fa != null) { + for (String fromAppIdValue : fa) { + fromAppId = fromAppIdValue; + } + } + + List 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> headers = CastUtils.cast((Map) message.get(Message.PROTOCOL_HEADERS)); + if (headers == null) { + headers = new HashMap>(); + } + + 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> headersList = CastUtils.cast((Map) inMessage.get(Message.PROTOCOL_HEADERS)); + if (headersList != null) { + List xt = headersList.get("X-TransactionId"); + if (xt != null) { + for (String transIdValue : xt) { + transId = transIdValue; + } + } + List 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 getProperties(); + /** + * + * @return a list of the required properties on the object + */ + public abstract List getRequiredProperties(); + /** + * + * @return a list of the properties that can be used to query the object in the db + */ + public abstract List getKeys(); + /** + * + * @return a list of the all key properties for this object + */ + public List getAllKeys() { + List 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 getIndexedProperties() { + List 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 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 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 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 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 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 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 getProperties() { + Set set = json.keySet(); + List result = new ArrayList<>(); + result.addAll(set); + return result; + } + + @Override + public List getRequiredProperties() { + //unknowable + + return this.getProperties(); + } + + @Override + public List getKeys() { + //unknowable + return this.getProperties(); + } + + @Override + public List 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 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 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 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 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 properties = new HashMap(); + 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 getProperties() { + List result = new ArrayList<>(); + for (String s : internalType.getPropertiesNames()) { + result.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, s)); + + } + return result; + } + + @Override + public List getRequiredProperties() { + List 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 getKeys() { + List result = new ArrayList<>(); + + for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) { + result.add(this.removeXPathDescriptor(name)); + } + return result; + } + + @Override + public Map getPropertyMetadata(String prop) { + String propName = this.convertPropertyName(prop); + DatabaseMapping mapping = cd.getMappingForAttributeName(propName); + Map 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 keys = null; + keys = this.getKeys(); + List 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 keyProps = null; + private Multimap requiredProps = null; + private Multimap 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 getProperties() { + Field[] fields = this.internalObject.getClass().getDeclaredFields(); + List result = new ArrayList<>(); + + for (Field field : fields) { + if (!field.getName().equals("any")) { + result.add(covertFieldToOutputFormat(field.getName())); + } + } + return result; + } + + @Override + public List getRequiredProperties() { + Field[] fields = this.internalObject.getClass().getDeclaredFields(); + List 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 getKeys() { + Field[] fields = this.internalObject.getClass().getDeclaredFields(); + List 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 getAllKeys() { + List 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 keys = null; + keys = this.getKeys(); + List 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 getPropertyMetadata(String prop) { + Field f; + Map 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 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 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 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 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 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 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 issues = null; + private List 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 getIssues() { + return this.issues; + } + + /** + * Sets the issue resolvers. + * + * @param resolvers the new issue resolvers + */ + public void setIssueResolvers(List 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 requiredProps = obj.getRequiredProperties(); + List 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 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 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(); + } + + /** + * 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 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 variables, LogLine logline) { + List acceptHeaders = new ArrayList(); + 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 acceptHeadersOrig, AAIException are, ArrayList variables, LogLine logline) {; + + + StringBuilder text = new StringBuilder(); + String response = null; + + List acceptHeaders = new ArrayList(); + // 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(); + } + + 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 acceptHeadersOrig, AAIException are, ArrayList 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 acceptHeaders, HashMap> 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>> it = areList.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry> pair = (Map.Entry>)it.next(); + AAIException are = pair.getKey(); + ArrayList 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(); + } + + 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, 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(); + } + + 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 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 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 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 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 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 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 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 uriKeys) { + this.resultResource = obj.getDbName(); + if (previous != null) { + this.parentName = previous.getDbName(); + } + this.previous = obj; + + + } + + + /** + * @{inheritDoc} + */ + @Override + public void processContainer(Introspector obj, Map 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 data = (List)relationship.getValue("relationship-data"); + Introspector wrapper = null; + String key = ""; + String value = ""; + String objectType = ""; + String propertyName = ""; + String[] split = null; + HashMap 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 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 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 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 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 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 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 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 uriKeys = new LinkedHashMap<>(); + i++; + if (i == parts.length && queryParams != null) { + Set 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 uriKeys = new LinkedHashMap<>(); + + if (isFinalContainer && queryParams != null) { + Set 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 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 uriKeys) { + + dbKeys.add(obj.getDbName()); + + for (String key : uriKeys.keySet()) { + dbKeys.add(uriKeys.get(key).toString()); + } + } + + /** + * @{inheritDoc} + */ + @Override + public void processContainer (Introspector obj, Map 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 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 uriKeys) { + String upperCamel = toUpperCamel(obj.getDbName()); + if (topObject.equals("")) { + topObject = upperCamel; + } + pieces.add(upperCamel); + + } + + /** + * @{inheritDoc} + */ + @Override + public void processContainer(Introspector obj, Map 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 parentList = null; + + private Version version = null; + private Loader loader = null; + private final HashMap 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 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 uriKeys) { + + if (this.entityName == null) { + this.topEntityName = obj.getDbName(); + this.topEntity = obj; + } + this.entityName = obj.getDbName(); + this.entity = obj; + this.parentList = (List)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 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 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 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)relationship.getValue("relationship-data")).add(data.getUnderlyingObject()); + + } + relationship.setValue("related-to", obj.getDbName()); + } + + /** + * @{inheritDoc} + */ + @Override + public void processContainer(Introspector obj, Map 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 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 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 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[] 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.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 clone = this.traversal.asAdmin().clone(); + GraphTraversal.Admin cloneAdmin = clone.asAdmin(); + List 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 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 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 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 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 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(); + } + + /** + * 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(); + } + + /** + * @{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 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 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.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 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 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 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 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 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 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>> allResponses = new ArrayList>>(); + + 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> tuples = new ArrayList>(); + 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 requests = new ArrayList<>(); + for (Pair 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>> results = httpEntry.process(g, requests, sourceOfTruth); + List> 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 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> 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 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>> allResponses){ + JsonObject ret = new JsonObject(); + JsonArray retArr = new JsonArray(); + + for(List> responses : allResponses){ + JsonObject tResp = new JsonObject(); + JsonArray tArrResp = new JsonArray(); + + for (Pair 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>> 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 uriResp = Pair.with(thisUri, failResp); + List> transRespList = new ArrayList>(); + 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 uriResp = Pair.with(thisUri, failResp); + List> 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 { + + @Context + private HttpServletRequest request; + + @Context + private HttpHeaders headers; + + /** + * @{inheritDoc} + */ + @Override + public Response toResponse(Exception exception) { + + Response response = null; + ArrayList templateVars = new ArrayList(); + + 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 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 requests = new ArrayList<>(); + requests.add(request); + Pair>> 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 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 requests = new ArrayList<>(); + requests.add(request); + Pair>> 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 requests = new ArrayList<>(); + requests.add(request); + Pair>> 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 requests = new ArrayList<>(); + requests.add(request); + Pair>> 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 map = info.getQueryParameters(false); + String params = "?"; + List 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 requests = new ArrayList<>(); + requests.add(request); + Pair>> 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 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 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 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 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 templateVars = new ArrayList(); + 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 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 templateVars = new ArrayList(); + + 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 allKeys = new HashMap(); + LinkedHashMap> keyList = new LinkedHashMap>(); + + 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 thisResourceKeys = keyList.get(aaiExtMap.getFullResourceName()); + + for (Map.Entry 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 templateVars = new ArrayList(); + 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 allKeys = new HashMap(); + LinkedHashMap> keyList = new LinkedHashMap>(); + + 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 thisResourceKeys = keyList.get(aaiExtMap.getFullResourceName()); + + for (Map.Entry 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 templateVars = new ArrayList(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 allKeys = new HashMap(); + LinkedHashMap> keyList = new LinkedHashMap>(); + + 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 params = uriInfo.getQueryParameters(); + if (dnHypNodeType.equals("cvlan-tag-entry")) { + dnHypNodeType = "cvlan-tag"; + } + Collection indexedProps = aaiRes.getNodeMapIndexedProps().get(dnHypNodeType); + + ArrayList stringFields = aaiRes.getStringFields(); + // get all the string props for this method + + boolean hasIndexProp = false; + + LinkedHashMap subKeyList = new LinkedHashMap(); + String keyString = ""; + for (Entry> param : params.entrySet()) { + + String paramName = param.getKey(); + if (indexedProps.contains(paramName)) { + hasIndexProp = true; + } + List 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 thisResourceKeys = keyList.get(aaiExtMap.getFullResourceName()); + String keyString = ""; + for (Map.Entry 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 allKeys, LinkedHashMap> 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 subKeyList = new LinkedHashMap(); + + // 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 subKeyList = new LinkedHashMap(); + subKeyList.put("container|example", p1.toString()); + keyList.put(tmpResource, subKeyList); + } + } + } + } else { + if (p.equals("relationship-list")) { + LinkedHashMap subKeyList = new LinkedHashMap(); + 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 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 itr = g.vertices(vertexid); + + if (!itr.hasNext()) { + throw new AAIException("AAI_6114", "no node at that vertex id"); + } + thisVertex = itr.next(); + String objName = thisVertex.property(AAIProperties.NODE_TYPE).orElse(null); + Introspector obj = loader.introspectorFromName(objName); + List vertexListWrapper= new ArrayList(); + 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 templateVars = new ArrayList(); + 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 templateVars = new ArrayList(); + 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 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>> process (TitanTransaction g, List 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> responses = new ArrayList<>(); + MultivaluedMap 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 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).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 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 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 pairedResp = Pair.with(request.getUri(), response); + responses.add(pairedResp); + } catch (AAIException e) { + success = false; + ArrayList templateVars = new ArrayList(); + 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 pairedResp = Pair.with(request.getUri(), response); + responses.add(pairedResp); + continue; + } catch (Exception e) { + success = false; + AAIException ex = new AAIException("AAI_4000", e); + ArrayList templateVars = new ArrayList(); + 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 pairedResp = Pair.with(request.getUri(), response); + responses.add(pairedResp); + continue; + } + } + + notification.triggerEvents(); + Pair>> 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 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 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> exceptionList = new HashMap>(); + + String keyString = ""; + + List resourceKeys = input.getKeys(); + for (String key : resourceKeys) { + keyString += key + "=" + input.getValue(key) + " "; + } + + for (AAIResponseMessage msg : aaiExtMap.getPrecheckResponseMessages().getAAIResponseMessage()) { + ArrayList templateVars = new ArrayList(); + + templateVars.add("PUT " + input.getDbName()); + templateVars.add(keyString); + List keys = new ArrayList(); + 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 getRelatedObjects(DBSerializer serializer, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, MalformedURLException, AAIException { + HashMap relatedVertices = new HashMap<>(); + List 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 templateVars = new ArrayList(); + 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 templateVars = new ArrayList(); + 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 startNodeKeyParams, + @QueryParam("include") final List 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 templateVars = new ArrayList(); + 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 edgeFilterList, + @QueryParam("filter") final List filterList) { + AAIException ex = null; + Response searchResult = null; + String fromAppId = null; + String transId = null; + LogLine logline = new LogLine(); + String rqstTm = genDate(logline); + ArrayList templateVars = new ArrayList(); + 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 templateVars = new ArrayList(); + 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 templateVars = new ArrayList(); + 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 methodList = new ArrayList(); + + 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 logList = txn.scan(transId); + for (String logValue : logList) { + sb += "\n" + logValue + "\n"; + } + } catch (Exception e) { + sb = "hbase scan got error="+e.toString(); + } + return "" + + "\n" + + transId + +"\n" + + "\n" + + sb + + "\n" + +"\n\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 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 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 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 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 templateVars = new ArrayList(); + 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> exceptionList = new HashMap>(); + + ArrayList templateVars = new ArrayList(); + 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 templateVars = new ArrayList(); +// 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 templateVars = new ArrayList(); + 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 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 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 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 List processObject (Introspector obj, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, NoSuchMethodException, SecurityException, AAIException, UnsupportedEncodingException { + Object value = null; + int objectCount = 0; + String propertyType = ""; + List properties = obj.getProperties(); + properties.remove(AAIProperties.RESOURCE_VERSION); + List dependentVertexes = new ArrayList<>(); + List 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 relationships = (List)wrapped.getValue("relationship"); + + Vertex cousinVertex = null; + Edge e = null; + List existingEdges = new ArrayList<>(); + GraphTraversal 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 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 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 required = latest.getRequiredProperties(); + String defaultValue = null; + Object vertexProp = null; + for (String field : required) { + defaultValue = latest.getPropertyMetadata(field).get("defaultValue"); + if (defaultValue != null) { + vertexProp = v.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 items = this.engine.getQueryEngine().executeQuery(p.getQuery()); + QueryBuilder query = this.engine.getQueryBuilder(v); + query.createEdgeTraversal(v, dependentObj); + query.createKeyQuery(dependentObj); + + List items = this.engine.getQueryEngine().executeQuery(graph, query); + + Vertex dependentVertex = null; + if (items.size() == 1) { + dependentVertex = items.get(0); + this.verifyResourceVersion("update", dependentObj.getDbName(), dependentVertex.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 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 seen = new HashSet<>(); + Introspector childObject = obj.newIntrospectorInstanceOfNestedProperty(listProperty); + dbToObject(childObject, v, seen, depth, cleanUp); + getList.add(childObject.getUnderlyingObject()); + } + } else if (vertices.size() == 1) { + Set 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 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 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.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.property(AAIProperties.NODE_TYPE).orElse(null); + if (nodeType == null) { + throw new AAIException("AAI_6143"); + } + Introspector obj = this.latestLoader.introspectorFromName(nodeType); + Set 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.property(AAIProperties.NODE_TYPE).orElse(null); + if (nodeType == null) { + throw new AAIException("AAI_6143"); + } + Introspector obj = this.latestLoader.introspectorFromName(nodeType); + Set 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.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 inEdges = v.edges(Direction.IN); + Iterator outEdges = v.edges(Direction.OUT); + + Introspector wrappedRelationshipList = IntrospectorFactory.newInstance(introspectionType, obj, llBuilder); + List relationshipObjList = (List)wrappedRelationshipList.getValue("relationship"); + Object temp = null; + Object isParent = null; + Edge edge = null; + while (inEdges.hasNext()) { + edge = inEdges.next(); + isParent = edge.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.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> tuple = this.getParents(cousin, true); + //damaged vertex found, ignore + if (tuple == null) { + return null; + } + List 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> tuple = this.getParents(v, false); + List 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 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> getParents(Vertex start, boolean removeDamaged) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + String uri = ""; + List results = this.engine.getQueryEngine().findParents(start); + List objs = new ArrayList<>(); + String nodeType = ""; + boolean shortCircuit = false; + for (Vertex v : results) { + nodeType = v.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 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 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 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 getEdgesBetween(Vertex outVertex, Vertex inVertex) throws AAIException { + + List result = new ArrayList<>(); + + if (inVertex != null) { + EdgeRule rule = edgeRules.getEdgeRule(outVertex, inVertex); + GraphTraversal findEdgesBetween = null; + findEdgesBetween = graph.traversal().V(outVertex).bothE().filter(__.otherV().hasId(inVertex.id())); + List 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 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 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 getDependentVertexesOfType(Vertex start, String nodeType) { + + List 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 vertexes) throws IllegalStateException { + for (Vertex v : vertexes) { + deleteWithTraversal(v); + } + } + + /** + * Delete with traversal. + * + * @param startVertex the start vertex + */ + public void deleteWithTraversal(Vertex startVertex) { + + List 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 inEdges = null; + List outEdges = null; + String errorDetail = " unknown delete semantic found"; + String aaiExceptionCode = ""; + nodeType = vertex.property(AAIProperties.NODE_TYPE).orElse(null); + if (!this.verifyResourceVersion("delete", nodeType, vertex.property(AAIProperties.RESOURCE_VERSION).orElse(null), resourceVersion, nodeType)) { + } + semantic = edgeRules.getDeleteSemantic(nodeType); + inEdges = (List)IteratorUtils.toList(vertex.edges(Direction.IN)); + outEdges = (List)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).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.property("isParent").orElse(null); + if (property != null && property.equals(Boolean.TRUE)) { + Vertex v = edge.inVertex(); + String vType = v.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 list = new ArrayList(); + 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 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 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 rules = DbEdgeRules.EdgeRules; + private Multimap 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 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 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.property("aai-node-type").orElse(null); + String inType = (String)inVertex.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 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.property(AAIProperties.NODE_TYPE).orElse(null); + String inType = (String)inVertex.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 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.property(AAIProperties.NODE_TYPE).orElse(null); + String inVertexType = inVertex.property(AAIProperties.NODE_TYPE).orElse(null); + String label = rule.getLabel(); + MultiplicityRule multiplicityRule = rule.getMultiplicityRule(); + List outEdges = outVertex.graph().traversal().V(outVertex).outE(label).as("outEdges").inV().has(AAIProperties.NODE_TYPE, inVertexType).select("outEdges").toList(); + List 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> 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> 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 executeQuery(Graph g, QueryBuilder query) { + List results = null; + Vertex start = query.getStart(); + GraphTraversal traversal = (GraphTraversal)query.getQuery(); + Traversal.Admin 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 executeParentQuery(Graph g, QueryBuilder query) { + List results = null; + Vertex start = query.getStart(); + GraphTraversal traversal = (GraphTraversal)query.getParentQuery(); + Traversal.Admin 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 findParents(Vertex start) { + GraphTraversal pipe = start.graph().traversal().V(start).emit() + .repeat(__.inE() + .has("isParent", true).outV()); + + List results = pipe.toList(); + //results.add(0, start); + return results; + } + + /** + * {@inheritDoc} + */ + @Override + public List findChildren(Vertex start) { + + GraphTraversal pipe = start.graph().traversal().V(start).emit() + .repeat(__.outE().has("isParent", true).inV()); + + List results = pipe.toList(); + //results.add(0, start); + return results; + + } + + /** + * {@inheritDoc} + */ + @Override + public List findDeletable(Vertex start) { + + GraphTraversal pipe = start.graph().traversal().V(start).emit() + .repeat(__.outE().or( + __.has("isParent", true), + __.has("hasDelTarget", true)).inV()); + + List results = pipe.toList(); + //results.add(0, start); + return results; + } + + /** + * {@inheritDoc} + */ + @Override + public List findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) { + GraphTraversal 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 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 executeQuery(TransactionalGraph g, QueryBuilder query) { + List 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 executeParentQuery(TransactionalGraph g, QueryBuilder query) { + List 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 findParents(Vertex start) { + GremlinPipeline pipe = new GremlinPipeline(start).as("x").inE() + .has("isParent", true).outV().loop("x", new PipeFunction, Boolean>() { + + @Override + public Boolean compute(LoopPipe.LoopBundle argument) { + GremlinPipeline pipe = new GremlinPipeline<>(argument.getObject()); + return pipe.inE().has("isParent", true).count() == 1 || argument.getLoops() < 100; + } + + }, new PipeFunction, Boolean>() { + + @Override + public Boolean compute(LoopPipe.LoopBundle argument) { + return true; + } + + }); + + List results = pipe.toList(); + results.add(0, start); + return results; + } + + @Override + public List findChildren(Vertex start) { + Set seen = new HashSet<>(); + seen.add(start); + GremlinPipeline pipe = new GremlinPipeline(start).as("x").outE().has("isParent", true).inV() + .except(seen).store(seen).loop("x", new PipeFunction, Boolean>() { + + @Override + public Boolean compute(LoopPipe.LoopBundle argument) { + GremlinPipeline pipe = new GremlinPipeline<>(argument.getObject()); + return pipe.outE().has("isParent", true).count() >= 1 || argument.getLoops() < 100; + } + + }, new PipeFunction, Boolean>() { + + @Override + public Boolean compute(LoopPipe.LoopBundle argument) { + return true; + } + + }); + + List results = pipe.toList(); + results.add(0, start); + return results; + } + + @Override + public List findDeletable(Vertex start) { + Set seen = new HashSet<>(); + seen.add(start); + GremlinPipeline pipe = new GremlinPipeline(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, Boolean>() { + + @Override + public Boolean compute(LoopPipe.LoopBundle argument) { + GremlinPipeline 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, Boolean>() { + + @Override + public Boolean compute(LoopPipe.LoopBundle argument) { + return true; + } + + }); + List results = pipe.toList(); + results.add(0, start); + + return results; + } + + private List process(GremlinPipeline start, GremlinPipeline pipe) { + + + return start.add(pipe).cast(Vertex.class).toList(); + } + + @Override + public List findRelatedVertices(Vertex start, Direction direction, String label, String nodeType) { + GremlinPipeline pipe = new GremlinPipeline(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 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 executeQuery(TransactionalGraph g, QueryBuilder query) { +// List 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 executeParentQuery(TransactionalGraph g, QueryBuilder query) { +// +// List 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 executeQuery(Vertex startVertex, String query) { +// +// return this.processGremlinQuery(startVertex, "_()" + query); +// +// } +// +// @Override +// public List findParents(Vertex start) { +// +// String findAllParents = ".as('x').inE.has('isParent', true).outV" +// + ".loop('x'){it.object.inE.has('isParent',true).count()==1}{true}"; +// +// List results = this.executeQuery(start, findAllParents); +// results.add(0, start); +// return results; +// +// } +// +// @Override +// public List findChildren(Vertex start) { +// String findAllChildren = ".as('x').outE.has('isParent', true).inV" +// + ".loop('x'){it.object.outE.has('isParent', true).count() >= 1}{true}"; +// +// List results = this.executeQuery(start, findAllChildren); +// results.add(0, start); +// return results; +// +// } +// +// @Override +// public List 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 results = this.executeQuery(start, findAllChildren); +// results.add(0, start); +// return results; +// } +// private List processGremlinQuery(String query) { +// +// Pattern firstHasSet = Pattern.compile("^(\\.has\\(.*?\\))(\\.has\\(.*?\\))*(?!\\.has)"); +// Pattern p = Pattern.compile("\\.has\\('(.*?)',\\s?'(.*?)'\\)"); +// Matcher m = firstHasSet.matcher(query); +// List results = null; +// GremlinPipeline 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 processGremlinQuery(Vertex startVertex, String query) { +// +// Pipe pipe = Gremlin.compile(query); +// pipe.setStarts(new SingleIterator(startVertex)); +// +// return (List)IteratorUtils.toList(pipe.iterator()); +// } +// private List processGremlinQuery(List list, String query) { +// +// Pipe pipe = Gremlin.compile(query); +// +// pipe.setStarts(list); +// +// return (List)IteratorUtils.toList(pipe.iterator()); +// } +// +// +// @Override +// public List 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 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 executeQuery(Graph g, QueryBuilder query); + + /** + * Execute parent query. + * + * @param g the g + * @param query the query + * @return the list + */ + public abstract List executeParentQuery(Graph g, QueryBuilder query); + + /** + * Find parents. + * + * @param start the start + * @return the list + */ + public abstract List findParents(Vertex start); + + /** + * Find children. + * + * @param start the start + * @return the list + */ + public abstract List findChildren(Vertex start); + + /** + * Find deletable. + * + * @param start the start + * @return the list + */ + public abstract List 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 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 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 keys = obj.getAllKeys(); + List 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 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 parentEndPoints = null; + private ArrayList childEndPoints = null; + private final Pattern parentPattern = Pattern.compile("\\/(?:[\\w\\-]+?\\/)+?(?:\\{[\\w\\-]+?\\}\\/?)+"); + + private Map> 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 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 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 getParentPaths() { + + return (List)this.parentEndPoints.clone(); + } + + /** + * Gets the child paths. + * + * @return the child paths + */ + public List getChildPaths() { + + return (List)this.childEndPoints.clone(); + } + + /** + * Gets the all paths. + * + * @return the all paths + */ + public List getAllPaths() { + List 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 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 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 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 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 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 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 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 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 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 keys = keyProps.get(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className)); + Collection 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 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 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 list = (List) 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 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 randNumList = new ArrayList(); + 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 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 DeleteScope; + protected Multimap 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 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 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 pages = findCascadeDeleteChildren(topLevel, additionalPath, path, lep, additionalName); + + Map 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 findCascadeDeleteChildren(Introspector obj, String fitNessePath, String restPath, LocateEndPoints lep, String additionalName) { + List 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 list, String fitNessePath, String restPath, LocateEndPoints lep, String additionalName) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, UnsupportedEncodingException { + + if (obj == null) { + return; + } + List 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 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 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 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|(? 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 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(); + 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 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 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 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 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 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 children = null; + private Version apiVersion = null; + private Version currentApiVersion = AAIProperties.LATEST; + + private Multimap DeleteScope; + private Multimap 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 getChildren() { + return children; + } + + /** + * Sets the children. + * + * @param children the children + * @return the test suite builder + */ + public TestSuiteBuilder setChildren(List 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 getDeleteScope() { + return DeleteScope; + } + + /** + * Gets the edge map. + * + * @return the edge map + */ + public Multimap 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)dbEdgeRules.getDeclaredField("DefaultDeleteScope").get(null); + EdgeMap = (Multimap)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 EXCEPTION_SET = new HashSet(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 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()); + notification.createNotificationEvent("test-generation", Status.OK, new URI(encodedPath), updatedParentObject, new HashMap()); + List 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 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 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 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 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()); + notification.createNotificationEvent("test-generation", Status.OK, new URI(encodedPath), updatedObj, new HashMap()); + List 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========================================================= +--> + + + + + + +<#if skip??> + <#lt> + + + + +<#if type == "test"> + <#lt> +<#elseif type == "suite"> + <#lt> +<#elseif type == "static"> + <#lt> + +<#if symLinks??> + <#lt> + <#list symLinks?keys as link><#lt> + <${link}>${symLinks[link]}<#lt> + <#lt> + <#lt> + + + + 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> + +!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> + + 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> 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> defaultBools = new HashMap>(); + // + 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 genericVnfBools = new ArrayList(); + ArrayList l3NetworkBools = new ArrayList(); + ArrayList pserverBools = new ArrayList(); + ArrayList subnetBools = new ArrayList(); + ArrayList vserverBools = new ArrayList(); + ArrayList vnfcBools = new ArrayList(); + + 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> 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 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 commands = new ArrayList(); + 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 commands = new ArrayList(); + 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 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 remoteHostList = new ArrayList(); + 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 remoteHostItr = remoteHostList.iterator(); + while (!remoteHostList.isEmpty() && remoteHostItr.hasNext()) { + String remoteHost = remoteHostItr.next(); + remoteConnString =user+"@"+remoteHost+":"+pickUpDirectory; + + List commands = new ArrayList(); + 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 getRemoteHostList(StringTokenizer serverList, String host) { + ArrayList remoteHostList = new ArrayList(); + 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 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 scan(String htid) { + + List list = new ArrayList(); + 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 the generic type + * @param iterable the iterable + * @return the iterable + */ + public static Iterable nullCheck(Iterable iterable) { + return iterable == null ? Collections.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 \n + " + + "for example: resource-path for a particular customer is business/customers/customer/global-customer-id-1 \n"; + + /** + * The main method. + * + * @param the generic type + * @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_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 defaultVerLst = new ArrayList (); + 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 restObj = new RestObject(); + @SuppressWarnings("unchecked") + T t = (T)getInstance(Class.forName(resourceClass)); + restObj.set(t); + + try + { + RestController.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 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 getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + + /** + * Gets the resource version. + * + * @param the generic type + * @param resource the resource + * @return the string + */ + public static 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 = new ArrayList(); + @JsonProperty("self-link") + private String selfLink; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + /** + * + * @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 getKeyValueList() { + return keyValueList; + } + + /** + * + * @param keyValueList + * The key-value-list + */ + @JsonProperty("key-value-list") + public void setKeyValueList(List keyValueList) { + this.keyValueList = keyValueList; + } + + public Entity withKeyValueList(List 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 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 = new ArrayList(); + @JsonIgnore + private Map additionalProperties = new HashMap(); + + /** + * + * @return + * The entity + */ + @JsonProperty("entity") + public List getEntity() { + return entity; + } + + /** + * + * @param entity + * The entity + */ + @JsonProperty("entity") + public void setEntity(List entity) { + this.entity = entity; + } + + public EntityList withEntity(List entity) { + this.entity = entity; + return this; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + @JsonAnyGetter + public Map 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 ln = le.getLogicalNames(); + List keys = new ArrayList(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 generatedJavaType = new HashMap(); + static Map appliedPaths = new HashMap(); + 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 addJavaType = new HashMap(); + + + 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(" \n"); + sb1.append(" \n"); + NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement); + if (properties != null) { + System.out.println("properties found for: " + xmlRootElementName); + sb1.append(" \r\n"); + insertAnnotation(properties, false, "class", sb1, " "); + + sb1.append(" \r\n"); + } else { + System.out.println("no properties found for: " + xmlRootElementName); + } + sb1.append(" \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(" \n"); + sb1.append(" \n"); + properties = GenerateXsd.locateXmlProperties(javaTypeElement); + if (properties != null) { + sb1.append(" \r\n"); + insertAnnotation(properties, false, "class", sb1, " "); + sb1.append(" \r\n"); + } else { + System.out.println("no properties found for: " + xmlElementWrapper); + } + sb1.append(" \n"); + sb1.append(" "); + } + if ( addType != null ) { + //sb1.append(" \n"); + sb1.append(" \r\n"); + insertAnnotation(properties, elementIsKey != null, "field", sb1, " "); + sb1.append(" \r\n"); + + if (xmlElementWrapper== null) { + sb1.append(" \n"); + } + } else { + sb1.append("/>\n"); + } + if ( xmlElementWrapper != null ) { + sb1.append(" \n"); + sb1.append(" \n"); + sb1.append(" \n"); + } + } + /* + if ( xmlRootElementName.equals("notify") || + xmlRootElementName.equals("relationship") || + xmlRootElementName.equals("relationship-data") || + xmlRootElementName.equals("related-to-property") ) + + sb1.append(" \n"); + */ + sb1.append(" \n"); + sb1.append(" \n"); + sb1.append(" \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(" \n"); + sb.append(" \n"); + sb.append(" \n"); + sb.append(" \n"); + sb.append(" \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 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("&", "&") + "\""); + System.out.println("property name: " + name); + + } + } + sb1.append( + indentation + " \r\n" + + indentation + " @org.openecomp.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")\r\n" + + indentation + " \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("\n"); + sb.append("\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 in " + oxmFile ); + return null; + } + + bindingElement = (Element) bindingsNodes.item(0); + javaTypesNodes = bindingElement.getElementsByTagName("java-types"); + if ( javaTypesNodes.getLength() < 1 ) { + System.out.println( "missing in " + oxmFile ); + return null; + } + javaTypesElement = (Element) javaTypesNodes.item(0); + javaTypeNodes = javaTypesElement.getElementsByTagName("java-type"); + if ( javaTypeNodes.getLength() < 1 ) { + System.out.println( "missing 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( " 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("\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 getIndexedProps( String attrValue ) + { + if ( attrValue == null ) + return null; + StringTokenizer st = new StringTokenizer( attrValue, ","); + if ( st.countTokens() == 0 ) + return null; + Vector result = new Vector(); + while ( st.hasMoreTokens()) { + result.add(st.nextToken()); + } + return result; + } + + static private Vector getEdgeRules( String nodeName ) + { + + Vector result = new Vector(); + Iterator 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 edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey); + Iterator 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 addJavaType = new HashMap(); + 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 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 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(); + 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 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 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 in " + oxmFile ); + return null; + } + + bindingElement = (Element) bindingsNodes.item(0); + javaTypesNodes = bindingElement.getElementsByTagName("java-types"); + if ( javaTypesNodes.getLength() < 1 ) { + System.out.println( "missing in " + oxmFile ); + return null; + } + javaTypesElement = (Element) javaTypesNodes.item(0); + + javaTypeNodes = javaTypesElement.getElementsByTagName("java-type"); + if ( javaTypeNodes.getLength() < 1 ) { + System.out.println( "missing 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( " 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 \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 additionalProperties = new HashMap(); + + /** + * + * @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 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 the generic type + * @param clazz the clazz + * @param value the value + * @return the t + * @throws AAIException the AAI exception + */ + public static T readAsObjectOf(Class 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 the generic type + * @param clazz the clazz + * @param value the value + * @return the t + * @throws AAIException the AAI exception + */ + public static T readWithDashesAsObjectOf(Class 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 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 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 the generic type + * @param fromresource the fromresource + * @param toresource the toresource + * @return the t + */ + public static T merge(T fromresource, T toresource) + { + return merge(fromresource, toresource, false, false); + } + + /** + * Merge. + * + * @param 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 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 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 List getKeyValueList(Entity e, T clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List 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 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 String getJsonFromObject(T clazz) throws JsonGenerationException, JsonMappingException, IOException { + return getJsonFromObject(clazz, false, true); + } + + /** + * Gets the json from object. + * + * @param 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 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 the generic type + * @param clazz the clazz + * @return the xml from object + * @throws JAXBException the JAXB exception + */ + public 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 lookupHash, Collection 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 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 lookupHash, Collection keyProps) { + int baseKeyLen = baseKey.length(); + StringBuffer newKey = new StringBuffer(); + if (baseKeyLen > 0) { + newKey.append(baseKey); + } + + Iterator 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> lookupHashes, Multimap _dbRulesNodeKeyProps) { + Iterator it = lookupHashes.keySet().iterator(); + String lookupKeys = ""; + while (it.hasNext()) { + String objectType = (String)it.next(); + HashMap lookupHash = lookupHashes.get(objectType); + + Collection keyProps = _dbRulesNodeKeyProps.get(objectType); + Iterator 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 propHash, + Map _propertyDataTypeMap, LinkedHashMap keysWithVals, AAIExtensionMap aaiExtMap) { + + for (Entry ent : keysWithVals.entrySet()) { + propHash.put(ent.getKey(), ent.getValue()); + } + + } + + /** + * Fill prop hash from object. + * + * @param 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 void fillPropHashFromObject(T clazz, + HashMap propHash, Map _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 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 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 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 void getAaiObjectFromVertex(T clazz, TitanVertex vert, Map _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.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.property(dnHypPropertyName).orElse(null); + if (intVal != null) { + val = intVal.longValue(); + } + } else { + val = (Long)vert.property(dnHypPropertyName).orElse(null); + } + if (val != null) { + meth.invoke(clazz, val); + } + } else if (retType.toLowerCase().contains("int")) { + Integer val = (Integer)vert.property(dnHypPropertyName).orElse(null); + if (val != null) { + meth.invoke(clazz, val); + } + } else if (retType.toLowerCase().contains("short")) { + Short val = (Short)vert.property(dnHypPropertyName).orElse(null); + if (val != null) { + meth.invoke(clazz, val); + } + } else if (retType.toLowerCase().contains("boolean")) { + Boolean val = (Boolean)vert.property(dnHypPropertyName).orElse(null); + if (val != null) { + meth.invoke(clazz, val); + } + } + } + } + } + } + + /** + * Gets the topology object. + * + * @param 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 void getTopologyObject(T clazz, Multimap _dbRulesNodeNameProps, Multimap _dbRulesNodeKeyProps, TitanVertex vert) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException { + Method[] methods = clazz.getClass().getDeclaredMethods(); + String dnHypPropertyName = ""; +// Object value = null; + List includeProps = new ArrayList(); + + 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 keepProps = _dbRulesNodeNameProps.get(dnHypClassName); + Iterator keepPropI = keepProps.iterator(); + while( keepPropI.hasNext() ){ + includeProps.add(keepPropI.next()); + } + Collection keepProps2 = _dbRulesNodeKeyProps.get(dnHypClassName); + Iterator 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.property(dnHypPropertyName).orElse(null); + if (val != null) { + meth.invoke(clazz, val); + } + } else if (retType.toLowerCase().contains("long")) { + Long val = (Long)vert.property(dnHypPropertyName).orElse(null); + if (val != null) { + meth.invoke(clazz, val); + } + } else if (retType.toLowerCase().contains("int")) { + Integer val = (Integer)vert.property(dnHypPropertyName).orElse(null); + if (val != null) { + meth.invoke(clazz, val); + } + } else if (retType.toLowerCase().contains("short")) { + Short val = (Short)vert.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 _dbRulesNodeNameProps, + Multimap _dbRulesNodeKeyProps, Map _propertyDataTypeMap, TitanVertex vert) throws AAIException { + + DynamicEntity meObject = meObjectType.newDynamicEntity(); + + List includeProps = new ArrayList(); + + if ("false".equals(AAIConfig.get("aai.notification.topology.allAttrs", "false"))) { + String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,meObjectType.getJavaClass().getSimpleName()); + Collection keepProps = _dbRulesNodeNameProps.get(dnHypClassName); + Iterator keepPropI = keepProps.iterator(); + while( keepPropI.hasNext() ){ + includeProps.add(keepPropI.next()); + } + Collection keepProps2 = _dbRulesNodeKeyProps.get(dnHypClassName); + Iterator 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.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.property(attrName).orElse(null); + if (intVal != null) { + val = intVal.longValue(); + } + } else { + val = (Long)vert.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.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.property(attrName).orElse(null); + if (intVal != null) { + val = intVal.shortValue(); + } + } else { + val = (Short)vert.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.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 _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 _propertyDataTypeMap, HashMap 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.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.>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.property(attrName).orElse(null); + if (intVal != null) { + val = intVal.longValue(); + } + } else { + val = (Long)vert.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.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.property(attrName).orElse(null); + if (intVal != null) { + val = intVal.shortValue(); + } + } else { + val = (Short)vert.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.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 propHash, + Map _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 val = (ArrayList)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 exampleList = new ArrayList(); + 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 \n" + + "resource-path for a particular resource or query starting after the aai/\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 the generic type + * @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_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.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 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 getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + + /** + * Read json file. + * + * @param the generic type + * @param clazz the clazz + * @param fName the f name + * @return the t + * @throws AAIException the AAI exception + */ + public static T readJsonFile( Class 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 \n" + + "for example 1: putNotify.sh actions/notify /tmp/request.json \n"; + + /** + * The main method. + * + * @param the generic type + * @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_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.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 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 getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + + /** + * Read json file. + * + * @param the generic type + * @param clazz the clazz + * @param fName the f name + * @return the t + * @throws AAIException the AAI exception + */ + public static T readJsonFile( Class 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 the generic type + * @param resource the resource + * @return the string + */ + public static 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 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 \n" + + "resource-path for a particular resource starting after the aai/\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 the generic type + * @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_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 defaultVerLst = new ArrayList (); + 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 restObj = new RestObject(); + @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.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.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 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 getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + + /** + * Read json file. + * + * @param the generic type + * @param clazz the clazz + * @param fName the f name + * @return the t + * @throws AAIException the AAI exception + */ + public static T readJsonFile( Class 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 the generic type + * @param resource the resource + * @return the string + */ + public static 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 \n" + + "resource-path for a particular resource starting after the aai/, 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 { + + 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 restObj; + public final boolean oldServer; + public final String apiVersion; + + + /** + * Instantiates a new request. + * + * @param builder the builder + */ + public Request(RequestBuilder 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 { + private String fromAppId; + private String transactionId; + private String path; + private RestObject 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 setFromAppId(String fromAppId) { + this.fromAppId = fromAppId; + return this; + } + + /** + * Sets the transaction id. + * + * @param transactionId the transaction id + * @return the request builder + */ + public RequestBuilder setTransactionId(String transactionId) { + this.transactionId = transactionId; + return this; + + } + + /** + * Sets the path. + * + * @param path the path + * @return the request builder + */ + public RequestBuilder setPath(String path) { + + this.path = path; + return this; + + } + + /** + * Sets the rest obj. + * + * @param restObj the rest obj + * @return the request builder + */ + public RequestBuilder setRestObj(RestObject restObj) { + this.restObj = restObj; + return this; + + } + + /** + * Sets the old server. + * + * @param oldServer the old server + * @return the request builder + */ + public RequestBuilder setOldServer(boolean oldServer) { + this.oldServer = oldServer; + return this; + + } + + /** + * Sets the api version. + * + * @param apiVersion the api version + * @return the request builder + */ + public RequestBuilder setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + return this; + } + + /** + * Builds the. + * + * @return the request + */ + public Request build() { + return new Request(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 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 void Get(T t, String sourceID, String transId, String path, RestObject 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 the generic type + * @param t the t + * @param requestObj the request obj + * @throws AAIException the AAI exception + */ + public static void Get(T t, Request 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 the generic type + * @param t the t + * @param requestObj the request obj + * @throws AAIException the AAI exception + */ + public static void Put(T t, Request 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 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 List 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 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 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 List mapJsonToObjectList(T typeDef,String json, Class clazz) throws Exception + { + List 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 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 void Put(T t, String sourceID, String transId, String path) throws AAIException { + Put( t, sourceID, transId, path, false); + } + + /** + * Put. + * + * @param 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 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 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 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 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 getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + + /** + * Does resource exist. + * + * @param 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/" + , resourceClassName, fromAppId, transId); + */ + public static 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 restObj = new RestObject(); + @SuppressWarnings("unchecked") + T resourceObj = (T)getInstance(Class.forName(resourceClassName)); + restObj.set(resourceObj); + RestController.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 { + + /** + * Generic version of the RestObject class. + * @param 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.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.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 depNodeTypeColl = dbMaps.NodeDependencies.get(currentNodeType); + Iterator depNodeTypeListIterator = (Iterator) 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 inEdges = currentNode.edges(Direction.IN); + while( inEdges.hasNext() ){ + TitanEdge inEdge = (TitanEdge) inEdges.next(); + Boolean inEdgeIsParent = inEdge.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.property("aai-node-type").orElse(null); + Collection keyProps = dbMaps.NodeKeyProps.get(depNodeType); + Iterator 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.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 keyProps = dbMaps.NodeKeyProps.get(nodeType); + Iterator 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.property("port-or-interface").orElse(null); + nodeUrl += encodeURL(nodeKey) + "/"; + } else { + while (keyPropI.hasNext()) { + Object nodeKey = node.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.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 depNodeTypeColl = dbMaps.NodeDependencies.get(currentNodeType); + Iterator depNodeTypeListIterator = (Iterator) 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 inEdges = currentNode.edges(Direction.IN); + while( inEdges.hasNext() ){ + TitanEdge inEdge = (TitanEdge) inEdges.next(); + Boolean inEdgeIsParent = inEdge.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.property("aai-node-type").orElse(null); + Collection keyProps = dbMaps.NodeKeyProps.get(depNodeType); + Iterator keyPropI = keyProps.iterator(); + + String nodeUrl = null; + String depNodeTypePlural = dbMaps.NodePlural.get(depNodeType); + + if (depNodeTypePlural != null) + nodeUrl = depNodeTypePlural + "/" + depNodeType + "/"; + + while (keyPropI.hasNext()) { + Object nodeKey = currentNode.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 keyProps = dbMaps.NodeKeyProps.get(nodeType); + Iterator 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.property("port-or-interface").orElse(null); + nodeUrl += encodeURL(nodeKey) + "/"; + } else { + while (keyPropI.hasNext()) { + Object nodeKey = node.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 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 getKeyHashes(TitanTransaction graph, TitanVertex node, String apiVersion) throws AAIException, UnsupportedEncodingException + { + String nodeType = node.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 returnHash = new LinkedHashMap (); + + // create the hash for the keys for the node passed in + HashMap thisNodeHash = new HashMap (); + Collection keyProps = dbMaps.NodeKeyProps.get(nodeType); + Iterator keyPropI = keyProps.iterator(); + + if (nodeType.equals("ipaddress")) { // this has 2 keys but API only uses port-or -address in URL + String nodeKeyValue = node.property("port-or-interface").orElse(null); + thisNodeHash.put("port-or-interface", nodeKeyValue); + } else { + while (keyPropI.hasNext()) { + String nodeKeyName = keyPropI.next(); + Object nodeKeyValue = node.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 depNodeTypeColl = DbRules.NodeDependencies.get(currentNodeType); +// Iterator depNodeTypeListIterator = (Iterator) depNodeTypeColl.iterator(); + HashMap depNodeHash = new HashMap (); +// +// 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 inEdges = currentNode.edges(Direction.IN); + while( inEdges.hasNext() ){ + TitanEdge inEdge = (TitanEdge) inEdges.next(); + Boolean inEdgeIsParent = inEdge.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.property("aai-node-type").orElse(null); + keyProps = dbMaps.NodeKeyProps.get(depNodeType); + keyPropI = keyProps.iterator(); + + while (keyPropI.hasNext()) { + String nodeKeyName = keyPropI.next(); + Object nodeKeyValue = currentNode.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 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 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 returnHash = new LinkedHashMap (); + + 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 thisNodeHash = new LinkedHashMap (); + Collection keyProps = dbMaps.NodeKeyProps.get(currentNodeType); + Iterator 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 depNodeHash = new LinkedHashMap (); + 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 allKeys, LinkedHashMap> keyList, String uri, + AAIExtensionMap aaiExtMap) throws UnsupportedEncodingException, AAIException { + List 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 subKeyList = new LinkedHashMap(); + + // 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 subKeyList = new LinkedHashMap(); + subKeyList.put("container|example", p1.toString()); + keyList.put(tmpResource, subKeyList); + } + } + } + } else { + if (p.toString().equals("relationship-list")) { + LinkedHashMap subKeyList = new LinkedHashMap(); + 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 defaultVerLst = new ArrayList (); + 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 returnHash = getKeyHashes(nodeURI); + + Set returnKeySet = returnHash.keySet(); + Iterator 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 valuesAndVidHash = new HashMap (); + HashMap dupeHash = new HashMap (); + + 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.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.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> pI = tVert.properties(); + while( pI.hasNext() ){ + VertexProperty tp = pI.next(); + Object val = tp.value(); + logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] "); + } + + Iterator 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.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" + + " :[,: 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 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.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/(?v\\d+)/cloud-infrastructure/tenants/tenant/(?.*?)/vservers/vserver/(?[^/]*?$)"; + 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/(?v[23])/(?.*?)/vservers/(?[^/]*?$)"; + 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 itemsUnderInventory = new ArrayList<>(); + for (int i = 0; i < nodes.getLength(); i++) { + itemsUnderInventory.add(nodes.item(i).getTextContent()); + } + Map 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 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 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 params) { + + + for (String param : blacklist) { + params.remove(param); + } + + + } + +} -- cgit 1.2.3-korg