From b5b99b72733ca5c064b46fdf4527ace28b8b545b Mon Sep 17 00:00:00 2001 From: Venkata Harish K Kajur Date: Fri, 12 May 2017 17:36:59 -0400 Subject: Add all of the traversal source files Change-Id: Id31f4bdda9c86f782f86829f8b86dada959a9729 Signed-off-by: Venkata Harish K Kajur --- aai-traversal/.classpath | 17 + aai-traversal/.gitignore | 10 + aai-traversal/ajsc-shared-config/README.txt | 6 + .../ajsc-shared-config/etc/aft.properties | 13 + .../etc/basic-logback_root_logger_level_off.xml | 84 + .../etc/csm-config-app.properties | 183 + .../etc/csm-framework-app.properties | 11 + .../etc/localhost-access-logback.xml | 38 + aai-traversal/ajsc-shared-config/etc/logback.xml | 382 ++ aai-traversal/antBuild/build.xml | 228 ++ .../etc/appprops/app-intercepts.properties | 6 + aai-traversal/bundleconfig-local/README.txt | 9 + aai-traversal/bundleconfig-local/RELEASE_NOTES.txt | 1 + .../etc/appprops/Introscope.properties | 8 + .../appprops/PostProcessorInterceptors.properties | 3 + .../appprops/PreProcessorInterceptors.properties | 3 + .../etc/appprops/aaiEventDMaaPPublisher.properties | 28 + .../etc/appprops/aaiconfig.properties | 82 + .../etc/appprops/app-intercepts.properties | 6 + .../etc/appprops/caet.properties | 0 .../etc/appprops/default-logback.xml | 20 + .../etc/appprops/error.properties | 164 + .../etc/appprops/gremlin-server-config.yaml | 3 + .../etc/appprops/logging.properties | 128 + .../etc/appprops/methodMapper.properties | 24 + .../etc/appprops/preferredRoute.txt | 1 + .../etc/appprops/titan-cached.properties | 18 + .../etc/appprops/titan-realtime.properties | 15 + .../bundleconfig-local/etc/auth/aai_keystore | Bin 0 -> 4002 bytes .../etc/query/stored-queries.properties | 0 .../getClfiRoadmTailSummary-1.0.json | 101 + .../named-query-json/getComplexByPnfName-1.0.json | 32 + .../named-query-json/getComponentList-1.0.json | 98 + .../named-query-json/getComponentList-1.1.json | 125 + .../named-query-json/getComponentList-1.2.json | 139 + .../getDHVComplexHostname-1.0.json | 32 + .../getDHVComplexLocationId-1.0.json | 32 + .../named-query-json/getDHVLogicalLink-1.0.json | 58 + .../getDHVLogicalLinkByCircuitId-1.0.json | 19 + .../getDHVServiceTopology-1.0.json | 273 ++ .../getDHVServiceTopology-1.1.json | 273 ++ .../getDHVServiceTopology2-1.0.json | 321 ++ .../getL3networkCloudRegionByNetworkRole-1.0.json | 71 + .../getLogicalLinkByCloudRegionId-1.0.json | 32 + .../getPinterfacePhysicalLinkBySvcInstId-1.0.json | 84 + .../getRouterRoadmTailSummary-1.0.json | 129 + .../getServiceInstanceSummary-1.0.json | 126 + .../getSvcSubscriberModelInfo-1.0.json | 46 + .../getTenantInfoAtSvcInstance-1.0.json | 87 + .../getTenantInfoAtSvcSubscription-1.0.json | 58 + .../getVnfVlanByCircuitId-1.0.json | 58 + .../named-query-json/getWlBundleId-1.0.json | 81 + .../etc/scriptdata/resource-model-json/000-README | 10 + .../etc/scriptdata/service-model-json/000-README | 10 + .../scriptdata/widget-model-json/action-1.0.json | 11 + .../widget-model-json/action-data-1.0.json | 11 + .../widget-model-json/allotted-resource-1.0.json | 11 + .../widget-model-json/availability-zone-1.0.json | 11 + .../widget-model-json/az-and-dvs-switches-1.0.json | 11 + .../widget-model-json/class-of-service-1.0.json | 11 + .../widget-model-json/cloud-region-1.0.json | 11 + .../scriptdata/widget-model-json/complex-1.0.json | 11 + .../widget-model-json/connector-1.0.json | 11 + .../constrained-element-set-1.0.json | 11 + .../widget-model-json/ctag-assignment-1.0.json | 11 + .../widget-model-json/ctag-pool-1.0.json | 11 + .../scriptdata/widget-model-json/customer-1.0.json | 11 + .../widget-model-json/cvlan-tag-entry-1.0.json | 11 + .../widget-model-json/dvs-switch-1.0.json | 11 + .../widget-model-json/edge-prop-names-1.0.json | 11 + .../widget-model-json/element-choice-set-1.0.json | 11 + .../widget-model-json/entitlement-1.0.json | 11 + .../scriptdata/widget-model-json/flavor-1.0.json | 11 + .../widget-model-json/generic-vnf-1.0.json | 11 + .../widget-model-json/group-assignment-1.0.json | 11 + .../scriptdata/widget-model-json/image-1.0.json | 11 + .../widget-model-json/include-node-filter-1.0.json | 11 + .../widget-model-json/instance-group-1.0.json | 11 + .../widget-model-json/inventory-item-1.0.json | 11 + .../widget-model-json/inventory-item-data-1.0.json | 11 + .../widget-model-json/ipsec-configuration-1.0.json | 11 + .../scriptdata/widget-model-json/key-data-1.0.json | 11 + .../widget-model-json/l-interface-1.0.json | 11 + .../l3-interface-ipv4-address-list-1.0.json | 11 + .../l3-interface-ipv6-address-list-1.0.json | 11 + .../widget-model-json/l3-network-1.0.json | 11 + .../widget-model-json/lag-interface-1.0.json | 11 + .../scriptdata/widget-model-json/lag-link-1.0.json | 11 + .../scriptdata/widget-model-json/license-1.0.json | 11 + .../license-key-resource-1.0.json | 11 + .../widget-model-json/logical-link-1.0.json | 11 + .../widget-model-json/metadatum-1.0.json | 11 + .../scriptdata/widget-model-json/model-1.0.json | 11 + .../widget-model-json/model-constraint-1.0.json | 11 + .../widget-model-json/model-element-1.0.json | 11 + .../widget-model-json/model-ver-1.0.json | 11 + .../multicast-configuration-1.0.json | 11 + .../widget-model-json/named-query-1.0.json | 11 + .../widget-model-json/named-query-element-1.0.json | 11 + .../widget-model-json/network-policy-1.0.json | 11 + .../widget-model-json/network-profile-1.0.json | 11 + .../scriptdata/widget-model-json/newvce-1.0.json | 11 + .../widget-model-json/oam-network-1.0.json | 11 + .../widget-model-json/p-interface-1.0.json | 11 + .../widget-model-json/physical-link-1.0.json | 11 + .../etc/scriptdata/widget-model-json/pnf-1.0.json | 11 + .../widget-model-json/port-group-1.0.json | 11 + .../widget-model-json/property-constraint-1.0.json | 11 + .../scriptdata/widget-model-json/pserver-1.0.json | 11 + .../widget-model-json/related-lookup-1.0.json | 11 + .../widget-model-json/reserved-prop-names-1.0.json | 11 + .../widget-model-json/result-data-1.0.json | 11 + .../route-table-reference-1.0.json | 11 + .../widget-model-json/routing-instance-1.0.json | 11 + .../widget-model-json/secondary-filter-1.0.json | 11 + .../segmentation-assignment-1.0.json | 11 + .../scriptdata/widget-model-json/service-1.0.json | 11 + .../widget-model-json/service-capability-1.0.json | 11 + .../widget-model-json/service-instance-1.0.json | 11 + .../service-subscription-1.0.json | 11 + .../widget-model-json/site-pair-1.0.json | 11 + .../widget-model-json/site-pair-set-1.0.json | 11 + .../scriptdata/widget-model-json/snapshot-1.0.json | 11 + .../scriptdata/widget-model-json/sriov-vf-1.0.json | 11 + .../widget-model-json/start-node-filter-1.0.json | 11 + .../scriptdata/widget-model-json/subnet-1.0.json | 11 + .../tagged-inventory-item-list-1.0.json | 11 + .../scriptdata/widget-model-json/tenant-1.0.json | 11 + .../widget-model-json/tunnel-xconnect-1.0.json | 11 + .../widget-model-json/update-node-key-1.0.json | 11 + .../etc/scriptdata/widget-model-json/vce-1.0.json | 11 + .../widget-model-json/vf-module-1.0.json | 11 + .../widget-model-json/vig-server-1.0.json | 11 + .../widget-model-json/virtual-data-center-1.0.json | 11 + .../etc/scriptdata/widget-model-json/vlan-1.0.json | 11 + .../widget-model-json/vnf-image-1.0.json | 11 + .../etc/scriptdata/widget-model-json/vnfc-1.0.json | 11 + .../scriptdata/widget-model-json/volume-1.0.json | 11 + .../widget-model-json/volume-group-1.0.json | 11 + .../etc/scriptdata/widget-model-json/vpe-1.0.json | 11 + .../scriptdata/widget-model-json/vpls-pe-1.0.json | 11 + .../widget-model-json/vpn-binding-1.0.json | 11 + .../scriptdata/widget-model-json/vserver-1.0.json | 11 + .../etc/scriptdata/widget-model-json/zone-1.0.json | 11 + .../etc/service-file-monitor.properties | 5 + .../etc/sysprops/sys-props.properties | 140 + .../etc/sysprops/template.sys-props.properties | 115 + aai-traversal/bundleconfig-local/symlinks.txt | 6 + aai-traversal/pom.xml | 695 ++++ .../ajsc-aai/v1/conf/FileMonitorBeans.xml | 20 + .../ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy | 26 + .../ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml | 47 + .../ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt | 1 + .../ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt | 1 + .../ajsc-aai_v1/ajsc-aai/v1/props/module.props | 1 + .../ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route | 4 + .../src/main/assemble/ajsc_module_assembly.xml | 66 + .../src/main/assemble/ajsc_props_assembly.xml | 23 + .../src/main/assemble/ajsc_runtime_assembly.xml | 44 + aai-traversal/src/main/config/ajsc-jetty.xml | 155 + .../src/main/config/ajsc-jolokia-override-web.xml | 46 + .../src/main/config/ajsc-override-web.xml | 41 + aai-traversal/src/main/config/ajsc-request.xml | 49 + aai-traversal/src/main/config/caet.properties | 0 .../src/main/config/hazelcast-client.properties | 25 + .../src/main/config/jul-redirect.properties | 13 + aai-traversal/src/main/config/keyfile | 27 + aai-traversal/src/main/config/realm.properties | 11 + aai-traversal/src/main/config/runner-web.xml | 111 + .../ajsc_aai/JaxrsErrorMessageLookupService.java | 98 + .../openecomp/aai/ajsc_aai/JaxrsUserService.java | 54 + .../filemonitor/ServicePropertiesListener.java | 19 + .../ajsc_aai/filemonitor/ServicePropertiesMap.java | 126 + .../filemonitor/ServicePropertyService.java | 19 + .../ajsc_aai/util/ServicePropertiesMapBean.java | 37 + .../java/org/openecomp/aai/db/DbMethHelper.java | 158 + .../org/openecomp/aai/dbgraphgen/DbEdgeGroup.java | 439 +++ .../java/org/openecomp/aai/dbgraphgen/DbMeth.java | 3643 +++++++++++++++++++ .../aai/dbgraphgen/ModelBasedProcessing.java | 3718 ++++++++++++++++++++ .../org/openecomp/aai/dbgraphgen/ResultSet.java | 168 + .../aai/dbgraphmap/RelationshipGraph.java | 299 ++ .../org/openecomp/aai/dbgraphmap/SearchGraph.java | 1207 +++++++ .../aai/dmaap/AAIDmaapEventJMSConsumer.java | 163 + .../aai/dmaap/AAIDmaapEventJMSProducer.java | 44 + .../openecomp/aai/extensions/AAIExtensionMap.java | 827 +++++ .../aai/extensions/ExtensionController.java | 145 + .../aai/interceptors/AAIHeaderProperties.java | 26 + .../aai/interceptors/AAILogJAXRSInInterceptor.java | 283 ++ .../interceptors/AAILogJAXRSOutInterceptor.java | 323 ++ .../aai/interceptors/PostAaiAjscInterceptor.java | 63 + .../aai/interceptors/PreAaiAjscInterceptor.java | 54 + .../org/openecomp/aai/rest/ExceptionHandler.java | 129 + .../java/org/openecomp/aai/rest/QueryConsumer.java | 182 + .../java/org/openecomp/aai/rest/db/DBRequest.java | 251 ++ .../java/org/openecomp/aai/rest/db/HttpEntry.java | 672 ++++ .../aai/rest/retired/RetiredConsumer.java | 143 + .../aai/rest/retired/V3ThroughV7Consumer.java | 28 + .../aai/rest/retired/V7V8NamedQueries.java | 28 + .../aai/rest/search/GenericQueryProcessor.java | 227 ++ .../rest/search/GremlinGroovyShellSingleton.java | 88 + .../aai/rest/search/GremlinServerImpl.java | 76 + .../aai/rest/search/GremlinServerSingleton.java | 130 + .../openecomp/aai/rest/search/GroovyShellImpl.java | 47 + .../search/ModelAndNamedQueryRestProvider.java | 203 ++ .../aai/rest/search/QueryProcessorType.java | 27 + .../openecomp/aai/rest/search/SearchProvider.java | 269 ++ .../openecomp/aai/rest/ueb/NotificationEvent.java | 96 + .../openecomp/aai/rest/ueb/UEBNotification.java | 178 + .../org/openecomp/aai/rest/util/EchoResponse.java | 121 + .../openecomp/aai/rest/util/LogFormatTools.java | 36 + .../openecomp/aai/rest/util/ValidateEncoding.java | 160 + .../org/openecomp/aai/transforms/Converter.java | 25 + .../LowerCamelToLowerHyphenConverter.java | 34 + .../LowerHyphenToLowerCamelConverter.java | 81 + .../org/openecomp/aai/transforms/MapTraverser.java | 87 + .../aai/util/AAIAppServletContextListener.java | 104 + .../main/java/org/openecomp/aai/util/RestURL.java | 704 ++++ .../openecomp/aai/util/StoreNotificationEvent.java | 358 ++ aai-traversal/src/main/resources/docker/Dockerfile | 85 + aai-traversal/src/main/resources/docker/aai.sh | 42 + .../src/main/resources/docker/commonLibs/README | 1 + .../src/main/resources/docker/docker-entrypoint.sh | 34 + .../src/main/resources/docker/init-chef.sh | 32 + .../src/main/resources/schema/UebEventLogEntry.xsd | 20 + ...ame__#__module.ajsc.namespace.version__.context | 1 + .../src/main/runtime/context/default#0.context | 1 + ...e.name__#__module.ajsc.namespace.version__.json | 1 + .../src/main/runtime/shiroRole/ajscadmin.json | 1 + ...ontextadmin#__module.ajsc.namespace.name__.json | 1 + .../runtime/shiroRole/contextadmin#default.json | 1 + aai-traversal/src/main/runtime/shiroUser/ajsc.json | 1 + .../main/runtime/shiroUserRole/ajsc#ajscadmin.json | 1 + ...ontextadmin#__module.ajsc.namespace.name__.json | 1 + .../shiroUserRole/ajsc#contextadmin#default.json | 1 + aai-traversal/src/main/scripts/getTool.sh | 88 + .../src/main/scripts/install/instutils.sh | 724 ++++ aai-traversal/src/main/scripts/install/siteconf.pl | 100 + .../src/main/scripts/install/updateQueryData.sh | 97 + aai-traversal/src/main/scripts/putTool.sh | 148 + aai-traversal/src/main/xjb/bindings.xjb | 21 + .../openecomp/aai/dbgraphgen/DbEdgeGroupTest.java | 104 + .../aai/dbgraphgen/ModelBasedProcessingTest.java | 86 + .../aai/dbgraphmap/SearchGraphEdgeRuleTest.java | 59 + .../org/openecomp/aai/rest/search/QueryTest.java | 85 + .../aai/rest/util/ValidateEncodingTest.java | 101 + .../org/openecomp/aai/transforms/JoltTestUtil.java | 61 + .../LowerHyphenToLowerCamelConverterTest.java | 73 + .../openecomp/aai/transforms/MapTraverserTest.java | 56 + .../etc/appprops/aaiconfig.properties | 105 + .../etc/appprops/error.properties | 163 + .../bundleconfig-local/etc/auth/aai_policy.json | 37 + .../resources/config/etc/titan-cached.properties | 37 + .../resources/config/etc/titan-realtime.properties | 34 + .../src/test/resources/inmemory_titan.properties | 21 + aai-traversal/src/test/resources/log4j.properties | 3 + aai-traversal/src/test/resources/logback.xml | 292 ++ .../resources/maputils/testcases/TestCase1.json | 32 + .../resources/maputils/testcases/TestCase2.json | 40 + .../src/test/resources/test_aaiconfig.properties | 97 + 259 files changed, 25733 insertions(+) create mode 100644 aai-traversal/.classpath create mode 100644 aai-traversal/.gitignore create mode 100644 aai-traversal/ajsc-shared-config/README.txt create mode 100644 aai-traversal/ajsc-shared-config/etc/aft.properties create mode 100644 aai-traversal/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml create mode 100644 aai-traversal/ajsc-shared-config/etc/csm-config-app.properties create mode 100644 aai-traversal/ajsc-shared-config/etc/csm-framework-app.properties create mode 100644 aai-traversal/ajsc-shared-config/etc/localhost-access-logback.xml create mode 100644 aai-traversal/ajsc-shared-config/etc/logback.xml create mode 100644 aai-traversal/antBuild/build.xml create mode 100644 aai-traversal/bundleconfig-csi/etc/appprops/app-intercepts.properties create mode 100644 aai-traversal/bundleconfig-local/README.txt create mode 100644 aai-traversal/bundleconfig-local/RELEASE_NOTES.txt create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/Introscope.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/aaiconfig.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/app-intercepts.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/caet.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/default-logback.xml create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/error.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/gremlin-server-config.yaml create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/logging.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/methodMapper.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/preferredRoute.txt create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/titan-cached.properties create mode 100644 aai-traversal/bundleconfig-local/etc/appprops/titan-realtime.properties create mode 100644 aai-traversal/bundleconfig-local/etc/auth/aai_keystore create mode 100644 aai-traversal/bundleconfig-local/etc/query/stored-queries.properties create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getClfiRoadmTailSummary-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComplexByPnfName-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.1.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.2.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexHostname-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexLocationId-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLink-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLinkByCircuitId-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.1.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology2-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getL3networkCloudRegionByNetworkRole-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getLogicalLinkByCloudRegionId-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getPinterfacePhysicalLinkBySvcInstId-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getRouterRoadmTailSummary-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getSvcSubscriberModelInfo-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcInstance-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcSubscription-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getVnfVlanByCircuitId-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getWlBundleId-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/resource-model-json/000-README create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/service-model-json/000-README create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-data-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/allotted-resource-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/az-and-dvs-switches-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/class-of-service-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/complex-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/connector-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/constrained-element-set-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-pool-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cvlan-tag-entry-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/dvs-switch-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/edge-prop-names-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/element-choice-set-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/entitlement-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/include-node-filter-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/instance-group-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-data-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ipsec-configuration-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/key-data-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-link-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-key-resource-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/metadatum-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-constraint-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-element-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-ver-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/multicast-configuration-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-element-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-policy-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-profile-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/newvce-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/oam-network-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/port-group-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/property-constraint-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/related-lookup-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/reserved-prop-names-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/result-data-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/route-table-reference-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/routing-instance-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/secondary-filter-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-capability-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-set-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/sriov-vf-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/start-node-filter-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tagged-inventory-item-list-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tunnel-xconnect-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/update-node-key-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vce-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vig-server-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/virtual-data-center-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnf-image-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpe-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpls-pe-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpn-binding-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/zone-1.0.json create mode 100644 aai-traversal/bundleconfig-local/etc/service-file-monitor.properties create mode 100644 aai-traversal/bundleconfig-local/etc/sysprops/sys-props.properties create mode 100644 aai-traversal/bundleconfig-local/etc/sysprops/template.sys-props.properties create mode 100644 aai-traversal/bundleconfig-local/symlinks.txt create mode 100644 aai-traversal/pom.xml create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props create mode 100644 aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route create mode 100644 aai-traversal/src/main/assemble/ajsc_module_assembly.xml create mode 100644 aai-traversal/src/main/assemble/ajsc_props_assembly.xml create mode 100644 aai-traversal/src/main/assemble/ajsc_runtime_assembly.xml create mode 100644 aai-traversal/src/main/config/ajsc-jetty.xml create mode 100644 aai-traversal/src/main/config/ajsc-jolokia-override-web.xml create mode 100644 aai-traversal/src/main/config/ajsc-override-web.xml create mode 100644 aai-traversal/src/main/config/ajsc-request.xml create mode 100644 aai-traversal/src/main/config/caet.properties create mode 100644 aai-traversal/src/main/config/hazelcast-client.properties create mode 100644 aai-traversal/src/main/config/jul-redirect.properties create mode 100644 aai-traversal/src/main/config/keyfile create mode 100644 aai-traversal/src/main/config/realm.properties create mode 100644 aai-traversal/src/main/config/runner-web.xml create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/db/DbMethHelper.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbEdgeGroup.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbMeth.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ModelBasedProcessing.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ResultSet.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/RelationshipGraph.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/SearchGraph.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/extensions/ExtensionController.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/QueryConsumer.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/db/DBRequest.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/GenericQueryProcessor.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinGroovyShellSingleton.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerImpl.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerSingleton.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/GroovyShellImpl.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/QueryProcessorType.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/transforms/Converter.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/transforms/MapTraverser.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/util/RestURL.java create mode 100644 aai-traversal/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java create mode 100644 aai-traversal/src/main/resources/docker/Dockerfile create mode 100644 aai-traversal/src/main/resources/docker/aai.sh create mode 100644 aai-traversal/src/main/resources/docker/commonLibs/README create mode 100644 aai-traversal/src/main/resources/docker/docker-entrypoint.sh create mode 100644 aai-traversal/src/main/resources/docker/init-chef.sh create mode 100644 aai-traversal/src/main/resources/schema/UebEventLogEntry.xsd create mode 100644 aai-traversal/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context create mode 100644 aai-traversal/src/main/runtime/context/default#0.context create mode 100644 aai-traversal/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json create mode 100644 aai-traversal/src/main/runtime/shiroRole/ajscadmin.json create mode 100644 aai-traversal/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json create mode 100644 aai-traversal/src/main/runtime/shiroRole/contextadmin#default.json create mode 100644 aai-traversal/src/main/runtime/shiroUser/ajsc.json create mode 100644 aai-traversal/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json create mode 100644 aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json create mode 100644 aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json create mode 100644 aai-traversal/src/main/scripts/getTool.sh create mode 100644 aai-traversal/src/main/scripts/install/instutils.sh create mode 100644 aai-traversal/src/main/scripts/install/siteconf.pl create mode 100644 aai-traversal/src/main/scripts/install/updateQueryData.sh create mode 100644 aai-traversal/src/main/scripts/putTool.sh create mode 100644 aai-traversal/src/main/xjb/bindings.xjb create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/dbgraphgen/DbEdgeGroupTest.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/dbgraphgen/ModelBasedProcessingTest.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/dbgraphmap/SearchGraphEdgeRuleTest.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/rest/search/QueryTest.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/rest/util/ValidateEncodingTest.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/transforms/JoltTestUtil.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverterTest.java create mode 100644 aai-traversal/src/test/java/org/openecomp/aai/transforms/MapTraverserTest.java create mode 100644 aai-traversal/src/test/resources/bundleconfig-local/etc/appprops/aaiconfig.properties create mode 100644 aai-traversal/src/test/resources/bundleconfig-local/etc/appprops/error.properties create mode 100644 aai-traversal/src/test/resources/bundleconfig-local/etc/auth/aai_policy.json create mode 100644 aai-traversal/src/test/resources/config/etc/titan-cached.properties create mode 100644 aai-traversal/src/test/resources/config/etc/titan-realtime.properties create mode 100644 aai-traversal/src/test/resources/inmemory_titan.properties create mode 100644 aai-traversal/src/test/resources/log4j.properties create mode 100644 aai-traversal/src/test/resources/logback.xml create mode 100644 aai-traversal/src/test/resources/maputils/testcases/TestCase1.json create mode 100644 aai-traversal/src/test/resources/maputils/testcases/TestCase2.json create mode 100644 aai-traversal/src/test/resources/test_aaiconfig.properties (limited to 'aai-traversal') diff --git a/aai-traversal/.classpath b/aai-traversal/.classpath new file mode 100644 index 0000000..eecfd16 --- /dev/null +++ b/aai-traversal/.classpath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/aai-traversal/.gitignore b/aai-traversal/.gitignore new file mode 100644 index 0000000..cd21128 --- /dev/null +++ b/aai-traversal/.gitignore @@ -0,0 +1,10 @@ +.settings +target/ +**/logs/ +bundleconfig-local/etc/auth/aai-client-cert.p12 +bundleconfig-local/etc/oxm +src/main/aai_schema +bundleconfig-local/etc/logback.xml +/.pydevproject +/test_csvWriter.csv +/bin/ diff --git a/aai-traversal/ajsc-shared-config/README.txt b/aai-traversal/ajsc-shared-config/README.txt new file mode 100644 index 0000000..a82eb64 --- /dev/null +++ b/aai-traversal/ajsc-shared-config/README.txt @@ -0,0 +1,6 @@ +The ajsc-shared-config folder is included in the service project to provide the functionality of the AJSC_SHARED_CONFIG +location that will exist in CSI envs. This includes the logback.xml for logging configurations, and some csm related +artifacts necessary for proper functionality of the csm framework within the CSI env. Within the 2 profiles that can +be utilized to run the AJSC locally, "runLocal" and "runAjsc", the system propery, "AJSC_SHARED_CONFIG", has been set +to point to this directory. The files in this folder will NOT be copied/moved anywhere within the AJSC SWM package. These +files will already be in existence within the CSI env. \ No newline at end of file diff --git a/aai-traversal/ajsc-shared-config/etc/aft.properties b/aai-traversal/ajsc-shared-config/etc/aft.properties new file mode 100644 index 0000000..43e896d --- /dev/null +++ b/aai-traversal/ajsc-shared-config/etc/aft.properties @@ -0,0 +1,13 @@ + +# Flow test 319 +com.att.aft.discovery.client.environment=AFTUAT +com.att.aft.discovery.client.latitude=35.318900 +com.att.aft.discovery.client.longitude=-80.762200 +com.att.aft.alias=ecomp-aai +#com.att.aft.keyStore=ajsc-shared-config/etc/spm2.jks +com.att.aft.keyStore=/opt/app/aai/bundleconfig/etc/m04353t.jks +com.att.aft.keyStorePassword=its4test +#com.att.aft.trustStore=ajsc-shared-config/etc/spm2.jks +com.att.aft.trustStore=/opt/app/aai/bundleconfig/etc/m04353t.jks +com.att.aft.trustStorePassword=its4test + diff --git a/aai-traversal/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml b/aai-traversal/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml new file mode 100644 index 0000000..326c8cb --- /dev/null +++ b/aai-traversal/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml @@ -0,0 +1,84 @@ + + + + + ERROR + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + + + + + + + DEBUG + + ${logDirectory}/info_ajsc.log + + ${logDirectory}/info_ajsc.%i.log.zip + + 1 + 9 + + + 5MB + + + "%d [%thread] %-5level %logger{1024} - %msg%n" + + + + + ERROR + + ${logDirectory}/error_ajsc.log + + ${logDirectory}/error_ajsc.%i.log.zip + + 1 + 9 + + + 5MB + + + + "%d [%thread] %-5level %logger{1024} - %msg%n" + + + + + + INFO + + localhost + USER + + AJSC_AUDIT: [%thread] [%logger] %msg + + + + INFO + + localhost + USER + + AJSC_AUDIT: [%thread] [%logger] mdc:[%mdc] %msg + + + + + + + + + diff --git a/aai-traversal/ajsc-shared-config/etc/csm-config-app.properties b/aai-traversal/ajsc-shared-config/etc/csm-config-app.properties new file mode 100644 index 0000000..b4d0476 --- /dev/null +++ b/aai-traversal/ajsc-shared-config/etc/csm-config-app.properties @@ -0,0 +1,183 @@ +Global.ExtendedProperty.AuthoritativeServers=${ChangeMe_csm.acfshost}:${ChangeMe_csm.acfsport} + +# +# The settings in this file control the behavior of the CSM Framework. +# The majority of the settings in this file adhere to the following +# pattern: +# +# [EntityType].[EntityId].[PropertyName]=[PropertyValue] +# +# Where: +# +# [EntityType] Identifies the type of entity (service or +# service group) that's being configured. +# [EntityId] Identifies the individual entity. +# [PropertyName] Identifies the property that is being set. +# [PropertyValue] Is the actual property value. +# +# In the formatting sample above, the EntityType can be setto one of the +# following values: +# +# * 'Service' if an individual service is being configured. +# * 'Group 'if a service group is being configured. +# +# The reference to 'entity' in the above description is intentionally +# generic. The CSM Framework supports the configuration of individual +# services as well as groups of services. The type of entity that is +# actually being configured is determined by the value of the +# [EntityType] portion of the property. +# +# There are two values for [EntityId] that have a special meaning within +# the CSM Framework: +# +# +# DefaultService - Identifies the default configuration for any service +# that is not explicitly configured elsewhere in this file. +# +# DefaultServiceGroup - This identifies the entity that provides the +# default configuration for any service group that is not explicitly +# configured elsewhere in this file. +# +# DO NOT use either of these as the identifier for any of your +# application-specific services or service groups. +# +# The CSM Framework treats all entity identifiers in a case-insensitive +# manner. The entity ids 'Service1' and 'SERVICE1' are equivalant. All +# properties with the same [EntityId] will be applied to the same +# configuration. The CSM Framework framework also treats property names +# in a case-insensitive manner. 'MaxRequestCount' and 'MAXREQUESTCOUNT' +# are considered equivalent within the CSM framework. +# +# The following properties are supported by the CSM Framework. Any +# properties that are entity-specific will include the '[EntityId].' +# prefix. +# +# [EntityType].[EntityId].Enabled - Indicates if the entity is enabled +# or disabled by default. The value of this property must be either +# 'true' or 'false'. +# +# [EntityType].[EntityId].MaxRequestCount - The maximum number of +# requests that can be running at any point in time. Once this limit is +# reached, the service is considered to be 'flooded', and subsequent +# requests are refused until the request count drops to the level +# specified by the RestartThreshold property. Once the restart +# threshold is reached, the service will be 'restarted' based on the +# values of the 'RestartFrequency' and 'RestartIncrement' properties. +# The value of this property must be a numeric value. +# The default value for this property is 20. +# +# [EntityType].[EntityId].MaxStalledRequestCount - the maximum number of +# 'stalled' requests that are allowed before subsequent requests are +# refused +# The value of this property must be a numeric value. +# The default value for this property is 10. +# +# [EntityType].[EntityId].RestartThreshold - the process count level at +# which requests will be allowed to proceed whenever a service becomes +# 'flooded'. This property is only used if the total process count +# reaches the level set by the 'MaxRequestCount' property. Once that +# occurs, subsequent requests will be refused until the active request +# count drops to the level specified by this property. Once the active +# request count drops to the level specified by this property, the +# service will be 'restarted' based on the values of the +# 'RestartFrequency' and 'RestartIncrement' properties. To cause the +# CSM framework to allow subsequent requests to proceed as soon as the +# active request count drops below level level set by the +# 'MaxRequestCount' property, just set this property to either -1 or 1 +# less than the value of the 'MaxRequestCount' property. +# The value of this property must be a numeric value. +# The default value for this property is -1. +# +# [EntityType].[EntityId].RestartIncrement - This property, along with +# the 'RestartFrequency' property helps determine how quickly the active +# request count will rise to the 'maximum request count' whenever a +# service is 'restarted' after becoming 'flooded'. The +# 'RestartFrequency' property determines how frequenty the permissable +# number of active requests will be increased. This property determines +# how much the permissible number of active requests will increase by +# whenever it is raised. If this property is set to a positive value, +# then the 'RestartFrequency' property must also be set to a positive +# value. If this property is set to 0, then the 'RestartFrequency' +# property must also be set to 0. In other words, either both +# properties are 0 or both properties are greater than 0. When both +# properties are set to 0, then the permissable number of active +# requests immediately rises back up to the maximum request count once +# it has droppedback down to the 'restart threshold'. When both +# properties are greater than 0, then the permissable number of active +# requests gradually rises to the maximum request count. +# The value of this property must be a numeric value greater than or equal to 0. +# The default value for this property is 0. +# +# [EntityType].[EntityId].RestartFrequency - This property, along with +# the 'RestartIncrement' property helps determine how quickly the active +# request count will rise to the 'maximum request count' whenever a +# service is 'restarted' after becoming 'flooded'. The +# 'RestartIncrement' property determines how quickly the permissable +# number of active requests will be increased. This property determines +# how frequently that increase will occur. If this property is set to +# a positive value, then the 'RestartIncrement' property must also be +# set to a positive value. If this property is set to 0, then the +# 'RestartIncrement' property must also be set to 0. In other words, +# either both properties are 0 or both properties are greater than 0. +# When both properties are set to 0, then the permissable number of +# active requests immediately rises back up to the maximum request count +# once it has droppedback down to the 'restart threshold'. When both +# properties are greater than 0, then the permissable number of active +# requests gradually rises to the maximum request count. +# The value of this property must be a numeric value greater than or equal to 0. +# The default value for this property is 0. +# +# [EntityType].[EntityId].ServiceGroupId - This property is only +# relevant for entities that are configured as services (i.e. the +# [EntityType] portion of the property is set to 'Service'). When the +# 'ServiceGroupId' property is set to a non-blank value, the behavior of +# the service is controled by the configuration of the corresponding +# service group. There is no default value for this property. +# +# [EntityType].[EntityId].Timeout - the timeout, in milliseconds, for +# each process that is controlled by this configuration. Once the +# duration of a process exceeds this value, the process will be +# considered to have entered a 'stalled' state. The default value for +# this property is 10000. +# +# FrameworkEnabled: - This is the one property that is not specific to a +# single entity. This property determines whether the entire CSM +# Framework is enabled or disabled. When disabled, the CSM Framework +# does not track any process counts. All requests to access a service +# are allowed, regardless of the current level of activity. The value +# of this property must be either 'true' or 'false'. +# + +# +# Enables the CSM Framework so that it can manage interactions with external +# services and/or resources. To disable the CSM Framework, simply set +# this property to false. +# +FrameworkEnabled=true + +# +# These are the default settings for any service that is no explicitly configured +# below. A few things to note about this configuration: +# 1) The "Enabled" property is not explicitly set. Instead, we are relying +# on the default value of 'true'. +# 2) The Timeout and Type properties are also not explicitly set. Again, we +# are relying on the default values for these properties. +# +Service.DefaultService.Enabled=true +Service.DefaultService.MaxRequestCount=30 +Service.DefaultService.MaxStalledRequestCount=20 +Service.DefaultService.Timeout=30000 +Service.DefaultService.RestartThreshold=-1 +Service.DefaultService.AutoPurgeAfter=150000 + + +# +# These are the default settings for any service group that is referenced in +# a service configuration but not configured below. +# +# Currently CSI does not use any service group configurations! +# +#Group.DefaultGroup.MaxRequestCount=-1 +#Group.DefaultGroup.MaxStalledRequestCount=-1 +#Group.DefaultGroup.RestartThreshold=-1 +#Group.DefaultGroup.Timeout=-1 diff --git a/aai-traversal/ajsc-shared-config/etc/csm-framework-app.properties b/aai-traversal/ajsc-shared-config/etc/csm-framework-app.properties new file mode 100644 index 0000000..140fde3 --- /dev/null +++ b/aai-traversal/ajsc-shared-config/etc/csm-framework-app.properties @@ -0,0 +1,11 @@ +# The csm-persist-to property identifies the file that the CSM Framework +# will write the current configuration to whenever it is told to save it's +# configuration. +# +#csm-persist-to=/opt/app/myapplication/csm.properties.persisted + +#Important . Please specify absolute path starting from the root directory for Property csm-persist-to +#(Giving relative path may result in undesired results in case the applcation is restarted from a different directory than the original start directory ) +#In the following example , relative path is specfied since the directory structure varies on diff env + +csm-persist-to=/opt/app/q103csi1m8/DATA/${ChangeMe_RELEASE}/${ChangeMe_CLUSTER}_ACFS_csm.properties.persisted diff --git a/aai-traversal/ajsc-shared-config/etc/localhost-access-logback.xml b/aai-traversal/ajsc-shared-config/etc/localhost-access-logback.xml new file mode 100644 index 0000000..cf37962 --- /dev/null +++ b/aai-traversal/ajsc-shared-config/etc/localhost-access-logback.xml @@ -0,0 +1,38 @@ + + + ${AJSC_HOME}/logs/ajsc-jetty/localhost_access.log + + ${AJSC_HOME}/logs/ajsc-jetty/localhost_access.log.%d{yyyy-MM-dd} + + + + %a %u %z [%t] "%m %U" %s %b %y %i{X-TransactionId} %i{X-FromAppId} %i{X-Forwarded-For} %i{X-AAI-SSL-Client-CN} %i{X-AAI-SSL-Client-OU} %i{X-AAI-SSL-Client-O} %i{X-AAI-SSL-Client-L} %i{X-AAI-SSL-Client-ST} %i{X-AAI-SSL-Client-C} %i{X-AAI-SSL-Client-NotBefore} %i{X-AAI-SSL-Client-NotAfter} %i{X-AAI-SSL-Client-DN} %D + + + + + + \ No newline at end of file diff --git a/aai-traversal/ajsc-shared-config/etc/logback.xml b/aai-traversal/ajsc-shared-config/etc/logback.xml new file mode 100644 index 0000000..3311342 --- /dev/null +++ b/aai-traversal/ajsc-shared-config/etc/logback.xml @@ -0,0 +1,382 @@ + + ${module.ajsc.namespace.name} + + + + + + + + + ERROR + ACCEPT + DENY + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + + + + + + ${logDirectory}/rest/sane.log + + ${logDirectory}/rest/sane.log.%d{yyyy-MM-dd} + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + + + + + + 1000 + true + + + + + + INFO + ACCEPT + DENY + + ${logDirectory}/rest/metrics.log + + ${logDirectory}/rest/metrics.log.%d{yyyy-MM-dd} + + + + ${eelfMetricLogPattern} + + + + 1000 + true + + + + + + DEBUG + ACCEPT + DENY + + ${logDirectory}/rest/debug.log + + ${logDirectory}/rest/debug.log.%d{yyyy-MM-dd} + + + + ${eelfLogPattern} + + + + + 1000 + true + + + + + + WARN + + ${logDirectory}/rest/error.log + + ${logDirectory}/rest/error.log.%d{yyyy-MM-dd} + + + + ${eelfLogPattern} + + + + + 1000 + true + + + + + ${logDirectory}/rest/audit.log + + ${logDirectory}/rest/audit.log.%d{yyyy-MM-dd} + + + + ${eelfAuditLogPattern} + + + + + 1000 + true + + + + + + DEBUG + ACCEPT + DENY + + ${logDirectory}/rest/translog.log + + ${logDirectory}/rest/translog.log.%d{yyyy-MM-dd} + + + + ${eelfLogPattern} + + + + + 1000 + true + + + + + + WARN + + ${logDirectory}/dmaapAAIEventConsumer/error.log + + ${logDirectory}/dmaapAAIEventConsumer/error.log.%d{yyyy-MM-dd} + + + + ${eelfLogPattern} + + + + + + DEBUG + ACCEPT + DENY + + ${logDirectory}/dmaapAAIEventConsumer/debug.log + + ${logDirectory}/dmaapAAIEventConsumer/debug.log.%d{yyyy-MM-dd} + + + + ${eelfLogPattern} + + + + + INFO + ACCEPT + DENY + + ${logDirectory}/dmaapAAIEventConsumer/metrics.log + + ${logDirectory}/dmaapAAIEventConsumer/metrics.log.%d{yyyy-MM-dd} + + + + ${eelfLogPattern} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${logDirectory}/perf-audit/Audit-${lrmRVer}-${lrmRO}-${Pid}.log + + + ${logDirectory}/perf-audit/Audit-${lrmRVer}-${lrmRO}-${Pid}.%i.log.zip + + 1 + 9 + + + 5MB + + + "%d [%thread] %-5level %logger{1024} - %msg%n" + + + + + ${logDirectory}/perf-audit/Perform-${lrmRVer}-${lrmRO}-${Pid}.log + + + ${logDirectory}/perf-audit/Perform-${lrmRVer}-${lrmRO}-${Pid}.%i.log.zip + + 1 + 9 + + + 5MB + + + "%d [%thread] %-5level %logger{1024} - %msg%n" + + + + + + + + + + + + + + + + + + + + + + + + + ${JMS_LOGGER_AUDIT_QUEUE_BINDING} + + + + + + + + ${JMS_LOGGER_PERF_QUEUE_BINDING} + + + + + + 1000 + true + 0 + + + + 1000 + true + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aai-traversal/antBuild/build.xml b/aai-traversal/antBuild/build.xml new file mode 100644 index 0000000..346380c --- /dev/null +++ b/aai-traversal/antBuild/build.xml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aai-traversal/bundleconfig-csi/etc/appprops/app-intercepts.properties b/aai-traversal/bundleconfig-csi/etc/appprops/app-intercepts.properties new file mode 100644 index 0000000..3230921 --- /dev/null +++ b/aai-traversal/bundleconfig-csi/etc/appprops/app-intercepts.properties @@ -0,0 +1,6 @@ +#This is where all your application intercept strategies must be configured. AJSC reads this property file and adds +#the list of intercepts specified here to the camel context. This can be useful for accessing every exchange object transferred from/to +#each endpoint in the request/response flow and can allow for more precise debugging and/or processing of the exchange. + +#e.g. +#intercepts=org.openecomp.aai.ajsc_aai.JaxrsEchoService,packagename.class1name,packagename.class2name diff --git a/aai-traversal/bundleconfig-local/README.txt b/aai-traversal/bundleconfig-local/README.txt new file mode 100644 index 0000000..a915213 --- /dev/null +++ b/aai-traversal/bundleconfig-local/README.txt @@ -0,0 +1,9 @@ +The bundleconfig-local directory contains the necessary configuration files to be used for running locally. When running +locally, the "mvn -P runLocal" or the "mvn -P runAjsc" profiles will be using this bundleconfig-local directory as the AJSC_CONF +directory. When deploying to a CSI env, the bundleconfig-csi directory will be copied to the ultimate installation/bundleconfig +directory and will be used for your AJSC service once installed. If you are not deploying to a CSI env, please look at the +antBuild/build.xml file for help in some simple copying of the appropriate folders/files for a NON-CSI env. + +The ajsc-shared-config directory houses the shared configurations that will be used in CSI envs. This includes the logging +functionality of the logback.xml and some csm related artifacts that may be necessary to use while running locally. +When running locally, the system property, "AJSC_SHARED_CONFIG", will point to this location to utilize the logback.xml. \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/RELEASE_NOTES.txt b/aai-traversal/bundleconfig-local/RELEASE_NOTES.txt new file mode 100644 index 0000000..a567d9b --- /dev/null +++ b/aai-traversal/bundleconfig-local/RELEASE_NOTES.txt @@ -0,0 +1 @@ +Place Release Notes here to provide updated Release information for CSTEM to better help manage your service in the CSI environment. \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/appprops/Introscope.properties b/aai-traversal/bundleconfig-local/etc/appprops/Introscope.properties new file mode 100644 index 0000000..319381e --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/Introscope.properties @@ -0,0 +1,8 @@ +#CSI environment uses the Introscope java agent for monitoring services. The AJSC has provided an implementation class that +#provides basic information to the Introscope Enterprise Manager for each http request/response. + +introscopeEventClass=com.att.ajsc.introscope.IntroscopeEventNotifierImpl +serviceName=N/A +conversationId=N/A +uniqueID=N/A +userID=N/A diff --git a/aai-traversal/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties b/aai-traversal/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties new file mode 100644 index 0000000..f4fed40 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties @@ -0,0 +1,3 @@ +#This properties file is for defining any PostProcessorInterceptors that have been created for your AJSC service. + +/**=ajsc.beans.interceptors.CsiPostInterceptor,org.openecomp.aai.interceptors.PostAaiAjscInterceptor diff --git a/aai-traversal/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties b/aai-traversal/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties new file mode 100644 index 0000000..a6dfe01 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties @@ -0,0 +1,3 @@ +#This properties file is for defining any PreProcessorInterceptors that have been created for your AJSC service. + +/**=com.att.ajsc.csi.restmethodmap.RestMethodMapInterceptor,ajsc.beans.interceptors.CsiPreInterceptor,org.openecomp.aai.interceptors.PreAaiAjscInterceptor diff --git a/aai-traversal/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties b/aai-traversal/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties new file mode 100644 index 0000000..1c2a6bf --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/aaiEventDMaaPPublisher.properties @@ -0,0 +1,28 @@ +TransportType=DME2 +Latitude=39.099727 +Longitude=-94.578567 +Version=1.0 +ServiceName=ONAPserverTBD +Environment=TEST +routeOffer=MR1SBKCD +SubContextPath=/ +Protocol=http +MethodType=POST +username=ONAPserverTBD +password= +contenttype=application/json +host=ONAPserverTBD +topic=AAI-EVENT +partition=AAI +maxBatchSize=100 +maxAgeMs=250 +AFT_DME2_EXCHANGE_REQUEST_HANDLERS=ONAPserverTBD +AFT_DME2_EXCHANGE_REPLY_HANDLERS=ONAPserverTBD +AFT_DME2_REQ_TRACE_ON=true +AFT_ENVIRONMENT=AFTUAT +AFT_DME2_EP_CONN_TIMEOUT=15000 +AFT_DME2_ROUNDTRIP_TIMEOUT_MS=240000 +AFT_DME2_EP_READ_TIMEOUT_MS=50000 +sessionstickinessrequired=NO +DME2preferredRouterFilePath=preferredRoute.txt +MessageSentThreadOccurance=50 diff --git a/aai-traversal/bundleconfig-local/etc/appprops/aaiconfig.properties b/aai-traversal/bundleconfig-local/etc/appprops/aaiconfig.properties new file mode 100644 index 0000000..a24c341 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/aaiconfig.properties @@ -0,0 +1,82 @@ +#################################################################### +# REMEMBER TO THINK ABOUT ENVIRONMENTAL DIFFERENCES AND CHANGE THE +# TEMPLATE AND *ALL* DATAFILES +#################################################################### + +aai.config.checktime=1000 + +# this could come from siteconfig.pl? +aai.config.nodename=AutomaticallyOverwritten + +aai.logging.hbase.interceptor=true +aai.logging.hbase.enabled=true +aai.logging.hbase.logrequest=true +aai.logging.hbase.logresponse=true + +aai.logging.trace.enabled=true +aai.logging.trace.logrequest=false +aai.logging.trace.logresponse=false + +aai.transaction.logging=true +aai.transaction.logging.get=true +aai.transaction.logging.post=true + +aai.server.url.base=https://localhost:8446/aai/ +aai.server.url=https://localhost:8446/aai/v10/ +aai.global.callback.url=https://localhost:8446/aai/ + +aai.auth.cspcookies_on=false +aai.dbmodel.filename=ex5.json +aai.truststore.filename=aai_keystore +aai.truststore.passwd.x=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0 +aai.keystore.filename=aai-client-cert.p12 +aai.keystore.passwd.x= + +# for transaction log +hbase.table.name=aailogging-dev1.dev +hbase.notificationTable.name=aainotification-dev1.dev +hbase.table.timestamp.format=YYYYMMdd-HH:mm:ss:SSS +hbase.zookeeper.quorum=ONAPserverTBD +hbase.zookeeper.property.clientPort=2181 +hbase.zookeeper.znode.parent=/hbase + + +# single primary server +aai.primary.filetransfer.serverlist=ONAPserverTBD +aai.primary.filetransfer.primarycheck=echo:8443/aai/util/echo +aai.primary.filetransfer.pingtimeout=5000 +aai.primary.filetransfer.pingcount=5 + + +#rsync properties +aai.rsync.command=rsync +aai.rsync.options.list=-v|-t +aai.rsync.remote.user=aaiadmin +aai.rsync.enabled=y + +aai.notification.current.version=v10 +aai.notificationEvent.default.status=UNPROCESSED +aai.notificationEvent.default.eventType=AAI-EVENT +aai.notificationEvent.default.domain=devINT1 +aai.notificationEvent.default.sourceName=aai +aai.notificationEvent.default.sequenceNumber=0 +aai.notificationEvent.default.severity=NORMAL +aai.notificationEvent.default.version=v10 +# This one lets us enable/disable resource-version checking on updates/deletes +aai.resourceversion.enableflag=true +aai.logging.maxStackTraceEntries=10 +aai.default.api.version=v10 + +# Used by Model-processing code +aai.model.delete.sleep.per.vtx.msec=500 +aai.model.query.resultset.maxcount=50 +aai.model.query.timeout.sec=90 + +aai.model.proc.max.levels=50 +aai.edgeTag.proc.max.levels=50 + +aai.dmaap.workload.enableEventProcessing=true + +aai.realtime.clients=RO,SDNC,MSO + +aai.server.rebind=g diff --git a/aai-traversal/bundleconfig-local/etc/appprops/app-intercepts.properties b/aai-traversal/bundleconfig-local/etc/appprops/app-intercepts.properties new file mode 100644 index 0000000..3230921 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/app-intercepts.properties @@ -0,0 +1,6 @@ +#This is where all your application intercept strategies must be configured. AJSC reads this property file and adds +#the list of intercepts specified here to the camel context. This can be useful for accessing every exchange object transferred from/to +#each endpoint in the request/response flow and can allow for more precise debugging and/or processing of the exchange. + +#e.g. +#intercepts=org.openecomp.aai.ajsc_aai.JaxrsEchoService,packagename.class1name,packagename.class2name diff --git a/aai-traversal/bundleconfig-local/etc/appprops/caet.properties b/aai-traversal/bundleconfig-local/etc/appprops/caet.properties new file mode 100644 index 0000000..e69de29 diff --git a/aai-traversal/bundleconfig-local/etc/appprops/default-logback.xml b/aai-traversal/bundleconfig-local/etc/appprops/default-logback.xml new file mode 100644 index 0000000..0dc841d --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/default-logback.xml @@ -0,0 +1,20 @@ + + + + + + ${defaultPattern} + + + + + + + + + + + + + + diff --git a/aai-traversal/bundleconfig-local/etc/appprops/error.properties b/aai-traversal/bundleconfig-local/etc/appprops/error.properties new file mode 100644 index 0000000..11416ca --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/error.properties @@ -0,0 +1,164 @@ +# Adding comment trying to trigger a build +#------------------------------------------------------------------------------- ---------- +#Key=Disposition:Category:Severity:Error Code:HTTP ResponseCode:RESTError Code:Error Message +#------------------------------------------------------------------------------- ---------- +# testing code, please don't change unless error utility source code changes +AAI_TESTING=5:2:WARN:0000:400:0001:Error code for testing + +# General success +AAI_0000=0:0:INFO:0000:200:0000:Success + +# health check success +AAI_0001=0:0:INFO:0001:200:0001:Success X-FromAppId=%1 X-TransactionId=%2 +AAI_0002=0:0:INFO:0002:200:0001:Successful health check + +# Success with additional info +AAI_0003=0:3:INFO:0003:202:0003:Success with additional info performing %1 on %2. Added %3 with key %4 +AAI_0004=0:3:INFO:0004:202:0003:Added prerequisite object to db + +#--- aairest: 3000-3299 +# svc errors +AAI_3000=5:2:INFO:3000:400:3000:Invalid input performing %1 on %2 +AAI_3001=5:6:INFO:3001:404:3001:Resource not found for %1 using id %2 +AAI_3002=5:1:WARN:3002:400:3002:Error writing output performing %1 on %2 +AAI_3003=5:1:WARN:3003:400:3003:Failed to make edge to missing target node of type %3 with keys %4 performing %1 on %2 +AAI_3005=5:6:WARN:3005:404:3001:Node cannot be directly accessed for read, must be accessed via ancestor(s) +AAI_3006=5:6:WARN:3006:404:3001:Node cannot be directly accessed for write, must be accessed via ancestor(s) +AAI_3007=5:6:INFO:3007:410:3007:This version (%1) of the API is retired, please migrate to %2 +AAI_3008=5:6:ERROR:3008:400:3008:URI is not encoded in UTF-8 +AAI_3009=5:6:ERROR:3009:400:3002:Malformed URL +# pol errors +AAI_3100=5:1:WARN:3100:400:3100:Unsupported operation %1 +AAI_3101=5:1:WARN:3101:403:3101:Attempt by client %1 to execute API %2 +AAI_3102=5:1:WARN:3102:400:3102:Error parsing input performing %1 on %2 +AAI_3300=5:1:WARN:3300:403:3300:Unauthorized +AAI_3301=5:1:WARN:3301:401:3301:Stale credentials +AAI_3302=5:1:WARN:3302:401:3301:Not authenticated +AAI_3303=5:1:ERROR:3303:403:3300:Too many objects would be returned by this request, please refine your request and retry + +#--- aaigen: 4000-4099 +AAI_4000=5:4:ERROR:4000:500:3002:Internal Error +AAI_4001=5:4:FATAL:4001:500:3002:Configuration file not found +AAI_4002=5:4:FATAL:4002:500:3002:Error reading Configuration file +AAI_4003=5:4:ERROR:4003:500:3002:Error writing to log file +AAI_4004=5:4:FATAL:4004:500:3002:Error reading/parsing the error properties file +AAI_4005=5:4:FATAL:4005:500:3002:Missing or invalid configuration parameter +AAI_4006=5:4:FATAL:4006:500:3002:Unexpected error in service +AAI_4007=5:4:ERROR:4007:500:3102:Input parsing error +AAI_4008=5:4:ERROR:4008:500:3002:Output parsing error +AAI_4009=4:0:ERROR:4009:400:3000:Invalid X-FromAppId in header +AAI_4010=4:0:ERROR:4010:400:3000:Invalid X-TransactionId in header +AAI_4011=5:4:ERROR:4011:500:3002:Missing data for REST error response +AAI_4012=5:4:ERROR:4012:500:3002:Bad rule data in RestRules +AAI_4013=5:4:ERROR:4013:500:3002:Error connecting to AAI REST API +AAI_4014=4:0:ERROR:4014:400:3000:Invalid Accept header +AAI_4015=4:0:ERROR:4015:400:3000:You must provide at least one indexed property +AAI_4016=4:0:ERROR:4016:400:3000:The depth parameter must be a number or the string "all" +AAI_4017=5:2:INFO:4017:400:3000:Could not set property +AAI_4018=5:2:ERROR:4018:400:3000:Unable to convert the string to integer +#--- aaidbmap: 5101-5199 +AAI_5101=5:4:FATAL:5101:500:3002:Could not connect to database +AAI_5102=5:4:FATAL:5102:500:3002:Graph database is null after open +AAI_5103=5:4:ERROR:5103:500:3002:Unexpected error during commit +AAI_5104=5:4:ERROR:5104:500:3002:Unexpected error during rollback +AAI_5105=5:4:ERROR:5105:500:3002:Unexpected error reading/updating database +AAI_5106=5:4:WARN:5106:404:3001:Node not found +AAI_5107=5:2:WARN:5107:400:3000:Required information missing +AAI_5108=5:2:WARN:5108:200:0:Unexpected information in request being ignored + +#--- aaidbgen: 6101-6199 +AAI_6101=5:4:ERROR:6101:500:3002:null TitanGraph object passed +AAI_6102=5:4:WARN:6102:400:3000:Passed-in property is not valid for this nodeType +AAI_6103=5:4:WARN:6103:400:3000:Required Node-property not found in input data +AAI_6104=5:4:WARN:6104:400:3000:Required Node-property was passed with no data +AAI_6105=5:4:WARN:6105:400:3000:Node-Key-Property not defined in DbMaps +AAI_6106=5:4:WARN:6106:400:3000:Passed-in property is not valid for this edgeType +AAI_6107=5:4:WARN:6107:400:3000:Required Edge-property not found in input data +AAI_6108=5:4:WARN:6108:400:3000:Required Edge-property was passed with no data +AAI_6109=5:4:WARN:6109:400:3000:Bad dependent Node value +AAI_6110=5:4:ERROR:6110:400:3100:Node cannot be deleted +AAI_6111=5:4:ERROR:6111:400:3000:JSON processing error +AAI_6112=5:4:ERROR:6112:400:3000:More than one node found by getUniqueNode() +AAI_6114=5:4:INFO:6114:404:3001:Node Not Found +AAI_6115=5:4:ERROR:6115:400:3000:Unrecognized NodeType +AAI_6116=5:4:ERROR:6116:400:3000:Unrecognized Property +AAI_6117=5:4:ERROR:6117:400:3000:Uniqueness constraint violated +AAI_6118=5:4:ERROR:6118:400:3000:Required Field not passed. +AAI_6120=5:4:ERROR:6120:400:3000:Bad Parameter Passed +AAI_6121=5:4:ERROR:6121:400:3000:Problem with internal AAI reference data +AAI_6122=5:4:ERROR:6122:400:3000:Data Set not complete in DB for this request +AAI_6123=5:4:ERROR:6123:500:3000:Bad Data found by DataGrooming Tool - Investigate +AAI_6124=5:4:ERROR:6124:500:3000:File read/write error +AAI_6125=5:4:WARN:6125:500:3000:Problem Pulling Data Set +AAI_6126=5:4:ERROR:6126:400:3000:Edge cannot be deleted +AAI_6127=5:4:INFO:6127:404:3001:Edge Not Found +AAI_6128=5:4:INFO:6128:500:3000:Unexpected error +AAI_6129=5:4:INFO:6129:404:3003:Error making edge to target node +AAI_6130=5:4:WARN:6130:412:3000:Precondition Required +AAI_6131=5:4:WARN:6131:412:3000:Precondition Failed +AAI_6132=5:4:WARN:6132:400:3000:Bad Model Definition +AAI_6133=5:4:WARN:6133:400:3000:Bad Named Query Definition +AAI_6134=5:4:ERROR:6134:500:6134:Could not persist transaction to storage back end. Exhausted retry amount +AAI_6135=5:4:WARN:6135:412:3000:Resource version specified on create +AAI_6136=5:4:ERROR:6136:400:3000:Object cannot hold multiple items +AAI_6137=5:4:ERROR:6137:400:3000:Cannot perform writes on multiple vertices +AAI_6138=5:4:ERROR:6138:400:3000:Cannot delete multiple vertices +AAI_6139=5:4:ERROR:6139:404:3000:Attempted to add edge to vertex that does not exist +AAI_6140=5:4:ERROR:6140:400:3000:Edge multiplicity violated +AAI_6141=5:4:WARN:6141:400:3000:Please Refine Query +AAI_6142=5:4:INFO:6142:400:3000:Retrying transaction +AAI_6143=5:4:INFO:6143:400:3000:Ghost vertex found +AAI_6144=5:4:WARN:6144:400:3000:Cycle found in graph +AAI_6145=5:4:ERROR:6145:400:3000:Cannot create a nested/containment edge via relationship +AAI_6146=5:4:ERROR:6146:400:3000:Ambiguous identity map found, use a URI instead + +#--- aaicsvp: 7101-7199 +AAI_7101=5:4:ERROR:7101:500:3002:Unexpected error in CSV file processing +AAI_7102=5:4:ERROR:7102:500:3002:Error in cleanup temporary directory +#AAI_7103=4:2:ERROR:7103:500:3002:Unsupported user +AAI_7104=5:4:ERROR:7104:500:3002:Failed to create directory +AAI_7105=5:4:ERROR:7105:500:3002:Temporary directory exists +AAI_7106=5:4:ERROR:7106:500:3002:Cannot delete +AAI_7107=5:4:ERROR:7107:500:3002:Input file does not exist +AAI_7108=5:4:ERROR:7108:500:3002:Output file does not exist +AAI_7109=5:4:ERROR:7109:500:3002:Error closing file +AAI_7110=5:4:ERROR:7110:500:3002:Error loading/reading properties file +AAI_7111=5:4:ERROR:7111:500:3002:Error executing shell script +AAI_7112=5:4:ERROR:7112:500:3002:Error creating output file +AAI_7113=5:4:ERROR:7113:500:3002:Trailer record error +AAI_7114=5:4:ERROR:7114:500:3002:Input file error +AAI_7115=5:4:ERROR:7115:500:3002:Unexpected error +AAI_7116=5:4:ERROR:7116:500:3002:Request error +AAI_7117=5:4:ERROR:7117:500:3002:Error in get http client object +AAI_7118=5:4:ERROR:7118:500:3002:Script Error +AAI_7119=5:4:ERROR:7119:500:3002:Unknown host + +#--- aaisdnc: 7201-7299 +AAI_7202=5:4:ERROR:7202:500:3002:Error getting connection to odl +AAI_7203=5:4:ERROR:7203:500:3002:Unexpected error calling DataChangeNotification API +AAI_7204=5:4:ERROR:7204:500:3002:Error returned by DataChangeNotification API +AAI_7205=5:4:ERROR:7205:500:3002:Unexpected error running notifySDNCOnUpdate +AAI_7206=5:4:ERROR:7206:500:3002:Invalid data returned from ODL + +#--- NotificationEvent, using UEB space +AAI_7350=5:4:ERROR:7305:500:3002:Notification event creation failed + +#--- aairestctlr: 7401-7499 +AAI_7401=5:4:ERROR:7401:500:3002:Error connecting to AAI REST API +AAI_7402=5:4:ERROR:7402:500:3002:Unexpected error +AAI_7403=5:4:WARN:7403:400:3001:Request error +AAI_7404=5:4:INFO:7404:404:3001:Node not found + +#--- aaiauth: 9101-9199 +AAI_9101=5:0:WARN:9101:403:3300:User is not authorized to perform function +AAI_9102=5:0:WARN:9102:401:3301:Refresh credentials from source +AAI_9103=5:0:WARN:9103:403:3300:User not found +AAI_9104=5:0:WARN:9104:401:3302:Authentication error +AAI_9105=5:0:WARN:9105:403:3300:Authorization error +AAI_9106=5:0:WARN:9106:403:3300:Invalid AppId +#AAI_9107=5:0:WARN:9107:403:3300:No Username in Request +AAI_9107=5:0:WARN:9107:403:3300:SSL is not provided in request, please contact admin + +#--- aaiinstar: 9201-9299 +AAI_9201=5:4:ERROR:9201:500:3002:Unable to send notification +AAI_9202=5:4:ERROR:9202:500:3002:Unable to start a thread diff --git a/aai-traversal/bundleconfig-local/etc/appprops/gremlin-server-config.yaml b/aai-traversal/bundleconfig-local/etc/appprops/gremlin-server-config.yaml new file mode 100644 index 0000000..19caebd --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/gremlin-server-config.yaml @@ -0,0 +1,3 @@ +hosts: [localhost] +port: 8182 +serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0 } \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/appprops/logging.properties b/aai-traversal/bundleconfig-local/etc/appprops/logging.properties new file mode 100644 index 0000000..e029cc4 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/logging.properties @@ -0,0 +1,128 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler + +.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler + +############################################################ +# Handler specific properties. +# Describes specific configuration info for Handlers. +############################################################ + +# this is where we will limit logging on components +org.apache.hadoop.level=WARNING +org.apache.zookeeper.level=WARNING +org.reflections.level=WARNING +com.thinkaurelius.level=WARNING + +1catalina.org.apache.juli.FileHandler.level = FINE +1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs +1catalina.org.apache.juli.FileHandler.prefix = catalina. + +2localhost.org.apache.juli.FileHandler.level = FINE +2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs +2localhost.org.apache.juli.FileHandler.prefix = localhost. + +3manager.org.apache.juli.FileHandler.level = FINE +3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs +3manager.org.apache.juli.FileHandler.prefix = manager. + +4host-manager.org.apache.juli.FileHandler.level = FINE +4host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs +4host-manager.org.apache.juli.FileHandler.prefix = host-manager. + +java.util.logging.ConsoleHandler.level = INFO +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter + + + +############################################################ +# Facility specific properties. +# Provides extra control for each logger. +############################################################ + +org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO +org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler + +org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO +org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler + +org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO +org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler + +# For example, set the org.apache.catalina.util.LifecycleBase logger to log +# each component that extends LifecycleBase changing state: +#org.apache.catalina.util.LifecycleBase.level = FINE + +# To see debug messages in TldLocationsCache, uncomment the following line: +#org.apache.jasper.compiler.TldLocationsCache.level = FINE + + +################################ +# OpenEJB/TomEE specific loggers +################################ +# +# ACTIVATE LEVEL/HANDLERS YOU WANT +# IF YOU ACTIVATE 5tomee.org.apache.juli.FileHandler +# ADD IT TO handlers LINE LIKE: +# +# handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# +# LEVELS: +# ======= +# +# OpenEJB.level = WARNING +# OpenEJB.options.level = INFO +# OpenEJB.server.level = INFO +# OpenEJB.startup.level = INFO +# OpenEJB.startup.service.level = WARNING +# OpenEJB.startup.config.level = INFO +# OpenEJB.hsql.level = INFO +# CORBA-Adapter.level = WARNING +# Transaction.level = WARNING +# org.apache.activemq.level = SEVERE +# org.apache.geronimo.level = SEVERE +# openjpa.level = WARNING +# OpenEJB.cdi.level = INFO +# org.apache.webbeans.level = INFO +# org.apache.openejb.level = FINE +# +# HANDLERS: +# ========= +# +# OpenEJB.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.options.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.server.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.startup.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.startup.service.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.startup.config.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.hsql.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# CORBA-Adapter.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# Transaction.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# org.apache.activemq.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# org.apache.geronimo.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# openjpa.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# OpenEJB.cdi.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# org.apache.webbeans.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# org.apache.openejb.handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler +# +# TOMEE HANDLER SAMPLE: +# ===================== +# +# 5tomee.org.apache.juli.FileHandler.level = FINEST +# 5tomee.org.apache.juli.FileHandler.directory = ${catalina.base}/logs +# 5tomee.org.apache.juli.FileHandler.prefix = tomee. + diff --git a/aai-traversal/bundleconfig-local/etc/appprops/methodMapper.properties b/aai-traversal/bundleconfig-local/etc/appprops/methodMapper.properties new file mode 100644 index 0000000..d6c1158 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/methodMapper.properties @@ -0,0 +1,24 @@ +{ + "ActiveAndAvailableInventory-Traversal" : [{ + "logicalName" : "getAAIResource", + "method" : "get", + "url" : "/aai/*" + }, { + "logicalName" : "putAAIResource", + "method" : "put", + "url" : "/aai/*" + }, { + "logicalName" : "deleteAAIResource", + "method" : "delete", + "url" : "/aai/*" + }, { + "logicalName" : "postAAIResource", + "method" : "post", + "url" : "/aai/*" + }, { + "logicalName" : "patchAAIResource", + "method" : "patch", + "url" : "/aai/*" + } + ] +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/appprops/preferredRoute.txt b/aai-traversal/bundleconfig-local/etc/appprops/preferredRoute.txt new file mode 100644 index 0000000..662b0aa --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/preferredRoute.txt @@ -0,0 +1 @@ +preferredRouteKey=MR1 \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/appprops/titan-cached.properties b/aai-traversal/bundleconfig-local/etc/appprops/titan-cached.properties new file mode 100644 index 0000000..0a3403f --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/titan-cached.properties @@ -0,0 +1,18 @@ +query.fast-property=true +# the following parameters are not reloaded automatically and require a manual bounce +#storage.backend=inmemory +storage.backend=inmemory +storage.hostname=localhost + +#schema.default=none +storage.lock.wait-time=300 +storage.hbase.table=aaigraph-dev02 +storage.hbase.ext.zookeeper.znode.parent=/hbase +#caching on +cache.db-cache = true +cache.db-cache-clean-wait = 20 +cache.db-cache-time = 180000 +cache.db-cache-size = 0.3 + +#load graphson file on startup +load.snapshot.file=false diff --git a/aai-traversal/bundleconfig-local/etc/appprops/titan-realtime.properties b/aai-traversal/bundleconfig-local/etc/appprops/titan-realtime.properties new file mode 100644 index 0000000..989f3be --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/appprops/titan-realtime.properties @@ -0,0 +1,15 @@ +query.fast-property=true +# the following parameters are not reloaded automatically and require a manual bounce +#storage.backend=inmemory +storage.backend=inmemory +storage.hostname=localhost + +#schema.default=none +storage.lock.wait-time=300 +storage.hbase.table=aaigraph-dev02 +storage.hbase.ext.zookeeper.znode.parent=/hbase +# Setting db-cache to false ensure the fastest propagation of changes across servers +cache.db-cache = false + +#load graphson file on startup +load.snapshot.file=false diff --git a/aai-traversal/bundleconfig-local/etc/auth/aai_keystore b/aai-traversal/bundleconfig-local/etc/auth/aai_keystore new file mode 100644 index 0000000..3eef135 Binary files /dev/null and b/aai-traversal/bundleconfig-local/etc/auth/aai_keystore differ diff --git a/aai-traversal/bundleconfig-local/etc/query/stored-queries.properties b/aai-traversal/bundleconfig-local/etc/query/stored-queries.properties new file mode 100644 index 0000000..e69de29 diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getClfiRoadmTailSummary-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getClfiRoadmTailSummary-1.0.json new file mode 100644 index 0000000..5c4f4fb --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getClfiRoadmTailSummary-1.0.json @@ -0,0 +1,101 @@ +{ + "named-query-uuid" : "4f448e43-339f-4c1c-85f6-896c444e25ca", + "named-query-name" : "GetClfiRoadmTailSummary", + "named-query-version" : "1.0", + "description" : "Named query - Get CLFI ROADM Tail Summary", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "link-name", "link-type", "operational-status", "speed-value", "speed-units" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name", "interface-role", "port-description", "equipment-identifier" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "pnf-name", "pnf-name2", "equip-model", "equip-type", "frame-id" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "862b25a1-262a-4961-bdaa-cdc55d69785a" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "94043c37-4e73-439c-a790-0fdd697924cd" + } ] + } ] + } + }, { + "property-collect-list" : [ "link-name", "link-name2", "link-type", "link-role", "operational-status"], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "service-instance-name", "operational-status" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-type" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "global-customer-id", "subscriber-name" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComplexByPnfName-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComplexByPnfName-1.0.json new file mode 100644 index 0000000..fef6c91 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComplexByPnfName-1.0.json @@ -0,0 +1,32 @@ +{ + "named-query-uuid" : "d27ccfea-7098-42d7-a4cd-bbddb37bf205", + "named-query-name" : "getComplexByPnfName", + "named-query-version" : "1.0", + "description" : "Named Query - get complex by pnfName", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "af91c2f7-35fc-43cf-a13d-443f385b2353" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "862b25a1-262a-4961-bdaa-cdc55d69785a" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json new file mode 100644 index 0000000..d3e307c --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.0.json @@ -0,0 +1,98 @@ +{ + "named-query-uuid" : "ed0a0f5b-cf79-4784-88b2-911cd726cd3d", + "named-query-name" : "get-component-list", + "named-query-version" : "1.0", + "description" : "Named Query - Get Component List", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fcec1b02-b2d0-4834-aef8-d71be04717dd" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fcec1b02-b2d0-4834-aef8-d71be04717dd" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ef86f9c5-2165-44f3-8fc3-96018b609ea5" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.1.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.1.json new file mode 100644 index 0000000..639cd41 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.1.json @@ -0,0 +1,125 @@ +{ + "named-query-uuid" : "0367193e-c785-4d5f-9cb8-7bc89dc9ddb7", + "named-query-name" : "get-component-list", + "named-query-version" : "1.1", + "description" : "Named Query - Get Component List", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "service-instance-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "1b2c9ba7-e449-4831-ba15-3073672f5ef2" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fcec1b02-b2d0-4834-aef8-d71be04717dd" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fcec1b02-b2d0-4834-aef8-d71be04717dd" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "1b2c9ba7-e449-4831-ba15-3073672f5ef2" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ef86f9c5-2165-44f3-8fc3-96018b609ea5" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.2.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.2.json new file mode 100644 index 0000000..22ba4c0 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getComponentList-1.2.json @@ -0,0 +1,139 @@ +{ + "named-query-uuid" : "2a183f99-2c66-482b-ade5-7962efd801ef", + "named-query-name" : "get-component-list", + "named-query-version" : "1.2", + "description" : "Named Query - Get Component List", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "service-instance-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "1b2c9ba7-e449-4831-ba15-3073672f5ef2" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fcec1b02-b2d0-4834-aef8-d71be04717dd" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "do-not-output" : "true", + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fcec1b02-b2d0-4834-aef8-d71be04717dd" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "1b2c9ba7-e449-4831-ba15-3073672f5ef2" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ef86f9c5-2165-44f3-8fc3-96018b609ea5" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexHostname-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexHostname-1.0.json new file mode 100644 index 0000000..a610aa6 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexHostname-1.0.json @@ -0,0 +1,32 @@ +{ + "named-query-uuid" : "670a94e9-874f-4087-8501-62d4d289c519", + "named-query-name" : "dhv-complex-by-hostname", + "named-query-version" : "1.0", + "description" : "Named Query - DHV Complex By Hostname", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "af91c2f7-35fc-43cf-a13d-443f385b2353" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexLocationId-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexLocationId-1.0.json new file mode 100644 index 0000000..70d6db1 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVComplexLocationId-1.0.json @@ -0,0 +1,32 @@ +{ + "named-query-uuid" : "59490c32-eaae-488d-8442-f301b1ed43a9", + "named-query-name" : "dhv-complex-by-location-id", + "named-query-version" : "1.0", + "description" : "Named Query - DHV Complex By LocationId", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "af91c2f7-35fc-43cf-a13d-443f385b2353" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLink-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLink-1.0.json new file mode 100644 index 0000000..6e90b61 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLink-1.0.json @@ -0,0 +1,58 @@ +{ + "named-query-uuid" : "47e5e7c7-719e-45af-b96f-0c15fa0691b9", + "named-query-name" : "logical-link-by-vnf-name", + "named-query-version" : "1.0", + "description" : "Named Query - get logical-link by vnf-name", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLinkByCircuitId-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLinkByCircuitId-1.0.json new file mode 100644 index 0000000..62de1b8 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVLogicalLinkByCircuitId-1.0.json @@ -0,0 +1,19 @@ +{ + "named-query-uuid" : "4028faed-b7d5-4059-9d49-7df06da9ebfb", + "named-query-name" : "logical-link-by-circuit-id-", + "named-query-version" : "1.0", + "description" : "Named Query - get logical-link by circuit-id", + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.0.json new file mode 100644 index 0000000..a0ba2fe --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.0.json @@ -0,0 +1,273 @@ +{ + "named-query-uuid" : "b546a34b-7e71-45dc-9907-4cbdcf675c64", + "named-query-name" : "dhv-service-topology", + "named-query-version" : "1.0", + "description" : "Named Query - DHV Service Topology", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "persona-model-id", "service-instance-name", "service-instance-location-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-type", "temp-ub-sub-account-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "global-customer-id" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + }, { + "property-collect-list" : [ "service-instance-id", "persona-model-id", "service-instance-name", "service-instance-location-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vnf-name", "vnf-id", "vnf-type", "prov-status", "operational-state" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vlan-interface", "vlan-id-inner", "vlan-id-outer", "vlan-description", "speed-value", "speed-units" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + }, { + "property-collect-list" : [ "vserver-name", "vserver-id", "prov-status" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vlan-interface", "vlan-id-inner", "vlan-id-outer", "vlan-description", "speed-value", "speed-units" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + }, { + "property-collect-list" : [ "hostname" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-provider-name" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c822d81f-822f-4304-9623-1025b53da568" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "94043c37-4e73-439c-a790-0fdd697924cd" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.1.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.1.json new file mode 100644 index 0000000..2512590 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology-1.1.json @@ -0,0 +1,273 @@ +{ + "named-query-uuid" : "888d6065-e1ff-409c-ac6b-baafc4777788", + "named-query-name" : "dhv-service-topology", + "named-query-version" : "1.1", + "description" : "Named Query - DHV Service Topology", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "model-invariant-id", "service-instance-name", "service-instance-location-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-type", "temp-ub-sub-account-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "global-customer-id" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + }, { + "property-collect-list" : [ "service-instance-id", "persona-model-id", "service-instance-name", "service-instance-location-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vnf-name", "vnf-id", "vnf-type", "prov-status", "operational-state" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vlan-interface", "vlan-id-inner", "vlan-id-outer", "vlan-description", "speed-value", "speed-units" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + }, { + "property-collect-list" : [ "vserver-name", "vserver-id", "prov-status" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vlan-interface", "vlan-id-inner", "vlan-id-outer", "vlan-description", "speed-value", "speed-units" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv4-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "property-collect-list" : [ "l3-interface-ipv6-address" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + }, { + "property-collect-list" : [ "hostname" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-provider-name" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c822d81f-822f-4304-9623-1025b53da568" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "94043c37-4e73-439c-a790-0fdd697924cd" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology2-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology2-1.0.json new file mode 100644 index 0000000..986c50a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getDHVServiceTopology2-1.0.json @@ -0,0 +1,321 @@ +{ + "named-query-uuid" : "09236f18-a9d2-4468-9086-464b8385b706", + "named-query-name" : "dhv-service-topology-2", + "named-query-version" : "1.0", + "description" : "Named Query - DHV Service Topology 2", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "af91c2f7-35fc-43cf-a13d-443f385b2353" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + }, { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "aad85df2-09be-40fa-b867-16415e4e10e2" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82966045-43ee-4982-8307-7e9610866140" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "f6d6a23d-a1a9-48ff-8419-b6530da2d381" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getL3networkCloudRegionByNetworkRole-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getL3networkCloudRegionByNetworkRole-1.0.json new file mode 100644 index 0000000..d6b3c34 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getL3networkCloudRegionByNetworkRole-1.0.json @@ -0,0 +1,71 @@ +{ + "named-query-uuid" : "96e54642-c0e1-4aa2-af53-e37c623b8d01", + "named-query-name" : "l3network-cloud-region-by-network-role", + "named-query-version" : "1.0", + "description" : "Named Query - get l3Network and cloudRegion by networkRole", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "425b2158-e51d-4509-9945-dad4556474a3" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "97c26c99-6870-44c1-8a07-1d900d3f4ce6" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getLogicalLinkByCloudRegionId-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getLogicalLinkByCloudRegionId-1.0.json new file mode 100644 index 0000000..e987d36 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getLogicalLinkByCloudRegionId-1.0.json @@ -0,0 +1,32 @@ +{ + "named-query-uuid" : "25096aa7-bc97-4ece-8a81-41dd28cd0f7d", + "named-query-name" : "getLogicalLinkByCloudRegionId", + "named-query-version" : "1.0", + "description" : "Named query - get logical link by cloud region id", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "425b2158-e51d-4509-9945-dad4556474a3" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getPinterfacePhysicalLinkBySvcInstId-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getPinterfacePhysicalLinkBySvcInstId-1.0.json new file mode 100644 index 0000000..e8b377b --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getPinterfacePhysicalLinkBySvcInstId-1.0.json @@ -0,0 +1,84 @@ +{ + "named-query-uuid" : "75d55786-200b-49fd-92d7-1393e755d693", + "named-query-name" : "pinterface-physical-link-by-service-instance-id", + "named-query-version" : "1.0", + "description" : "Named Query - get pInterface and physicalLink by serviceInstanceId", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c822d81f-822f-4304-9623-1025b53da568" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "94043c37-4e73-439c-a790-0fdd697924cd" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getRouterRoadmTailSummary-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getRouterRoadmTailSummary-1.0.json new file mode 100644 index 0000000..0fb6dd5 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getRouterRoadmTailSummary-1.0.json @@ -0,0 +1,129 @@ +{ + "named-query-uuid" : "cbf22b8a-f29a-4b9b-a466-a878095b258a", + "named-query-name" : "GetRouterRoadmTailSummary", + "named-query-version" : "1.0", + "description" : "Named query - Get Router ROADM Tail Summary", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "pnf-name", "pnf-name2", "equip-model", "equip-type", "frame-id" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name", "port-description", "equipment-identifier" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "link-name", "link-type", "operational-status", "speed-value", "speed-units" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "interface-name", "interface-role", "port-description", "equipment-identifier" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "pnf-name", "equip-model", "equip-type", "frame-id" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "862b25a1-262a-4961-bdaa-cdc55d69785a" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "94043c37-4e73-439c-a790-0fdd697924cd" + } ] + } ] + } + }, { + "property-collect-list" : [ "link-name", "link-name2", "link-type", "link-role", "operational-status" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "service-instance-name", "operational-status" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-type" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "global-customer-id", "subscriber-name" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "94043c37-4e73-439c-a790-0fdd697924cd" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "862b25a1-262a-4961-bdaa-cdc55d69785a" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json new file mode 100644 index 0000000..971b1a2 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getServiceInstanceSummary-1.0.json @@ -0,0 +1,126 @@ +{ + "named-query-uuid" : "5aaae840-ca96-4e5f-9308-58883564a80f", + "named-query-name" : "get-service-instance-summary", + "named-query-version" : "1.0", + "description" : "Named Query - Get Service Instance Summary", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "service-instance-name", "operational-status" ], + "named-query-elements" : { + "named-query-element" : [ { + "do-not-output" : "true", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "cloud-region-id" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "425b2158-e51d-4509-9945-dad4556474a3" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "3d560d81-57d0-438b-a2a1-5334dba0651a" + } ] + } ] + } + }, { + "property-collect-list" : [ "service-type" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "global-customer-id", "subscriber-name" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + }, { + "do-not-output" : "true", + "named-query-elements" : { + "named-query-element" : [ { + "do-not-output" : "true", + "named-query-elements" : { + "named-query-element" : [ { + "do-not-output" : "true", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "cloud-region-id" ], + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "425b2158-e51d-4509-9945-dad4556474a3" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "97c26c99-6870-44c1-8a07-1d900d3f4ce6" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getSvcSubscriberModelInfo-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getSvcSubscriberModelInfo-1.0.json new file mode 100644 index 0000000..5dcd475 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getSvcSubscriberModelInfo-1.0.json @@ -0,0 +1,46 @@ +{ + "named-query-uuid" : "6e806bc2-8f9b-4534-bb68-be91267ff6c8", + "named-query-name" : "get-service-instance-model-info", + "named-query-version" : "1.0", + "description" : "Named Query - Get Service Instance Model Info", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "do-not-output" : "false", + "related-lookups" : { + "related-lookup" : [ { + "source-node-type" : "service-instance", + "source-node-property" : "model-invariant-id-local", + "target-node-type" : "model", + "target-node-property" : "model-invariant-id", + "property-collect-list" : ["model-invariant-id", "model-type", "model-description" ] + }, { + "source-node-type" : "service-instance", + "source-node-property" : "model-version-id-local", + "target-node-type" : "model-ver", + "target-node-property" : "model-version-id", + "property-collect-list" : [ "model-version-id", "model-name", "model-version", "model-description" ] + } ] + }, + "relationship-list" : { + "relationship" : [ { + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcInstance-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcInstance-1.0.json new file mode 100644 index 0000000..ee1bec5 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcInstance-1.0.json @@ -0,0 +1,87 @@ +{ + "named-query-uuid" : "3c167fdb-5a99-46a3-8165-e566d289358d", + "named-query-name" : "getTenantInfoAtSvcInstance", + "named-query-version" : "1.0", + "description" : "Named Query - Tenant Info At Service Instance", + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "service-instance-id", "service-instance-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vnf-id", "vnf-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "property-collect-list" : [ "vserver-id", "vserver-name" ], + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "af91c2f7-35fc-43cf-a13d-443f385b2353" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "425b2158-e51d-4509-9945-dad4556474a3" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "97c26c99-6870-44c1-8a07-1d900d3f4ce6" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcSubscription-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcSubscription-1.0.json new file mode 100644 index 0000000..e520585 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getTenantInfoAtSvcSubscription-1.0.json @@ -0,0 +1,58 @@ +{ + "named-query-uuid" : "35b13965-ef9d-4597-9859-bde64c521c91", + "named-query-name" : "getTenantInfoAtSvcSubscription", + "named-query-version" : "1.0", + "description" : "Named Query - Tenant Info At ServiceSubscription", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "af91c2f7-35fc-43cf-a13d-443f385b2353" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "425b2158-e51d-4509-9945-dad4556474a3" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "97c26c99-6870-44c1-8a07-1d900d3f4ce6" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getVnfVlanByCircuitId-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getVnfVlanByCircuitId-1.0.json new file mode 100644 index 0000000..2260ab3 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getVnfVlanByCircuitId-1.0.json @@ -0,0 +1,58 @@ +{ + "named-query-uuid" : "9abb2661-d92c-4f84-aea6-b16acfa00e22", + "named-query-name" : "generic-vnf-vlan-by-circuit-id", + "named-query-version" : "1.0", + "description" : "Named Query - get genericVnf and vlan by circuitId", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "acc6edd8-a8d4-4b93-afaa-0994068be14c" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "cea0a982-8d55-4093-921e-418fbccf7060" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getWlBundleId-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getWlBundleId-1.0.json new file mode 100644 index 0000000..203aa38 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/named-query-json/getWlBundleId-1.0.json @@ -0,0 +1,81 @@ +{ + "named-query-uuid" : "88aae9bc-9b3d-44c8-a0ba-3c4911da755c", + "named-query-name" : "GetWlBundleId", + "named-query-version" : "1.0", + "description" : "Named query for wavelength services with same Bundle Id", + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "named-query-elements" : { + "named-query-element" : [ { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "2e1a602a-acd8-4f78-94ff-618b802a303b" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "82194af1-3c2c-485a-8f44-420e22a9eaa4" + } ] + } ] + } + }, { + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "fe012535-2c31-4a39-a739-612374c638a0" + } ] + } ] + } + } ] + }, + "relationship-list" : { + "relationship" : [ { + "related-to" : "model", + "relationship-data" : [ { + "relationship-key" : "model.model-invariant-id", + "relationship-value" : "86ffe6e5-4d0e-4cec-80b5-5c38aa3eff98" + } ] + } ] + } + } ] + } +} \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/resource-model-json/000-README b/aai-traversal/bundleconfig-local/etc/scriptdata/resource-model-json/000-README new file mode 100644 index 0000000..9647972 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/resource-model-json/000-README @@ -0,0 +1,10 @@ +Add resource models here in the order you want them to be added to the graph. + +Recommended that they are spaced by 10's. + +So, if you are adding a resource model it should be: + +100-ipe-resource-model-1.0.json +110-vBgf-resource-model-1.0.json + +This will allow others to insert models between existing models. \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/service-model-json/000-README b/aai-traversal/bundleconfig-local/etc/scriptdata/service-model-json/000-README new file mode 100644 index 0000000..bb30e02 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/service-model-json/000-README @@ -0,0 +1,10 @@ +Add service models here in the order you want them to be added to the graph. + +Recommended that they are spaced by 10's. + +So, if you are adding a resource model it should be: + +100-connector-service-model-1.0.json +110-service-instance-service-model-1.0.json + +This will allow others to insert models between existing models. \ No newline at end of file diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-1.0.json new file mode 100644 index 0000000..9d3e00c --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "af593b4b-490e-4665-ad74-2f6351c0a7ce", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "fd7fb09e-d930-41b9-b83f-cfde9df48640", + "model-version" : "1.0", + "model-name" : "action" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-data-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-data-1.0.json new file mode 100644 index 0000000..7229f5a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/action-data-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "9551346c-7d8b-4daf-9926-b93e96e2344a", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd", + "model-version" : "1.0", + "model-name" : "action-data" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/allotted-resource-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/allotted-resource-1.0.json new file mode 100644 index 0000000..9329af8 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/allotted-resource-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "f6d6a23d-a1a9-48ff-8419-b6530da2d381", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "7ad0915f-25c0-4a70-b9bc-185a75f87564", + "model-version" : "1.0", + "model-name" : "allotted-resource" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json new file mode 100644 index 0000000..0c423fe --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/availability-zone-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "61b88c01-d819-41c0-8e21-7fd7ba47148e", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "6c092fb1-21b2-456b-9e01-67fb4de1896e", + "model-version" : "1.0", + "model-name" : "availability-zone" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/az-and-dvs-switches-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/az-and-dvs-switches-1.0.json new file mode 100644 index 0000000..620a33d --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/az-and-dvs-switches-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "53dc00d4-e6d9-48ec-b6cc-3d3797e9b896", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "b2dea88d-78a0-49bf-95c9-5819df08e966", + "model-version" : "1.0", + "model-name" : "az-and-dvs-switches" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/class-of-service-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/class-of-service-1.0.json new file mode 100644 index 0000000..2b28152 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/class-of-service-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "18094b19-d16d-4822-8acf-e92c6aefa178", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "d2fb27cc-15eb-4c4e-828e-71d41aaecc5b", + "model-version" : "1.0", + "model-name" : "class-of-service" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json new file mode 100644 index 0000000..a2957c4 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cloud-region-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "425b2158-e51d-4509-9945-dad4556474a3", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "2a160989-b202-47dd-874b-4a0f275998f7", + "model-version" : "1.0", + "model-name" : "cloud-region" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/complex-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/complex-1.0.json new file mode 100644 index 0000000..c8ca766 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/complex-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "af91c2f7-35fc-43cf-a13d-443f385b2353", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "3a8ab1ee-9220-4fe8-b89c-9251d160ddc2", + "model-version" : "1.0", + "model-name" : "complex" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/connector-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/connector-1.0.json new file mode 100644 index 0000000..f9bfed0 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/connector-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "4c01c948-7607-4d66-8a6c-99c2c2717936", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "22104c9f-29fd-462f-be07-96cd6b46dd33", + "model-version" : "1.0", + "model-name" : "connector" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/constrained-element-set-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/constrained-element-set-1.0.json new file mode 100644 index 0000000..44f5de2 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/constrained-element-set-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "c0292b4f-ee97-40cc-8c2e-f967c48f5701", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "01102126-9c04-4a89-945b-b131e61e95d7", + "model-version" : "1.0", + "model-name" : "constrained-element-set" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json new file mode 100644 index 0000000..87eee5c --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-assignment-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "fcb8d46b-b656-4ad6-8fa4-22cef74b443f", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "44e5cb1f-0938-41aa-b766-d4595109fe89", + "model-version" : "1.0", + "model-name" : "ctag-assignment" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-pool-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-pool-1.0.json new file mode 100644 index 0000000..c85e267 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ctag-pool-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "46c51d4e-d67e-4a9c-b1f5-49b1e9c6fcaa", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "2056c41f-23b9-4de7-9f50-819adad37d76", + "model-version" : "1.0", + "model-name" : "ctag-pool" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json new file mode 100644 index 0000000..35cf683 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/customer-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "c1d4305f-cdbd-4bbe-9069-a2f4978fd89e", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "d4df5c27-98a1-4812-a8aa-c17f055b7a3f", + "model-version" : "1.0", + "model-name" : "customer" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cvlan-tag-entry-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cvlan-tag-entry-1.0.json new file mode 100644 index 0000000..95211f2 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/cvlan-tag-entry-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "245cf4b0-7cc5-4eea-bbd9-753e939adcab", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "c3878ffb-8d85-4114-bee6-e4074a9db10b", + "model-version" : "1.0", + "model-name" : "cvlan-tag-entry" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/dvs-switch-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/dvs-switch-1.0.json new file mode 100644 index 0000000..22dc769 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/dvs-switch-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "98fbb471-1f86-428e-bd8a-c8a25de6fa23", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "4cb44ae8-e3ab-452a-9f95-bcc8a44c55ea", + "model-version" : "1.0", + "model-name" : "dvs-switch" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/edge-prop-names-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/edge-prop-names-1.0.json new file mode 100644 index 0000000..4ed663f --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/edge-prop-names-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "7a08cad4-8759-46a5-8245-095d1ba57ac6", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f0442326-8201-4d0e-857c-74b4ddcbfc9f", + "model-version" : "1.0", + "model-name" : "edge-prop-names" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/element-choice-set-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/element-choice-set-1.0.json new file mode 100644 index 0000000..46c7348 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/element-choice-set-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "9a011958-7165-47a3-b872-00951d1f09ae", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "af27fbfd-598d-44da-aeae-0f9d3a5fcd6a", + "model-version" : "1.0", + "model-name" : "element-choice-set" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/entitlement-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/entitlement-1.0.json new file mode 100644 index 0000000..b6bf0e8 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/entitlement-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "ae75b5a0-d5e1-4f3a-b8fb-37626a753da3", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "7e27ba2e-b7db-4e13-9fae-d142152ef98a", + "model-version" : "1.0", + "model-name" : "entitlement" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json new file mode 100644 index 0000000..c44e554 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/flavor-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "bace8d1c-a261-4041-9e37-823117415d0f", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "36200fb5-f251-4f5d-a520-7c5ad5c2cd4b", + "model-version" : "1.0", + "model-name" : "flavor" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json new file mode 100644 index 0000000..afab83a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/generic-vnf-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "acc6edd8-a8d4-4b93-afaa-0994068be14c", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "93a6166f-b3d5-4f06-b4ba-aed48d009ad9", + "model-version" : "1.0", + "model-name" : "generic-vnf" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json new file mode 100644 index 0000000..33e1495 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/group-assignment-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "7cc05f25-7ba2-42b7-a237-c5662a1689e1", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "fe578080-ce19-4604-8760-fc264fbb2565", + "model-version" : "1.0", + "model-name" : "group-assignment" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json new file mode 100644 index 0000000..59f095b --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/image-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "3f4c7204-739b-4bbb-87a7-8a6856439c90", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f6a038c2-820c-42ba-8c2b-375e24e8f932", + "model-version" : "1.0", + "model-name" : "image" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/include-node-filter-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/include-node-filter-1.0.json new file mode 100644 index 0000000..83d9255 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/include-node-filter-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "2a2d8ad2-af0a-4e1f-9982-0c899e7dc827", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f05f804d-7057-4ffe-bdc5-39f2f0c9c9fd", + "model-version" : "1.0", + "model-name" : "include-node-filter" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/instance-group-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/instance-group-1.0.json new file mode 100644 index 0000000..81eeff0 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/instance-group-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "3bf1e610-45f7-4ad6-b833-ca4c5ee6a3fd", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "8e6ee9dc-9017-444a-83b3-219edb018128", + "model-version" : "1.0", + "model-name" : "instance-group" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-1.0.json new file mode 100644 index 0000000..307d29d --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "cd57d844-9017-4078-aa19-926935a3d77c", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "69957f4a-2155-4b95-8d72-d6dd9b88b27b", + "model-version" : "1.0", + "model-name" : "inventory-item" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-data-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-data-1.0.json new file mode 100644 index 0000000..46cb9f0 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/inventory-item-data-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "87a383ae-cf03-432e-a9de-04e6a622d0fd", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "0e54bb87-bd6e-4a2b-ad1c-6d935b87ae51", + "model-version" : "1.0", + "model-name" : "inventory-item-data" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ipsec-configuration-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ipsec-configuration-1.0.json new file mode 100644 index 0000000..165ebbe --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/ipsec-configuration-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "aca4c310-cb45-42bd-9f88-73e40ba7b962", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "d949fd10-36bf-408a-ac7a-cad5004d2e0d", + "model-version" : "1.0", + "model-name" : "ipsec-configuration" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/key-data-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/key-data-1.0.json new file mode 100644 index 0000000..f0f7cb4 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/key-data-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "f5faa464-c2f2-4cc3-89d2-a90452dc3a07", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "c23ea04d-1a3b-453d-bc49-a6c783a5e92b", + "model-version" : "1.0", + "model-name" : "key-data" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json new file mode 100644 index 0000000..0f63ba5 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l-interface-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "cea0a982-8d55-4093-921e-418fbccf7060", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "a32613fd-18b9-459e-aab8-fffb3912966a", + "model-version" : "1.0", + "model-name" : "l-interface" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json new file mode 100644 index 0000000..0bb4d41 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv4-address-list-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "aad85df2-09be-40fa-b867-16415e4e10e2", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "41e76b6f-1e06-4fd4-82cd-81c50fc4574b", + "model-version" : "1.0", + "model-name" : "l3-interface-ipv4-address-list" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json new file mode 100644 index 0000000..9a830f4 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-interface-ipv6-address-list-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "82966045-43ee-4982-8307-7e9610866140", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "d040621d-541a-477b-bb1b-a2b61b14e295", + "model-version" : "1.0", + "model-name" : "l3-interface-ipv6-address-list" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json new file mode 100644 index 0000000..0d92d38 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/l3-network-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "3d560d81-57d0-438b-a2a1-5334dba0651a", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "9111f20f-e680-4001-b83f-19a2fc23bfc1", + "model-version" : "1.0", + "model-name" : "l3-network" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json new file mode 100644 index 0000000..9bf0715 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-interface-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "e0ee9bde-c1fc-4651-a95d-8e0597bf7d70", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "ce95f7c3-b61b-4758-ae9e-7e943b1c103d", + "model-version" : "1.0", + "model-name" : "lag-interface" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-link-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-link-1.0.json new file mode 100644 index 0000000..44046a9 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/lag-link-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "86ffe6e5-4d0e-4cec-80b5-5c38aa3eff98", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "d29a087a-af59-4053-a3f8-0f95a92faa75", + "model-version" : "1.0", + "model-name" : "lag-link" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-1.0.json new file mode 100644 index 0000000..fc79b60 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "b9a9b337-1f86-42d3-b9f9-f987a089507c", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "6889274b-a1dc-40ab-9090-93677e13e2e6", + "model-version" : "1.0", + "model-name" : "license" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-key-resource-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-key-resource-1.0.json new file mode 100644 index 0000000..b56df16 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/license-key-resource-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "9022ebfe-b54f-4911-a6b2-8c3f5ec189b7", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "24b25f8c-b8bd-4c62-9421-87c12667aac9", + "model-version" : "1.0", + "model-name" : "license-key-resource" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json new file mode 100644 index 0000000..66300e7 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/logical-link-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "fe012535-2c31-4a39-a739-612374c638a0", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "a1481a38-f8ba-4ae4-bdf1-06c2c6af4c54", + "model-version" : "1.0", + "model-name" : "logical-link" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/metadatum-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/metadatum-1.0.json new file mode 100644 index 0000000..1110746 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/metadatum-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "86dbb63a-265e-4614-993f-6771c30b56a5", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "6bae950e-8939-41d3-a6a7-251b03e4c1fc", + "model-version" : "1.0", + "model-name" : "metadatum" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-1.0.json new file mode 100644 index 0000000..4c5da8c --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "06d1418a-5faa-452d-a94b-a2829df5f67b", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "1f51c05c-b164-4c27-9c03-5cbb239fd6be", + "model-version" : "1.0", + "model-name" : "model" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-constraint-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-constraint-1.0.json new file mode 100644 index 0000000..37b7272 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-constraint-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "c28966f3-e758-4483-b37b-a90b05d3dd33", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "ad70dd19-f156-4fb5-a865-97b5563b0d37", + "model-version" : "1.0", + "model-name" : "model-constraint" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-element-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-element-1.0.json new file mode 100644 index 0000000..6e4df08 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-element-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "2076e726-3577-477a-a300-7fa65cd4df11", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "753e813a-ba9e-4a1d-ab34-b2f6dc6eec0c", + "model-version" : "1.0", + "model-name" : "model-element" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-ver-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-ver-1.0.json new file mode 100644 index 0000000..98511b0 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/model-ver-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "b5cd462f-e426-4146-b1fe-5475ae272c3d", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "93f2f8bc-cb12-4a01-96c8-3d2649e4ab8f", + "model-name" : "model-ver", + "model-version" : "1.0" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/multicast-configuration-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/multicast-configuration-1.0.json new file mode 100644 index 0000000..c76e423 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/multicast-configuration-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "ea78c9e3-514d-4a0a-9162-13837fa54c35", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "666a06ee-4b57-46df-bacf-908da8f10c3f", + "model-version" : "1.0", + "model-name" : "multicast-configuration" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-1.0.json new file mode 100644 index 0000000..7aef873 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "80b712fd-0ad3-4180-a99c-8c995cf1cc32", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "5c3b7c33-afa3-4be5-8da7-1a5ac6f99896", + "model-version" : "1.0", + "model-name" : "named-query" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-element-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-element-1.0.json new file mode 100644 index 0000000..6f6d11a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/named-query-element-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "3c504d40-b847-424c-9d25-4fb7e0a3e994", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "204c641a-3494-48c8-979a-86856f5fd32a", + "model-version" : "1.0", + "model-name" : "named-query-element" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-policy-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-policy-1.0.json new file mode 100644 index 0000000..a28b19e --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-policy-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "6aa05779-94d7-4d8b-9bee-59ef2ab0c246", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "a0ccd9dc-7062-4940-9bcc-e91dd28af510", + "model-version" : "1.0", + "model-name" : "network-policy" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-profile-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-profile-1.0.json new file mode 100644 index 0000000..30d6d9d --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/network-profile-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "2734b44a-b8a2-40f6-957d-6256589e5d00", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "01f45471-4240-498c-a9e1-235dc0b8b4a6", + "model-version" : "1.0", + "model-name" : "network-profile" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/newvce-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/newvce-1.0.json new file mode 100644 index 0000000..b2285d4 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/newvce-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "4b05ec9c-c55d-4987-83ff-e08d6ddb694f", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "7c79e11f-a408-4593-aa86-ba948a1236af", + "model-version" : "1.0", + "model-name" : "newvce" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/oam-network-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/oam-network-1.0.json new file mode 100644 index 0000000..7a3cd18 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/oam-network-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "2851cf01-9c40-4064-87d4-6184a6fcff35", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f4fb34f3-fd6e-4a8f-a3fb-4ab61a343b79", + "model-version" : "1.0", + "model-name" : "oam-network" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json new file mode 100644 index 0000000..3d02918 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/p-interface-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "94043c37-4e73-439c-a790-0fdd697924cd", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "d2cdb2d0-fc1f-4a57-a89e-591b1c4e3754", + "model-version" : "1.0", + "model-name" : "p-interface" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json new file mode 100644 index 0000000..904a4cc --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/physical-link-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "c822d81f-822f-4304-9623-1025b53da568", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "9c523936-95b4-4d7f-9f53-6bdfe0cf2c05", + "model-version" : "1.0", + "model-name" : "physical-link" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json new file mode 100644 index 0000000..9260b17 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pnf-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "862b25a1-262a-4961-bdaa-cdc55d69785a", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "e9f1fa7d-c839-418a-9601-03dc0d2ad687", + "model-version" : "1.0", + "model-name" : "pnf" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/port-group-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/port-group-1.0.json new file mode 100644 index 0000000..8aac84d --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/port-group-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "8ce940fb-55d7-4230-9e7f-a56cc2741f77", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "03e8bb6b-b48a-46ae-b5d4-e5af577e6844", + "model-version" : "1.0", + "model-name" : "port-group" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/property-constraint-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/property-constraint-1.0.json new file mode 100644 index 0000000..4db5389 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/property-constraint-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "f4a863c3-6886-470a-a6ae-05723837ea45", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "81706bbd-981e-4362-ae20-995cbcb2d995", + "model-version" : "1.0", + "model-name" : "property-constraint" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json new file mode 100644 index 0000000..a22b859 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/pserver-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "6d932c8f-463b-4e76-83fb-87acfbaa2e2d", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "72f0d495-bc27-4653-9e1a-eef76bd34bc9", + "model-version" : "1.0", + "model-name" : "pserver" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/related-lookup-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/related-lookup-1.0.json new file mode 100644 index 0000000..e67fa07 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/related-lookup-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "468f6f5b-2996-41bb-b2a3-7cf9613ebb9b", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "0988bab5-bf4f-4938-a419-ab249867d12a", + "model-version" : "1.0", + "model-name" : "related-lookup" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/reserved-prop-names-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/reserved-prop-names-1.0.json new file mode 100644 index 0000000..1bfc7d3 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/reserved-prop-names-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "0c3e0ba3-618c-498d-9127-c8d42b00170f", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "ac49d26d-9163-430e-934a-13b738a04f5c", + "model-version" : "1.0", + "model-name" : "reserved-prop-names" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/result-data-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/result-data-1.0.json new file mode 100644 index 0000000..059dfb0 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/result-data-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "ff656f23-6185-406f-9006-4b26834f3e1c", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "4e9b50aa-5227-4f6f-b489-62e6bbc03c79", + "model-version" : "1.0", + "model-name" : "result-data" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/route-table-reference-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/route-table-reference-1.0.json new file mode 100644 index 0000000..f7910a9 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/route-table-reference-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "a8614b63-2636-4c4f-98df-fd448c4241db", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "fed7e326-03a7-45ff-a3f2-471470d268c4", + "model-version" : "1.0", + "model-name" : "route-table-reference" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/routing-instance-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/routing-instance-1.0.json new file mode 100644 index 0000000..caec0d6 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/routing-instance-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "1c2ded4f-8b01-4193-829c-966847dfec3e", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "3ccbcbc7-d19e-44d5-a52f-7e18aa8d69fa", + "model-version" : "1.0", + "model-name" : "routing-instance" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/secondary-filter-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/secondary-filter-1.0.json new file mode 100644 index 0000000..cef0a94 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/secondary-filter-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "738ff299-6290-4c00-8998-bd0e96a07b93", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "1380619d-dd1a-4cec-b755-c6407833e065", + "model-version" : "1.0", + "model-name" : "secondary-filter" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json new file mode 100644 index 0000000..4335e10 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/segmentation-assignment-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "6e814aee-46e1-4583-a9d4-0049bfd2b59b", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "c5171ae0-44fb-4c04-b482-d56702241a44", + "model-version" : "1.0", + "model-name" : "segmentation-assignment" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-1.0.json new file mode 100644 index 0000000..ab3295a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "07a3a60b-1b6c-4367-8173-8014386f89e3", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "ecce2c42-3957-4ae0-9442-54bc6afe27b6", + "model-version" : "1.0", + "model-name" : "service" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-capability-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-capability-1.0.json new file mode 100644 index 0000000..038a993 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-capability-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "b1a7cc05-d19d-443b-a5d1-733e325c4232", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f9cfec1b-18da-4bba-bd83-4b26cca115cd", + "model-version" : "1.0", + "model-name" : "service-capability" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json new file mode 100644 index 0000000..b5ef861 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-instance-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "82194af1-3c2c-485a-8f44-420e22a9eaa4", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "46b92144-923a-4d20-b85a-3cbd847668a9", + "model-version" : "1.0", + "model-name" : "service-instance" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json new file mode 100644 index 0000000..2af765f --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/service-subscription-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "2e1a602a-acd8-4f78-94ff-618b802a303b", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "5e68299a-79f2-4bfb-8fbc-2bae877a2459", + "model-version" : "1.0", + "model-name" : "service-subscription" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-1.0.json new file mode 100644 index 0000000..eef13ea --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "db63f3e6-f8d1-484e-8d5e-191600b7914b", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "7106bc02-6552-4fc3-8a56-4f3df9034531", + "model-version" : "1.0", + "model-name" : "site-pair" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-set-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-set-1.0.json new file mode 100644 index 0000000..3c77903 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/site-pair-set-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "5d4dae3e-b402-4bfd-909e-ece12ff75d26", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "a5c6c1bc-dc38-468e-9459-bb08f87247df", + "model-version" : "1.0", + "model-name" : "site-pair-set" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json new file mode 100644 index 0000000..24ea90b --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/snapshot-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "24de00ef-aead-4b52-995b-0adf8d4bd90d", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "962a7c8b-687f-4d32-a775-fe098e214bcd", + "model-version" : "1.0", + "model-name" : "snapshot" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/sriov-vf-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/sriov-vf-1.0.json new file mode 100644 index 0000000..a5c077a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/sriov-vf-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "04b2935f-33c4-40a9-8af0-8b52690042dc", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "1e8b331f-3d4a-4160-b7aa-f4d5a8916625", + "model-version" : "1.0", + "model-name" : "sriov-vf" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/start-node-filter-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/start-node-filter-1.0.json new file mode 100644 index 0000000..743d89e --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/start-node-filter-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "083093a3-e407-447a-ba5d-7583e4d23e1d", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "aad96fd3-e75f-42fc-9777-3450c36f1168", + "model-version" : "1.0", + "model-name" : "start-node-filter" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json new file mode 100644 index 0000000..f6b2e55 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/subnet-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "1b2c9ba7-e449-4831-ba15-3073672f5ef2", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f902a6bc-6be4-4fe5-8458-a6ec0056b374", + "model-version" : "1.0", + "model-name" : "subnet" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tagged-inventory-item-list-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tagged-inventory-item-list-1.0.json new file mode 100644 index 0000000..5146b99 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tagged-inventory-item-list-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "e78a7eaa-f65d-4919-9c2b-5b258c8c4d7e", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "c246f6e2-e3a1-4697-94c0-5672a7fbbf04", + "model-version" : "1.0", + "model-name" : "tagged-inventory-item-list" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json new file mode 100644 index 0000000..e105783 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tenant-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "97c26c99-6870-44c1-8a07-1d900d3f4ce6", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "abcc54bc-bb74-49dc-9043-7f7171707545", + "model-version" : "1.0", + "model-name" : "tenant" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tunnel-xconnect-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tunnel-xconnect-1.0.json new file mode 100644 index 0000000..5c6d5c6 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/tunnel-xconnect-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "50b9e2fa-005c-4bbe-b651-3251dece4cd8", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "e7cb4ca8-e1a5-4487-a716-4ae0bcd8aef5", + "model-version" : "1.0", + "model-name" : "tunnel-xconnect" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/update-node-key-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/update-node-key-1.0.json new file mode 100644 index 0000000..25c5efd --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/update-node-key-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "fe81c801-f65d-408a-b2b7-a729a18f8154", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "6004cfa6-eb6d-4062-971f-b1fde6b74aa0", + "model-version" : "1.0", + "model-name" : "update-node-key" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vce-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vce-1.0.json new file mode 100644 index 0000000..45f01d4 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vce-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "bab6dceb-e7e6-4301-a5e0-a7399b48d792", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "b6cf54b5-ec45-43e1-be64-97b4e1513333", + "model-version" : "1.0", + "model-name" : "vce" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json new file mode 100644 index 0000000..383d187 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vf-module-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "ef86f9c5-2165-44f3-8fc3-96018b609ea5", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "c00563ae-812b-4e62-8330-7c4d0f47088a", + "model-version" : "1.0", + "model-name" : "vf-module" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vig-server-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vig-server-1.0.json new file mode 100644 index 0000000..6fd8d24 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vig-server-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "bed7c3b7-35d0-4cd9-abde-41b20e68b28e", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "8e8c22f1-fbdf-48ea-844c-8bdeb44e7b16", + "model-version" : "1.0", + "model-name" : "vig-server" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/virtual-data-center-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/virtual-data-center-1.0.json new file mode 100644 index 0000000..a36361e --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/virtual-data-center-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "5150abcf-0c5f-4593-9afe-a19c48fc4824", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "6dd43ced-d789-47af-a759-d3abc14e3ac1", + "model-version" : "1.0", + "model-name" : "virtual-data-center" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json new file mode 100644 index 0000000..64608f8 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vlan-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "257d88a5-a269-4c35-944f-aca04fbdb791", + "model-version" : "1.0", + "model-name" : "vlan" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnf-image-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnf-image-1.0.json new file mode 100644 index 0000000..1756e38 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnf-image-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "f9a628ff-7aa0-40e2-a93d-02d91c950982", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "c4d3e747-ba4a-4b17-9896-94c6f18c19d3", + "model-version" : "1.0", + "model-name" : "vnf-image" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json new file mode 100644 index 0000000..8c663a7 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vnfc-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "96129eb9-f0de-4e05-8af2-73146473f766", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "5761e0a7-c6df-4d8a-9ebd-b8f445054dec", + "model-version" : "1.0", + "model-name" : "vnfc" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json new file mode 100644 index 0000000..dd5d239 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "ddd739b4-2b25-46c4-affc-41a32af5cc42", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "0fbe2e8f-4d91-4415-a772-88387049b38d", + "model-version" : "1.0", + "model-name" : "volume" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json new file mode 100644 index 0000000..4ccde3a --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/volume-group-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "fcec1b02-b2d0-4834-aef8-d71be04717dd", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "99d44c90-1f61-4418-b9a6-56586bf38c79", + "model-version" : "1.0", + "model-name" : "volume-group" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpe-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpe-1.0.json new file mode 100644 index 0000000..ed5017e --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpe-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "053ec3a7-5b72-492d-b54d-123805a9b967", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "203817d3-829c-42d4-942d-2a935478e993", + "model-version" : "1.0", + "model-name" : "vpe" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpls-pe-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpls-pe-1.0.json new file mode 100644 index 0000000..0d072bc --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpls-pe-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "457ba89b-334c-4fbd-acc4-160ac0e0cdc0", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "b1566228-6785-4ce1-aea2-053736f80341", + "model-version" : "1.0", + "model-name" : "vpls-pe" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpn-binding-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpn-binding-1.0.json new file mode 100644 index 0000000..e0439b6 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vpn-binding-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "9e23b675-db2b-488b-b459-57aa9857baa0", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "21a146e5-9901-448c-9197-723076770119", + "model-version" : "1.0", + "model-name" : "vpn-binding" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json new file mode 100644 index 0000000..a069209 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/vserver-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "ff69d4e0-a8e8-4108-bdb0-dd63217e63c7", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "8ecb2c5d-7176-4317-a255-26274edfdd53", + "model-version" : "1.0", + "model-name" : "vserver" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/zone-1.0.json b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/zone-1.0.json new file mode 100644 index 0000000..8427ded --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/scriptdata/widget-model-json/zone-1.0.json @@ -0,0 +1,11 @@ +{ + "model-invariant-id" : "16f7cb93-e807-4065-816b-9cdf391d4992", + "model-type" : "widget", + "model-vers" : { + "model-ver" : [ { + "model-version-id" : "f7f21a66-4714-431c-af17-52d64e21de95", + "model-name" : "zone", + "model-version" : "1.0" + } ] + } +} diff --git a/aai-traversal/bundleconfig-local/etc/service-file-monitor.properties b/aai-traversal/bundleconfig-local/etc/service-file-monitor.properties new file mode 100644 index 0000000..4d9bee9 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/service-file-monitor.properties @@ -0,0 +1,5 @@ +#This properties file is used for defining any file paths that you would like to have monitored. + +#user config file paths go here as (key-value) pairs. File extension will have to be either .properties or .json in order for it to be monitored. +#file1=/opt/app/yourService/file.properties + diff --git a/aai-traversal/bundleconfig-local/etc/sysprops/sys-props.properties b/aai-traversal/bundleconfig-local/etc/sysprops/sys-props.properties new file mode 100644 index 0000000..13c97a9 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/sysprops/sys-props.properties @@ -0,0 +1,140 @@ +#This file is used for defining AJSC system properties for different configuration schemes and is necessary for the AJSC to run properly. +#The sys-props.properties file is used for running locally. The template.sys-props.properties file will be used when deployed +#to a SOA/CSI Cloud node. + +#AJSC System Properties. The following properties are required for ALL AJSC services. If you are adding System Properties for your +#particular service, please add them AFTER all AJSC related System Properties. + +#For Cadi Authorization, use value="authentication-scheme-1 +CadiAuthN=authentication-scheme-1 + +#For Basic Authorization, use value="authentication-scheme-1 +authN=authentication-scheme-2 + +#Persistence used for AJSC meta-data storage. For most environments, "file" should be used. +ajscPersistence=file + +# If using hawtio for local development, these properties will allow for faster server startup and usage for local development +hawtio.authenticationEnabled=false +hawtio.config.pullOnStartup=false + +#Removes the extraneous restlet console output +org.restlet.engine.loggerFacadeClass=org.restlet.ext.slf4j.Slf4jLoggerFacade + +#server.host property to be enabled for local DME2 related testing +#server.host= + +#Enable/disable SSL (values=true/false). This property also determines which protocol to use (https if true, http otherwise), to register services into GRM through DME2. +enableSSL=false + +#Enable/disable csi logging (values=true/false). This can be disabled during local development +csiEnable=false + +#Enable/disable EJB Container +ENABLE_EJB=false + +#Enable/disable OSGI +isOSGIEnable=false + +#Configure JMS Queue (WMQ/TIBCO) +JMS_BROKER=WMQ + +#JMS properties needed for CSI Logging +JMS_TIBCO_PROVIDER_URL=ONAPserverTBD +JMS_LOGGER_USER_NAME=spm2 +JMS_LOGGER_PASSWORD=its4test +JMS_LOGGER_AUDIT_QUEUE_BINDING=pub.m2e.audit.logger.queue +JMS_LOGGER_PERF_QUEUE_BINDING=log.csi.performance02 + +#WMQ connectivity +JMS_WMQ_PROVIDER_URL=aftdsc://AFTUAT/34.07/-84.28 +JMS_WMQ_CONNECTION_FACTORY_NAME=aftdsc://AFTUAT/?service=CSILOG,version=1.0,bindingType=fusionBus,envContext=Q,Q25A=YES +JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME=com.att.aft.jms.FusionCtxFactory +JMS_WMQ_AUDIT_DESTINATION_NAME=queue:///CSILOGQL.M2E.DASHBOARD01.NOT.Q25A +JMS_WMQ_PERF_DESTINATION_NAME=queue:///CSILOGQL.M2E.PERFORMANCE01.NOT.Q25A + + +#CSI related variables for CSM framework +csm.hostname=d1a-m2e-q112m2e1.edc.cingular.net + +#Enable/disable endpoint level logging (values=true/false). This can be disabled during local development +endpointLogging=false + +#SOA_CLOUD_ENV is used to register your service with dme2 and can be turned off for local development (values=true/false). +SOA_CLOUD_ENV=false + +#CONTINUE_ON_LISTENER_EXCEPTION will exit the application if there is a DME2 exception at the time of registration. +CONTINUE_ON_LISTENER_EXCEPTION=false + +#Jetty Container ThreadCount Configuration Variables +AJSC_JETTY_ThreadCount_MIN=10 +AJSC_JETTY_ThreadCount_MAX=500 +AJSC_JETTY_IDLETIME_MAX=60000 +AJSC_JETTY_BLOCKING_QUEUE_SIZE=100 + +#Camel Context level default threadPool Profile configuration +CAMEL_POOL_SIZE=10 +CAMEL_MAX_POOL_SIZE=20 +CAMEL_KEEP_ALIVE_TIME=60 +CAMEL_MAX_QUEUE_SIZE=1000 + +#File Monitor configurations +ssf_filemonitor_polling_interval=5 +ssf_filemonitor_threadpool_size=10 + +#GRM/DME2 System Properties +AFT_DME2_CONN_IDLE_TIMEOUTMS=5000 +AJSC_ENV=SOACLOUD + +SOACLOUD_NAMESPACE=com.att.ajsc +SOACLOUD_ENV_CONTEXT=DEV +SOACLOUD_PROTOCOL=http +SOACLOUD_ROUTE_OFFER=DEFAULT + +sslport=8446 +server.port=8083 + +AFT_LATITUDE=23.4 +AFT_LONGITUDE=33.6 +AFT_ENVIRONMENT=AFTUAT + +#Restlet Component Default Properties +RESTLET_COMPONENT_CONTROLLER_DAEMON=true +RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS=100 +RESTLET_COMPONENT_INBOUND_BUFFER_SIZE=8192 +RESTLET_COMPONENT_MIN_THREADS=1 +RESTLET_COMPONENT_MAX_THREADS=10 +RESTLET_COMPONENT_LOW_THREADS=8 +RESTLET_COMPONENT_MAX_QUEUED=0 +RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST=-1 +RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS=-1 +RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE=8192 +RESTLET_COMPONENT_PERSISTING_CONNECTIONS=true +RESTLET_COMPONENT_PIPELINING_CONNECTIONS=false +RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS=60000 +RESTLET_COMPONENT_USE_FORWARDED_HEADER=false +RESTLET_COMPONENT_REUSE_ADDRESS=true + +#Externalized jar and properties file location. In CSI environments, there are a few libs that have been externalized to aid +#in CSTEM maintenance of the versions of these libs. The most important to the AJSC is the DME2 lib. Not only is this lib necessary +#for proper registration of your AJSC service on a node, but it is also necessary for running locally as well. Another framework +#used in CSI envs is the CSM framework. These 2 framework libs are shown as "provided" dependencies within the pom.xml. These +#dependencies will be copied into the target/commonLibs folder with the normal "mvn clean package" goal of the AJSC. They will +#then be added to the classpath via AJSC_EXTERNAL_LIB_FOLDERS system property. Any files (mainly property files) that need +#to be on the classpath should be added to the AJSC_EXTERNAL_PROPERTIES_FOLDERS system property. The default scenario when +#testing your AJSC service locally will utilize the target/commonLibs directory for DME2 and CSM related artifacts and 2 +#default csm properties files will be used for local testing with anything CSM knorelated. +#NOTE: we are using maven-replacer-plugin to replace "(doubleUnderscore)basedir(doubleUnderscore)" with ${basedir} within the +#target directory for running locally. Multiple folder locations can be separated by the pipe ("|") character. +#Please, NOTE: for running locally, we are setting this system property in the antBuild/build.xml "runLocal" target and in the +#"runAjsc" profile within the pom.xml. This is to most effectively use maven variables (${basedir}, most specifically. Therefore, +#when running locally, the following 2 properties should be set within the profile(s) themselves. +#Example: target/commonLibs|target/otherLibs +#AJSC_EXTERNAL_LIB_FOLDERS=__basedir__/target/commonLibs +#AJSC_EXTERNAL_PROPERTIES_FOLDERS=__basedir__/ajsc-shared-config/etc +#End of AJSC System Properties + +#Service System Properties. Please, place any Service related System Properties below. +KEY_STORE_PASSWORD=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0 +KEY_MANAGER_PASSWORD=OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0 +AAI_CORE_VERSION=1.1.0-SNAPSHOT diff --git a/aai-traversal/bundleconfig-local/etc/sysprops/template.sys-props.properties b/aai-traversal/bundleconfig-local/etc/sysprops/template.sys-props.properties new file mode 100644 index 0000000..778ac62 --- /dev/null +++ b/aai-traversal/bundleconfig-local/etc/sysprops/template.sys-props.properties @@ -0,0 +1,115 @@ +#This file is used for defining AJSC system properties for different configuration schemes and is necessary for the AJSC to run properly. +#The sys-props.properties file is used for running locally. + +#For Cadi Authorization, use value="authentication-scheme-1" +CadiAuthN=__AJSC_CADI_AUTHN__ + +#For Basic Authorization, use value="authentication-scheme-1" +authN=__AJSC_AUTH_SCHEME__ + +#Persistence used for AJSC meta-data storage. For most environments, "file" should be used. +ajscPersistence=__AJSC_PERSISTENCE__ + +#Configure externalized logback location +logback.configurationFile=__LOGBACK_CONFIG_FILE__ + +# If using hawtio for local development, these properties will allow for faster server startup and usage for local development. +# You may wish to deploy hawtio.war to dev/test environments to help debugging as well, but should not be used in PROD env. +hawtio.authenticationEnabled=__HAWTIO_AUTHENTICATION_ENABLED__ +hawtio.config.pullOnStartup=__HAWTIO_CONFIG_PULLONSTARTUP__ + +#Removes the extraneous restlet console output +org.restlet.engine.loggerFacadeClass=org.restlet.ext.slf4j.Slf4jLoggerFacade + +#Enable/disable SSL (values=true/false). +enableSSL=__AJSC_ENABLE_SSL__ + +#Enable/disable csi logging (values=true/false). +csiEnable=__CSI_ENABLE__ + +#Enable/disable EJB Container +ENABLE_EJB=__ENABLE_EJB__ + +#Enable/disable OSGI +isOSGIEnable=__OSGI_ENABLE__ + +#Configure JMS Queue (WMQ/TIBCO) +JMS_BROKER=WMQ + +#JMS properties needed for CSI Logging +JMS_TIBCO_PROVIDER_URL=ONAPserverTBD +JMS_LOGGER_USER_NAME=spm2 +JMS_LOGGER_PASSWORD= +JMS_LOGGER_AUDIT_QUEUE_BINDING=pub.m2e.audit.logger.queue +JMS_LOGGER_PERF_QUEUE_BINDING=log.csi.performance02 + +#WMQ connectivity +JMS_WMQ_PROVIDER_URL=__JMS_WMQ_PROVIDER_URL__ +JMS_WMQ_CONNECTION_FACTORY_NAME=__JMS_WMQ_CONNECTION_FACTORY_NAME__ +JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME=__JMS_WMQ_INITIAL_CONNECTION_FACTORY_NAME__ +JMS_WMQ_AUDIT_DESTINATION_NAME=__JMS_WMQ_AUDIT_DESTINATION_NAME__ +JMS_WMQ_PERF_DESTINATION_NAME=__JMS_WMQ_PERF_DESTINATION_NAME__ + +#CSI related variables for CSM framework +csm.hostname=d1a-m2e-q112m2e1.edc.cingular.net + +#Enable/disable endpoint level logging (values=true/false). +endpointLogging=__END_POINT_LEVEL_LOGGING__ + +#SOA_CLOUD_ENV is used to register your service with dme2 (values=true/false). +SOA_CLOUD_ENV=__SOA_CLOUD_ENV__ + +#Jetty Container ThreadCount Configuration Variables +AJSC_JETTY_ThreadCount_MAX=__AJSC_JETTY_ThreadCount_MAX__ +AJSC_JETTY_ThreadCount_MIN=__AJSC_JETTY_ThreadCount_MIN__ +AJSC_JETTY_IDLETIME_MAX=__AJSC_JETTY_IDLETIME_MAX__ +AJSC_SERVICE_NAMESPACE=ActiveAndAvailableInventory-Traversal +AJSC_SERVICE_VERSION=__AJSC_SERVICE_VERSION__ +AJSC_JETTY_BLOCKING_QUEUE_SIZE=100 + +#Camel Context level default threadPool Profile configuration +CAMEL_POOL_SIZE=__CAMEL_POOL_SIZE__ +CAMEL_MAX_POOL_SIZE=__CAMEL_MAX_POOL_SIZE__ +CAMEL_KEEP_ALIVE_TIME=__CAMEL_KEEP_ALIVE_TIME__ +CAMEL_MAX_QUEUE_SIZE=__CAMEL_MAX_QUEUE_SIZE__ + +#File Monitor configurations +ssf_filemonitor_polling_interval=__AJSC_SSF_FILE_MONITOR_POLLING_INTERVAL__ +ssf_filemonitor_threadpool_size=__AJSC_SSF_FILE_MONITOR_THREAD_POOL_SIZE__ + +#GRM/DME2 System Properties below +AFT_DME2_CONN_IDLE_TIMEOUTMS=__AFT_DME2_CONN_IDLE_TIMEOUTMS__ +AJSC_ENV=__AJSC_ENV__ +SOACLOUD_NAMESPACE=__SOA_CLOUD_NAMESPACE__ +SOACLOUD_ENV_CONTEXT=__SCLD_ENV__ +SOACLOUD_PROTOCOL=__SOACLOUD_PROTOCOL__ +SOACLOUD_ROUTE_OFFER=__AAIENV__ +sslport=8446 +server.port=8083 +AFT_LATITUDE=__LATITUDE__ +AFT_LONGITUDE=__LONGITUDE__ +AFT_ENVIRONMENT=__AFT_ENVIRONMENT__ + +#Restlet Component Properties +RESTLET_COMPONENT_CONTROLLER_DAEMON=__RESTLET_COMPONENT_CONTROLLER_DAEMON__ +RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS=__RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS__ +RESTLET_COMPONENT_INBOUND_BUFFER_SIZE=__RESTLET_COMPONENT_INBOUND_BUFFER_SIZE__ +RESTLET_COMPONENT_MIN_THREADS=__RESTLET_COMPONENT_MIN_THREADS__ +RESTLET_COMPONENT_MAX_THREADS=__RESTLET_COMPONENT_MAX_THREADS__ +RESTLET_COMPONENT_LOW_THREADS=__RESTLET_COMPONENT_LOW_THREADS__ +RESTLET_COMPONENT_MAX_QUEUED=__RESTLET_COMPONENT_MAX_QUEUED__ +RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST=__RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST__ +RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS=__RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS__ +RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE=__RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE__ +RESTLET_COMPONENT_PERSISTING_CONNECTIONS=__RESTLET_COMPONENT_PERSISTING_CONNECTIONS__ +RESTLET_COMPONENT_PIPELINING_CONNECTIONS=__RESTLET_COMPONENT_PIPELINING_CONNECTIONS__ +RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS=__RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS__ +RESTLET_COMPONENT_USE_FORWARDED_HEADER=__RESTLET_COMPONENT_USE_FORWARDED_HEADER__ +RESTLET_COMPONENT_REUSE_ADDRESS=__RESTLET_COMPONENT_REUSE_ADDRESS__ + +AJSC_EXTERNAL_LIB_FOLDERS=__CSM_LIB__|__DME2_LIB__|__AJSC_EXTERNAL_LIB_FOLDERS__ +AJSC_EXTERNAL_PROPERTIES_FOLDERS=__AJSC_SHARED_CONFIG__|__AJSC_EXTERNAL_PROPERTIES_FOLDERS__ + +KEY_STORE_PASSWORD=__KEY_STORE_PASSWORD__ +KEY_MANAGER_PASSWORD=__KEY_MANAGER_PASSWORD__ +AAI_CORE_VERSION=1.1.0-SNAPSHOT diff --git a/aai-traversal/bundleconfig-local/symlinks.txt b/aai-traversal/bundleconfig-local/symlinks.txt new file mode 100644 index 0000000..70f2c0d --- /dev/null +++ b/aai-traversal/bundleconfig-local/symlinks.txt @@ -0,0 +1,6 @@ +#This file provides the definitions of sym-links to CSTEM that will be used by your project once installed on a CSI node. + +link_jre=ajsc-shared-config +link_csi-csm=ajsc-shared-config +link_csi-dme=ajsc-shared-config +link_introscope=ajsc-shared-config diff --git a/aai-traversal/pom.xml b/aai-traversal/pom.xml new file mode 100644 index 0000000..1423572 --- /dev/null +++ b/aai-traversal/pom.xml @@ -0,0 +1,695 @@ + + + 4.0.0 + + org.openecomp.aai + traversal + 1.1.0-SNAPSHOT + + aai-traversal + aai-traversal + http://maven.apache.org + + UTF-8 + ${basedir}/target/swm/package/nix/dist_files/ + yyyyMMdd'T'HHmmss + 1.0.0 + 1.1.0-SNAPSHOT + 1.1.0-SNAPSHOT + 1.0.2 + java + jacoco + ${project.build.directory}/surefire-reports + ${project.build.directory}/coverage-reports/jacoco.exec + false + ${project.version} + + + + + org.openecomp.aai + aai-schema + ${aai-schema.version} + + + org.openecomp.aai + aai-core + ${aai-core.version} + + + + com.rabbitmq + amqp-client + 3.6.1 + + + log4j + apache-log4j-extras + 1.2.17 + + + log4j + log4j + + + + + + commons-beanutils + commons-beanutils + 1.9.2 + + + + org.apache.commons + commons-compress + 1.10 + + + + commons-configuration + commons-configuration + 1.9 + + + commons-lang + commons-lang + + + + + + com.googlecode.java-diff-utils + diffutils + 1.3.0 + + + + org.codehaus.jackson + jackson-core-asl + 1.9.13 + + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + + + + org.apache.httpcomponents + httpmime + 4.5.2 + + + + + com.att.ajsc + ajsc-runner + ${ajscRuntimeVersion} + + + com.att.ajsc + ajsc-core + ${ajscRuntimeVersion} + provided + + + + + dom4j + dom4j + 1.6.1 + + + + commons-lang + commons-lang + 2.6 + + + + + com.att.eelf + eelf-core + 1.0.0 + + + + ch.qos.logback + logback-core + 1.1.7 + + + + ch.qos.logback + logback-classic + 1.1.7 + + + + ch.qos.logback + logback-access + 1.1.7 + + + + org.hamcrest + hamcrest-junit + 2.0.0.0 + + + org.codehaus.janino + janino + 2.7.8 + + + commons-collections + commons-collections + + + + jdk.tools + jdk.tools + 1.8.0_101 + system + ${JAVA_HOME}/lib/tools.jar + + + + junit + junit + test + + + com.google.guava + guava + 16.0 + + + com.thinkaurelius.titan + titan-core + 1.0.0 + + + org.slf4j + slf4j-log4j12 + + + + + com.thinkaurelius.titan + titan-cassandra + 1.0.0 + + + org.slf4j + slf4j-log4j12 + + + + + com.thinkaurelius.titan + titan-hbase + 1.0.0 + + + org.slf4j + slf4j-log4j12 + + + + + + org.apache.tinkerpop + gremlin-driver + 3.0.1-incubating + + + org.apache.hbase + hbase-client + ${hbase.version} + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + + + + + org.apache.hbase + hbase-protocol + ${hbase.version} + + + log4j + log4j + + + + + org.apache.hbase + hbase-common + ${hbase.version} + + + log4j + log4j + + + + + com.sun.jersey + jersey-json + 1.18 + + + jivesoftware + smack + 3.0.4 + + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + 2.1.4 + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + com.sun.jersey + jersey-client + 1.18 + + + org.springframework + spring-web + + + org.springframework.ws + spring-ws + 1.5.2 + + + + org.springframework + spring-core + 4.2.5.RELEASE + + + org.mockito + mockito-all + 1.10.19 + test + + + org.powermock + powermock-module-junit4 + 1.6.2 + test + + + org.powermock + powermock-api-mockito + 1.6.2 + test + + + com.beust + jcommander + 1.48 + + + org.json + json + 20090211 + + + org.freemarker + freemarker + 2.3.14 + + + javax.xml.bind + jaxb-api + 2.2.11 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + com.sun.xml.bind + jaxb-core + 2.2.11 + + + com.sun.xml.bind + jaxb-xjc + 2.2.11 + + + org.eclipse.persistence + eclipselink + 2.6.2 + + + org.eclipse.persistence + org.eclipse.persistence.moxy + 2.6.2 + compile + + + org.powermock + powermock-module-javaagent + 1.6.2 + test + + + org.powermock + powermock-module-junit4-rule-agent + 1.6.2 + test + + + com.github.fge + json-patch + 1.9 + + + org.javatuples + javatuples + 1.2 + compile + + + com.google.code.gson + gson + 2.7 + + + com.att.nsa + dmaapClient + 0.2.13 + + + org.apache.httpcomponents + httpcore + 4.4 + + + com.bazaarvoice.jolt + jolt-complete + 0.0.24 + + + com.jayway.jsonpath + json-path + 2.0.0 + + + + traversal + + + + org.jsonschema2pojo + jsonschema2pojo-maven-plugin + 0.4.13 + + jsonschema + src/main/resources/json + ${project.build.directory}/generated-sources + jackson2 + true + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.8 + + + copy-agent + process-test-classes + + copy + + + + + org.powermock + powermock-module-javaagent + 1.6.2 + ${project.build.directory}/agents + powermock-javaagent.jar + + + + + + unpack-schema-dependency + initialize + + unpack + + + + + + + org.openecomp.aai + aai-schema + ${aai-schema.version} + bundleconfig-local/etc + oxm/*.xml + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + -javaagent:${project.build.directory}/agents/powermock-javaagent.jar + -noverify + + . + bundleconfig-local + + + + + org.codehaus.groovy.maven + gmaven-plugin + + + validate + + execute + + + + println project.properties['aai.project.version']; + def versionArray; + if ( project.properties['aai.project.version'] != null ) { + versionArray = project.properties['aai.project.version'].split('\\.'); + } + + if ( project.properties['aai.project.version'].endsWith("-SNAPSHOT") ) { + project.properties['project.docker.latesttag.version']=versionArray[0] + '.' + versionArray[1] + "-SNAPSHOT-latest"; + } else { + project.properties['project.docker.latesttag.version']=versionArray[0] + '.' + versionArray[1] + "-STAGING-latest"; + } + + println 'New Tag for docker:' + project.properties['project.docker.latesttag.version']; + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + copy-docker-file + package + + copy-resources + + + ${dockerLocation} + true + + + ${basedir}/src/main/resources/docker + true + + **/* + + + + + + + copy-commonlibs-file + package + + copy-resources + + + ${dockerLocation}/commonLibs + true + + + ${basedir}/target/commonLibs + false + + *.jar + + + + + + + + + io.fabric8 + docker-maven-plugin + 0.16.5 + + true + 1.23 + + + ${docker.push.registry}/openecomp/aai-traversal:%l + + + ${project.docker.latesttag.version} + ${project.version}-STAGING-${maven.build.timestamp} + + try + ${dockerLocation} + ${dockerLocation}/Dockerfile + + + + + + + clean-images + pre-clean + + remove + + + true + openecomp/aai-traversal:%l + + + + generate-images + generate-sources + + build + + + + push-images + deploy + + build + push + + + openecomp/aai-traversal:%l + + + + + + + + + org.codehaus.mojo + sonar-maven-plugin + 3.2 + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + true + + + + jacoco-initialize-unit-tests + + prepare-agent + + + ${project.build.directory}/coverage-reports/jacoco.exec + + + + + + + + + + + passwordGenerator + + initialize + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + initialize + + java + + + org.eclipse.jetty.util.security.Password + + user + aaiDomain2 + + + + + + java + + + + + + + + diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml new file mode 100644 index 0000000..9e3e060 --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/FileMonitorBeans.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy new file mode 100644 index 0000000..4029d25 --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/jaxrsBeans.groovy @@ -0,0 +1,26 @@ +beans{ + xmlns cxf: "http://camel.apache.org/schema/cxf" + xmlns jaxrs: "http://cxf.apache.org/jaxrs" + xmlns util: "http://www.springframework.org/schema/util" + + SearchProvider(org.openecomp.aai.rest.search.SearchProvider) + ModelAndNamedQueryRestProvider(org.openecomp.aai.rest.search.ModelAndNamedQueryRestProvider) + QueryConsumer(org.openecomp.aai.rest.QueryConsumer) + + V3ThroughV7Retired(org.openecomp.aai.rest.retired.V3ThroughV7Consumer) + V7V8NamedQueries(org.openecomp.aai.rest.retired.V7V8NamedQueries) + + EchoResponse(org.openecomp.aai.rest.util.EchoResponse) + + + util.list(id: 'jaxrsServices') { + + ref(bean:'SearchProvider') + ref(bean:'ModelAndNamedQueryRestProvider') + ref(bean:'QueryConsumer') + ref(bean: 'V7V8NamedQueries') + ref(bean:'V3ThroughV7Retired') + + ref(bean:'EchoResponse') + } +} \ No newline at end of file diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml new file mode 100644 index 0000000..f4bc26a --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/conf/serviceBeans.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt new file mode 100644 index 0000000..3707179 --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/docs/README.txt @@ -0,0 +1 @@ +Place any docs here that you want to access within the ajsc upon deployment of your service. diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt new file mode 100644 index 0000000..639e21b --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/lib/README.txt @@ -0,0 +1 @@ +3rd party JAR's needed by your jars (if any) for a ajsc deployment package go here... \ No newline at end of file diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props new file mode 100644 index 0000000..17ebc08 --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/props/module.props @@ -0,0 +1 @@ +EXAMPLE.PROPERTY=EXAMLE_VALUE \ No newline at end of file diff --git a/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route new file mode 100644 index 0000000..6a86246 --- /dev/null +++ b/aai-traversal/src/main/ajsc/ajsc-aai_v1/ajsc-aai/v1/routes/aai.route @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/aai-traversal/src/main/assemble/ajsc_module_assembly.xml b/aai-traversal/src/main/assemble/ajsc_module_assembly.xml new file mode 100644 index 0000000..4ec4e28 --- /dev/null +++ b/aai-traversal/src/main/assemble/ajsc_module_assembly.xml @@ -0,0 +1,66 @@ + + ${version} + false + + zip + + + + ${project.basedir}/target/versioned-ajsc/routes/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/routes/ + + *.route + + + + + + ${project.basedir}/target/versioned-ajsc/docs/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/docs/ + + *.* + + + + + + + ${project.basedir}/target/versioned-ajsc/lib/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/ + + *.jar + + + + + ${project.basedir}/target/versioned-ajsc/extJars/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/extJars/ + + *.jar + + + + + + ${project.basedir}/target/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/ + + *.jar + + + + + ${project.basedir}/target/versioned-ajsc/conf/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/conf/ + + *.* + + + + + + + diff --git a/aai-traversal/src/main/assemble/ajsc_props_assembly.xml b/aai-traversal/src/main/assemble/ajsc_props_assembly.xml new file mode 100644 index 0000000..5b8a6fa --- /dev/null +++ b/aai-traversal/src/main/assemble/ajsc_props_assembly.xml @@ -0,0 +1,23 @@ + + ${version}_properties + false + + zip + + + + ${project.basedir}/target/versioned-ajsc/props + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/props/ + + *.props + + + + + + + + diff --git a/aai-traversal/src/main/assemble/ajsc_runtime_assembly.xml b/aai-traversal/src/main/assemble/ajsc_runtime_assembly.xml new file mode 100644 index 0000000..e37d366 --- /dev/null +++ b/aai-traversal/src/main/assemble/ajsc_runtime_assembly.xml @@ -0,0 +1,44 @@ + + runtimeEnvironment + false + + zip + + + + ${project.basedir}/target/versioned-runtime/context/ + runtime/context/ + + *.context + + + + ${project.basedir}/target/versioned-runtime/serviceProperties/ + runtime/serviceProperties/ + + *.props + + + ${project.basedir}/target/versioned-runtime/shiroRole + runtime/shiroRole/ + + *.json + + + ${project.basedir}/target/versioned-runtime/shiroUser + runtime/shiroUser/ + + *.json + + + ${project.basedir}/target/versioned-runtime/shiroUserRole + runtime/shiroUserRole + + *.json + + + + \ No newline at end of file diff --git a/aai-traversal/src/main/config/ajsc-jetty.xml b/aai-traversal/src/main/config/ajsc-jetty.xml new file mode 100644 index 0000000..d7e60ed --- /dev/null +++ b/aai-traversal/src/main/config/ajsc-jetty.xml @@ -0,0 +1,155 @@ + + + + + + + true + + + /etc/runner-web.xml + /etc/ajsc-override-web.xml + true + + + false + + + + /extJars/aai-core-.jar, + /extJars/traversal.jar, + /extJars/logback-core-1.1.7.jar, + /extJars/logback-access-1.1.7.jar, + /extJars/eelf-core-1.0.0.jar, + /extJars/slf4j-api-1.7.21.jar + + + + + + + + + + + + + + + + + + + + + + + + /bundleconfig/etc/localhost-access-logback.xml + + + + + + + + + + + + + + + + + + + /extApps + 10 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http/1.1 + + + file:/bundleconfig/etc/auth/aai_keystore + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + 30000 + + + + + + + + + false + + + + + Test Realm + /etc/realm.properties + 5 + + + + + diff --git a/aai-traversal/src/main/config/ajsc-jolokia-override-web.xml b/aai-traversal/src/main/config/ajsc-jolokia-override-web.xml new file mode 100644 index 0000000..b242129 --- /dev/null +++ b/aai-traversal/src/main/config/ajsc-jolokia-override-web.xml @@ -0,0 +1,46 @@ + + + + + InterceptorFilter + /services/* + + + InterceptorFilter + /rest/* + + + + springSecurityFilterChain + /* + + + + ManagementServlet + /mgmt + + + + RestletServlet + /rest/* + + + + CamelServlet + /services/* + + + + jolokia-agent + org.jolokia.http.AgentServlet + 2 + + + + jolokia-agent + /jolokia/* + + + \ No newline at end of file diff --git a/aai-traversal/src/main/config/ajsc-override-web.xml b/aai-traversal/src/main/config/ajsc-override-web.xml new file mode 100644 index 0000000..61e2836 --- /dev/null +++ b/aai-traversal/src/main/config/ajsc-override-web.xml @@ -0,0 +1,41 @@ + + + + + WriteableRequestFilter + /* + + + InterceptorFilter + /* + + + InterceptorFilter + /rest/* + + + + springSecurityFilterChain + /* + + + + ManagementServlet + /mgmt + + + + RestletServlet + /rest/* + + + + CamelServlet + /* + + + + + \ No newline at end of file diff --git a/aai-traversal/src/main/config/ajsc-request.xml b/aai-traversal/src/main/config/ajsc-request.xml new file mode 100644 index 0000000..5d09b7a --- /dev/null +++ b/aai-traversal/src/main/config/ajsc-request.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/aai-traversal/src/main/config/caet.properties b/aai-traversal/src/main/config/caet.properties new file mode 100644 index 0000000..e69de29 diff --git a/aai-traversal/src/main/config/hazelcast-client.properties b/aai-traversal/src/main/config/hazelcast-client.properties new file mode 100644 index 0000000..2624d3f --- /dev/null +++ b/aai-traversal/src/main/config/hazelcast-client.properties @@ -0,0 +1,25 @@ +# +# Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +hazelcast.client.group.name = ajsc +hazelcast.client.group.pass = ajscpass +hazelcast.client.connection.timeout = 30000 +hazelcast.client.connection.attempts.limit = 3 +hazelcast.client.reconnection.timeout = 5000 +hazelcast.client.reconnection.attempts.limit= 5 +hazelcast.client.shuffle.addresses = false +hazelcast.client.update.automatic = true +hazelcast.client.addresses = localhost, 127.0.0.1 \ No newline at end of file diff --git a/aai-traversal/src/main/config/jul-redirect.properties b/aai-traversal/src/main/config/jul-redirect.properties new file mode 100644 index 0000000..8b6624d --- /dev/null +++ b/aai-traversal/src/main/config/jul-redirect.properties @@ -0,0 +1,13 @@ + +# Bridge JUL->slf4j Logging Configuration File +# +# This file bridges the JUL logging infrastructure into +# SLF4J so JUL logs go to logback implementation provided +# in this project. SLF4J also captures log4j and has +# other framework options as well providing a common +# logging infrastructure for capturing all logs from different +# libraries using different frameworks in one place. + +# Global properties +handlers=org.slf4j.bridge.SLF4JBridgeHandler +.level= ALL diff --git a/aai-traversal/src/main/config/keyfile b/aai-traversal/src/main/config/keyfile new file mode 100644 index 0000000..6a1657e --- /dev/null +++ b/aai-traversal/src/main/config/keyfile @@ -0,0 +1,27 @@ +ctRt8XTd7N57kcm0npZOWSDF5I69w9K97cQS_ep0AgxgHmYB0WtYblsrMGuHfyS1o4697zLiIeoS +Nn5kE1kedl4c4HevfuwfoJpWyiugYusNOqbTGQJ1MHOwqiBEJnjXepZEoz1btaW_hDO7uz-BoD4t +SxwNRwVQpcg0_CmBX-yIW2YCIECoxZH9_X_8fcXYHP2VgFxxBpvjgycNQlyN15_VSuLwn3Wj0W8_ +8chRxGURyhp8iEBSb4tIdN5jXkhCma7AP7wreMufFQqXjdfWqIisJPfIpS3znl5IiTOZP22XhHay +gq2KFwABVqjM71m5czEz1ojGkbFEAGImrY-VFHuug2u4ss4VW7TGeJst0z7I5vrn5M6i9Eb6xiGh +jNUebRCV3cYGrtD9SlvjJBVVeP_3OrkxlD4oktx-JTRJzYtXADB5if2gtpYxy84kqrz7ltr5rXUH +zSG7ujKCXOOE_Wk6vQPSjYPnum6R_mxOorCNCvtf6ne85Xd81DZlJM-CleVNdOU7g1xie-gBZPAX +bOvWf6p_pVNmH76v-m4XLAAUqEzt-9PvNmirODiDiY5bNz6l-1ejw8IyQYb37e_3sN_LjF7A9HgB +Dia7kNjsfB7_2vB7R4qjwNLsmTMnQCDANnNpl9VpotZ4blPhhOWhB1Tg3lxc-z-VRV7GBbl_2eQd +3eYUT1Z5Li184W4-pft_TCaDJ1NyaJd1CQxQEuIORdq5B6Q2L9SMmmOOh82Czu5_Ro80IGikHXHp +Lqf2fIaceY_IBAeGp2iPjtXdkghV24vIT49oRfqf6sBKAPy-88xILnMWM6M5bMCETKn7UvM1kV5y +ZQYlsi-36n73ETZyiFs1PLqe8D6dRURrcBG_B9i1MafNiWa-elG6E0X0pSK9CadchSA0KRMaKtfE +6-iyUqE-bx-0ELTbV2y7gLdu5MVtjRmQB5ozoaBq8ik4-jAWAsKpTv4DfWoMp9DkRENlKeauayuT +j_VAGhqy07pIntQKtbK9EP0tndSKtF3WLwHel1I5C3lthhkxxfzpxURBxO1ZJMFJZ6rLu1Ku03zw +LJ7nFFR_YfJ7tnGZE4PEt7MOZNiNoD3__9PthO5HmZdk1gPMrKlojU1hyR3IlbVShUst6rA3MkWk +MD-zlw9mhNgaV3xvPJ945pYPe4C6qIwxXoiXGHyhv_0MpcvuMW-pUuAZXfkuiqNwQnpUTLBD0YJw +uwMbE7sN40e6-BSxEiMOab7s2gShbaK9JjCMQUH_vAuQSZjU4sn53jsS7U4DHntzgxVYttIwGZaU +b-1R7jYphNJnCI8rPB_xjJ0OMssNKT7lYRgG_ZuKvifYvJWt-NwD0z2qoePcRGExXuioRDNR4SlB +-RN33dYhp6vRsHKT1oLpl-UJB6dqJlZ2dCsfc7vT1Vs0SYidRYXCUJNBSePI4-1LMlHKOqGASBcg +pl589601-EtO7ch3RoaL26rNXzA-umUWYRPQPZ76wcgK2j4k5Ndub5dWK9jI6UW3RbF6ixe0Yw2j +_Pipt4EX8R6-sb87D69JOOnZlFVB6EcCO07Q7j6DavpUNHlLmDmPgArqODh002scvW1ryMxBR2XE +m3kGQh2IFh5Qru8duxblEYE-lmHGxXVgDtKiKgHwPTkaxcquEtZTEJxaIJIgoKj7SgMzdfbeLlJM +RwbdvExmnRT9ivFImeIV7ACPnfBP3URd82kTG8FyiMvSpdCLL16FWOd9gjZuMstqZrmIVF8tO2WT +COMIx-jqvQD2zS1Ul5p0szJaf-CxBjy7-cJIaAyEToR1T5bBFtQt4sEFxG7XG0cCoXShqclL70TV +W13X5pY55YwHkCR4mRjc0o0ZKStY3OADVLFom1bC9AmMBqU4PsKNAX29LT37WE-I23tQgzid0Ix9 +JuVzlbOTvi19uLYbltrHavU3UbVhYxNNI7Y7tM02xfq3LhGqZG5EPS-WAB9bBixHQqw78cd9iqIr +hHlZW80l1kgs1ezMqgxfwDuiFOZIu9UWQ6vSnTAvfhwJhcr77gSk5Gu957uxzleaS4gVwTYU diff --git a/aai-traversal/src/main/config/realm.properties b/aai-traversal/src/main/config/realm.properties new file mode 100644 index 0000000..88d9e56 --- /dev/null +++ b/aai-traversal/src/main/config/realm.properties @@ -0,0 +1,11 @@ +# format : username: password[,rolename ...] +# default username/password: AAI/AAI, MSO/MSO, ModelLoader/ModelLoader... +AAI:OBF:1gfr1ev31gg7,admin +MSO:OBF:1jzx1lz31k01,admin +SDNC:OBF:1itr1i0l1i151isv,admin +DCAE:OBF:1g8u1f9d1f991g8w,admin +POLICY:OBF:1mk61i171ima1im41i0j1mko,admin +ASDC:OBF:1f991j0u1j001f9d,admin +VID:OBF:1jm91i0v1jl9,admin +APPC:OBF:1f991ksf1ksf1f9d,admin +ModelLoader:OBF:1qvu1v2h1sov1sar1wfw1j7j1wg21saj1sov1v1x1qxw,admin diff --git a/aai-traversal/src/main/config/runner-web.xml b/aai-traversal/src/main/config/runner-web.xml new file mode 100644 index 0000000..44ba656 --- /dev/null +++ b/aai-traversal/src/main/config/runner-web.xml @@ -0,0 +1,111 @@ + + + + + contextConfigLocation + /WEB-INF/spring-servlet.xml, + classpath:applicationContext.xml + + + + + spring.profiles.default + nooauth + + + + org.springframework.web.context.ContextLoaderListener + + + + ManagementServlet + ajsc.ManagementServlet + + + + WriteableRequestFilter + com.att.ajsc.csi.writeablerequestfilter.WriteableRequestFilter + + + + InterceptorFilter + ajsc.filters.InterceptorFilter + + preProcessor_interceptor_config_file + /etc/PreProcessorInterceptors.properties + + + postProcessor_interceptor_config_file + /etc/PostProcessorInterceptors.properties + + + + + + RestletServlet + ajsc.restlet.RestletSpringServlet + + org.restlet.component + restletComponent + + + + + CamelServlet + ajsc.servlet.AjscCamelServlet + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + + spring + org.springframework.web.servlet.DispatcherServlet + 1 + + + + + + spring + / + + + + + org.openecomp.aai.util.AAIAppServletContextListener + + + + + org.openecomp.aai.ingestModel.IngestModelListener + + + + + Open Source + /aai/* + + + admin + + + CONFIDENTIAL + + + + + BASIC + Test Realm + + + + admin + + + diff --git a/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java new file mode 100644 index 0000000..ca78bac --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.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.ajsc_aai; + +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.ContextLoader; +import org.springframework.web.context.WebApplicationContext; + +import ajsc.ErrorMessageLookupService; + +@Path("/errormessage") +public class JaxrsErrorMessageLookupService { + + private final static Logger logger = LoggerFactory + .getLogger(ErrorMessageLookupService.class); + + /** + * Gets the message. + * + * @param input the input + * @param errorCode the error code + * @param appId the app id + * @param operation the operation + * @param messageText the message text + * @param isRESTService the is REST service + * @param faultEntity the fault entity + * @param ConvID the conv ID + * @return the message + */ + @GET + @Path("/emls") + @Produces("text/plain") + public String getMessage(@PathParam("input") String input, + @HeaderParam("errorCode") String errorCode, + @HeaderParam("appId") String appId, + @HeaderParam("operation") String operation, + @HeaderParam("messageText") String messageText, + @HeaderParam("isRESTService") String isRESTService, + @HeaderParam("faultEntity") String faultEntity, + @HeaderParam("ConvID") String ConvID) { + + Map headers = new HashMap(); + headers.put(errorCode, errorCode); + headers.put(appId, appId); + headers.put(operation, operation); + headers.put(messageText, messageText); + headers.put(isRESTService, isRESTService); + headers.put(faultEntity, faultEntity); + headers.put(ConvID, ConvID); + + WebApplicationContext applicationContext = ContextLoader + .getCurrentWebApplicationContext(); + + ErrorMessageLookupService e = (ErrorMessageLookupService) applicationContext + .getBean("errorMessageLookupService"); + + String message = e.getExceptionDetails(appId, operation, errorCode, + messageText,isRESTService, faultEntity, ConvID); + + System.out.println("Error code = " + errorCode); + System.out.println("appId = " + appId); + System.out.println("operation = " + operation); + System.out.println("messageText = " + messageText); + System.out.println("isRESTService = " + isRESTService); + System.out.println("faultEntity = " + faultEntity); + System.out.println("ConvID = " + ConvID); + return "The exception message is:\n " + message; + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java new file mode 100644 index 0000000..39c78f6 --- /dev/null +++ b/aai-traversal/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/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java new file mode 100644 index 0000000..22c1cb9 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java @@ -0,0 +1,19 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ diff --git a/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java new file mode 100644 index 0000000..656b290 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.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.ajsc_aai.filemonitor; + +import java.io.File; +import java.io.FileInputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class ServicePropertiesMap +{ + private static HashMap> mapOfMaps = new HashMap>(); + private static final EELFLogger LOGGER = EELFManager.getInstance().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/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java new file mode 100644 index 0000000..22c1cb9 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java @@ -0,0 +1,19 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ diff --git a/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java b/aai-traversal/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java new file mode 100644 index 0000000..7577de7 --- /dev/null +++ b/aai-traversal/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/aai-traversal/src/main/java/org/openecomp/aai/db/DbMethHelper.java b/aai-traversal/src/main/java/org/openecomp/aai/db/DbMethHelper.java new file mode 100644 index 0000000..79172d9 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/db/DbMethHelper.java @@ -0,0 +1,158 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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 java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; + +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; + +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.parsers.query.QueryParser; +import org.openecomp.aai.parsers.relationship.RelationshipToURI; +import org.openecomp.aai.query.builder.QueryBuilder; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; + +public class DbMethHelper { + + private final Loader loader; + private final TransactionalGraphEngine engine; + + protected DbMethHelper() { + this.loader = null; + this.engine = null; + } + public DbMethHelper(Loader loader, TransactionalGraphEngine engine) { + this.loader = loader; + this.engine = engine; + } + /** + * + * @param type + * @param map - form [{type}.{propname}:{value}] + * @return + * @throws UnsupportedEncodingException + * @throws AAIException + */ + public Optional searchVertexByIdentityMap(String type, Map map) throws AAIException { + + Introspector relationship = constructRelationship(type, map); + RelationshipToURI parser; + URI uri; + QueryParser queryParser; + try { + parser = new RelationshipToURI(loader, relationship); + uri = parser.getUri(); + queryParser = this.engine.getQueryBuilder().createQueryFromURI(uri); + } catch (UnsupportedEncodingException e) { + throw new AAIException("AAI_3000"); + } + + List results = queryParser.getQueryBuilder().toList(); + + return reduceToSingleVertex(results, map); + } + + /** + * @param type + * @param map - form [{propname}:{value}] + * @return + * @throws AAIException + */ + public Optional locateUniqueVertex(String type, Map map) throws AAIException { + + return reduceToSingleVertex(locateUniqueVertices(type, map), map); + } + + public List locateUniqueVertices(String type, Map map) throws AAIException { + Introspector obj = this.createIntrospectorFromMap(type, map); + QueryBuilder builder = this.engine.getQueryBuilder().exactMatchQuery(obj); + + return builder.toList(); + } + private Introspector constructRelationship(String type, Map map) throws AAIUnknownObjectException { + final Introspector relationship = loader.introspectorFromName("relationship"); + relationship.setValue("related-to", type); + final List data = relationship.getValue("relationship-data"); + for (Entry entry : map.entrySet()) { + final Introspector dataObj = loader.introspectorFromName("relationship-data"); + dataObj.setValue("relationship-key", entry.getKey()); + dataObj.setValue("relationship-value", entry.getValue()); + data.add(dataObj.getUnderlyingObject()); + } + + return relationship; + } + + private Introspector createIntrospectorFromMap(String targetNodeType, Map propHash) throws AAIUnknownObjectException { + final Introspector result = loader.introspectorFromName(targetNodeType); + for (Entry entry : propHash.entrySet()) { + result.setValue(entry.getKey(), entry.getValue()); + } + return result; + } + + private Optional reduceToSingleVertex(List vertices, Map map) throws AAIException { + if (vertices.isEmpty()){ + return Optional.empty(); + } else if (vertices.size() > 1) { + throw new AAIException("AAI_6112", "More than one Node found by getUniqueNode for params: " + map); + } + + return Optional.of(vertices.get(0)); + } + public List getVertexProperties(Vertex v) { + List retArr = new ArrayList<>(); + if( v == null ){ + retArr.add("null Node object passed to showPropertiesForNode()\n"); + } + else { + String nodeType; + Object ob = v.property("aai-node-type").orElse(null); + if( ob == null ){ + nodeType = "null"; + } + else{ + nodeType = ob.toString(); + } + + retArr.add(" AAINodeType/VtxID for this Node = [" + nodeType + "/" + v.id() + "]"); + retArr.add(" Property Detail: "); + Iterator> pI = v.properties(); + while( pI.hasNext() ){ + VertexProperty tp = pI.next(); + Object val = tp.value(); + retArr.add("Prop: [" + tp.key() + "], val = [" + val + "] "); + } + } + return retArr; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbEdgeGroup.java b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbEdgeGroup.java new file mode 100644 index 0000000..56a9a4b --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbEdgeGroup.java @@ -0,0 +1,439 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.dbgraphgen; + +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.dbgen.DbMeth; +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.serialization.db.EdgeRule; +import org.openecomp.aai.serialization.db.EdgeRules; +import org.openecomp.aai.serialization.db.EdgeType; +import org.openecomp.aai.serialization.db.MultiplicityRule; +import org.openecomp.aai.serialization.db.exceptions.NoEdgeRuleFoundException; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.thinkaurelius.titan.core.TitanEdge; +import com.thinkaurelius.titan.core.TitanTransaction; +import com.thinkaurelius.titan.core.TitanVertex; + +public class DbEdgeGroup { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DbEdgeGroup.class); + + /** + * 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{ + + // -------------------------------------------------------------------- + // 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") ){ + throw new AAIException("AAI_6120", "Illegal scope parameter passed: [" + scope + "]."); + } + + 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 + 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); + + LOGGER.info("Found connected cousin vid(s) in db: [" + cousinV.id().toString() + "]"); + } + } + + //------------------------------------------------------------------------------------------------------------ + //2) Get a List of the Titan nodes that the end-state list wants to be connected to + //------------------------------------------------------------------------------------------------------------ + 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); + + LOGGER.info("They request edges to these vids:[" + targetVert.id().toString() + "]"); + } + } + } + + //------------------------------------------------------------------------------------------------------------------- + // 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); + for( Map.Entry entry : vidToEdgeInDbHash.entrySet() ){ + String vertId = entry.getKey(); + TitanEdge dbEd = entry.getValue(); + if( ! vidToTargetVertexHash.containsKey(vertId) ){ + if( scope.equals("ALL_COUSIN_REL") ){ + LOGGER.info("We will DELETE existing DB-edge to vids = [" + 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) ){ + LOGGER.info("We will DELETE existing DB-edge to vids = [" + entry.getKey() + "]"); + DbMeth.removeAaiEdge(transId, fromAppId, graph, dbEd); + } + } + } + } + + //--------------------------------------------------------------- + // 4) add/update (persist) all the relations on the new-list + //--------------------------------------------------------------- + for( Map.Entry entry : vidToTargetVertexHash.entrySet() ){ + LOGGER.info("Call persistAaiEdge on edge(s) going to vids = " + "[" + entry.getKey() + "]"); + TitanVertex targV = entry.getValue(); + DbMeth.persistAaiEdge(transId, fromAppId, graph, startVert, targV, apiVersion, "cousin"); + } + + 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. + + EdgeRule edgeRule = null; + boolean reversed = false; + + if (EdgeRules.getInstance().hasEdgeRule(startNodeType, endNodeType)) { + } else if (EdgeRules.getInstance().hasEdgeRule(endNodeType, startNodeType)) { + reversed = true; + } + + try { + edgeRule = EdgeRules.getInstance().getEdgeRule(EdgeType.COUSIN, startNodeType, endNodeType); + } catch (NoEdgeRuleFoundException e) { + return false; + } + + + if (edgeRule.getMultiplicityRule().equals(MultiplicityRule.ONE2ONE)) { + return true; + } else if (reversed && edgeRule.getMultiplicityRule().equals(MultiplicityRule.ONE2MANY)) { + return true; + } else if (!reversed && edgeRule.getMultiplicityRule().equals(MultiplicityRule.MANY2ONE)) { + return true; + } else { + 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{ + // -------------------------------------------------------------------- + // 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) ){ + throw new AAIException("AAI_6127", "COUSIN Edge between " + startVertVid + " (" + startVertNT + ") and " + reqDelConnectedVid + + "(" + otherNT + ") not found. "); + } + 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) ){ + throw new AAIException("AAI_6126", "Edge between " + startVertVid + " and " + reqDelConnectedVid + + " cannot be deleted because of a uniqueness-dependancy between nodeTypes, " + + startVertNT + " and " + otherNT); + } + } + } + + Collection depNTColl = dbMaps.NodeDependencies.get(otherNT); + Iterator ntItr2 = depNTColl.iterator(); + if( ntItr2.hasNext() ){ + while( ntItr2.hasNext() ){ + if( ntItr2.next().equals(startVertNT) ){ + throw new AAIException("AAI_6126", "Edge between " + startVertVid + " and " + reqDelConnectedVid + + " cannot be deleted because of a uniqueness-dependancy between nodeTypes: " + + otherNT + " and " + startVertNT); + } + } + } + + // 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 + "]"; + + LOGGER.info(msg); + + 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{ + + LOGGER.debug("scope={}", scope); + LOGGER.debug("vid={}", startVert.id().toString()); + LOGGER.debug("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") ){ + throw new AAIException("AAI_6120", "Illegal scope parameter passed: [" + scope + "]."); + } + + //------------------------------------------------------------------------------------------------------------ + // 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(); + + 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); + + LOGGER.debug("Found connected cousin vid(s) in db: " + "[" + cousinV.id().toString() + "]"); + } + +}// End getEdgeGroup() + + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbMeth.java b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbMeth.java new file mode 100644 index 0000000..5951a10 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/DbMeth.java @@ -0,0 +1,3643 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.dbgraphgen; + +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.process.traversal.dsl.graph.__; +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.serialization.db.EdgeRule; +import org.openecomp.aai.serialization.db.EdgeRules; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.common.net.InetAddresses; +import com.thinkaurelius.titan.core.TitanEdge; +import com.thinkaurelius.titan.core.TitanGraph; +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 final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DbMeth.class); + + /** + * 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{ + // 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); + 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{ + 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); + 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{ + 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); + 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{ + + if( graph == null ){ + throw new AAIException("AAI_6101", "null graph object passed to persistAaiNodeBASE()"); + } + + 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 + throw new AAIException("AAI_6109", "null dependentNode object passed to persistAaiNodeBASE() but " + nodeType + " requires one."); + } + 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 + throw new AAIException("AAI_6109", "dependentNode of type " + depNodeVal.property("aai-node-type").orElse(null) + " passed to persistAaiNodeBASE() for nodeType" + nodeType + "."); + } + 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 + String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); + throw new AAIException("AAI_6105", "No node-key-properties defined in dbMaps for nodeType = " + nodeType + " (ver=" + defVer + ")"); + } + + 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("") ){ + throw new AAIException("AAI_6130", "Resource-version not passed for update of = " + nodeType + ", " + nodeKeyPropsHash.toString()); + } + else if( (existingResVer != null) && !resourceVersion.equals(existingResVer) ){ + throw new AAIException("AAI_6131", "Resource-version " + resourceVersion + " MISMATCH WITH EXISTING " + existingResVer + " for update of = " + nodeType + ", " + nodeKeyPropsHash.toString()); + } + } + + // 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()) ){ + throw new AAIException("AAI_6117", "In-Use AlternateKey value passed for update of nodeType = " + nodeType); + } + } + 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. "; + } + throw new AAIException("AAI_6114", "Patch Request, but no Node of type " + nodeType + " found for properties: [" + propHash + "] " + depMsg); + } + + if( needToDoResourceVerCheck(apiVersion, patchOnly) && (resourceVersion != null) && !resourceVersion.equals("") ){ + throw new AAIException("AAI_6131", "Resource-version was passed in, but this is an ADD of a " + nodeType + ", with these params: " + nodeKeyPropsHash.toString()); + } + 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. + throw new AAIException("AAI_6117", "Conflicting Key and Alternate-Key values passed for add of nodeType = " + nodeType); + } + 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); + LOGGER.info("UPDATE existing node: type = " + nodeType + ", key(s) = [" + nodeKeyPropsHash + + "] which rides on dependent node: type = " + depNType + ", with key(s) = [" + depNodePropKeysHash + "]."); + } + else { + LOGGER.info("UPDATE existing node: type = " + nodeType + ", key(s) = [" + nodeKeyPropsHash + "] (no dep. node)."); + } + 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("") ){ + LOGGER.info("Removed these props on update: [" + removeList + "]"); + } + 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 ); + + LOGGER.info(msg + ", [aai-last-mod-ts]/[" + unixTimeNow + "]"); + + return( existingVert ); + } + else{ + // ----- Not found in the DB, This must be an ADD ------ + if( DbEdgeRules.NodeTypeCategory.containsKey(nodeType) ){ + throw new AAIException("AAI_6120", "nodeTypeCategory " + nodeType + " cannot be used to ADD a node. Need to pass a valid nodeType"); + } + + 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; + long unixTime = System.currentTimeMillis(); + 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 ); + } + + LOGGER.info(msg + ", [aai-created-ts]/[" + unixTime + "]"); + 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 ){ + throw new AAIException("AAI_6121", " Bad Version (format) passed to getVerNumFromVerString: [" + versionString + "]."); + } + + 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{ + + 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 { + String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); + throw new AAIException("AAI_6105", "Required Property name(s) not found for nodeType = " + nodeType+ " (ver=" + defVer + ")"); + } + + String [] flds = catInfo.split(","); + if( flds.length != 4 ){ + throw new AAIException("AAI_6121", "Bad EdgeRule.NodeTypeCategory data for nodeType = [" + nodeType + "]."); + } + + String keyPropsString = flds[0]; + String [] propNames = keyPropsString.split("\\|"); + for( int i = 0; i < propNames.length; i++ ){ + keyProps.add(propNames[i]); + } + } + else { + String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); + throw new AAIException("AAI_6105", "Required Property name(s) not found for nodeType = " + nodeType+ " (ver=" + defVer + ")"); + } + + 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{ + + 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 ){ + throw new AAIException("AAI_6121", "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "]."); + } + + String altKeyPropsString = flds[1]; + String [] propNames = altKeyPropsString.split("\\|"); + for( int i = 0; i < propNames.length; i++ ){ + altKey1Props.add(propNames[i]); + } + } + } + + 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 + */ + @Deprecated + 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). + + // 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 + throw new AAIException("AAI_6109", "null dependentNode object passed to getUniqueNode() but " + nodeType + " requires one."); + } + 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 + throw new AAIException("AAI_6109", "dependentNode of type " + depNodeVal.property("aai-node-type").orElse(null) + " passed to getUniqueNode() for nodeType" + nodeType + ".\n"); + } + 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; + + if( topPropIndex == -1 ){ + // Problem if no key Properties defined for this nodeType + String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); + throw new AAIException("AAI_6105", "Bad or Incomplete Key Property params: (" + keyPropsHash.toString() + + ") for nodeType: " + nodeType + " (ver=" + defVer + ")"); + } + 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. + throw new AAIException("AAI_6112", "More than one Node found by getUniqueNode for params: " + propsAndValuesForMsg); + } + } + else { + // No Vertex was found for this key - throw a not-found exception + throw new AAIException("AAI_6114", "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg); + } + } + 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. + throw new AAIException("AAI_6112", "More than one Node found by getUniqueNode for params: " + propsAndValuesForMsg); + } + else if( resultList.size() == 1 ){ + tiV = resultList.get(0); + } + } + + if( tiV == null ){ + // No Vertex was found for this key - throw a not-found exception + throw new AAIException("AAI_6114", "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg); + } + 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) ){ + throw new AAIException("AAI_6114", "No Node of type " + nodeType + " found for properties: " + propsAndValuesForMsg + " (did find a " + foundNodeType + " though.)"); + } + } + + 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 + */ + @Deprecated + 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. + + // 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. + 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); + + 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); + + 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); + + 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); + + 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); + + 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! + throw new AAIException("AAI_6114", "CODE-LIMITATION - Can't resolve dependant node layers for nodeType = " + nodeType); + } + } + } + } + } + } + } // 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. + */ + + if( passedHash == null ){ + throw new AAIException("AAI_6120", "Bad param: null passedHash "); + } + + 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 ){ + throw new AAIException("AAI_6120", "Bad filter param key passed in: [" + k + "]. Expected format = [nodeName.paramName]\n"); + } + 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. + */ + + 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 { + throw new AAIException("AAI_6121", "Error getting DbEdgeRules.NodeTypeCategory info for nodeTypeCat = " + nodeType); + } + + String [] flds = catInfo.split(","); + if( flds.length != 4 ){ + throw new AAIException("AAI_6121", "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "]."); + } + + 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); + } + } + } + } + } + + + 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{ + + // 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() ){ + throw new AAIException("AAI_6121", "No default deleteScope found for nodeType = [" + nodeType + "] "); + } + else { + 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. + * + */ + + if( requestParamHash == null ){ + throw new AAIException("AAI_6120", "Bad param: null requestParamHash "); + } + + 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 ){ + throw new AAIException("AAI_6120", "Bad filter param key passed in: [" + k + "]. Expected format = [nodeName.paramName]\n"); + } + 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). + */ + + int deletedCount = 0; + + if( startNodeVal == null ){ + // They should have passed in the node that this query starts from + throw new AAIException("AAI_6109", "null startNode object passed to detachConnectedNodes()."); + } + + // 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; + } + } + 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 + */ + @Deprecated + 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 + */ + @Deprecated + 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(); + if( nodeType == null || nodeType.equals("") ){ + // They should have passed in a nodeType + throw new AAIException("AAI_6118", "Required field: nodeType not passed to getNodes()."); + } + + if( !noFilterOnPurpose && (propFilterHash == null || propFilterHash.isEmpty()) ){ + // They should have passed at least one property to filter on + throw new AAIException("AAI_6118", "Required field: propFilterHash not passed to getNodes()."); + } + + 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) ){ + LOGGER.info("IN-LINE GROOMING - Unreachable Node DETECTED > skipping it. "); + } + else if( thisVertexHasBadEdges(transId, fromAppId, graph, v, apiVersion) ){ + LOGGER.info("IN-LINE GROOMING - BAD EDGE DETECTED > skipping vtxId = [" + v.id() + "] "); + } + else if( thisVertexIsAPhantom(transId, fromAppId, graph, v, apiVersion) ){ + LOGGER.info("IN-LINE GROOMING - BAD NODE DETECTED > skipping vtxId = [" + v.id() + "] "); + } + else { + returnVertList.add( v ); + } + } + } + } + + 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; + if( limitToThisNodeType != null && ! limitToThisNodeType.equals("") ){ + doNodeTypeCheck = true; + } + + + List verts = graph.traversal().V(startVtx).union(__.outE().has("isParent-REV", true).inV(), __.inE().has("isParent", true).outV()).toList(); + TitanVertex tmpVtx = null; + int vertsSize = verts.size(); + for (int i = 0; i < vertsSize; i++){ + tmpVtx = (TitanVertex) verts.get(i); + 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. + */ + + String startNodeNT = ""; + if( startNodeVal == null ){ + // They should have passed in the node that this query starts from + throw new AAIException("AAI_6109", "null startNode object passed to getConnectedNodes()."); + } + 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) ){ + throw new AAIException("AAI_6115", "Unrecognized nodeType [" + nodeType + "] passed to getConnectedNodes()."); + } + 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) ){ + throw new AAIException("AAI_6116", "Unrecognized property name [" + propName + "] passed to getConnectedNodes()."); + } + // 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 ){ + throw new AAIException("AAI_6125", "Titan null pointer exception trying to get nodes connected to vertexId = " + + startNodeVal.id() + ", aai-node-type = [" + startNodeVal.property("aai-node-type") + "]."); + } + + while( resultI != null && resultI.hasNext() ){ + boolean addThisOne = true; + TitanVertex tmpV = (TitanVertex)resultI.next(); + if( tmpV == null ){ + LOGGER.info("Titan gave a null vertex when looking for nodes connected to vertexId = " + + startNodeVal.id() + ", aai-node-type = [" + startNodeVal.property("aai-node-type") + "]."); + // 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) ){ + //LOGGER.info("Found a connected vertex (vertexId = " + + // tmpVid + "), but we will not collect it. It had aai-node-type [" + + // nto + "], we are looking for [" + nodeType + "]. "); + // Note - we will skip this one, but try to return any others that we find. + addThisOne = false; + } + } + + if( excludeVidList.contains(tmpVid) ){ + LOGGER.info("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."); + // 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" + */ + + if( addrVal == null ){ + throw new AAIException("AAI_6120", "Bad data (addrVal = null) passed to ipAddressFormatOK()"); + } + else if( addrVer == null ){ + throw new AAIException("AAI_6120", "Bad data (addrType = null) passed to ipAddressFormatOK()"); + } + + 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 { + throw new AAIException("AAI_6120", " Bad data for addressVersion [" + addrVer + "] passed to ipAddressFormatOK()"); + } + + try { + inetAddr = InetAddresses.forString(addrVal); + if( inetAddr instanceof Inet4Address ){ + if( lookingForV4 ){ + retVal = true; + } + else { + throw new AAIException("AAI_6120", "Bad data. Address is a V4, but addressType said it should be V6. [" + + addrVal + "], [" + addrVer + "] passed to ipAddressFormatOK()"); + } + } + else if( inetAddr instanceof Inet6Address ){ + if( lookingForV6 ){ + retVal = true; + } + else { + throw new AAIException("AAI_6120", "Bad data. Address is a V6, but addressType said it should be V4. [" + + addrVal + "], [" + addrVer + "] passed to ipAddressFormatOK()."); + } + } + } + catch (IllegalArgumentException e) { + throw new AAIException("AAI_6120", "Badly formed ip-address: [" + addrVal + "] passed to ipAddressFormatOK()"); + } + + 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{ + + // 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() ){ + LOGGER.debug("update edge property/val = [" + entry.getKey() + "]/[" + entry.getValue() + "]"); + existingEdge.property( entry.getKey(), entry.getValue() ); + } + + 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 ){ + String propInfo = ""; + if( nodeKeyPropsHash != null ){ + propInfo = nodeKeyPropsHash.toString(); + } + throw new AAIException("AAI_6117", "Failed to add edge. This node (" + inV_NType + ") already has an edge to a " + outV_NType + + " node with kepProps [" + propInfo + "]"); + } + } + 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 ){ + String propInfo = ""; + if( nodeKeyPropsHash != null ){ + propInfo = nodeKeyPropsHash.toString(); + } + throw new AAIException("AAI_6117", "Failed to add edge. This node (" + outV_NType + ") already has an edge to a " + inV_NType + + " node with kepProps [" + propInfo + "]"); + } + } + + + // 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 ); + + 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{ + + 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( EdgeRules.getInstance().hasEdgeRule(startNodeType, targetNodeType) ){ + // We can use the node info in the order they were given + return( key ); + } + else { + key = targetNodeType + "|" + startNodeType; + if( EdgeRules.getInstance().hasEdgeRule(targetNodeType, startNodeType) ){ + return( key ); + } + else { + // Couldn't find a rule for this edge + throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + startNodeType + ", " + + targetNodeType); + } + } + }// 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{ + + 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 + throw new AAIException("AAI_6120", "Multiple EdgeRules found for nodeTypes: [" + startNodeType + "], [" + + targetNodeType + "], edgeType = [" + edgeType + "]."); + } + 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 + throw new AAIException("AAI_6120", "Multiple EdgeRules found for nodeTypes: [" + targetNodeType + "], [" + + startNodeType + "], edgeType = [" + edgeType + "]."); + } + 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 + throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + startNodeType + ", " + targetNodeType + + "], checkLabelType = [" + edgeType + "]."); + } + else if( (fwdRuleCount > 0) && (revRuleCount > 0) ){ + // We found more than one with the given info + throw new AAIException("AAI_6120", "Multiple EdgeRules (fwd and rev) found for nodeTypes: [" + startNodeType + "], [" + + targetNodeType + "], checkLabelType = [" + edgeType + "]."); + } + + // 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); + + 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 + */ + TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, null); + + 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{ + + TitanVertex targetVert = getUniqueNodeWithDepParams( transId, fromAppId, graph, targetNodeType, targetNodeParamHash, apiVersion ); + TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion); + + 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{ + TitanVertex targetVert = getUniqueNodeWithDepParams( transId, fromAppId, graph, targetNodeType, targetNodeParamHash, apiVersion ); + TitanEdge returnEdge = persistAaiEdge(transId, fromAppId, graph, startVert, targetVert, apiVersion, edgeType); + + 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{ + + if( vtx == null ){ + throw new AAIException("AAI_6109", "null node object passed to getNodeKeyPropHash()."); + } + + 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 + String defVer = AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP); + throw new AAIException("AAI_6105", "No node-key-properties defined in dbMaps for nodeType = " + nType + " (ver=" + defVer + ")"); + } + + 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); + } + + 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{ + + if( vtx == null ){ + throw new AAIException("AAI_6109", "null node object passed to getNodeNamePropHash()." ); + } + + 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); + } + + 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){ + // 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(); + + }// 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{ + String nodeType2Del = thisVtx.property("aai-node-type").orElse(null); + String deleteScope = scopeParam; + if( scopeParam.equals("USE_DEFAULT") ){ + deleteScope = getDefaultDeleteScope(transId, fromAppId, nodeType2Del, apiVersion); + } + + 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("") ){ + throw new AAIException("AAI_6130", "Resource-version not passed for delete of = " + nodeType2Del); + } + else if( (existingResVer != null) && !resourceVersion.equals(existingResVer) ){ + throw new AAIException("AAI_6131", "Resource-version MISMATCH for delete of = " + nodeType2Del); + } + } + + 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") ){ + throw new AAIException("AAI_6120", "Unrecognized value in deleteScope: [" + deleteScope + "]."); + } + + if( deleteScope.equals("ERROR_IF_ANY_EDGES") ){ + if ( thisVtx.edges(Direction.BOTH).hasNext() ) { + throw new AAIException("AAI_6110", "Node cannot be deleted because it still has Edges and the ERROR_IF_ANY_EDGES scope was used."); + } + } + 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) { + throw new AAIException("AAI_6110", "Node cannot be deleted because it still has Edges and the " + deleteScope + " scope was used."); + } + } + } + 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. + throw new AAIException("AAI_6110", "Node cannot be deleted using scope = " + deleteScope + + " another node (type = " + nodeTypeA + ") depends on it for uniqueness."); + } + } + } + + // 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(); + } + } + + LOGGER.info(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. + throw new AAIException("AAI_6110", "Node could be deleted because it unexpectedly still has Edges.\n"); + } + } + + + /** + * 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. + * ====================================================================== + **/ + LOGGER.warn("deleteAllGraphData called! Run for the hills!"); + 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(); + } + + + /** + * 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.IN); + if( ! eI.hasNext() ){ + retArr.add("No IN 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 IN edge (" + lab + ") to this vertex from a [" + nType + "] node with VtxId = " + vid ); + //DEBUG --- + //showPropertiesForEdge( transId, fromAppId, ed ); + } + } + + eI = tVert.edges(Direction.OUT); + if( ! eI.hasNext() ){ + retArr.add("No OUT 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 OUT 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{ + + 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 { + throw new AAIException("AAI_6105", "Required Property name(s) not found for nodeType = " + nodeType); + } + + String [] flds = catInfo.split(","); + if( flds.length != 4 ){ + throw new AAIException("AAI_6121", "Bad EdgeRule.NodeTypeCategory data (itemCount=" + flds.length + ") for nodeType = [" + nodeType + "]."); + } + + 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. + HashMap retEdgePropPutMap = new HashMap (); + + if( (edRule == null) || edRule.equals("") ){ + // No edge rule found for this + throw new AAIException("AAI_6120", "blank edRule passed to getEdgeTagPropPutHash4Rule()"); + } + + int tagCount = DbEdgeRules.EdgeInfoMap.size(); + String [] rules = edRule.split(","); + if( rules.length != tagCount ){ + throw new AAIException("AAI_6121", "Bad EdgeRule data (itemCount =" + rules.length + ") for rule = [" + edRule + "]."); + } + + // 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 { + throw new AAIException("AAI_6121", "Bad EdgeRule data for rule = [" + edRule + "], val = [" + booleanStr + "]."); + } + + } + + 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 Map 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 + + String[] edgeRuleKeys = edgeRuleKey.split("\\|"); + + if (edgeRuleKeys.length < 2 || ! EdgeRules.getInstance().hasEdgeRule(edgeRuleKeys[0], edgeRuleKeys[1])) { + throw new AAIException("AAI_6120", "Could not find an DbEdgeRule entry for passed edgeRuleKey (nodeTypeA|nodeTypeB): " + edgeRuleKey + "."); + } + + Map edgeRules = EdgeRules.getInstance().getEdgeRules(edgeRuleKeys[0], edgeRuleKeys[1]); + + return edgeRules; + + } // 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 (and ex5.json), 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/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ModelBasedProcessing.java b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ModelBasedProcessing.java new file mode 100644 index 0000000..f51e67b --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ModelBasedProcessing.java @@ -0,0 +1,3718 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.dbgraphgen; + +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.Optional; +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.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; + +import org.openecomp.aai.db.DbMethHelper; +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.dbgen.PropertyLimitDesc; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.ingestModel.DbMaps; +import org.openecomp.aai.ingestModel.IngestModelMoxyOxm; +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.query.builder.QueryBuilder; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.db.EdgeRules; +import org.openecomp.aai.serialization.db.EdgeType; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +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.TitanVertex; + +/** + * Utility class that uses Model/Named-Query definitions to navigate the graph. + */ +public class ModelBasedProcessing{ + + private EELFLogger LOGGER = EELFManager.getInstance().getLogger(ModelBasedProcessing.class); + private final int MAX_LEVELS = 50; // max depth allowed for our model - to protect against infinite loop problems + + private TransactionalGraphEngine engine; + private Loader loader; + private DBSerializer serializer; + private DbMethHelper dbMethHelper; + + protected ModelBasedProcessing() { + + } + public ModelBasedProcessing(Loader loader, TransactionalGraphEngine engine, DBSerializer serializer) { + this.loader = loader; + this.engine = engine; + this.serializer = serializer; + dbMethHelper = new DbMethHelper(loader, engine); + } + /** + * Gets the start nodes and model-ver's. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param passedModelVersionId the passed model-version-id -- optional (unique id for a model-ver) + * @param passedModelId the passed model-invariant-id -- optional + * @param passedModelName the passed model-name -- optional + * @param passedTopNodeType the passed top node type -- optional (needed if neither model=invariant-id nor model-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 HashMap of startNodes and their corresponding model-version-id's + * @throws AAIException the AAI exception + */ + public Map getStartNodesAndModVersionIds( String transId, String fromAppId, + String passedModelVersionId, + String passedModelInvId, + String passedModelName, + String passedTopNodeType, + List> startNodeFilterArrayOfHashes, + String apiVer ) + throws AAIException{ + // ---------------------------------------------------------------------------------------------------- + // Get a hash for all start-nodes (key = vtxId, val = modelVersionId that applies) + // If no start-node-key info is passed, then use either the passed modelVersion or + // the passed model-invariant-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. + // ---------------------------------------------------------------------------------------------------- + + Iterator startVerts = null; + Map 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( (passedModelVersionId == null || passedModelVersionId.equals("")) + && (passedModelInvId == null || passedModelInvId.equals("")) + && (passedModelName == null || passedModelName.equals(""))){ + throw new AAIException("AAI_6118", "ModelInvariantId or ModelName or ModelVersionId required if no startNodeFilter data passed."); + } + else { + // Use whatever model info they pass to find start-node instances + // Get the first/top named-query-element used by this query + if( passedModelVersionId != null && !passedModelVersionId.equals("") ){ + // Need to look up the model-invariant-id and model-version to check against persona data + Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", passedModelVersionId); + Vertex modVtx = getModelGivenModelVer( modVerVtx, "" ); + String calcModId = modVtx.property("model-invariant-id").orElse(null); + // Now we can look up instances that match this model's info + if( calcModId != null ){ + startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V().has("model-invariant-id-local",calcModId).has("model-version-id-local",passedModelVersionId); + } + } + else if( passedModelInvId != null && !passedModelInvId.equals("") ){ + // They gave us the model-invariant-id + startVerts = this.engine.asAdmin().getReadOnlyTraversalSource().V().has("model-invariant-id-local",passedModelInvId); + } + else if( passedModelName != null && !passedModelName.equals("") ){ + List modelVerVtxList = getModelVersUsingName(transId, fromAppId, passedModelName); + List startVtxList = new ArrayList<>(); + // Need to look up the model-inv-ids and model-versions to check against persona data + if( !modelVerVtxList.isEmpty() ){ + for( int i = 0; i < modelVerVtxList.size(); i++ ){ + String calcModVerId = (modelVerVtxList.get(i)).property("model-version-id").orElse(null); + Vertex modVtx = getModelGivenModelVer(modelVerVtxList.get(i),""); + String calcModInvId = modVtx.property("model-invariant-id").orElse(null); + // Now we can look up instances that match this model's info + Iterator tmpStartIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has("model-invariant-id-local",calcModInvId).has("model-version-id-local",calcModVerId); + while( tmpStartIter.hasNext() ){ + Vertex tmpStartVert = (Vertex) tmpStartIter.next(); + startVtxList.add(tmpStartVert); + } + } + } + if( !startVtxList.isEmpty() ){ + startVerts = startVtxList.iterator(); + } + } + } + + if( startVerts != null ){ + while( startVerts.hasNext() ){ + Vertex tmpStartVert = (Vertex) startVerts.next(); + String vid = tmpStartVert.id().toString(); + String tmpModId = tmpStartVert.property("model-invariant-id-local").orElse(null); + String tmpModVerId = tmpStartVert.property("model-version-id-local").orElse(null); + startVertInfo.put(vid, tmpModVerId); + } + } + if( startVertInfo.isEmpty() ){ + throw new AAIException("AAI_6114", "Start Node(s) could not be found for model data passed. " + + "(modelVersionId = [" + passedModelVersionId + + "], modelInvariantId = [" + passedModelInvId + + "], modelName = [" + passedModelName + + "])"); + } + + return startVertInfo; + } + 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( passedModelVersionId != null && !passedModelVersionId.equals("") ){ + modTopNodeType = getModelVerTopWidgetType( transId, fromAppId, passedModelVersionId, "", "" ); + modInfoStr = "modelVersionId = (" + passedModelVersionId + ")"; + } + else if( passedModelInvId != null && !passedModelInvId.equals("") ){ + modTopNodeType = getModelVerTopWidgetType( transId, fromAppId,"", passedModelInvId, "" ); + modInfoStr = "modelId = (" + passedModelInvId + ")"; + } + else if( passedModelName != null && !passedModelName.equals("") ){ + modTopNodeType = getModelVerTopWidgetType( transId, fromAppId,"", "", 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) ){ + throw new AAIException("AAI_6120", "topNodeType passed in [" + passedTopNodeType + + "] does not match nodeType derived for model info passed in: [" + + modTopNodeType + "]"); + } + } + + List modelVersionIds2Check = new ArrayList<>(); + if( (passedModelName != null && !passedModelName.equals("")) ){ + // They passed a modelName, so find all the model UUIDs (model-version-id's) that map to this + modelVersionIds2Check = getModelVerIdsUsingName(transId, fromAppId, passedModelName); + } + if( (passedModelVersionId != null && !passedModelVersionId.equals("")) ){ + // They passed in a modelNameVersionId + if( modelVersionIds2Check.isEmpty() ){ + // There was no modelName passed, so we can use the passed modelNameVersionId + modelVersionIds2Check.add(passedModelVersionId); + } + else if( modelVersionIds2Check.contains(passedModelVersionId) ){ + // 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. + modelVersionIds2Check = new ArrayList<>(); // Clear out what we had + modelVersionIds2Check.add(passedModelVersionId); + } + } + + // 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 + Vertex startVtx = null; + try { + Optional result = dbMethHelper.searchVertexByIdentityMap(modTopNodeType, startNodeFilterArrayOfHashes.get(i)); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", "No Node of type " + modTopNodeType + " found for properties"); + } + startVtx = result.get(); + } + 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 personaModInvId = startVtx.property("model-invariant-id-local").orElse(null); + String personaModVerId = startVtx.property("model-version-id-local").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( personaModVerId != null && !personaModVerId.equals("") ){ + // There is persona data in this start-node. So make sure it doesn't contradict any "passed" stuff + if( modelVersionIds2Check.isEmpty() + && (passedModelInvId == null || passedModelInvId.equals("")) ){ + // They didn't pass any model info, so use the persona one. + startVertInfo.put(vid, personaModVerId); + } + else if( modelVersionIds2Check.isEmpty() + && (passedModelInvId != null && !passedModelInvId.equals("")) ){ + // They passed in just the modelId - so check it + if( passedModelInvId.equals(personaModInvId) ){ + startVertInfo.put(vid, personaModVerId); + } + } + else if( !modelVersionIds2Check.isEmpty() + && (passedModelInvId == null || passedModelInvId.equals("")) ){ + // They passed in just modelVersionId - so check + if( modelVersionIds2Check.contains(personaModVerId) ){ + startVertInfo.put(vid, personaModVerId); + } + } + else if( !modelVersionIds2Check.isEmpty() + && (passedModelInvId != null && !passedModelInvId.equals("")) ){ + // We have BOTH a modelVersionIds and a modelId to check + if( passedModelInvId.equals(personaModInvId) + && modelVersionIds2Check.contains(personaModVerId) ){ + startVertInfo.put(vid, personaModVerId); + } + } + } + else { + // This start node did not have persona info -- so we will use the passed in model info if they passed one + if( passedModelVersionId!= null && !passedModelVersionId.equals("") ){ + // The model-version-id uniquely identifies a model-ver, so we can use it. + startVertInfo.put(vid, passedModelVersionId); + } + else { + throw new AAIException("AAI_6118", "Found startNode but since it does not have persona data, the " + + " model-version-id is required. "); + } + } + } + } + + return startVertInfo; + + }//end of getStartNodesAndModVersionIds() + + + /** + * Query by model. (really model-ver) + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model-version-id (unique id in model-ver) + * @param modelInvariantId the model-invariant-id (unique id in model) + * @param modelName the model name + * @param topNodeType - optional (needed if neither model-invariant-id nor model-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 List queryByModel( String transId, String fromAppId, + String modelVersionId, + String modelInvariantId, + String modelName, + String topNodeType, + List> startNodeFilterArrayOfHashes, + String apiVer ) + throws AAIException{ + + final String transId_f = transId; + final String fromAppId_f = fromAppId; + final String modelVersionId_f = modelVersionId; + final String modelInvId_f = modelInvariantId; + final String modelName_f = modelName; + final String topNodeType_f = topNodeType; + final List> 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, + modelVersionId, + modelInvariantId, + modelName, + topNodeType, + startNodeFilterArrayOfHashes, + apiVer ); + } + + List resultList = new ArrayList<>(); + TimeLimiter limiter = new SimpleTimeLimiter(); + try { + resultList = limiter.callWithTimeout(new Callable >() { + public List call() throws AAIException { + return queryByModel_Timed( transId_f, fromAppId_f, + modelVersionId_f, + modelInvId_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 (model-ver) timed. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model-version-id (unique id in model-ver) + * @param modelInvariantId the model-invariant-id (unique id in model) + * @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 List queryByModel_Timed( String transId, String fromAppId, + String modelVersionId, + String modelInvariantId, + String modelName, + String topNodeType, + List> startNodeFilterArrayOfHashesVal, + String apiVer ) + throws AAIException{ + + DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + + List resultArray = new ArrayList<>(); + + // NOTE: this method can be used for different styles of queries: + // a) They could pass neither a modelVersionId or a modelInvariantId but just pass 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. + // Then use whatever model corresponds to each instance to pull that instance's data. + // b) They could pass a modelInvariantId, but no modelVersionId and no startNode info. In this case, we + // Would look in the database for all nodes that have a model-invariant-id-local 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-version-id, but no startNode info. We'd make sure that if a + // model-invariant-id was also passed, that it does not conflict - but it really should be null if they + // are passing a full model-version-id. Like case -b-, we'd do a query for all nodes + // that have persona info that corresponds to the model-version-id passed and then + // collect data for each one. + // d) They could pass either modelVersionId or modelInvariantId 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. + + + // Sorry to do this, but code that gets called with an empty hash as the first array element was causing errors + List> startNodeFilterArrayOfHashes = new ArrayList >(); + if( !startNodeFilterArrayOfHashesVal.isEmpty() ){ + Map tmpH = startNodeFilterArrayOfHashesVal.get(0); + if( !tmpH.isEmpty() ){ + for( int i=0; i < startNodeFilterArrayOfHashesVal.size(); i++ ){ + startNodeFilterArrayOfHashes.add( startNodeFilterArrayOfHashesVal.get(i) ); + } + } + } + + // ---------------------------------------------------------------------------------------------------------- + // Get a Hash of all the start-nodes (top instance-data node for a model-ver where we will + // start collecting data) for startNode2ModelVerHash: + // key = vertex-id for the startNode, + // value = model-version-id for the corresponding model-ver + // ---------------------------------------------------------------------------------------------------------- + Map startNode2ModelVerHash = getStartNodesAndModVersionIds( transId, fromAppId, + modelVersionId, modelInvariantId, modelName, topNodeType, + startNodeFilterArrayOfHashes, apiVer ); + + //System.out.println("\nDEBUG -- Here's a dump of the startnodes/model-vers: " + startNode2ModelVerHash.toString()); + + // -------------------------------------------------------------------------------------------------------- + // Figure out what-all models (model-ver nodes) we will be dealing with + // Note - Instances must all use the same type of start-node, but do not have to all use the same model-ver. + // -------------------------------------------------------------------------------------------------------- + Map distinctModelVersHash = new HashMap<>(); + // For distinctModelVersHash: key = modelVersionId, val= modelVerVertex + String startNodeType = ""; + if( topNodeType != null && !topNodeType.equals("") ){ + startNodeType = topNodeType; + } + + List skipModelVerIdList = new ArrayList<>(); + List skipStartVertVerIdList = new ArrayList<>(); + Set snKeySet = startNode2ModelVerHash.keySet(); + Iterator startNodeIterator = snKeySet.iterator(); + while( startNodeIterator.hasNext() ){ + String modVerIdKey = (String) startNodeIterator.next(); + String modVerId = startNode2ModelVerHash.get(modVerIdKey); + if( !distinctModelVersHash.containsKey(modVerId) ){ + // First time seeing this model-version-id + Vertex modVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", modVerId); + String tmpNodeType = ""; + try { + tmpNodeType = getModelVerTopWidgetType( modVerVtx, "" ); + } + catch( AAIException ae ){ + // There must be some old bad data in the db - we will skip over this model-ver since its + // model is not good anymore - but will log that this is happening. + skipModelVerIdList.add(modVerId); + skipStartVertVerIdList.add(modVerIdKey); + System.out.println(">>> WARNING - will not collect model data for this vertex since " + + "it uses an inconsistant model-ver model. Model-version-id = " + modVerId ); + } + + if( tmpNodeType != null && !tmpNodeType.equals("") ){ + 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); + } + distinctModelVersHash.put(modVerId, modVerVtx); + } + } + } + + //System.out.println("\nDEBUG -- Here's a dump of the DISTINCT model-ver hash: " + distinctModelVersHash.toString() ); + + // ------------------------------------------------------------------------------------------------------ + // Get the "valid-next-step" hash for each distinct model-ver + // While we're at it, get a mapping of model-invariant-id|model-version to model-version-id for + // the model-vers being used + // ------------------------------------------------------------------------------------------------------ + Map> validNextStepHash = new HashMap<>(); + // validNextStepHash: key = modelVerId, value = nextStepMap + Set keySet = distinctModelVersHash.keySet(); + Iterator modelVerIterator = keySet.iterator(); + while( modelVerIterator.hasNext() ){ + String modVerKey = (String) modelVerIterator.next(); + if( ! skipModelVerIdList.contains(modVerKey) ){ + Vertex modelVerVtx = (Vertex)distinctModelVersHash.get(modVerKey); + Multimap tmpTopoMap = genTopoMap4ModelVer( transId, fromAppId, + modelVerVtx, modVerKey, dbMaps ); + validNextStepHash.put(modVerKey, tmpTopoMap); + } + } + + // ------------------------------------------------------------------------------------------------- + // Figure out what the "start-node" for each instance will be (plus the info we will use to + // represent that in our topology) + // ------------------------------------------------------------------------------------------------- + List failedPersonaCheckVids = new ArrayList<>(); + Map 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 = startNode2ModelVerHash.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 = startNode2ModelVerHash.keySet(); + startNodeIterator = snKeySet.iterator(); + while( startNodeIterator.hasNext() ){ + String vtxKey = (String) startNodeIterator.next(); + Iterator vtxIterator = this.engine.asAdmin().getReadOnlyTraversalSource().V(vtxKey); + Vertex tmpVtx = (Vertex)vtxIterator.next(); + String thisVtxModelVerId = startNode2ModelVerHash.get(vtxKey); + if( skipModelVerIdList.contains(thisVtxModelVerId) ){ + // Skip this vertex because it uses a model-ver that is bad + continue; + } + Vertex modelVerVtx = (Vertex)distinctModelVersHash.get(thisVtxModelVerId); + Vertex modelVtx = getModelGivenModelVer( modelVerVtx, "" ); + String modInvId = modelVtx.property("model-invariant-id").orElse(null); + String personaModInvId = tmpVtx.property("model-invariant-id-local").orElse(null); + String personaModVerId = tmpVtx.property("model-version-id-local").orElse(null); + if( modInvId.equals(personaModInvId) && thisVtxModelVerId.equals(personaModVerId) ){ + String tmpPersonaInfoStr = startNodeType + "," + personaModInvId + "," + personaModVerId; + 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 && (startNode2ModelVerHash.size() > maxSets) ){ + String msg = " Query returns " + startNode2ModelVerHash.size() + " resultSets. Max allowed is: " + maxSets; + throw new AAIException("AAI_6141", msg); + } + } + + snKeySet = startNode2ModelVerHash.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; + } + if( skipStartVertVerIdList.contains(topNodeVtxId) ){ + // Skip this vertex because it uses a model-ver that is bad + continue; + } + + Iterator vtxIterator = this.engine.asAdmin().getReadOnlyTraversalSource().V(topNodeVtxId); + Vertex tmpStartVtx = (Vertex)vtxIterator.next(); + String elementLocationTrail = firstStepInfoHash.get(topNodeVtxId); + String modelVerId = startNode2ModelVerHash.get(topNodeVtxId); + Multimap validNextStepMap = validNextStepHash.get(modelVerId); + + List vidsTraversed = new ArrayList<>(); + Map emptyDelKeyHash = new HashMap<>(); + Map emptyNQElementHash = new HashMap<>(); // Only applies to Named Queries + ResultSet tmpResSet = collectInstanceData( transId, fromAppId, + tmpStartVtx, elementLocationTrail, + validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, emptyNQElementHash, apiVer ); + + resultArray.add(tmpResSet); + } + + return resultArray; + + }// queryByModel_Timed() + + + + /** + * Run delete by model-ver. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model version id -- unique id for a model-ver node + * @param topNodeTypeVal the top node type val -- required if no model-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 Map runDeleteByModel( String transId, String fromAppId, + String modelVersionId, String topNodeTypeVal, Map startNodeFilterHash, String apiVer, String resVersion ) + throws AAIException{ + + Map retHash = new HashMap<>(); + + DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + + // Locate the Model-ver node to be used + Vertex modelVerVtx = null; + if( modelVersionId != null && !modelVersionId.equals("") ){ + modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", modelVersionId); + } + else { + // if they didn't pass the modelVersionId, 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("") ){ + throw new AAIException("AAI_6118", "If no model info is passed, then topNodeType is required. "); + } + + Optional result = dbMethHelper.searchVertexByIdentityMap(topNodeTypeVal, startNodeFilterHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", "No Node of type " + topNodeTypeVal + " found for properties"); + } + Vertex startVtx = result.get(); + + String startVertModVerId = startVtx.property("model-version-id-local").orElse(null); + modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", startVertModVerId); + } + + if( modelVerVtx == null ){ + throw new AAIException("AAI_6114", "Could not determine the model-ver for the given input parameters. "); + } + + String topNType = "unknown"; + String modelType = getModelTypeFromModelVer( modelVerVtx, "" ); + + 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 = modelVerVtx.property("model-name").orElse(null); + if( (widgModNodeType == null) || widgModNodeType.equals("") ){ + String msg = "Could not find model-name for the widget model [" + modelVersionId + "]."; + throw new AAIException("AAI_6132", msg); + } + Optional result = dbMethHelper.locateUniqueVertex(widgModNodeType, startNodeFilterHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties"); + } + Vertex widgetVtx = result.get(); + String widgId = widgetVtx.id().toString(); + serializer.delete(widgetVtx, resVersion, true); + 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. + // NOTE- deleteByModel is deleting data based on one specific version of a model. + // --------------------------------------------------------------------------------- + String chkFirstNodePersonaModInvId = ""; + String chkFirstNodePersonaModVerId = ""; + String personaData = ""; + Vertex firstModElementVertex = getTopElementForSvcOrResModelVer( modelVerVtx, "" ); + topNType = getModElementWidgetType( firstModElementVertex, "" ); + if( (topNType == null) || topNType.equals("") ){ + String msg = "Could not determine the top-node nodeType for model-version-id: [" + modelVersionId + "]"; + throw new AAIException("AAI_6132", msg); + } + if( nodeTypeSupportsPersona(topNType, dbMaps) ){ + Vertex modelVtx = getModelGivenModelVer(modelVerVtx,""); + chkFirstNodePersonaModInvId = modelVtx.property("model-invariant-id").orElse(null); + chkFirstNodePersonaModVerId = modelVerVtx.property("model-version-id").orElse(null); + personaData = "," + chkFirstNodePersonaModInvId + "," + chkFirstNodePersonaModVerId; + } + + // Get the deleteKeyHash for this model + String incomingTrail = ""; + Map currentHash = new HashMap<>(); + Map modConHash = new HashMap<>(); + ArrayList vidsTraversed = new ArrayList<>(); + Map delKeyHash = collectDeleteKeyHash( transId, fromAppId, + firstModElementVertex, incomingTrail, currentHash, vidsTraversed, + 0, dbMaps, modConHash, + chkFirstNodePersonaModInvId, chkFirstNodePersonaModVerId ); + + + System.out.println("\n ----DEBUG -----: Delete Hash for model: [" + modelVersionId + "] 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 + Optional result = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties"); + } + Vertex startVtx = result.get(); + if( !chkFirstNodePersonaModInvId.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 startVertPersonaModInvId = startVtx.property("model-invariant-id-local").orElse(null); + String startVertPersonaModVerId = startVtx.property("model-version-id-local").orElse(null); + if( !chkFirstNodePersonaModInvId.equals(startVertPersonaModInvId) + || !chkFirstNodePersonaModVerId.equals(startVertPersonaModVerId) ){ + 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-ver into a Map for processing + Multimap validNextStepMap = genTopoMap4ModelVer(transId, fromAppId, + modelVerVtx, modelVersionId, dbMaps ); + + // Collect the data + String elementLocationTrail = topNType + personaData; + vidsTraversed = new ArrayList<>(); + Map emptyHash = new HashMap<>(); + + // Pass emptyHash for the NQElement hash since that parameter only applies to Named Queries + ResultSet retResSet = collectInstanceData( transId, fromAppId, + 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, retResSet, + vidToResCheck, apiVer, resVersion, emptyHash ); + //String msgStr = "processed deletes for these vids: (\n"+ retHash.keySet().toString() + ")."; + + return retHash; + + }// End of runDeleteByModel() + + + + /** + * Delete as needed from result set. + * + * @param transId the trans id + * @param fromAppId the from app id + * @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 Map deleteAsNeededFromResultSet( String transId, String fromAppId, + ResultSet resSet, String vidToResCheck, String apiVer, String resVersion, Map hashSoFar ) + throws AAIException + { + Map retHash = new HashMap<>(); + retHash.putAll( hashSoFar ); + Boolean deleteIt = false; + + if( resSet.getVert() == null ){ + return retHash; + } + + TitanVertex thisVtx = resSet.getVert(); + String thisGuyId = ""; + String thisNT = ""; + String thisGuyStr = ""; + + try { + if( thisVtx != null && !thisVtx.isRemoved() ){ + thisGuyId = thisVtx.id().toString(); + thisNT = thisVtx.property(AAIProperties.NODE_TYPE).orElse(null); + thisGuyStr = thisGuyId + "[" + thisNT + " found at:" + resSet.getLocationInModelSubGraph() + "]"; + } + } + catch (Exception ex) { + // Sometimes things have already been deleted by the time we get to them - just log it. + LOGGER.warn("Exception when deleting " + thisGuyStr + ". msg = " + ex.getMessage(), ex); + } + + if( thisGuyId.equals("") ){ + // The vertex must have already been removed. Just return. + return retHash; + } + else { + if( resSet.getNewDataDelFlag() != null && resSet.getNewDataDelFlag().equals("T") ){ + LOGGER.info(">> will try to delete this one >> " + thisGuyStr); + + try { + Boolean requireResourceVersion = false; + if( thisGuyId.equals(vidToResCheck) ){ + // This is the one vertex that we want to check the resourceId before deleting + requireResourceVersion = true; + } + this.serializer.delete(thisVtx, resVersion, requireResourceVersion); + } + 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.getMessage(); + LOGGER.warn("Exception when deleting " + thisGuyStr + ". ErrorCode = " + errorCode + + ", errorText = " + errText + ", details = " + errDetail); + } + } + 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. + LOGGER.warn("Exception when deleting " + thisGuyStr + e.getMessage(), e); + } + + // 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 ); + List retArr = dbMethHelper.getVertexProperties(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, tmpSubResSet, + vidToResCheck, apiVer, resVersion, retHash ); + } + + if( deleteIt ){ + retHash.put(thisGuyId, thisGuyStr); + } + + return retHash; + + }// deleteAsNeededFromResultSet() + + + + /** + * Query by named query (old version). + * + * @param transId the trans id + * @param fromAppId the from app id + * @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 List queryByNamedQuery( String transId, String fromAppId, + String namedQueryUuid, + ArrayList > startNodeFilterArrayOfHashes, + String apiVer ) + throws AAIException{ + + String dummyCutPoint = null; + Map dummySecondaryFilterHash = null; + + return queryByNamedQuery( transId, fromAppId, + namedQueryUuid, + startNodeFilterArrayOfHashes, + apiVer, + dummyCutPoint, + dummySecondaryFilterHash ); + } + + + /** + * Query by named query. + * + * @param transId the trans id + * @param fromAppId the from app id + * @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 + * @param secondaryCutPoint nodeType where we will prune if secondary filter is not met + * @param secondaryFilterHash secondary filter params + * @return resultSet + * @throws AAIException the AAI exception + */ + public List queryByNamedQuery( String transId, String fromAppId, + String namedQueryUuid, + List> startNodeFilterArrayOfHashes, + String apiVer, + String secondaryFilterCutPoint, + Map secondaryFilterHash ) + throws AAIException{ + + final String transId_f = transId; + final String fromAppId_f = fromAppId; + final String namedQueryUuid_f = namedQueryUuid; + final List> startNodeFilterArrayOfHashes_f = startNodeFilterArrayOfHashes; + final String apiVer_f = apiVer; + final String secondaryFilterCutPoint_f = secondaryFilterCutPoint; + final Map secondaryFilterHash_f = secondaryFilterHash; + + // 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, + namedQueryUuid, + startNodeFilterArrayOfHashes, + apiVer, + secondaryFilterCutPoint_f, + secondaryFilterHash_f ); + } + + List resultList = new ArrayList<>(); + TimeLimiter limiter = new SimpleTimeLimiter(); + try { + resultList = limiter.callWithTimeout(new Callable >() { + public List call() throws AAIException { + return queryByNamedQuery_Timed( transId_f, fromAppId_f, + namedQueryUuid_f, + startNodeFilterArrayOfHashes_f, + apiVer_f, + secondaryFilterCutPoint_f, + secondaryFilterHash_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 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 + * @param secondaryFilterCutPoint the nodeType where we will parse for the secondary Filter + * @param secondaryFilterHash the secondary filter hash + * @return resultSet + * @throws AAIException the AAI exception + */ + public List queryByNamedQuery_Timed( String transId, String fromAppId, + String namedQueryUuid, + List> startNodeFilterArrayOfHashes, + String apiVer, + String secondaryFilterCutPoint, + Map secondaryFilterHash + ) + throws AAIException{ + + // Locate the Query to be used + Vertex queryVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query", + "named-query-uuid", namedQueryUuid); + + // Get the first/top named-query-element used by this query + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, queryVtx, "named-query-element"); + Vertex firstNqElementVert = null; + int count = 0; + String topNType = ""; + while( vertI != null && vertI.hasNext() ){ + firstNqElementVert = vertI.next(); + count++; + topNType = getNqElementWidgetType( transId, fromAppId, firstNqElementVert, "" ); + } + + if( count < 1 ){ + // A named query must start with a single top element + throw new AAIException("AAI_6133", "No top-node defined for named-query-uuid = [" + namedQueryUuid + "]"); + } + else if( count > 1 ){ + // A named query should start with a single top element + throw new AAIException("AAI_6133", "More than one top-node defined for named-query-uuid = [" + namedQueryUuid + "]"); + } + 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, queryVtx, namedQueryUuid); + + List 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. + Map cleanHash = new HashMap<>(); + Map tmpHash = startNodeFilterArrayOfHashes.get(0); + Set propKeySet = tmpHash.keySet(); + Iterator propIter = propKeySet.iterator(); + Introspector obj = loader.introspectorFromName(topNType); + Set keys = obj.getKeys(); + boolean foundIndexedField = false; + int propertiesSet = 0; + 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); + if (obj.hasProperty(newKey)) { + if (keys.contains(newKey)) { + foundIndexedField = true; + } + obj.setValue(newKey, obVal); + propertiesSet++; + } + } + //we found all the properties in the startNodeType + if (propertiesSet == propKeySet.size()) { + if (foundIndexedField) { + QueryBuilder builder = this.engine.getQueryBuilder().exactMatchQuery(obj); + startVertList = builder.toList(); + } else { + //force a filter from aai-node-type + QueryBuilder builder = this.engine.getQueryBuilder().createContainerQuery(obj).exactMatchQuery(obj); + startVertList = builder.toList(); + } + } else { + Optional tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterArrayOfHashes.get(0)); + // Only found one, so just use it. + if (tmpVtx.isPresent()) { + startVertList.add(tmpVtx.get()); + } + } + } + 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 + Optional tmpVtx = dbMethHelper.searchVertexByIdentityMap(topNType, startNodeFilterArrayOfHashes.get(i)); + if (tmpVtx.isPresent()) { + startVertList.add(tmpVtx.get()); + } + } + } + + if (startVertList.isEmpty()) { + throw new AAIException("AAI_6114", "No Node of type " + topNType + " found for properties"); + } + // 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 + List resSetList = new ArrayList<>(); + for( int i = 0; i < startVertList.size(); i++ ){ + Vertex startVtx = startVertList.get(i); + // Collect the data + String elementLocationTrail = topNType; + ArrayList vidsTraversed = new ArrayList<>(); + Map emptyDelKeyHash = new HashMap<>(); // Does not apply to Named Queries + + // Get the mapping of namedQuery elements to our widget topology for this namedQuery + String incomingTrail = ""; + Map currentHash = new HashMap<>(); + + Map namedQueryElementHash = collectNQElementHash( transId, fromAppId, + firstNqElementVert, incomingTrail, currentHash, vidsTraversed, 0 ); + + vidsTraversed = new ArrayList<>(); + ResultSet tmpResSet = collectInstanceData( transId, fromAppId, + startVtx, elementLocationTrail, + validNextStepMap, vidsTraversed, 0, emptyDelKeyHash, namedQueryElementHash, apiVer ); + resSetList.add(tmpResSet); + } + + // If a secondary filter was defined, we will prune the collected instance data result set(s) based on it. + List prunedResSetList = new ArrayList<>(); + if( resSetList != null && !resSetList.isEmpty() ){ + for( int i = 0; i < resSetList.size(); i++ ){ + if( secondaryFilterCutPoint == null || secondaryFilterCutPoint.equals("") || secondaryFilterHash == null ){ + // They didn't want to do any pruning, so just use the results we already had + prunedResSetList.add(resSetList.get(i)); + } + else { + ResultSet tmpResSet = pruneResultSet(resSetList.get(i), secondaryFilterCutPoint, secondaryFilterHash); + if( tmpResSet != null ){ + prunedResSetList.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. + List collapsedResSetList = new ArrayList<>(); + if( prunedResSetList != null && !prunedResSetList.isEmpty() ){ + for( int i = 0; i < prunedResSetList.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. + List tmpResSetList = collapseForDoNotOutput(prunedResSetList.get(i)); + if( tmpResSetList != null && !tmpResSetList.isEmpty() ){ + for( int x = 0; x < tmpResSetList.size(); x++ ){ + //showResultSet( tmpResSetList.get(x), 0 ); //DEBUG-- this was just for testing + collapsedResSetList.add(tmpResSetList.get(x)); + } + } + } + } + + return collapsedResSetList; + + }// End of queryByNamedQuery() + + + /** + * Prune a result set as per a secondary filter. + * + * @param resSetVal the res set val + * @param cutPoint the nodeType where the trim will happen + * @param secFilterHash hash of properties and values to use as the secondary filter + * @return pruned result set + * @throws AAIException the AAI exception + */ + public ResultSet pruneResultSet( ResultSet resSetVal, String cutPointType, Map secFilterHash ) + throws AAIException { + + // Given a ResultSet and some secondary filter info, do pruning as needed + ResultSet pResSet = new ResultSet(); + + // For this ResultSet, we will see if we are on a node of the type that is our cutPoint; + // then only keep it if we peek "below" and see a match for our filter. + + String nt = resSetVal.getVert().property(AAIProperties.NODE_TYPE).orElse(null); + if( nt != null && nt.equals(cutPointType) ){ + // We are on the type of node that may need to be "pruned" along with it's sub-results + if( ! satisfiesFilters(resSetVal, secFilterHash) ){ + // Return an empty result set since we are pruning at this level. + return pResSet; + } + } + + // If we made it to here, we will not be pruning at this level, so we will + // be returning a copy of this resultSet that has it's subResults pruned (as needed). + pResSet.setVert(resSetVal.getVert()); + pResSet.setDoNotOutputFlag(resSetVal.getDoNotOutputFlag()); + pResSet.setExtraPropertyHash(resSetVal.getExtraPropertyHash()); + pResSet.setLocationInModelSubGraph(resSetVal.getLocationInModelSubGraph()); + pResSet.setNewDataDelFlag(resSetVal.getNewDataDelFlag()); + pResSet.setPropertyLimitDesc(resSetVal.getPropertyLimitDesc()); + pResSet.setPropertyOverRideHash(resSetVal.getPropertyOverRideHash()); + + if( !resSetVal.getSubResultSet().isEmpty() ){ + ListIterator listItr = resSetVal.getSubResultSet().listIterator(); + List newSubSetList = new ArrayList<>(); + while( listItr.hasNext() ){ + ResultSet tmpSubResSet = pruneResultSet( listItr.next(), cutPointType, secFilterHash ); + if( tmpSubResSet.getVert() != null ){ + // This one wasn't pruned - so keep it. + newSubSetList.add(tmpSubResSet); + } + } + pResSet.setSubResultSet(newSubSetList); + } + + return pResSet; + + }// End pruneResultSet() + + + /** + * Satisfies hash of filters. + * + * @param resSet the res set + * @param filterHash the filter hash + * @return true, if successful + * @throws AAIException the AAI exception + */ + public boolean satisfiesFilters( ResultSet resSet, Map filterHash ) + throws AAIException { + + if( filterHash.isEmpty() ){ + // Nothing to look for, so no, we didn't find it. + return false; + } + + 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"; + 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 -- satisfied/matched filter: [" + fnt + "|" + fpn + "|" + fpv + "]."); + } + else { + //System.out.println(" DEBUG -- NOT satisfied/matched filter: [" + fnt + "|" + fpn + "|" + fpv + "]."); + return false; + } + } + } + + // Made it through all the filters -- it found what we were looking for. + return true; + + }// end of satisfiesFilters() + + + /** + * 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 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" + + Vertex vert = resSet.getVert(); + if( vert == null ){ + return false; + } + else { + String nt = resSet.getVert().property(AAIProperties.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) ){ + return true; + } + } + else { + Object thisValObj = vert.property(filtPropName).orElse(null); + if( thisValObj != null ){ + String thisVal = thisValObj.toString(); + if( thisVal.equals(filtPropVal) ){ + return true; + } + } + } + } + } + + // Didn't find a match at the this level, so check the sets below it meet the criteria + if( resSet.getSubResultSet() != null ){ + ListIterator listItr = resSet.getSubResultSet().listIterator(); + while( listItr.hasNext() ){ + if( filterMetByThisSet(listItr.next(), filtNodeType, filtPropName, filtPropVal) ){ + return true; + } + } + } + + return false; + + }// end of filterMetByThisSet() + + + + /** + * Collapse for do not output. + * + * @param resSetVal the res set val + * @return the array list + * @throws AAIException the AAI exception + */ + public List 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. + List colResultSet = new ArrayList<>(); + + if( resSetVal.getDoNotOutputFlag().equals("true") ){ + // This ResultSet isn't to be displayed, so replace it with it's sub-ResultSets + List subResList = (ArrayList) resSetVal.getSubResultSet(); + for( int k = 0; k < subResList.size(); k++ ){ + List 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++ ){ + List newSubSet = new ArrayList<>(); + List subResList = (ArrayList) colResultSet.get(i).getSubResultSet(); + for( int n = 0; n < subResList.size(); n++ ){ + List newSubResList = collapseForDoNotOutput(subResList.get(n)); + newSubSet.addAll(newSubResList); + } + // Replace the old subResultSet with the collapsed set + colResultSet.get(i).setSubResultSet(newSubSet); + } + + return colResultSet; + + }// End collapseForDoNotOutput() + + + + /** + * Collect instance data. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param thisLevelElemVtx the element vtx at this level + * @param thisVertsTrail the this verts trail + * @param elementLocationTrail -- trail of nodeTypes that got us here (this element 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 ResultSet collectInstanceData( String transId, String fromAppId, + Vertex thisLevelElemVtx, + String thisVertsTrail, + Multimap validNextStepMap, + List vidsTraversed, + int levelCounter, + Map delKeyHash, // only applies when collecting data using the default model for delete + Map namedQueryElementHash, // only applies to named-query data collecting + String apiVer + ) throws AAIException { + + levelCounter++; + + String thisElemVid = thisLevelElemVtx.id().toString(); + + if( levelCounter > MAX_LEVELS ) { + throw new AAIException("AAI_6125", "collectInstanceData() has looped across more levels than allowed: " + MAX_LEVELS + ". "); + } + + 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); + Vertex nqElementVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query-element", + "named-query-element-uuid", nqElUuid); + + String tmpDoNotShow = nqElementVtx.property("do-not-output").orElse(null); + if( tmpDoNotShow != null && tmpDoNotShow.equals("true") ){ + rs.setDoNotOutputFlag("true"); + } + + if( namedQueryConstraintSaysStop(transId, fromAppId, nqElementVtx, thisLevelElemVtx, 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("") ){ + if (propLimDesc.equalsIgnoreCase("show-all")) { + rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_ALL); + } else if (propLimDesc.equalsIgnoreCase("show-none")) { + rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NONE); + }else if (propLimDesc.equalsIgnoreCase("name-and-keys-only")) { + rs.setPropertyLimitDesc(PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY); + } + } + + // Look to see if we need to use an Override of the normal properties + Map tmpPropertyOverRideHash = getNamedQueryPropOverRide(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer); + //System.out.println(" DEBUG --- USING this propertyOverride data set on ResSet [" + tmpPropertyOverRideHash.toString() + "]"); + rs.setPropertyOverRideHash(tmpPropertyOverRideHash); + + // See if we need to look up any "unconnected" data that needs to be associated with this result set + Map tmpExtraPropHash = getNamedQueryExtraDataLookup(transId, fromAppId, nqElementVtx, thisLevelElemVtx, apiVer); + //System.out.println(" DEBUG --- ADDING this EXTRA Lookup data to the ResSet [" + tmpExtraPropHash.toString() + "]"); + rs.setExtraPropertyHash(tmpExtraPropHash); + } + + rs.setVert((TitanVertex)thisLevelElemVtx); + rs.setLocationInModelSubGraph(thisVertsTrail); + if( delKeyHash.containsKey(thisVertsTrail) && delKeyHash.get(thisVertsTrail).equals("T") ){ + rs.setNewDataDelFlag("T"); + } + else { + rs.setNewDataDelFlag("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 + Set validNextStepHashSet = new HashSet<>(); + Iterator ntcItr = validNextStepColl.iterator(); + while( ntcItr.hasNext() ){ + String targetStepStr = ntcItr.next(); + validNextStepHashSet.add(targetStepStr); + } + + List tmpVidsTraversedList = new ArrayList<>(); + tmpVidsTraversedList.addAll(vidsTraversed); + tmpVidsTraversedList.add(thisElemVid); + + 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 + // model-invariant-id-local and model-version-id-local (the two persona properties) + // if those need to be checked also. + // When the persona stuff is part of the step, it is a comma separated string. + // Ie. "nodeType,model-inv-id-local,model-version-id-local" (the two "persona" props) + // + String targetNodeType = ""; + String pmid = ""; + String pmv = ""; + Boolean stepIsJustNT = true; + if( targetStep.contains(",") ){ + stepIsJustNT = false; + String[] pieces = targetStep.split(","); + if( pieces.length != 3 ){ + throw new AAIException("AAI_6128", "Unexpected format for nextStep in model processing = [" + + targetStep + "]. "); + } + 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 = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx).both().has(AAIProperties.NODE_TYPE, targetNodeType); + } + else { + modPipe = this.engine.asAdmin().getReadOnlyTraversalSource().V(thisLevelElemVtx).both().has(AAIProperties.NODE_TYPE, targetNodeType).has("model-invariant-id-local",pmid).has("model-version-id-local",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() ){ + Vertex tmpVert = (Vertex) 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, + tmpVert, tmpTrail, + validNextStepMap, tmpVidsTraversedList, + levelCounter, delKeyHash, namedQueryElementHash, apiVer ); + + rs.getSubResultSet().add(tmpResSet); + } + } + } + } + + return rs; + + } // End of collectInstanceData() + + + /** + * Gen topo map 4 model. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVerVertex the model-ver vertex + * @param modelVerId the model-version-id + * @param dbMaps the db maps + * @return MultiMap of valid next steps for each potential model-element + * @throws AAIException the AAI exception + */ + public Multimap genTopoMap4ModelVer( String transId, String fromAppId, + Vertex modelVerVertex, String modelVerId, DbMaps dbMaps ) + throws AAIException { + + if( modelVerVertex == null ){ + throw new AAIException("AAI_6114", "null modelVerVertex passed to genTopoMap4ModelVer()"); + } + + Multimap initialEmptyMap = ArrayListMultimap.create(); + List vidsTraversed = new ArrayList<>(); + String modelType = getModelTypeFromModelVer( modelVerVertex, "" ); + 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 + Iterator vertI= this.traverseIncidentEdges(EdgeType.TREE, modelVerVertex, "model-element"); + if( vertI != null && vertI.hasNext() ){ + throw new AAIException("AAI_6132", "Bad Model Definition: Widget Model has a startsWith edge to a model-element. " + + " model-version-id = " + modelVerId); + } + else { + return initialEmptyMap; + } + } + + String firstModelVerId = modelVerVertex.property("model-version-id").orElse(null); + String firstModelVersion = modelVerVertex.property("model-version").orElse(null); + if( firstModelVerId == null || firstModelVerId.equals("") || firstModelVersion == null || firstModelVersion.equals("") ){ + throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-version-id or model-version. model-version-id = " + + modelVerId); + } + + Vertex firstElementVertex = getTopElementForSvcOrResModelVer( modelVerVertex, "" ); + Vertex firstEleModVerVtx = getModelVerThatElementRepresents( firstElementVertex, "" ); + String firstElemModelType = getModelTypeFromModelVer( firstEleModVerVtx, "" ); + if( ! firstElemModelType.equals("widget") ){ + throw new AAIException("AAI_6132", "Bad Model Definition: First element must correspond to a widget type model. Model UUID = " + + modelVerId); + } + + Vertex firstModVtx = getModelGivenModelVer( modelVerVertex, "" ); + String firstModelInvId = firstModVtx.property("model-invariant-id").orElse(null); + if( firstModelInvId == null || firstModelInvId.equals("") ){ + throw new AAIException("AAI_6132", "Bad Model Definition: Could not find model.model-invariant-id given model-ver.model-version-id = " + + modelVerId); + } + + Multimap collectedMap = collectTopology4ModelVer( transId, fromAppId, + firstElementVertex, "", initialEmptyMap, vidsTraversed, 0, dbMaps, null, firstModelInvId, firstModelVersion ); + + return collectedMap; + + } // End of genTopoMap4ModelVer() + + + public List makeSureItsAnArrayList( String listStringVal ){ + // We're sometimes getting a String back on db properties that should be ArrayList + // Seems to be how they're defined in OXM - whether they use a "xml-wrapper" or not + // Need to translate them into ArrayLists sometimes... + + List retArrList = new ArrayList(); + String listString = listStringVal; + listString = listString.replace(" ", ""); + 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; + } + + + /** + * 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 Map getModConstraintHash( Vertex modelElementVtx, Map 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(AAIProperties.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); + } + + Map thisHash = new HashMap<>(); + if( currentHash != null ){ + thisHash.putAll(currentHash); + } + + int count = 0; + List modelConstraintArray = new ArrayList<>(); + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, modelElementVtx, "model-constraint"); + while( vertI != null && vertI.hasNext() ){ + Vertex tmpVert = vertI.next(); + String connectToType = tmpVert.property(AAIProperties.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++ ){ + Vertex 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 + Iterator mvertI = this.traverseIncidentEdges(EdgeType.TREE, vtxOfModelConstraint, "constrained-element-set"); + while( mvertI != null && mvertI.hasNext() ){ + // There better only be one... + Vertex tmpVert = mvertI.next(); + String connectToType = tmpVert.property(AAIProperties.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 vertex for service or resource model. + * + * @param modelVerVtx the model-ver vertex + * @return first element pointed to by this model-ver + * @throws AAIException the AAI exception + */ + public Vertex getTopElementForSvcOrResModelVer( Vertex modelVerVtx, String trail ) + throws AAIException { + + // For a "resource" or "service" type model, return the "top" element in that model + if( modelVerVtx == null ){ + String msg = " null modelVertex passed to getTopoElementForSvcOrResModelVer() at [" + trail + "]. "; + throw new AAIException("AAI_6114", msg); + } + + String modelVerId = modelVerVtx.property("model-version-id").orElse(null); + if( modelVerId == null ){ + String nt = modelVerVtx.property(AAIProperties.NODE_TYPE).orElse(null); + if( nt != null && !nt.equals("model-ver") ){ + String msg = "Illegal model defined: model element pointing to nodeType: [" + + nt + "], should be pointing to: [model-ver] at [" + trail + "]. "; + throw new AAIException("AAI_6132", msg); + } + } + + Vertex firstElementVertex = null; + + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, modelVerVtx, "model-element"); + int elCount = 0; + while( vertI != null && vertI.hasNext() ){ + elCount++; + firstElementVertex = vertI.next(); + } + + if( elCount > 1 ){ + String msg = "Illegal model defined: More than one first element defined for model-ver-id = " + + modelVerId + " at [" + trail + "]. "; + throw new AAIException("AAI_6132", msg); + } + + if( firstElementVertex == null ){ + String msg = "Could not find first model element for model-ver-id = " + + modelVerId + " at [" + trail + "]. "; + throw new AAIException("AAI_6132", msg); + } + + return firstElementVertex; + + } // End of getTopElementForSvcOrResModelVer() + + + + /** + * Gets the named query prop over ride. + * + * @param transId the trans id + * @param fromAppId the from app id + * @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 Map getNamedQueryPropOverRide( String transId, String fromAppId, + Vertex namedQueryElementVertex, Vertex 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. + + Map altPropHash = new HashMap<>(); + + if( namedQueryElementVertex == null ){ + String msg = " null namedQueryElementVertex passed to getNamedQueryPropOverRide() "; + throw new AAIException("AAI_6114", msg); + } + + List propCollectList = new ArrayList<>(); + Iterator > vpI = namedQueryElementVertex.properties("property-collect-list"); + while( vpI.hasNext() ){ + propCollectList.add((String)vpI.next().value()); + } + + for( int i = 0; i < propCollectList.size(); i++ ){ + String thisPropName = propCollectList.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 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 Boolean namedQueryConstraintSaysStop( String transId, String fromAppId, + Vertex namedQueryElementVertex, Vertex 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); + } + + Iterator constrPipe = this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "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() ){ + Vertex constrVtx = (Vertex) 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 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 Map getNamedQueryExtraDataLookup( String transId, String fromAppId, + Vertex namedQueryElementVertex, Vertex 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); + } + + Map retHash = new HashMap<>(); + + Iterator lookPipe = this.traverseIncidentEdges(EdgeType.TREE, namedQueryElementVertex, "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() ){ + Vertex relLookupVtx = (Vertex) lookPipe.next(); + // 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); + } + + List 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 = ""; + } + + Map propHash = new HashMap(); + propHash.put(targetProp, valFromInstance); + + Optional result = dbMethHelper.locateUniqueVertex(targetNodeType, propHash); + if (!result.isPresent()) { + throw new AAIException("AAI_6114", "No Node of type " + targetNodeType + " found for properties"); + } + Vertex tmpVtx = result.get(); + // 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 thisLevelElemVtx the element verrtx for this level + * @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 Map collectNQElementHash( String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, + Map currentHash, ArrayList vidsTraversed, + int levelCounter ) throws AAIException { + + levelCounter++; + + Map thisHash = new HashMap<>(); + thisHash.putAll(currentHash); + + if( levelCounter > MAX_LEVELS ) { + throw new AAIException("AAI_6125", "collectNQElementHash() has looped across more levels than allowed: " + MAX_LEVELS + ". "); + } + String thisGuysTrail = ""; + String thisElemVid = thisLevelElemVtx.id().toString(); + + // Find out what widget (and thereby what aai-node-type) this element represents. + String thisElementNodeType = getNqElementWidgetType( transId, fromAppId, thisLevelElemVtx, incomingTrail ); + + if( incomingTrail == null || incomingTrail.equals("") ){ + // This is the first one + thisGuysTrail = thisElementNodeType; + } + else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType; + } + vidsTraversed.add(thisElemVid); + + String nqElementUuid = thisLevelElemVtx.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. + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element"); + while( vertI != null && vertI.hasNext() ){ + Vertex tmpVert = vertI.next(); + String vid = tmpVert.id().toString(); + Map elementHash = new HashMap(); + + String connectToType = tmpVert.property(AAIProperties.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() ){ + Vertex elVert = (Vertex)(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 + Map tmpHash = collectNQElementHash( transId, fromAppId, + 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 thisLevelElemVtx the element vertex at this level + * @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 overRideModelVersionId the over ride model version id + * @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 Map collectDeleteKeyHash( String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, + Map currentHash, ArrayList vidsTraversed, + int levelCounter, DbMaps dbMaps, Map modConstraintHash, + String overRideModelId, String overRideModelVersionId ) + throws AAIException { + + levelCounter++; + + Map thisHash = new HashMap<>(); + thisHash.putAll(currentHash); + + if( levelCounter > MAX_LEVELS ) { + throw new AAIException("AAI_6125", "collectDeleteKeyHash() has looped across more levels than allowed: " + MAX_LEVELS + ". "); + } + String thisGuysTrail = ""; + String thisElemVid = thisLevelElemVtx.id().toString(); + Map 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". + List linkagePtList = new ArrayList<>(); + Iterator > vpI = thisLevelElemVtx.properties("linkage-points"); + //DEBUG -- AAI-8002 + // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM definition, + // we get back the whole array of Strings in one String - but still use the "vtx.properties()" to + // get it - but only look at the first thing returned by the iterator. + if( vpI.hasNext() ){ + String tmpLinkageThing = (String)vpI.next().value(); + linkagePtList = makeSureItsAnArrayList( tmpLinkageThing ); + } + + 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 = thisLevelElemVtx.property("new-data-del-flag").orElse(null); + + Set linkageConnectNodeTypes = getLinkageConnectNodeTypes( linkagePtList ); + Iterator linkNtIter = linkageConnectNodeTypes.iterator(); + String incTrail = ""; + if( incomingTrail != null && !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 = getModElementWidgetType( thisLevelElemVtx, incomingTrail ); + String firstElementModelInfo = ""; + + vidsTraversed.add(thisElemVid); + Vertex elementVtxForThisLevel = null; + Vertex thisElementsModelVerVtx = getModelVerThatElementRepresents( thisLevelElemVtx, incomingTrail ); + Vertex thisElementsModelVtx = getModelGivenModelVer( thisElementsModelVerVtx, incomingTrail ); + String modType = getModelTypeFromModel( thisElementsModelVtx, incomingTrail ); + String subModelFirstModInvId = thisElementsModelVtx.property("model-invariant-id").orElse(null); + String subModelFirstVerId = thisElementsModelVerVtx.property("model-version-id").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 + "," + overRideModelVersionId; + } + } + else if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) ){ + firstElementModelInfo = "," + subModelFirstModInvId + "," + subModelFirstVerId; + } + + 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 = thisLevelElemVtx; + // 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 element with the "top" element for that resource/service model so that the + // topology of that resource/service model will be included in this topology. + String modelVerId = thisElementsModelVerVtx.property("model-version-id").orElse(null); + if( subModelFirstModInvId == null || subModelFirstModInvId.equals("") + || subModelFirstVerId == null || subModelFirstVerId.equals("") ){ + throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-version-id = " + + modelVerId + ", at [" + incomingTrail + "]"); + } + + // 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 = thisLevelElemVtx.property("new-data-del-flag").orElse(null); + elementVtxForThisLevel = getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, thisGuysTrail); + if( tmpFlag != null && tmpFlag.equals("T") ){ + modConstraintHash2Use = getModConstraintHash( thisLevelElemVtx, 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. + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, "model-element", "constrained-element-set"); + while( vertI != null && vertI.hasNext() ){ + Vertex tmpVert = vertI.next(); + String vid = tmpVert.id().toString(); + Map elementHash = new HashMap(); + + String connectToType = tmpVert.property(AAIProperties.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 Vertex'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 + Vertex 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() ){ + Vertex elVert = (Vertex)(entry.getValue()); + String tmpElVid = elVert.id().toString(); + String tmpElNT = getModElementWidgetType( 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 + Map tmpHash = collectDeleteKeyHash( transId, fromAppId, + 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 Set getLinkageConnectNodeTypes(List 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. + + Set 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 for model-ver. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelElement vertex to collect for + * @param incomingTrail the incoming trail -- trail of nodeTypes/personaInfo 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 overRideModelInvId the override model-invariant-id + * @param overRideModelVersionId the override model-version-id + * @return Map of the topology + * @throws AAIException the AAI exception + */ + public Multimap collectTopology4ModelVer( String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, + Multimap currentMap, List vidsTraversed, + int levelCounter, DbMaps dbMaps, Map modConstraintHash, + String overRideModelInvId, String overRideModelVersionId ) + throws AAIException { + + levelCounter++; + + Multimap thisMap = ArrayListMultimap.create(); + thisMap.putAll(currentMap); + + if( levelCounter > MAX_LEVELS ) { + throw new AAIException("AAI_6125", "collectTopology4ModelVer() has looped across more levels than allowed: " + MAX_LEVELS + ". "); + } + String thisGuysTrail = ""; + String thisElemVid = thisLevelElemVtx.id().toString(); + Map 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 = getModElementWidgetType( thisLevelElemVtx, incomingTrail ); + if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) && overRideModelInvId != null && !overRideModelInvId.equals("") ){ + firstElementModelInfo = "," + overRideModelInvId + "," + overRideModelVersionId; + } + + Vertex elementVtxForThisLevel = null; + Vertex thisElementsModelVerVtx = getModelVerThatElementRepresents( thisLevelElemVtx, incomingTrail ); + String subModelFirstModInvId = ""; + String subModelFirstModVerId = ""; + String modInfo4Trail = ""; + String modType = getModelTypeFromModelVer( thisElementsModelVerVtx, 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 + Vertex thisElementsModelVtx = getModelGivenModelVer(thisElementsModelVerVtx, incomingTrail); + subModelFirstModInvId = thisElementsModelVtx.property("model-invariant-id").orElse(null); + subModelFirstModVerId = thisElementsModelVerVtx.property("model-version-id").orElse(null); + + if( nodeTypeSupportsPersona(thisElementNodeType, dbMaps) ){ + modInfo4Trail = "," + subModelFirstModInvId + "," + subModelFirstModVerId; + } + String modelVerId = thisElementsModelVerVtx.property("model-version-id").orElse(null); + if( subModelFirstModInvId == null || subModelFirstModInvId.equals("") || subModelFirstModVerId == null || subModelFirstModVerId.equals("") ){ + throw new AAIException("AAI_6132", "Bad Model Definition: Bad model-invariant-id or model-version-id. Model-ver-id = " + modelVerId); + } + + elementVtxForThisLevel = getTopElementForSvcOrResModelVer(thisElementsModelVerVtx, incomingTrail); + modConstraintHash2Use = getModConstraintHash( thisLevelElemVtx, modConstraintHash ); + } + else { + elementVtxForThisLevel = thisLevelElemVtx; + } + + if( incomingTrail.equals("") ){ + // This is the first one + thisGuysTrail = thisElementNodeType + firstElementModelInfo; + } + else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType + modInfo4Trail; + } + + // We only want to ensure that a particular element does not repeat on a single "branch". + // It could show up on other branches in the case where it is a sub-model which is being + // used in more than one place. + // + List thisTrailsVidsTraversed = new ArrayList (); + thisTrailsVidsTraversed.addAll(vidsTraversed); + thisTrailsVidsTraversed.add(thisElemVid); + + // Look at the elements pointed to at this level and add on their data + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, elementVtxForThisLevel, "model-element", "constrained-element-set"); + + while( vertI != null && vertI.hasNext() ){ + Vertex tmpVert = vertI.next(); + String vid = tmpVert.id().toString(); + Map elementHash = new HashMap(); + String connectToType = tmpVert.property(AAIProperties.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 Vertex'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 + Vertex 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() ){ + Vertex elVert = (Vertex)(entry.getValue()); + String tmpElVid = elVert.id().toString(); + String tmpElNT = getModElementWidgetType( elVert, thisGuysTrail ); + String tmpElStepName = getModelElementStepName( elVert, thisGuysTrail, dbMaps ); + + List linkagePtList = new ArrayList (); + Iterator > vpI = elVert.properties("linkage-points"); + //DEBUG -- AAI-8002 + // I am not sure why, but since "linkage-points" is an xml-element-wrapper in the OXM definition, + // we get back the whole array of Strings in one String - but still use the "vtx.properties()" to + // get it - but only look at the first thing returned by the iterator. + if( vpI.hasNext() ){ + String tmpLinkageThing = (String)vpI.next().value(); + linkagePtList = makeSureItsAnArrayList( tmpLinkageThing ); + } + + 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( !thisTrailsVidsTraversed.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 = collectTopology4ModelVer( transId, fromAppId, + elVert, thisGuysTrail, + currentMap, thisTrailsVidsTraversed, levelCounter, + dbMaps, modConstraintHash2Use, subModelFirstModInvId, subModelFirstModVerId ); + thisMap.putAll(tmpMap); + } + else { + String modelElementUuid = elVert.property("model-element-uuid").orElse(null); + String msg = "Bad Model Definition: looping model-element (model-element-uuid = [" + + modelElementUuid + "]) found trying to add step: [" + tmpElStepName + "], " + + " on trail = [" + thisGuysTrail + "]. "; + System.out.println( msg ); + throw new AAIException("AAI_6132", msg); + } + } + } + } + + return thisMap; + + } // End of collectTopology4ModelVer() + + + /** + * 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 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. + + final EdgeRules edgeRules = EdgeRules.getInstance(); + + if( !edgeRules.hasEdgeRule(nodeTypeA, nodeTypeB) + && !edgeRules.hasEdgeRule(nodeTypeB, nodeTypeA) ){ + // 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 Multimap collectTopology4LinkagePoint( String transId, String fromAppId, + String linkagePointStrVal, String incomingTrail, Multimap currentMap, DbMaps dbMaps ) + throws AAIException { + + 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 = thisGuysTrail.split("\\|"); + if( trailSteps == null || trailSteps.length == 0 ){ + throw new AAIException("AAI_6125", "Bad incomingTrail passed to collectTopology4LinkagePoint(): [" + incomingTrail + "] "); + } + 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 AAIProperties.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 linkagePointStr = linkagePointStrVal; + // --- DEBUG For AAI-8002 + // We are getting these with more than linkage thing in one string. + // Ie. "pserver|lag-interface|l-interface, pserver|p-interface|l-interface, vlan|l-interface" + linkagePointStr = linkagePointStr.replace("[", ""); + linkagePointStr = linkagePointStr.replace("]", ""); + linkagePointStr = linkagePointStr.replace(" ", ""); + + String [] linkage = linkagePointStr.split("\\,"); + for( int x = 0; x < linkage.length; x++ ){ + lastStepNT = stepPieces[0]; + String thisStepNT = ""; + String [] linkageSteps = linkage[x].split("\\|"); + if( linkageSteps == null || linkageSteps.length == 0 ){ + throw new AAIException("AAI_6125", "Bad linkagePointStr passed to collectTopology4LinkagePoint(): [" + linkagePointStr + "] "); + } + 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 Map getNextStepElementsFromSet( Vertex 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. + + Map retElementHash = new HashMap(); + + if( constrElemSetVtx == null ){ + String msg = " getNextStepElementsFromSet() called with null constrElemSetVtx "; + throw new AAIException("AAI_6125", msg); + } + + String constrNodeType = constrElemSetVtx.property(AAIProperties.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(); + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, constrElemSetVtx, "element-choice-set"); + int setCount = 0; + while( vertI != null && vertI.hasNext() ){ + Vertex choiceSetVertex = vertI.next(); + String constrSetType = choiceSetVertex.property(AAIProperties.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++ ){ + Vertex choiceSetVert = choiceSetVertArray.get(i); + Iterator mVertI = this.traverseIncidentEdges(EdgeType.TREE, choiceSetVert, "model-element"); + int elCount = 0; + while( mVertI != null && mVertI.hasNext() ){ + Vertex tmpElVertex = mVertI.next(); + String elNodeType = tmpElVertex.property(AAIProperties.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 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 Multimap genTopoMap4NamedQ( String transId, String fromAppId, + Vertex queryVertex, String namedQueryUuid ) + throws AAIException { + + if( queryVertex == null ){ + throw new AAIException("AAI_6125", "null queryVertex passed to genTopoMap4NamedQ()"); + } + + Multimap initialEmptyMap = ArrayListMultimap.create(); + List vidsTraversed = new ArrayList<>(); + + Vertex firstElementVertex = null; + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, queryVertex, "named-query-element"); + int elCount = 0; + while( vertI != null && vertI.hasNext() ){ + elCount++; + firstElementVertex = vertI.next(); + } + + if( elCount > 1 ){ + throw new AAIException("AAI_6133", "Illegal query defined: More than one first element defined for = " + namedQueryUuid); + } + + if( firstElementVertex == null ){ + throw new AAIException("AAI_6114", "Could not find first query element = " + namedQueryUuid); + } + + Vertex modVtx = getModelThatNqElementRepresents( firstElementVertex, "" ); + String modelType = getModelTypeFromModel( modVtx, "" ); + if( ! modelType.equals("widget") ){ + throw new AAIException("AAI_6133", "Bad Named Query Definition: First element must correspond to a widget type model. Named Query UUID = " + + namedQueryUuid); + } + + Multimap collectedMap = collectTopology4NamedQ( transId, fromAppId, + 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 thisLevelElemVtx the model element vertex for this level + * @param levelCounter the level counter + * @return resultSet + * @throws AAIException the AAI exception + */ + public Multimap collectTopology4NamedQ( String transId, String fromAppId, + Vertex thisLevelElemVtx, String incomingTrail, + Multimap currentMap, List vidsTraversed, int levelCounter ) + throws AAIException { + + levelCounter++; + + Multimap thisMap = ArrayListMultimap.create(); + thisMap.putAll(currentMap); + + String thisElemVid = thisLevelElemVtx.id().toString(); + if( levelCounter > MAX_LEVELS ) { + throw new AAIException("AAI_6125", "collectModelStructure() has looped across more levels than allowed: " + MAX_LEVELS + ". "); + } + String thisGuysTrail = ""; + + // find out what widget (and thereby what aai-node-type) this element represents + String thisElementNodeType = getNqElementWidgetType( transId, fromAppId, thisLevelElemVtx, incomingTrail ); + + if( incomingTrail.equals("") ){ + // This is the first one + thisGuysTrail = thisElementNodeType; + } + else { + thisGuysTrail = incomingTrail + "|" + thisElementNodeType; + } + + vidsTraversed.add(thisElemVid); + + // Look at the elements pointed to at this level and add on their data + Iterator vertI = this.traverseIncidentEdges(EdgeType.TREE, thisLevelElemVtx, "named-query-element"); + while( vertI != null && vertI.hasNext() ){ + Vertex tmpVert = vertI.next(); + String tmpVid = tmpVert.id().toString(); + String tmpElNT = getNqElementWidgetType( transId, fromAppId, 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, + tmpVert, thisGuysTrail, + currentMap, vidsTraversed, levelCounter); + thisMap.putAll(tmpMap); + } + } + + return thisMap; + + } // End of collectTopology4NamedQ() + + + /** + * Gets the model that NamedQuery element represents. + * + * @param elementVtx the NQ element vtx + * @param elementTrail the element trail + * @return the model that element represents + * @throws AAIException the AAI exception + */ + public Vertex getModelThatNqElementRepresents( Vertex elementVtx, String elementTrail ) + throws AAIException { + + // Get the model that a named-query element represents + Vertex modVtx = null; + Iterator mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model"); + int modCount = 0; + while( mvertI != null && mvertI.hasNext() ){ + modCount++; + modVtx = mvertI.next(); + } + + if( modCount > 1 ){ + String msg = "Illegal element defined: More than one model pointed to by a single named-query-element at [" + + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + if( modVtx == null ){ + String msg = "Bad named-query definition: Could not find model for element. "; + if( !elementTrail.equals("") ){ + msg = "Bad named-query definition: Could not find model for named-query-element at [" + elementTrail + "]."; + } + throw new AAIException("AAI_6132", msg); + } + + String nodeType = modVtx.property(AAIProperties.NODE_TYPE).orElse(null); + if( (nodeType != null) && nodeType.equals("model") ){ + return modVtx; + } + else { + String msg = "Illegal Named Query element defined: expecting a 'model', but found 'isA' edge pointing to nodeType = " + + nodeType + "] at [" + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + }// getModelThatNqElementRepresents() + + + /** + * Gets the model-ver that element represents. + * + * @param elementVtx the element vtx + * @param elementTrail the element trail + * @return the model-ver that element represents + * @throws AAIException the AAI exception + */ + public Vertex getModelVerThatElementRepresents( Vertex elementVtx, String elementTrail ) + throws AAIException { + + // Get the model-ver that an element represents + Vertex modVerVtx = null; + Iterator mvertI = this.traverseIncidentEdges(EdgeType.COUSIN, elementVtx, "model-ver"); + int modCount = 0; + while( mvertI != null && mvertI.hasNext() ){ + modCount++; + modVerVtx = 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( modVerVtx == null ){ + String msg = "Bad model definition: Could not find model-ver for model-element. "; + if( !elementTrail.equals("") ){ + msg = "Bad model definition: Could not find model-VER for model-element at [" + elementTrail + "]."; + } + throw new AAIException("AAI_6132", msg); + } + + String nodeType = modVerVtx.property(AAIProperties.NODE_TYPE).orElse(null); + if( (nodeType != null) && nodeType.equals("model-ver") ){ + return modVerVtx; + } + else { + String msg = "Illegal model-element defined: expecting a 'model-ver', but found 'isA' edge pointing to nodeType = " + + nodeType + "] at [" + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + }// getModelVerThatElementRepresents() + + + + /** + * Gets the model that is parent to model-ver node. + * + * @param modVerVtx the model-ver vtx + * @param elementTrail the element trail + * @return the model that element represents + * @throws AAIException the AAI exception + */ + public Vertex getModelGivenModelVer( Vertex modVerVtx, String elementTrail ) + throws AAIException { + + // Get the parent model for this "model-ver" node + Vertex modVtx = null; + Iterator mvertI = this.traverseIncidentEdges(EdgeType.TREE, modVerVtx, "model"); + int modCount = 0; + while( mvertI != null && mvertI.hasNext() ){ + modCount++; + modVtx = mvertI.next(); + } + + if( modCount > 1 ){ + String msg = "Illegal model-ver node defined: More than one model points to it with a 'has' edge [" + + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + if( modVtx == null ){ + String msg = "Bad model-ver node: Could not find parent model. "; + if( !elementTrail.equals("") ){ + msg = "Bad model-ver node: Could not find parent model. [" + elementTrail + "]."; + } + throw new AAIException("AAI_6132", msg); + } + + String nodeType = modVtx.property(AAIProperties.NODE_TYPE).orElse(null);; + if( (nodeType != null) && nodeType.equals("model") ){ + // Found what we were looking for. + return modVtx; + } + else { + // Something is amiss + String msg = " Could not find parent model node for model-ver node at [" + + elementTrail + "]."; + throw new AAIException("AAI_6125", msg); + } + + + }// getModelGivenModelVer() + + + + /** + * Gets the model type. + * + * @param modelVtx the model vtx + * @param elementTrail the element trail + * @return the model type + * @throws AAIException the AAI exception + */ + public String getModelTypeFromModel( Vertex modelVtx, String elementTrail ) + throws AAIException { + + // Get the model-type from a model vertex + if( modelVtx == null ){ + String msg = " null modelVtx passed to getModelTypeFromModel() "; + 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 encountered at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", 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; + + }// getModelTypeFromModel() + + + + /** + * Gets the model type given model-ver + * + * @param modelVerVtx the model-ver vtx + * @param elementTrail the element trail + * @return the model type + * @throws AAIException the AAI exception + */ + public String getModelTypeFromModelVer( Vertex modelVerVtx, String elementTrail ) + throws AAIException { + + // Get the model-type given a model-ver vertex + if( modelVerVtx == null ){ + String msg = " null modelVerVtx passed to getModelTypeFromModelVer() "; + throw new AAIException("AAI_6114", msg); + } + + Vertex modVtx = getModelGivenModelVer( modelVerVtx, elementTrail ); + String modelType = modVtx.property("model-type").orElse(null); + if( (modelType == null) || modelType.equals("") ){ + String msg = "Could not find model-type for model encountered at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", 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; + + }// getModelTypeFromModelVer() + + + + /** + * Gets the model-element step name. + * + * @param elementVtx the model-element vtx + * @param elementTrail the element trail + * @param dbMaps the db maps + * @return the element step name + * @throws AAIException the AAI exception + */ + public String getModelElementStepName( Vertex elementVtx, String elementTrail, DbMaps dbMaps) + throws AAIException { + + // Get the "step name" for a model-element + // Step names look like this for widget-models: AAIProperties.NODE_TYPE + // Step names look like this for resource/service models: "aai-node-type,model-invariant-id,model-version-id" + // 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 = "?"; + Vertex modVerVtx = getModelVerThatElementRepresents( elementVtx, elementTrail ); + String modelType = getModelTypeFromModelVer( modVerVtx, elementTrail ); + + if( modelType == null ){ + String msg = " could not determine modelType in getModelElementStepName(). elementTrail = [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + if( modelType.equals("widget") ){ + // NOTE: for models that have model-type = "widget", their "model-name" maps directly to aai-node-type + thisElementNodeType = modVerVtx.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") ){ + Vertex modVtx = getModelGivenModelVer( modVerVtx, elementTrail ); + String modInvId = modVtx.property("model-invariant-id").orElse(null); + String modVerId = modVerVtx.property("model-version-id").orElse(null); + Vertex relatedTopElementModelVtx = getTopElementForSvcOrResModelVer( modVerVtx, elementTrail ); + Vertex relatedModelVtx = getModelVerThatElementRepresents( 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-invariant-id and model-version-id as part of the step name. + stepName = thisElementNodeType + "," + modInvId + "," + modVerId; + } + else { + stepName = thisElementNodeType; + } + return stepName; + } + else { + String msg = " Unrecognized model-type = [" + modelType + "] pointed to by element at [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + }// getModelElementStepName() + + + + /** + * Node type supports persona. + * + * @param nodeType the node type + * @param dbMaps the db maps + * @return the boolean + * @throws AAIException the AAI exception + */ + public 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: "model-invariant-id-local" and "model-version-id-local" + 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("model-invariant-id-local") || !props4ThisNT.contains("model-version-id-local") ){ + return false; + } + else { + return true; + } + + }// nodeTypeSupportsPersona() + + + /** + * Gets a Named Query element's widget type. + * + * @param elementVtx the named-query element vtx + * @param elementTrail the element trail + * @return the element widget type + * @throws AAIException the AAI exception + */ + public String getNqElementWidgetType( String transId, String fromAppId, + Vertex elementVtx, String elementTrail ) + throws AAIException { + + String thisNqElementWidgetType = ""; + // Get the associated node-type for the model pointed to by 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. + Vertex modVtx = getModelThatNqElementRepresents( elementVtx, elementTrail ); + String modelType = getModelTypeFromModel( modVtx, elementTrail ); + + if( modelType == null || !modelType.equals("widget") ){ + String emsg = " Model Type must be 'widget' for NamedQuery elements. Found [" + modelType + "] at [" + + elementTrail + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + else { + // For a Widget model, the nodeType is just mapped to the model-element.model-name + List modVerVtxArr = getModVersUsingModel(transId, fromAppId, modVtx); + if( modVerVtxArr != null && !modVerVtxArr.isEmpty() ){ + thisNqElementWidgetType = (modVerVtxArr.get(0)).property("model-name").orElse(null); + } + if( thisNqElementWidgetType == null || thisNqElementWidgetType.equals("") ){ + String emsg = " Widget type could not be determined at [" + elementTrail + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + else { + return thisNqElementWidgetType; + } + } + + + }// End getNqElementWidgetType() + + + /** + * Gets a model-element's top widget type. + * + * @param elementVtx the model element vtx + * @param elementTrail the element trail + * @return the element widget type + * @throws AAIException the AAI exception + */ + public String getModElementWidgetType( Vertex elementVtx, String elementTrail ) + throws AAIException { + + // Get the associated node-type for the model-ver pointed to by a model-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. + Vertex modVerVtx = getModelVerThatElementRepresents( elementVtx, elementTrail ); + String thisElementNodeType = getModelVerTopWidgetType( modVerVtx, elementTrail ); + return thisElementNodeType; + + }// End getModElementWidgetType() + + + /** + * Gets the node using unique identifier + * + * @param transId the trans id + * @param fromAppId the from app id + * @param nodeType the nodeType + * @param idPropertyName the property name of the unique identifier + * @param uniqueIdVal the UUID value + * @return unique vertex found using UUID + * @throws AAIException the AAI exception + */ + public Vertex getNodeUsingUniqueId( String transId, String fromAppId, + String nodeType, String idPropertyName, String uniqueIdVal ) + throws AAIException { + + // Given a unique identifier, get the Vertex + if( uniqueIdVal == null || uniqueIdVal.equals("") ){ + String emsg = " Bad uniqueIdVal passed to getNodeUsingUniqueId(): [" + + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + if( idPropertyName == null || idPropertyName.equals("") ){ + String emsg = " Bad idPropertyName passed to getNodeUsingUniqueId(): [" + + idPropertyName + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + if( nodeType == null || nodeType.equals("") ){ + String emsg = " Bad nodeType passed to getNodeUsingUniqueId(): [" + + nodeType + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + Vertex uniqVtx = null; + Iterable uniqVerts = null; + uniqVerts = engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,nodeType).has(idPropertyName,uniqueIdVal).toList(); + if( uniqVerts == null ){ + String emsg = "Node could not be found for nodeType = [" + nodeType + + "], propertyName = [" + idPropertyName + + "], propertyValue = [" + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6114", emsg); + } + else { + int count = 0; + Iterator uniqVertsIter = uniqVerts.iterator(); + if( !uniqVertsIter.hasNext() ){ + String emsg = "Node could not be found for nodeType = [" + nodeType + + "], propertyName = [" + idPropertyName + + "], propertyValue = [" + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6114", emsg); + } + else { + while( uniqVertsIter.hasNext() ){ + count++; + uniqVtx = (Vertex) uniqVertsIter.next(); + if( count > 1 ){ + String emsg = "More than one node found for nodeType = [" + nodeType + + "], propertyName = [" + idPropertyName + + "], propertyValue = [" + uniqueIdVal + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + } + } + } + + return uniqVtx; + }// End getNodeUsingUniqueId() + + + /** + * Gets the model-ver nodes using name. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelName the model name + * @return the model-ver's that use this name + * @throws AAIException the AAI exception + */ + public List getModelVersUsingName( String transId, String fromAppId, + String modelName ) + throws AAIException { + + // Given a "model-name", find the model-ver vertices that this maps to + if( modelName == null || modelName.equals("") ){ + String emsg = " Bad modelName passed to getModelVersUsingName(): [" + + modelName + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + List retVtxArr = new ArrayList<>(); + Iterator modVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName); + if( !modVertsIter.hasNext() ){ + String emsg = "Model-ver record(s) could not be found for model-ver data passed. model-name = [" + + modelName + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + else { + while( modVertsIter.hasNext() ){ + Vertex tmpModelVerVtx = (Vertex) modVertsIter.next(); + retVtxArr.add(tmpModelVerVtx); + } + } + + return retVtxArr; + + }// End getModelVersUsingName() + + + /** + * Gets the model-ver nodes using model-invariant-id. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param model-invariant-id (uniquely identifies a model) + * @return the model-ver's defined for the corresponding model + * @throws AAIException the AAI exception + */ + public Iterator getModVersUsingModelInvId( String transId, String fromAppId, + String modelInvId ) + throws AAIException { + + // Given a "model-invariant-id", find the model-ver nodes that this maps to + if( modelInvId == null || modelInvId.equals("") ){ + String emsg = " Bad model-invariant-id passed to getModVersUsingModelInvId(): [" + + modelInvId + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + Vertex modVtx = getNodeUsingUniqueId(transId, fromAppId, "model", "model-invariant-id", modelInvId); + List retVtxArr = getModVersUsingModel(transId, fromAppId, modVtx); + if( retVtxArr == null || retVtxArr.isEmpty() ){ + String emsg = " Model-ver record(s) could not be found attached to model with model-invariant-id = [" + + modelInvId + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + + return retVtxArr.iterator(); + }// End getModVersUsingModelInvId() + + + /** + * Gets the model-ver nodes using a model node. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param model vertex + * @return the model-ver's defined for the corresponding model + * @throws AAIException the AAI exception + */ + public List getModVersUsingModel( String transId, String fromAppId, + Vertex modVtx ) + throws AAIException { + + if( modVtx == null ){ + String emsg = " Null model vertex passed to getModVersUsingModel(): "; + throw new AAIException("AAI_6118", emsg); + } + + List retVtxArr = new ArrayList<>(); + Iterator modVerVertsIter = this.traverseIncidentEdges(EdgeType.TREE, modVtx, "model-ver"); + if(!modVerVertsIter.hasNext()){ + String modelInvId = modVtx.property("model-invariant-id").orElse(null); + String emsg = "Model-ver record(s) could not be found attached to model with model-invariant-id = [" + + modelInvId + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + else { + while( modVerVertsIter.hasNext() ){ + Vertex tmpModelVtx = (Vertex) modVerVertsIter.next(); + retVtxArr.add(tmpModelVtx); + } + } + + return retVtxArr; + + }// End getModVersUsingModel() + + /** + * Gets the model-version-ids using model-name. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelName the model name + * @return the model uuids using name + * @throws AAIException the AAI exception + */ + public List getModelVerIdsUsingName( String transId, String fromAppId, + String modelName ) + throws AAIException { + + // Given a model-name find the model-ver nodes that it maps to + if( modelName == null || modelName.equals("") ){ + String emsg = " Bad modelName passed to getModelVerIdsUsingName(): [" + + modelName + "]\n"; + throw new AAIException("AAI_6118", emsg); + } + + List retArr = new ArrayList<>(); + Iterator modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName); + if( !modVerVertsIter.hasNext() ){ + String emsg = " model-ver record(s) could not be found for model data passed. model-name = [" + + modelName + "]\n"; + throw new AAIException("AAI_6114", emsg); + } + else { + while( modVerVertsIter.hasNext() ){ + Vertex modelVerVtx = (Vertex) modVerVertsIter.next(); + String tmpUuid = modelVerVtx.property("model-version-id").orElse(null); + if( (tmpUuid != null) && !tmpUuid.equals("") && !retArr.contains(tmpUuid) ){ + retArr.add(tmpUuid); + } + } + } + + if( retArr.isEmpty() ){ + String emsg = "No model-ver record found for model-name = [" + + modelName + "]\n"; + throw new AAIException("AAI_6132", emsg); + } + + return retArr; + }// End getModelVerIdsUsingName() + + + /** + * Gets the model top widget type. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelVersionId the model-version-id + * @param modelInvId the model-invariant-id + * @param modelName the model-name + * @return the model top widget type + * @throws AAIException the AAI exception + */ + public String getModelVerTopWidgetType( String transId, String fromAppId, + String modelVersionId, String modelInvId, String modelName ) + throws AAIException { + + // Could be given a model-ver's key info (model-version-id), OR, just a (non-unique) model-name, + // Or just a model-invariant-id (which could have multiple model-ver records under it). + // In any case, they should only map to one single "top" node-type for the first element. + + String nodeType = "?"; + Iterator modVerVertsIter; + + if( modelVersionId != null && !modelVersionId.equals("") ){ + // this would be the best - we can just look up the model-ver records directly + modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-version-id",modelVersionId); + } + else if( modelName != null && !modelName.equals("") ){ + modVerVertsIter = this.engine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE,"model-ver").has("model-name",modelName); + } + else if( modelInvId != null && !modelInvId.equals("") ){ + modVerVertsIter = getModVersUsingModelInvId(transId, fromAppId, modelInvId); + } + else { + String msg = "Neither modelVersionId, modelInvariantId, nor modelName passed to: getModelVerTopWidgetType() "; + throw new AAIException("AAI_6120", msg); + } + + if( !modVerVertsIter.hasNext() ){ + String emsg = "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + modelInvId + + "], modeVersionId = [" + modelVersionId + "], modelName = [" + modelName + "]\n"; + throw new AAIException("AAI_6114", emsg); + } + else { + String lastNT = ""; + if( !modVerVertsIter.hasNext() ){ + String emsg = "model-ver record(s) could not be found for model data passed: modelInvariantId = [" + modelInvId + + "], modeVersionId = [" + modelVersionId + "], modelName = [" + modelName + "]\n"; + throw new AAIException("AAI_6114", emsg); + } + while( modVerVertsIter.hasNext() ){ + Vertex tmpModVerVtx = (Vertex) modVerVertsIter.next(); + String tmpNT = getModelVerTopWidgetType( tmpModVerVtx, "" ); + if( lastNT != null && !lastNT.equals("") ){ + if( !lastNT.equals(tmpNT) ){ + String emsg = "Different top-node-types (" + tmpNT + ", " + lastNT + + ") found for model data passed. (" + + " modelVersionId = [" + modelVersionId + + "], modelId = [" + modelInvId + + "], modelName = [" + modelName + + "])\n"; + throw new AAIException("AAI_6114", emsg); + } + } + lastNT = tmpNT; + nodeType = tmpNT; + } + } + + return nodeType; + + }// End getModelVerTopWidgetType() + + + /** + * Gets the widget type that this model-ver starts with. + * + * @param modVerVtx the model-version vtx + * @param elementTrail the element trail + * @return the widget type of the starting node of this model + * @throws AAIException the AAI exception + */ + public String getModelVerTopWidgetType( Vertex modVerVtx, String elementTrail ) + throws AAIException { + // Get the associated nodeType (Ie. aai-node-type / widget-type) for a model-ver. + // 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 = getModelTypeFromModelVer( modVerVtx, elementTrail ); + if( modelType == null ){ + String msg = " Could not determine modelType in getModelVerTopWidgetType(). elementTrail = [" + elementTrail + "]."; + throw new AAIException("AAI_6132", msg); + } + + String thisElementNodeType = "?"; + if( modelType.equals("widget") ){ + // NOTE: for models that have model-type = "widget", their child model-ver nodes will + // have "model-name" which maps directly to aai-node-type (all model-ver's under one + // model should start with the same widget-type, so we only need to look at one). + thisElementNodeType = modVerVtx.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") ){ + Vertex relatedTopElementVtx = getTopElementForSvcOrResModelVer( modVerVtx, elementTrail ); + Vertex relatedModVerVtx = getModelVerThatElementRepresents( relatedTopElementVtx, elementTrail ); + thisElementNodeType = relatedModVerVtx.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; + + }// getModelVerTopWidgetType() + + + /** + * Validate model. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param modelNameVersionId the model name version id + * @param apiVersion the api version + * @throws AAIException the AAI exception + */ + public void validateModel(String transId, String fromAppId, String modelVersionIdVal, 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. + DbMaps dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + Vertex modelVerVtx = getNodeUsingUniqueId(transId, fromAppId, "model-ver", + "model-version-id", modelVersionIdVal); + if( modelVerVtx == null ){ + String msg = " Could not find model-ver with modelVersionId = [" + modelVersionIdVal + "]."; + throw new AAIException("AAI_6114", msg); + } + else { + Multimap topoMap = genTopoMap4ModelVer( transId, fromAppId, + modelVerVtx, modelVersionIdVal, dbMaps ); + String msg = " modelVer [" + modelVersionIdVal + "] 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 namedQueryUuid the named query uuid + * @param apiVersion the api version + * @throws AAIException the AAI exception + */ + public void validateNamedQuery(String transId, String fromAppId, 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. + Vertex nqVtx = getNodeUsingUniqueId(transId, fromAppId, "named-query", + "named-query-uuid", namedQueryUuid); + + if( nqVtx == null ){ + String msg = " Could not find named-query with namedQueryUuid = [" + namedQueryUuid + "]."; + throw new AAIException("AAI_6114", msg); + } + else { + //Multimap topoMap = genTopoMap4NamedQ( "junkTransId", "junkFromAppId", + // graph, nqVtx, namedQueryUuid ); + //System.out.println("DEBUG -- for test only : --- "); + //System.out.println("DEBUG -- topomap = [" + topoMap + "]"); + } + return; + + }// End validateNamedQuery() + + + /** + * Show result set. + * + * @param resSet the res set + * @param levelCount the level count + */ + public void showResultSet( ResultSet resSet, int levelCount ) { + + levelCount++; + String propsStr = ""; + for( int i= 1; i <= levelCount; i++ ){ + propsStr = propsStr + "-"; + } + if( resSet.getVert() == null ){ + return; + } + String nt = resSet.getVert().property(AAIProperties.NODE_TYPE).orElse(null); + propsStr = propsStr + "[" + nt + "] "; + + //propsStr = propsStr + " newDataDelFlag = " + resSet.getNewDataDelFlag() + ", trail = " + resSet.getLocationInModelSubGraph(); + //propsStr = propsStr + "limitDesc = [" + resSet.getPropertyLimitDesc() + "]"; + propsStr = propsStr + " trail = " + resSet.getLocationInModelSubGraph(); + + Map 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.getVert().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 + Map 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 ); + LOGGER.info(propsStr); + + if( !resSet.getSubResultSet().isEmpty() ){ + ListIterator listItr = resSet.getSubResultSet().listIterator(); + while( listItr.hasNext() ){ + showResultSet( listItr.next(), levelCount ); + } + } + + }// end of showResultSet() + + private Iterator traverseIncidentEdges(EdgeType treeType, Vertex startV, String connectedNodeType) throws AAIUnknownObjectException, AAIException { + QueryBuilder builder = this.engine.getQueryBuilder(startV).createEdgeTraversal(treeType, startV, loader.introspectorFromName(connectedNodeType)); + return builder; + } + + private Iterator traverseIncidentEdges(EdgeType treeType, Vertex startV, String... connectedNodeType) throws AAIUnknownObjectException, AAIException { + QueryBuilder[] builders = new QueryBuilder[connectedNodeType.length]; + for (int i = 0; i < connectedNodeType.length; i++) { + builders[i] = this.engine.getQueryBuilder(startV).createEdgeTraversal(EdgeType.TREE, startV, loader.introspectorFromName(connectedNodeType[i])); + } + QueryBuilder builder = this.engine.getQueryBuilder(startV).union(builders); + return builder; + + } + +} + diff --git a/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ResultSet.java b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ResultSet.java new file mode 100644 index 0000000..46c9b5e --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphgen/ResultSet.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.dbgraphgen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.openecomp.aai.dbgen.PropertyLimitDesc; +import com.thinkaurelius.titan.core.TitanVertex; + +public class ResultSet { + private TitanVertex vert; + private String newDataDelFlag; + private String doNotOutputFlag; + private String locationInModelSubGraph; + private List subResultSet; + private PropertyLimitDesc propertyLimitDesc; + private Map propertyOverRideHash; + private Map extraPropertyHash; + + /** + * Instantiates a new result set. + */ + public ResultSet(){ + this.vert = null; + this.newDataDelFlag = ""; + this.doNotOutputFlag = ""; + this.locationInModelSubGraph = ""; + this.subResultSet = new ArrayList<>(); + this.propertyLimitDesc = null; + this.propertyOverRideHash = new HashMap<>(); + this.extraPropertyHash = new HashMap<>(); + } + + + public void setPropertyLimitDesc(PropertyLimitDesc pld) { + this.propertyLimitDesc = pld; + } + + /** + * Gets the vert. + * + * @return the vert + */ + public TitanVertex getVert(){ + return this.vert; + } + + /** + * Gets the sub result set. + * + * @return the sub result set + */ + public List 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 PropertyLimitDesc getPropertyLimitDesc(){ + return this.propertyLimitDesc; + } + + /** + * Gets the property over ride hash. + * + * @return the property over ride hash + */ + public Map getPropertyOverRideHash(){ + return this.propertyOverRideHash; + } + + /** + * Gets the extra property hash. + * + * @return the extra property hash + */ + public Map getExtraPropertyHash(){ + return this.extraPropertyHash; + } + + + public void setVert(TitanVertex vert) { + this.vert = vert; + } + + + public void setNewDataDelFlag(String newDataDelFlag) { + this.newDataDelFlag = newDataDelFlag; + } + + + public void setDoNotOutputFlag(String doNotOutputFlag) { + this.doNotOutputFlag = doNotOutputFlag; + } + + + public void setLocationInModelSubGraph(String locationInModelSubGraph) { + this.locationInModelSubGraph = locationInModelSubGraph; + } + + + public void setSubResultSet(List subResultSet) { + this.subResultSet = subResultSet; + } + + + public void setPropertyOverRideHash(Map propertyOverRideHash) { + this.propertyOverRideHash = propertyOverRideHash; + } + + + public void setExtraPropertyHash(Map extraPropertyHash) { + this.extraPropertyHash = extraPropertyHash; + } + + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/RelationshipGraph.java b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/RelationshipGraph.java new file mode 100644 index 0000000..8277b2c --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/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.dbgraphmap; + +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.DbMeth; +import org.openecomp.aai.dbgraphgen.DbEdgeGroup; +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(".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/aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/SearchGraph.java b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/SearchGraph.java new file mode 100644 index 0000000..f45c3f5 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dbgraphmap/SearchGraph.java @@ -0,0 +1,1207 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.dbgraphmap; + +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilderException; +import javax.xml.bind.JAXBException; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +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.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.structure.Vertex; +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.db.DbMethHelper; +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.dbgen.PropertyLimitDesc; +import org.openecomp.aai.dbgraphgen.ModelBasedProcessing; +import org.openecomp.aai.dbgraphgen.ResultSet; +import org.openecomp.aai.dbmap.DBConnectionType; +import org.openecomp.aai.domain.model.AAIResources; +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.LoaderFactory; +import org.openecomp.aai.introspection.ModelType; +import org.openecomp.aai.introspection.PropertyPredicates; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.parsers.relationship.RelationshipToURI; +import org.openecomp.aai.query.builder.QueryBuilder; +import org.openecomp.aai.schema.enums.ObjectMetadata; +import org.openecomp.aai.schema.enums.PropertyMetadata; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.db.EdgeRule; +import org.openecomp.aai.serialization.db.EdgeRules; +import org.openecomp.aai.serialization.engines.QueryStyle; +import org.openecomp.aai.serialization.engines.TitanDBEngine; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +import org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; +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.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.common.base.CaseFormat; +import com.thinkaurelius.titan.core.TitanTransaction; +import com.thinkaurelius.titan.core.TitanVertex; + +import edu.emory.mathcs.backport.java.util.Collections; + +/** + * Database Mapping class which acts as the middle man between the REST interface objects + * for the Search namespace + + */ +public class SearchGraph { + + private final String COMPONENT = "aaidbmap"; + private AAIExtensionMap aaiExtMap; + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(SearchGraph.class); + /** + * 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 ( + HttpHeaders headers, + String startNodeType, + List startNodeKeyParams, + List includeNodeTypes, + final int depth, + TransactionalGraphEngine dbEngine, + Loader loader, + UrlBuilder urlBuilder) throws AAIException { + Response response = null; + boolean success = true; + String result = ""; + try { + dbEngine.startTransaction(); + + if( startNodeType == null ){ + throw new AAIException("AAI_6120", "null start-node-type passed to the generic query"); + } + + if( startNodeKeyParams == null ){ + throw new AAIException("AAI_6120", "no key param passed to the generic query"); + } + + if( includeNodeTypes == null ){ + throw new AAIException("AAI_6120", "no include params passed to the generic query"); + } + + if (depth > 6) { + throw new AAIException("AAI_6120", "The maximum depth supported by the generic query is 6"); + } + final QueryBuilder queryBuilder; + + // there is an issue with service-instance - it is a unique node but still dependent + // for now query it directly without attempting to craft a valid URI + if (startNodeType.equalsIgnoreCase("service-instance")) { + Introspector obj = loader.introspectorFromName(startNodeType); + // Build a hash with keys to uniquely identify the start Node + String keyName = null; + String keyValue = null; + + QueryBuilder builder = dbEngine.getQueryBuilder().getVerticesByIndexedProperty(AAIProperties.NODE_TYPE, "service-instance"); + for( String keyData : startNodeKeyParams ){ + int colonIndex = keyData.indexOf(":"); + if( colonIndex <= 0 ){ + throw new AAIException("AAI_6120", "Bad key param passed in: [" + keyData + "]"); + } + else { + keyName = keyData.substring(0, colonIndex).split("\\.")[1]; + keyValue = keyData.substring(colonIndex + 1); + builder.getVerticesByProperty(keyName, keyValue); + + } + } + + queryBuilder = builder; + } else { + URI uri = craftUriFromQueryParams(loader, startNodeType, startNodeKeyParams); + queryBuilder = dbEngine.getQueryBuilder().createQueryFromURI(uri).getQueryBuilder(); + } + List results = queryBuilder.toList(); + if( results.isEmpty()){ + throw new AAIException("AAI_6114", "No Node of type " + + startNodeType + + " found for properties: " + + startNodeKeyParams.toString()); + } else if (results.size() > 1) { + String detail = "More than one Node found by getUniqueNode for params: " + startNodeKeyParams.toString() + "\n"; + throw new AAIException("AAI_6112", detail); + } + + Vertex startNode = results.get(0); + + Collection ver = new HashSet <>(); + List queryResults = new ArrayList<>(); + GraphTraversalSource traversalSource = dbEngine.asAdmin().getReadOnlyTraversalSource(); + GraphTraversal traversal; + if (includeNodeTypes.contains(startNodeType) || depth == 0 || includeNodeTypes.contains("all") ) + ver.add(startNode); + + // Now look for a node of includeNodeType within a given depth + traversal = traversalSource.withSideEffect("x", ver).V(startNode) + .times(depth).repeat(__.both().store("x")).cap("x").unfold(); + + if (!includeNodeTypes.contains("all")) { + traversal.where(__.has(AAIProperties.NODE_TYPE, P.within(includeNodeTypes))); + } + queryResults = traversal.toList(); + + + if( queryResults.isEmpty()){ + LOGGER.warn("No nodes found - apipe was null/empty"); + } + else { + + Introspector searchResults = loader.introspectorFromName("search-results"); + List resultDataList = searchResults.getValue("result-data"); + for (Vertex thisNode: queryResults){ + String nodeType = thisNode.property(AAIProperties.NODE_TYPE).orElse(null); + + String thisNodeURL = urlBuilder.pathed(thisNode); + Introspector resultData = loader.introspectorFromName("result-data"); + + resultData.setValue("resource-type", nodeType); + resultData.setValue("resource-link", thisNodeURL); + resultDataList.add(resultData.getUnderlyingObject()); + + } + + String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); + org.openecomp.aai.introspection.MarshallerProperties properties = new org.openecomp.aai.introspection.MarshallerProperties.Builder( + org.openecomp.aai.restcore.MediaType.getEnum(outputMediaType)).build(); + + result = searchResults.marshal(properties); + response = Response.ok().entity(result).build(); + + LOGGER.debug(ver.size() + " node(s) traversed, " + resultDataList.size() + " found"); + } + success = true; + } catch (AAIException e) { + success = false; + throw e; + } catch (Exception e) { + success = false; + throw new AAIException("AAI_5105", e); + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + + } + + return response; + } + + private URI craftUriFromQueryParams(Loader loader, String startNodeType, List startNodeKeyParams) throws UnsupportedEncodingException, IllegalArgumentException, UriBuilderException, AAIException { + Introspector relationship = loader.introspectorFromName("relationship"); + + relationship.setValue("related-to", startNodeType); + List relationshipDataList = relationship.getValue("relationship-data"); + + for( String keyData : startNodeKeyParams ){ + int colonIndex = keyData.indexOf(":"); + if( colonIndex <= 0 ){ + throw new AAIException("AAI_6120", "Bad key param passed in: [" + keyData + "]"); + } + else { + Introspector data = loader.introspectorFromName("relationship-data"); + data.setValue("relationship-key", keyData.substring(0, colonIndex)); + data.setValue("relationship-value", keyData.substring(colonIndex + 1)); + relationshipDataList.add(data.getUnderlyingObject()); + } + } + + RelationshipToURI parser = new RelationshipToURI(loader, relationship); + + return parser.getUri(); + } + + /** + * 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 ( + HttpHeaders headers, + String targetNodeType, + List edgeFilterParams, + List filterParams, + TransactionalGraphEngine dbEngine, + Loader loader, + UrlBuilder urlBuilder) throws AAIException { + + Response response = null; + boolean success = true; + String result = ""; + final String EQUALS = "EQUALS"; + final String DOES_NOT_EQUAL = "DOES-NOT-EQUAL"; + final String EXISTS = "EXISTS"; + final String DOES_NOT_EXIST = "DOES-NOT-EXIST"; + try { + + dbEngine.startTransaction(); + + Introspector target; + + if( targetNodeType == null || targetNodeType == "" ){ + throw new AAIException("AAI_6120", "null or empty target-node-type passed to the node query"); + } + + try { + target = loader.introspectorFromName(targetNodeType); + } catch (AAIUnknownObjectException e) { + throw new AAIException("AAI_6115", "Unrecognized nodeType [" + targetNodeType + "] passed to node query."); + } + + 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. + LOGGER.warn("No filters passed to the node query"); + } + + StringBuilder queryStringForMsg = new StringBuilder(); + GraphTraversal traversal = dbEngine.asAdmin().getReadOnlyTraversalSource().V().has(AAIProperties.NODE_TYPE, targetNodeType); + queryStringForMsg.append("has(\"aai-node-type\"," + targetNodeType + ")"); + + for( String filter : filterParams ) { + String [] pieces = filter.split(":"); + if( pieces.length < 2 ){ + throw new AAIException("AAI_6120", "bad filter passed to node query: [" + filter + "]"); + } + else { + String propName = this.findDbPropName(target, pieces[0]); + String filterType = pieces[1]; + if( filterType.equals(EQUALS)){ + if( pieces.length < 3 ){ + throw new AAIException("AAI_6120", "No value passed for filter: [" + filter + "]"); + } + String value = "?"; + if( pieces.length == 3 ){ + value = pieces[2]; + } + else if( pieces.length > 3 ){ + // When a ipv6 address comes in as a value, it has colons in it which require us to + // pull the "value" off the end of the filter differently + int startPos4Value = propName.length() + filterType.length() + 3; + value = filter.substring(startPos4Value); + } + queryStringForMsg.append(".has(" + propName + "," + value + ")"); + traversal.has(propName,value); + } + else if( filterType.equals(DOES_NOT_EQUAL)){ + if( pieces.length < 3 ){ + throw new AAIException("AAI_6120", "No value passed for filter: [" + filter + "]"); + } + String value = "?"; + if( pieces.length == 3 ){ + value = pieces[2]; + } + else if( pieces.length > 3 ){ + // When a ipv6 address comes in as a value, it has colons in it which require us to + // pull the "value" off the end of the filter differently + int startPos4Value = propName.length() + filterType.length() + 3; + value = filter.substring(startPos4Value); + } + queryStringForMsg.append(".hasNot(" + propName + "," + value + ")"); + traversal.not(__.has(propName,value)); + } + else if( filterType.equals(EXISTS)){ + queryStringForMsg.append(".has(" + propName + ")"); + traversal.has(propName); + } + else if( filterType.equals(DOES_NOT_EXIST)){ + queryStringForMsg.append(".hasNot(" + propName + ")"); + traversal.hasNot(propName); + } + else { + throw new AAIException("AAI_6120", "bad filterType passed: [" + filterType + "]"); + } + } + } + + 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){ + throw new AAIException("AAI_6120", "bad edge-filter passed: [" + filter + "]"); + } else { + String nodeType = pieces[0].toLowerCase(); + String filterType = pieces[1].toUpperCase(); + Introspector otherNode; + if (!filterType.equals(EXISTS) && !filterType.equals(DOES_NOT_EXIST)) { + throw new AAIException("AAI_6120", "bad filterType passed: [" + filterType + "]"); + } + try { + otherNode = loader.introspectorFromName(nodeType); + } catch (AAIUnknownObjectException e) { + throw new AAIException("AAI_6115", "Unrecognized nodeType [" + nodeType + "] passed to node query."); + } + String propName = null; + String propValue = null; + if ( pieces.length >= 3) { + propName = this.findDbPropName(otherNode, pieces[2].toLowerCase()); + propValue = pieces[3]; + } + String[] edgeLabels = getEdgeLabel(targetNodeType, nodeType); + + GraphTraversal edgeSearch = __.start(); + + edgeSearch.both(edgeLabels); + if (propName != null) { + // check for matching property + if (propValue != null) { + edgeSearch.has(propName, propValue); + } else { + edgeSearch.has(propName); + } + } + + if( filterType.equals(DOES_NOT_EXIST)){ + traversal.where(__.not(edgeSearch)); + } else if (filterType.equals(EXISTS)) { + traversal.where(edgeSearch); + } + } + } + + List results = traversal.toList(); + Introspector searchResults = loader.introspectorFromName("search-results"); + List resultDataList = searchResults.getValue("result-data"); + for (Vertex thisNode: results){ + String nodeType = thisNode.property(AAIProperties.NODE_TYPE).orElse(null); + + String thisNodeURL = urlBuilder.pathed(thisNode); + Introspector resultData = loader.introspectorFromName("result-data"); + + resultData.setValue("resource-type", nodeType); + resultData.setValue("resource-link", thisNodeURL); + resultDataList.add(resultData.getUnderlyingObject()); + + } + + String outputMediaType = getMediaType(headers.getAcceptableMediaTypes()); + org.openecomp.aai.introspection.MarshallerProperties properties = new org.openecomp.aai.introspection.MarshallerProperties.Builder( + org.openecomp.aai.restcore.MediaType.getEnum(outputMediaType)).build(); + + result = searchResults.marshal(properties); + response = Response.ok().entity(result).build(); + + success = true; + } catch (AAIException e) { + success = false; + throw e; + } catch (Exception e) { + success = false; + throw new AAIException("AAI_5105", e); + } finally { + if (dbEngine != null) { + if (success) { + dbEngine.commit(); + } else { + dbEngine.rollback(); + } + } + } + + return response; + } + + private String findDbPropName(Introspector obj, String propName) { + + Optional result = obj.getPropertyMetadata(propName, PropertyMetadata.DB_ALIAS); + if (result.isPresent()) { + return result.get(); + } else { + return propName; + } + } + + + /** + * 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{ + Map rules = EdgeRules.getInstance().getEdgeRules(targetNodeType, nodeType); + String[] results = rules.keySet().toArray(new String[0]); + return results; + } + + + /** + * 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, + DBConnectionType connectionType, + 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(); + + Introspector inventoryItems; + boolean success = true; + TitanTransaction g = null; + TransactionalGraphEngine dbEngine = null; + try { + + Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, AAIProperties.LATEST); + dbEngine = new TitanDBEngine( + QueryStyle.TRAVERSAL, + connectionType, + loader); + DBSerializer serializer = new DBSerializer(AAIProperties.LATEST, dbEngine, ModelType.MOXY, fromAppId); + ModelBasedProcessing processor = new ModelBasedProcessing(loader, dbEngine, serializer); + + g = dbEngine.startTransaction(); + 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.ecomp.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) { + + DbMethHelper dbMethHelper = new DbMethHelper(loader, dbEngine); + List namedQueryVertices = dbMethHelper.locateUniqueVertices("named-query", namedQueryLookupHash); + for (Vertex vert : namedQueryVertices) { + namedQueryUuid = vert.property("named-query-uuid").orElse(null); + // there should only be one, we'll pick the first if not + break; + } + } + + String secondaryFilterCutPoint = null; + + if (modelAndNamedQuerySearch.isSet("secondaryFilterCutPoint")) { + secondaryFilterCutPoint = modelAndNamedQuerySearch.get("secondaryFilterCutPoint"); + } + + List> startNodeFilterHash = new ArrayList<>(); + + mapInstanceFilters((DynamicEntity)modelAndNamedQuerySearch.get("instanceFilters"), + startNodeFilterHash, jaxbContext); + + Map secondaryFilterHash = new HashMap<>(); + + mapSecondaryFilters((DynamicEntity)modelAndNamedQuerySearch.get("secondaryFilts"), + secondaryFilterHash, jaxbContext); + + List resultSet = processor.queryByNamedQuery(transId, fromAppId, + namedQueryUuid, startNodeFilterHash, aaiExtMap.getApiVersion(), secondaryFilterCutPoint, secondaryFilterHash); + + inventoryItems = loader.introspectorFromName("inventory-response-items"); + + List invItemList = unpackResultSet(resultSet, dbEngine, loader, serializer); + + inventoryItems.setValue("inventory-response-item", invItemList); + success = true; + } catch (AAIException e) { + success = false; + throw e; + } catch (Exception e) { + success = false; + throw new AAIException("AAI_5105", e); + } finally { + if (g != null) { + if (success) { + g.commit(); + } else { + g.rollback(); + } + } + } + + return getResponseFromIntrospector(inventoryItems, aaiExtMap.getHttpHeaders()); + } + + + /** + * 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, + DBConnectionType connectionType, + 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; + TransactionalGraphEngine dbEngine = null; + try { + + Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, AAIProperties.LATEST); + dbEngine = new TitanDBEngine( + QueryStyle.TRAVERSAL, + connectionType, + loader); + DBSerializer serializer = new DBSerializer(AAIProperties.LATEST, dbEngine, ModelType.MOXY, fromAppId); + ModelBasedProcessing processor = new ModelBasedProcessing(loader, dbEngine, serializer); + g = dbEngine.startTransaction(); + + + 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"); + } + + Map modelQueryLookupHash = new HashMap<>(); + + String modelVersionId = null; + String modelName = null; + String modelInvariantId = null; + String modelVersion = null; + String topNodeType = null; + + if (modelAndNamedQuerySearch.isSet("topNodeType")) { + topNodeType = modelAndNamedQuerySearch.get("topNodeType"); + } + + // the ways to get a model: + + // 1. model-version-id (previously model-name-version-id + // 2. model-invariant-id (previously model-id) + model-version + // 3. model-name + model-version + + // we will support both using the OverloadedModel object in the v9 oxm. This allows us to unmarshal + // either an old-style model or new-style model + model-ver object + if (modelAndNamedQuerySearch.isSet("queryParameters")) { + DynamicEntity qp = modelAndNamedQuerySearch.get("queryParameters"); + + if (qp.isSet("model")) { + DynamicEntity model = (DynamicEntity) qp.get("model"); + + // on an old-style model object, the following 4 attrs were all present + if (model.isSet("modelNameVersionId")) { + modelVersionId = model.get("modelNameVersionId"); + } + if (model.isSet("modelId")) { + modelInvariantId = model.get("modelId"); + } + if (model.isSet("modelName")) { + modelName = model.get("modelName"); + } + if (model.isSet("modelVersion")) { + modelVersion = model.get("modelVersion"); + } + + // new style splits model-invariant-id from the other 3 attrs. This is + // the only way to directly look up the model object + if (model.isSet("modelInvariantId")) { + modelInvariantId = model.get("modelInvariantId"); + } + + if (model.isSet("modelVers")) { + // we know that this is new style, because modelVers was not an option + // before v9 + DynamicEntity modelVers = (DynamicEntity) model.get("modelVers"); + if (modelVers.isSet("modelVer")) { + List modelVerList = modelVers.get("modelVer"); + // if they send more than one, too bad, they get the first one + DynamicEntity modelVer = modelVerList.get(0); + if (modelVer.isSet("modelName")) { + modelName = modelVer.get("modelName"); + } + if (modelVer.isSet("modelVersionId")) { + modelVersionId = modelVer.get("modelVersionId"); + } + if (modelVer.isSet("modelVersion")) { + modelVersion = modelVer.get("modelVersion"); + } + } + } + } + } + + List> startNodeFilterHash = new ArrayList<>(); + + String resourceVersion = mapInstanceFilters((DynamicEntity)modelAndNamedQuerySearch.get("instanceFilters"), + startNodeFilterHash, jaxbContext); + + if (isDelete) { + + List resultSet = processor.queryByModel(transId, fromAppId, + modelVersionId, modelInvariantId, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion() ); + + Map objectToVertMap = new HashMap<>(); + List invItemList = unpackResultSet(resultSet, dbEngine, loader, serializer); + + ResultSet rs = resultSet.get(0); + + TitanVertex firstVert = rs.getVert(); + String restURL = RestURL.get(g, firstVert); + + Map delResult = processor.runDeleteByModel( transId, fromAppId, + modelVersionId, 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((DynamicEntity)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 { + List resultSet = processor.queryByModel( transId, fromAppId, + modelVersionId, modelInvariantId, modelName, topNodeType, startNodeFilterHash, aaiExtMap.getApiVersion() ); + + Introspector inventoryItems = loader.introspectorFromName("inventory-response-items"); + + List invItemList = unpackResultSet(resultSet, dbEngine, loader, serializer); + + inventoryItems.setValue("inventory-response-item", invItemList); + + response = getResponseFromIntrospector(inventoryItems, aaiExtMap.getHttpHeaders()); + } + success = true; + } catch (AAIException e) { + success = false; + throw e; + } catch (Exception e) { + success = false; + throw new AAIException("AAI_5105", e); + } finally { + if (g != null) { + if (success) { + g.commit(); + } else { + g.rollback(); + } + } + } + + return response; + } + + private Response getResponseFromIntrospector(Introspector obj, HttpHeaders headers) { + boolean isJson = false; + for (MediaType mt : headers.getAcceptableMediaTypes()) { + if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) { + isJson = true; + break; + } + } + org.openecomp.aai.introspection.MarshallerProperties properties; + if (isJson) { + properties = + new org.openecomp.aai.introspection.MarshallerProperties.Builder(org.openecomp.aai.restcore.MediaType.APPLICATION_JSON_TYPE).build(); + } else { + properties = + new org.openecomp.aai.introspection.MarshallerProperties.Builder(org.openecomp.aai.restcore.MediaType.APPLICATION_XML_TYPE).build(); + } + + String marshalledObj = obj.marshal(properties); + return Response.ok().entity(marshalledObj).build(); + } + + /** + * 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, List> 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; + } + + /** + * Map secondary filters. + * + * @param secondaryFilts the secondary filters + * @param secondaryFilterHash the secondary filter hash + * @param jaxbContext the jaxb context + * @return the string + */ + private void mapSecondaryFilters(DynamicEntity secondaryFilts, Map secondaryFilterHash, DynamicJAXBContext jaxbContext) { + + if (secondaryFilts == null || !secondaryFilts.isSet("secondaryFilt")) { + return; + } + @SuppressWarnings("unchecked") + List secondaryFilter = (ArrayList)secondaryFilts.get("secondaryFilt"); + + for (DynamicEntity secondaryFilt : secondaryFilter) { + List any = secondaryFilt.get("any"); + + 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)) { + secondaryFilterHash.put(nodeType + "." + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName), anyEnt.get(propName)); + } + } + } + } + } + + /** + * 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, + Map includeTheseVertices, Map objectToVertMap, AAIExtensionMap aaiExtMap) { + + + DynamicEntity inventoryItem = jaxbContext.newDynamicEntity("inventory.aai.ecomp.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.ecomp.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 List unpackResultSet(List resultSetList, + TransactionalGraphEngine engine, + Loader loader, + DBSerializer serializer) throws AAIException { + + List resultList = new ArrayList<>(); + + for (ResultSet resultSet : resultSetList) { + + if( resultSet.getVert() == null ){ + continue; + } + + Introspector inventoryItem = loader.introspectorFromName("inventory-response-item"); + Introspector inventoryItems = loader.introspectorFromName("inventory-response-items"); + // add this inventoryItem to the resultList for this level + resultList.add(inventoryItem.getUnderlyingObject()); + + TitanVertex vert = resultSet.getVert(); + + Long vertId = (Long)vert.longId(); + + String aaiNodeType = vert.property("aai-node-type").orElse(null); + + + + PojoUtils pu = new PojoUtils(); + if (aaiNodeType != null) { + Introspector thisObj = loader.introspectorFromName(aaiNodeType); + + if (resultSet.getExtraPropertyHash() != null) { + Map extraProperties = resultSet.getExtraPropertyHash(); + + Introspector extraPropertiesEntity = loader.introspectorFromName("extra-properties"); + + List extraPropsList = extraPropertiesEntity.getValue("extra-property"); + + for (Map.Entry ent : extraProperties.entrySet()) { + String propName = ent.getKey(); + Object propVal = ent.getValue(); + + Introspector extraPropEntity = loader.introspectorFromName("extra-property"); + + extraPropEntity.setValue("property-name", propName); + extraPropEntity.setValue("property-value", propVal); + + extraPropsList.add(extraPropEntity.getUnderlyingObject()); + + } + inventoryItem.setValue("extra-properties", extraPropertiesEntity.getUnderlyingObject()); + } + + try { + serializer.dbToObject(Collections.singletonList(vert), thisObj, 0, true, "false"); + } catch (UnsupportedEncodingException e1) { + throw new AAIException("AAI_5105"); + } + PropertyLimitDesc propertyLimitDesc = resultSet.getPropertyLimitDesc(); + + if (propertyLimitDesc != null) { + + if (PropertyLimitDesc.SHOW_NONE.equals(propertyLimitDesc)) { + HashMap emptyPropertyOverRideHash = new HashMap(); + for (String key : thisObj.getAllKeys()) { + emptyPropertyOverRideHash.put(key, null); + } + filterProperties(thisObj, emptyPropertyOverRideHash); + } else if (PropertyLimitDesc.SHOW_ALL.equals(propertyLimitDesc)) { + //keep everything + } else if (PropertyLimitDesc.SHOW_NAME_AND_KEYS_ONLY.equals(propertyLimitDesc)) { + HashMap keysAndNamesPropHash = new HashMap(); + + for (String key : thisObj.getAllKeys()) { + keysAndNamesPropHash.put(key, null); + } + String namePropMetaData = thisObj.getMetadata(ObjectMetadata.NAME_PROPS); + if (namePropMetaData != null) { + String[] nameProps = namePropMetaData.split(","); + for (String names : nameProps) { + keysAndNamesPropHash.put(names, null); + } + } + filterProperties(thisObj, keysAndNamesPropHash); + } + } else { + if (resultSet.getPropertyOverRideHash() != null && resultSet.getPropertyOverRideHash().size() > 0) { + Map propertyOverRideHash = resultSet.getPropertyOverRideHash(); + if (propertyOverRideHash.containsKey("persona-model-id")) { + propertyOverRideHash.remove("persona-model-id"); + propertyOverRideHash.put("model-invariant-id", null); + } + for (String key : thisObj.getAllKeys()) { + propertyOverRideHash.put(key, null); + } + filterProperties(thisObj, propertyOverRideHash); + } else { + //keep everything + } + } + + if (thisObj != null) { + inventoryItem.setValue("item", thisObj.getUnderlyingObject()); + + String modelName = null; + try { + String modelInvariantIdLocal = (String)vert.property("model-invariant-id-local").orElse(null); // this one points at a model + String modelVersionIdLocal = (String)vert.property("model-version-id-local").orElse(null); // this one points at a model-ver + + if ( (modelInvariantIdLocal != null && modelVersionIdLocal != null) + && (modelInvariantIdLocal.length() > 0 && modelVersionIdLocal.length() > 0) ) { + HashMap modelLookupHash = new HashMap(); + + Introspector modelVer = loader.introspectorFromName("model-ver"); + modelVer.setValue("model-version-id", modelVersionIdLocal); + QueryBuilder builder = engine.getQueryBuilder().createDBQuery(modelVer); + + List modelVerVerts = builder.toList(); + if (modelVerVerts.size() != 1) { + throw new AAIException("AAI_6112"); + } + Vertex modelVerVert = modelVerVerts.get(0); + + modelName = modelVerVert.property("model-name").orElse(null); + + if (modelName != null && modelName.length() > 0) { + inventoryItem.setValue("model-name", 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) { + List subResultSet = resultSet.getSubResultSet(); + if (subResultSet != null && subResultSet.size() > 0 ) { + List res = unpackResultSet(subResultSet, engine, loader, serializer); + if (res.size() > 0) { + inventoryItems.setValue("inventory-response-item", res); + inventoryItem.setValue("inventory-response-items", inventoryItems.getUnderlyingObject()); + } + } + } + } + } + } + + return resultList; + } + + private void filterProperties(Introspector thisObj, Map override) { + + thisObj.getProperties().stream().filter(x -> { + return !override.containsKey(x); + }).forEach(prop -> { + if (thisObj.isSimpleType(prop)) { + thisObj.setValue(prop, null); + } + }); + + } + + /** + * 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; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java b/aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java new file mode 100644 index 0000000..d8a0ce7 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.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.dmaap; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Properties; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.TextMessage; +import javax.ws.rs.core.MediaType; + +import org.apache.log4j.MDC; +import org.eclipse.jetty.util.security.Password; +import org.json.JSONException; +import org.json.JSONObject; + +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.nsa.mr.client.MRBatchingPublisher; +import com.att.nsa.mr.client.MRClientFactory; +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.filter.HTTPBasicAuthFilter; + +public class AAIDmaapEventJMSConsumer implements MessageListener { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIDmaapEventJMSConsumer.class); + + private final static String COMPONENT = "aaiDmaapEvent"; + private MRBatchingPublisher adp = null; + + private Properties props; + + private String username; + private String password; + private String contentType; + + private String url; + private Client client; + + public AAIDmaapEventJMSConsumer() throws org.apache.commons.configuration.ConfigurationException { + super(); + + if (this.adp == null) { + try { + FileReader reader = new FileReader(new File(AAIConstants.AAI_EVENT_DMAAP_PROPS)); + props = new Properties(); + props.load(reader); + props.setProperty("DME2preferredRouterFilePath", AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "preferredRoute.txt"); + if (props.getProperty("password") != null && props.getProperty("password").startsWith("OBF:")) { + props.setProperty("password", Password.deobfuscate(props.getProperty("password"))); + } + this.adp = MRClientFactory.createBatchingPublisher(props); + + String host = props.getProperty("host"); + String topic = props.getProperty("topic"); + String protocol = props.getProperty("Protocol"); + + username = props.getProperty("username"); + password = props.getProperty("password"); + contentType = props.getProperty("contenttype"); + + url = protocol + "://" + host + "/events/" + topic; + client = Client.create(); + client.addFilter(new HTTPBasicAuthFilter(username, password)); + + } catch (IOException e) { + ErrorLogHelper.logError("AAI_4000", "Error updating dmaap config file for aai event."); + } + } + + } + + @Override + public void onMessage(Message message) { + + String jsmMessageTxt = ""; + String aaiEvent = ""; + String transId = ""; + String fromAppId = ""; + String fullId = ""; + + if (message instanceof TextMessage) { + try { + jsmMessageTxt = ((TextMessage) message).getText(); + JSONObject jo = new JSONObject(jsmMessageTxt); + + if (jo.has("aaiEventPayload")) { + aaiEvent = jo.getJSONObject("aaiEventPayload").toString(); + } else { + return; + } + if (jo.getString("transId") != null) { + MDC.put("requestId", jo.getString("transId")); + } + if (jo.getString("fromAppId") != null) { + MDC.put("partnerName", jo.getString("fromAppId")); + } + if (jo.getString("fullId") != null) { + fullId = jo.getString("fullId"); + } + + LOGGER.info(fullId + "|" + transId + "|" + fromAppId + "|" + aaiEvent); + + String environment = System.getProperty("lrmRO"); + + if (environment == null) { + this.adp.send(aaiEvent); + } else { + if (environment.startsWith("dev") || environment.startsWith("testINT") || environment.startsWith("testEXT")) { + + WebResource webResource = client.resource(url); + + ClientResponse response = webResource.accept(contentType).type(MediaType.APPLICATION_JSON).post(ClientResponse.class, aaiEvent); + + if (response.getStatus() != 200) { + System.out.println("Failed : HTTP error code : " + response.getStatus()); + } + } else { + this.adp.send(aaiEvent); + } + } + + } catch (IOException e) { + if (e instanceof java.net.SocketException) { + if (e.getMessage().contains("Connection reset")) { + } else { + ErrorLogHelper.logError("AAI_7304", "Error reaching DMaaP to send event. " + aaiEvent); + } + } else { + ErrorLogHelper.logError("AAI_7304", "Error reaching DMaaP to send event. " + aaiEvent); + } + } catch (JMSException | JSONException e) { + ErrorLogHelper.logError("AAI_7350", "Error parsing aaievent jsm message for sending to dmaap. " + jsmMessageTxt); + } + } + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java b/aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java new file mode 100644 index 0000000..305e585 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.command.ActiveMQQueue; +import org.json.JSONObject; +import org.springframework.jms.connection.CachingConnectionFactory; +import org.springframework.jms.core.JmsTemplate; + +public class AAIDmaapEventJMSProducer { + + private JmsTemplate jmsTemplate; + + public AAIDmaapEventJMSProducer() { + this.jmsTemplate = new JmsTemplate(); + this.jmsTemplate.setConnectionFactory(new CachingConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61446"))); + this.jmsTemplate.setDefaultDestination(new ActiveMQQueue("IN_QUEUE")); + } + + public void sendMessageToDefaultDestination(JSONObject finalJson) { + jmsTemplate.convertAndSend(finalJson.toString()); + CachingConnectionFactory ccf = (CachingConnectionFactory)this.jmsTemplate.getConnectionFactory(); + ccf.destroy(); + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java b/aai-traversal/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java new file mode 100644 index 0000000..167dae4 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/extensions/AAIExtensionMap.java @@ -0,0 +1,827 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.responseMessage.AAIResponseMessages; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.rest.db.DBRequest; +import org.openecomp.aai.rest.db.HttpEntry; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +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) + // ----------------------------------------------------------------------- + // objFromRequestType | String (ex. ?org.openecomp.aai.domain.yang.Vce?) (RO) + // ----------------------------------------------------------------------- + // objFromRequest | $TYPE {ObjFromRequestType) (RO) + // ----------------------------------------------------------------------- + // 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 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 TransactionalGraphEngine dbEngine; + private Loader loader; + private UriInfo uriInfo; + private DBRequest dbRequest; + private HttpEntry httpEntry; + /** + * 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 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; + } + + /** + * 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; + } + + public DBRequest getDbRequest() { + return dbRequest; + } + + public void setDbRequest(DBRequest dbRequest) { + this.dbRequest = dbRequest; + } + + public HttpEntry getHttpEntry() { + return httpEntry; + } + + public void setHttpEntry(HttpEntry httpEntry) { + this.httpEntry = httpEntry; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/extensions/ExtensionController.java b/aai-traversal/src/main/java/org/openecomp/aai/extensions/ExtensionController.java new file mode 100644 index 0000000..09cfe50 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/extensions/ExtensionController.java @@ -0,0 +1,145 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.util.AAIConfig; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class ExtensionController { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ExtensionController.class); + + /** + * 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 extensionClassName = "org.openecomp.aai.extensions." + + apiVersion.toLowerCase() + "." + namespace + "." + + resourceName + "Extension"; + String defaultErrorCallback = resourceName + "ExtensionErrorCallback"; + + 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) { + + Object ret = extension.invoke(clazz.newInstance(), aaiExtMap); + + if (ret instanceof Integer) { + 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) { + errorCallback.invoke(clazz.newInstance(), + aaiExtMap); + } else { + Method defaultErrorCallbackExtension = clazz + .getMethod( + defaultErrorCallback, + new Class[] { AAIExtensionMap.class }); + 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 + LOGGER.warn("Error while processing extension - " + aaiExtMap.getMessage()); + } + } + } + } catch (ClassNotFoundException ex) { + LOGGER.debug("Extension class not found: " + extensionClassName + ", method: " + methodName + "."); + } catch (NoSuchMethodException e) { + LOGGER.debug("Method " + methodName + " does not exist for class " + extensionClassName); + } catch (AAIException e) { + throw e; + } catch (Exception e) { + throw new AAIException("AAI_5105", e); + } + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java new file mode 100644 index 0000000..4798d90 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.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.interceptors; + +public class AAIHeaderProperties { + + public static final String REQUEST_CONTEXT = "aai-request-context"; +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java new file mode 100644 index 0000000..80127d0 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java @@ -0,0 +1,283 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.LoggingMessage; +import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor; +import org.apache.cxf.message.Message; + +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.logging.ErrorLogHelper; +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; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +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}$"); + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAILogJAXRSInInterceptor.class); + + /** + * {@inheritDoc} + */ + public void handleMessage(Message message) { + + boolean go = false; + 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) { + ErrorLogHelper.logException(e1); + } + + 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(); + + 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) { + LOGGER.debug("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 = ""; + 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 contentType = headersList.get("Content-Type"); + if (contentType == null) { + ct = (String)message.get(Message.CONTENT_TYPE); + headersList.put(Message.CONTENT_TYPE, Collections.singletonList(ct)); + } + + LOGGER.auditEvent("REST " + httpMethod + " " + ((query != null)? uri+"?"+query : uri) + " HbaseTxId=" + fullId); + LOGGER.info(logMsg); + } + + + 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()); + } + + /** + * Gen date. + * + * @param aaiLogger the aai logger + * @param logline the logline + * @return the string + */ + protected String genDate() { + Date date = new Date(); + DateFormat formatter = null; + try { + formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT)); + } catch (AAIException ex) { + ErrorLogHelper.logException(ex); + } finally { + if (formatter == null) { + formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS"); + } + } + + return formatter.format(date); + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java new file mode 100644 index 0000000..0f5e457 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java @@ -0,0 +1,323 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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 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.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +// right after the request is complete, there may be content +public class AAILogJAXRSOutInterceptor extends JAXRSOutInterceptor { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAILogJAXRSOutInterceptor.class); + + protected final String COMPONENT = "aairest"; + protected final String CAMEL_REQUEST = "CamelHttpUrl"; + + /** + * {@inheritDoc} + */ + public void handleMessage(Message message) { + + 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; + } + + // 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")) { + + 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) { + + String getValue = ""; + String postValue = ""; + String logValue = ""; + + try { + logValue = AAIConfig.get("aai.transaction.logging"); + getValue = AAIConfig.get("aai.transaction.logging.get"); + postValue = AAIConfig.get("aai.transaction.logging.post"); + } catch (AAIException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED") && !message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) { + return; + } + + 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; + } + } + } + + 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(); + } + + + String respTm = genDate(); + + 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) { + + } 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")) { + + 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", ""); + LOGGER.debug(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", ""); + + LOGGER.debug(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"; + } + + LOGGER.debug("action={}, urlin={}, HbTransId={}", httpMethod, fullUri, fullId); + + if (logValue.equals("false")) { + } else if (getValue.equals("false") && httpMethod.equals("GET")) { + } else if (postValue.equals("false") && httpMethod.equals("POST")) { + } else { + putTransaction(transId, responseCode.toString(), rqstTm, respTm, fromAppId + ":" + transId, fullUri, httpMethod, request, response, actualResponse); + + } + } + } catch (Exception ex) { + // ignore + } + + message.setContent(OutputStream.class, origStream); + + LOGGER.auditEvent("HTTP Response Code: {}", responseCode.toString()); + } + + } + + protected String genDate() { + Date date = new Date(); + DateFormat formatter = null; + try { + formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT)); + } catch (AAIException ex) { + ErrorLogHelper.logException(ex); + } finally { + if (formatter == null) { + formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS"); + } + } + return formatter.format(date); + } + + public String putTransaction(String tid, String status, String rqstTm, String respTm, String srcId, String rsrcId, String rsrcType, String rqstBuf, String respBuf, String actualResponse) { + String tm = null; + String fromAppId = srcId.substring(0, srcId.indexOf(':')); + String transId = srcId.substring(srcId.indexOf(':') + 1); + + 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; + + if (rqstTm == null || "".equals(rqstTm)) { + rqstTm = tm; + } + + if (respTm == null || "".equals(respTm)) { + respTm = tm; + } + + try { + LOGGER.debug(" transactionId:" + tid + " status: " + status + " rqstDate: " + rqstTm + " respDate: " + respTm + " sourceId: " + srcId + " resourceId: " + + rsrcId + " resourceType: " + rsrcType + " payload rqstBuf: " + rqstBuf + " payload respBuf: " + respBuf + " Payload Error Messages: " + actualResponse); + return htid; + } catch (Exception e) { + ErrorLogHelper.logError("AAI_4000", "Exception updating HBase:"); + return htid; + } + + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java new file mode 100644 index 0000000..3a4f899 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.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.interceptors; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.openecomp.aai.logging.LoggingContext; +import org.openecomp.aai.logging.LoggingContext.StatusCode; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import ajsc.beans.interceptors.AjscInterceptor; + +public class PostAaiAjscInterceptor implements AjscInterceptor { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(PostAaiAjscInterceptor.class); + + private static class LazyAaiAjscInterceptor { + public static final PostAaiAjscInterceptor INSTANCE = new PostAaiAjscInterceptor(); + } + + public static PostAaiAjscInterceptor getInstance() { + return LazyAaiAjscInterceptor.INSTANCE; + } + + @Override + public boolean allowOrReject(HttpServletRequest req, HttpServletResponse resp, Map paramMap) + throws Exception { + final String responseCode = LoggingContext.responseCode(); + + if (responseCode != null && responseCode.startsWith("ERR.")) { + LoggingContext.statusCode(StatusCode.ERROR); + LOGGER.error(req.getRequestURL() + " call failed with responseCode=" + responseCode); + } else { + LoggingContext.statusCode(StatusCode.COMPLETE); + LOGGER.info(req.getRequestURL() + " call succeeded"); + } + + LoggingContext.clear(); + return true; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java new file mode 100644 index 0000000..a2c56d0 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.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.interceptors; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.openecomp.aai.logging.LoggingContext; + +import ajsc.beans.interceptors.AjscInterceptor; + +public class PreAaiAjscInterceptor implements AjscInterceptor { + + private static class LazyAaiAjscInterceptor { + public static final PreAaiAjscInterceptor INSTANCE = new PreAaiAjscInterceptor(); + } + + public static PreAaiAjscInterceptor getInstance() { + return LazyAaiAjscInterceptor.INSTANCE; + } + + @Override + public boolean allowOrReject(HttpServletRequest req, HttpServletResponse resp, Map paramMap) + throws Exception { + + LoggingContext.init(); + + LoggingContext.requestId(req.getHeader("X-TransactionId")); + LoggingContext.partnerName(req.getHeader("X-FromAppId")); + LoggingContext.serviceName(req.getMethod() + " " + req.getRequestURI().toString()); + + return true; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java new file mode 100644 index 0000000..f1a6f47 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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 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(); + + //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)) + .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)) + .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)) + .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)) + .build(); + setError = 1; + } + } + if (setError == 0) { + response = Response + .status(400) + .type(MediaType.APPLICATION_JSON_TYPE) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars)) + .build(); + } + } + } + return response; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/QueryConsumer.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/QueryConsumer.java new file mode 100644 index 0000000..af1d350 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/QueryConsumer.java @@ -0,0 +1,182 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +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.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.dbmap.DBConnectionType; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.ModelType; +import org.openecomp.aai.introspection.Version; +import org.openecomp.aai.parsers.query.QueryParser; +import org.openecomp.aai.rest.db.HttpEntry; +import org.openecomp.aai.rest.search.GenericQueryProcessor; +import org.openecomp.aai.rest.search.QueryProcessorType; +import org.openecomp.aai.restcore.HttpMethod; +import org.openecomp.aai.restcore.RESTAPI; +import org.openecomp.aai.restcore.util.URITools; +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.serialization.queryformats.Format; +import org.openecomp.aai.serialization.queryformats.FormatFactory; +import org.openecomp.aai.serialization.queryformats.Formatter; +import org.openecomp.aai.serialization.queryformats.SubGraphStyle; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +@Path("{version: v9|v1[0]}/query") +public class QueryConsumer extends RESTAPI { + + /** The introspector factory type. */ + private ModelType introspectorFactoryType = ModelType.MOXY; + + private QueryProcessorType processorType = QueryProcessorType.GREMLIN_SERVER; + /** The query style. */ + private QueryStyle queryStyle = QueryStyle.TRAVERSAL; + @PUT + @Consumes({ MediaType.APPLICATION_JSON}) + @Produces({ MediaType.APPLICATION_JSON}) + public Response executeQuery(String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("graphson") @QueryParam("format") String queryFormat,@DefaultValue("no_op") @QueryParam("subgraph") String subgraph, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + + String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor"); + QueryProcessorType processorType = this.processorType; + Response response = null; + TransactionalGraphEngine dbEngine = null; + try { + + Format format = Format.valueOf(queryFormat); + if (queryProcessor != null) { + processorType = QueryProcessorType.valueOf(queryProcessor); + } + SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph); + JsonParser parser = new JsonParser(); + + JsonObject input = parser.parse(content).getAsJsonObject(); + + JsonElement startElement = input.get("start"); + JsonElement queryElement = input.get("query"); + JsonElement gremlinElement = input.get("gremlin"); + List startURIs = new ArrayList<>(); + String queryURI = ""; + String gremlin = ""; + + Version version = Version.valueOf(versionParam); + DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime); + HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type); + dbEngine = httpEntry.getDbEngine(); + + if (startElement != null) { + + if (startElement.isJsonArray()) { + for (JsonElement element : startElement.getAsJsonArray()) { + startURIs.add(new URI(element.getAsString())); + } + } else { + startURIs.add(new URI(startElement.getAsString())); + } + } + + if (queryElement != null) { + queryURI = queryElement.getAsString(); + } + if (gremlinElement != null) { + gremlin = gremlinElement.getAsString(); + } + URI queryURIObj = new URI(queryURI); + GenericQueryProcessor processor = null; + + if (!startURIs.isEmpty()) { + Set vertexSet = new LinkedHashSet<>(); + QueryParser uriQuery; + List vertices; + for (URI startUri : startURIs) { + uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(startUri, URITools.getQueryMap(startUri)); + vertices = uriQuery.getQueryBuilder().toList(); + vertexSet.addAll(vertices); + } + + processor = new GenericQueryProcessor.Builder(dbEngine) + .startFrom(vertexSet).queryFrom(queryURIObj) + .processWith(processorType).create(); + } else if (!queryURI.equals("")){ + processor = new GenericQueryProcessor.Builder(dbEngine) + .queryFrom(queryURIObj) + .processWith(processorType).create(); + } else { + processor = new GenericQueryProcessor.Builder(dbEngine) + .queryFrom(gremlin) + .processWith(processorType).create(); + } + String result = ""; + List vertices = processor.execute(subGraphStyle); + DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); + FormatFactory ff = new FormatFactory(httpEntry.getLoader(), serializer); + + Formatter formater = ff.get(format); + + result = formater.output(vertices).toString(); + + response = Response.status(Status.OK) + .type(MediaType.APPLICATION_JSON) + .entity(result).build(); + + } catch (AAIException e) { + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e); + } catch (Exception e ) { + AAIException ex = new AAIException("AAI_4000", e); + + response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex); + } finally { + if (dbEngine != null) { + dbEngine.rollback(); + } + } + + return response; + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/db/DBRequest.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/db/DBRequest.java new file mode 100644 index 0000000..e7b6858 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/db/DBRequest.java @@ -0,0 +1,251 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.rest.db; + +import java.net.URI; +import java.util.Optional; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.UriInfo; + +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.MarshallerProperties; +import org.openecomp.aai.parsers.query.QueryParser; +import org.openecomp.aai.restcore.HttpMethod; + +/** + * The Class DBRequest. + */ +public class DBRequest { + + private final QueryParser parser; + + private final Introspector introspector; + + private final HttpHeaders headers; + + private final String transactionId; + + private final UriInfo info; + + private final HttpMethod method; + + private final URI uri; + + private final Optional rawRequestContent; + + private final Optional marshallerProperties; + + + /** + * 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 + */ + private DBRequest(Builder builder) { + this.method = builder.getMethod(); + this.parser = builder.getParser(); + this.introspector = builder.getIntrospector(); + this.headers = builder.getHeaders(); + this.transactionId = builder.getTransactionId(); + this.info = builder.getInfo(); + this.uri = builder.getUri(); + this.marshallerProperties = builder.getMarshallerProperties(); + this.rawRequestContent = builder.getRawRequestContent(); + } + + /** + * Gets the headers. + * + * @return the headers + */ + public HttpHeaders getHeaders() { + return headers; + } + + + /** + * Gets the transaction id. + * + * @return the transaction id + */ + public String getTransactionId() { + return transactionId; + } + + /** + * Gets the info. + * + * @return the info + */ + public UriInfo getInfo() { + return info; + } + + /** + * Gets the parser. + * + * @return the parser + */ + public QueryParser getParser() { + return parser; + } + + /** + * Gets the introspector. + * + * @return the introspector + */ + public Introspector getIntrospector() { + return introspector; + } + + /** + * Gets the method. + * + * @return the method + */ + public HttpMethod getMethod() { + return method; + } + + /** + * Gets the uri. + * + * @return the uri + */ + public URI getUri() { + return uri; + } + + /** + * Gets the raw content. + * + * @return the raw content + */ + public Optional getRawRequestContent() { + return rawRequestContent; + } + + public Optional getMarshallerProperties() { + return marshallerProperties; + } + + + + public static class Builder { + + 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 Optional marshallerProperties = Optional.empty(); + + private Optional rawRequestContent = Optional.empty(); + /** + * 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 Builder(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; + + } + + public QueryParser getParser() { + return parser; + } + + public Introspector getIntrospector() { + return introspector; + } + + public HttpHeaders getHeaders() { + return headers; + } + + public String getTransactionId() { + return transactionId; + } + + public UriInfo getInfo() { + return info; + } + + public HttpMethod getMethod() { + return method; + } + + public URI getUri() { + return uri; + } + + public Builder customMarshaller(MarshallerProperties properties) { + this.marshallerProperties = Optional.of(properties); + return this; + } + + public Builder rawRequestContent(String content) { + this.rawRequestContent = Optional.of(content); + return this; + } + protected Optional getMarshallerProperties() { + return marshallerProperties; + } + protected Optional getRawRequestContent() { + return rawRequestContent; + } + public DBRequest build() { + + return new DBRequest(this); + } + + + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java new file mode 100644 index 0000000..60438de --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java @@ -0,0 +1,672 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +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.Vertex; +import org.javatuples.Pair; + +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.dbmap.DBConnectionType; +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.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.parsers.query.QueryParser; +import org.openecomp.aai.parsers.uri.URIToExtensionInformation; +import org.openecomp.aai.rest.ueb.UEBNotification; +import org.openecomp.aai.restcore.HttpMethod; +import org.openecomp.aai.schema.enums.ObjectMetadata; +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 org.openecomp.aai.serialization.engines.query.QueryEngine; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +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.TitanException; +import com.thinkaurelius.titan.core.TitanTransaction; + +/** + * The Class HttpEntry. + */ +public class HttpEntry { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(HttpEntry.class); + + private final ModelType introspectorFactoryType; + + private final QueryStyle queryStyle; + + private final Version version; + + private final Loader loader; + + private final TransactionalGraphEngine dbEngine; + + private boolean processSingle = true; + + /** + * 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, DBConnectionType connectionType) { + this.introspectorFactoryType = modelType; + this.queryStyle = queryStyle; + this.version = version; + this.loader = LoaderFactory.createLoaderForVersion(introspectorFactoryType, version); + this.dbEngine = new TitanDBEngine( + queryStyle, + connectionType, + loader); + //start transaction on creation + dbEngine.startTransaction(); + + } + + /** + * 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; + } + + public Pair>> process (List requests, String sourceOfTruth) throws AAIException { + return this.process(requests, sourceOfTruth, true); + } + /** + * Process. + * @param requests the requests + * @param sourceOfTruth the source of truth + * + * @return the pair + * @throws AAIException the AAI exception + */ + public Pair>> process (List requests, String sourceOfTruth, boolean enableResourceVersion) throws AAIException { + DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); + Response response = null; + Status status = Status.NOT_FOUND; + Introspector obj = null; + QueryParser query = null; + URI uri = null; + String transactionId = null; + UEBNotification notification = new UEBNotification(loader); + int depth = AAIProperties.MAXIMUM_DEPTH; + List> responses = new ArrayList<>(); + MultivaluedMap params = null; + HttpMethod method = null; + String uriTemp = ""; + Boolean success = true; + QueryEngine queryEngine = dbEngine.getQueryEngine(); + int maxRetries = 10; + int retry = 0; + for (DBRequest request : requests) { + try { + for (retry = 0; retry < maxRetries; ++retry) { + try { + method = request.getMethod(); + obj = request.getIntrospector(); + query = request.getParser(); + transactionId = request.getTransactionId(); + uriTemp = request.getUri().getRawPath().replaceFirst("^v\\d+/", ""); + uri = UriBuilder.fromPath(uriTemp).build(); + List vertices = query.getQueryBuilder().toList(); + boolean isNewVertex = false; + String outputMediaType = getMediaType(request.getHeaders().getAcceptableMediaTypes()); + String result = null; + params = request.getInfo().getQueryParameters(false); + depth = setDepth(obj, params.getFirst("depth")); + String cleanUp = params.getFirst("cleanup"); + String requestContext = ""; + List requestContextList = request.getHeaders().getRequestHeader("aai-request-context"); + if (requestContextList != null) { + requestContext = requestContextList.get(0); + } + + 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)) { + String resourceVersion = (String)obj.getValue("resource-version"); + if (vertices.size() == 1) { + if (enableResourceVersion) { + serializer.verifyResourceVersion("update", query.getResultType(), (String)vertices.get(0).property("resource-version").orElse(null), resourceVersion, obj.getURI()); + } + isNewVertex = false; + } else { + if (enableResourceVersion) { + 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 = vertices.get(0); + } + HashMap relatedObjects = new HashMap<>(); + switch (method) { + case GET: + String nodeOnly = params.getFirst("nodes-only"); + boolean isNodeOnly = nodeOnly != null; + + obj = this.getObjectFromDb(vertices, serializer, query, obj, request.getUri(), depth, isNodeOnly, cleanUp); + if (obj != null) { + status = Status.OK; + MarshallerProperties properties; + if (!request.getMarshallerProperties().isPresent()) { + properties = + new MarshallerProperties.Builder(org.openecomp.aai.restcore.MediaType.getEnum(outputMediaType)).build(); + } else { + properties = request.getMarshallerProperties().get(); + } + result = obj.marshal(properties); + } + + break; + case PUT: + response = this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true); + if (isNewVertex) { + v = serializer.createNewVertex(obj); + } else { + serializer.touchStandardVertexProperties(v, false); + } + serializer.serializeToDb(obj, v, query, uri.getRawPath(), requestContext); + this.invokeExtension(dbEngine, this.dbEngine.tx(), HttpMethod.PUT, request, sourceOfTruth, version, loader, obj, uri, false); + status = Status.OK; + if (isNewVertex) { + status = Status.CREATED; + } + obj = serializer.getLatestVersionView(v); + if (query.isDependent()) { + relatedObjects = this.getRelatedObjects(serializer, queryEngine, v); + } + notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects); + + break; + case PUT_EDGE: + serializer.touchStandardVertexProperties(v, false); + serializer.createEdge(obj, v); + status = Status.OK; + break; + case MERGE_PATCH: + Introspector existingObj = (Introspector) obj.clone(); + existingObj = this.getObjectFromDb(vertices, serializer, query, existingObj, request.getUri(), 0, false, cleanUp); + String existingJson = existingObj.marshal(false); + String newJson; + + if (request.getRawRequestContent().isPresent()) { + newJson = request.getRawRequestContent().get(); + } else { + newJson = ""; + } + Object relationshipList = request.getIntrospector().getValue("relationship-list"); + 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); + if (relationshipList == null) { + //if the caller didn't touch the relationship-list, we shouldn't either + patchedObj.setValue("relationship-list", null); + } + serializer.touchStandardVertexProperties(v, false); + serializer.serializeToDb(patchedObj, v, query, uri.getRawPath(), requestContext); + status = Status.OK; + patchedObj = serializer.getLatestVersionView(v); + if (query.isDependent()) { + relatedObjects = this.getRelatedObjects(serializer, queryEngine, v); + } + notification.createNotificationEvent(transactionId, 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, queryEngine, v); + } + this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, true); + serializer.delete(v, resourceVersion, enableResourceVersion); + this.invokeExtension(dbEngine, this.dbEngine.tx(), method, request, sourceOfTruth, version, loader, obj, uri, false); + status = Status.NO_CONTENT; + notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects); + break; + case DELETE_EDGE: + serializer.touchStandardVertexProperties(v, false); + 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 && v != null && ( + method.equals(HttpMethod.PUT) + || method.equals(HttpMethod.GET) + || method.equals(HttpMethod.MERGE_PATCH)) + ) { + String myvertid = v.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); + //break out of retry loop + break; + } catch (TitanException e) { + this.dbEngine.rollback(); + AAIException ex = new AAIException("AAI_6142", e); + ErrorLogHelper.logException(ex); + Thread.sleep((retry + 1) * 20); + this.dbEngine.startTransaction(); + queryEngine = dbEngine.getQueryEngine(); + serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth); + } + + if (retry == maxRetries) { + throw new AAIException("AAI_6134"); + } + } + } 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()); + + response = Response + .status(e.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), e, templateVars)) + .build(); + Pair pairedResp = Pair.with(request.getUri(), response); + responses.add(pairedResp); + continue; + } catch (Exception e) { + success = false; + e.printStackTrace(); + 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()); + + response = Response + .status(ex.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), ex, templateVars)) + .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 + * @throws AAIUnknownObjectException + * @throws URISyntaxException + */ + private Introspector getObjectFromDb(List results, DBSerializer serializer, QueryParser query, Introspector obj, URI uri, int depth, boolean nodeOnly, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIUnknownObjectException, URISyntaxException { + + //nothing found + if (results.size() == 0) { + String msg = createNotFoundMessage(query.getResultType(), uri); + throw new AAIException("AAI_6114", msg); + } + + obj = serializer.dbToObject(results, obj, depth, nodeOnly, 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, DBRequest request, String fromAppId, Version apiVersion, Loader loader, Introspector obj, URI uri, boolean isPreprocess) throws IllegalArgumentException, UnsupportedEncodingException, AAIException { + AAIExtensionMap aaiExtMap = new AAIExtensionMap(); + ModelInjestor injestor = ModelInjestor.getInstance(); + Response response = null; + URIToExtensionInformation extensionInformation = new URIToExtensionInformation(loader, uri); + aaiExtMap.setHttpEntry(this); + aaiExtMap.setDbRequest(request); + aaiExtMap.setTransId(request.getTransactionId()); + aaiExtMap.setFromAppId(fromAppId); + aaiExtMap.setGraph(g); + aaiExtMap.setApiVersion(apiVersion.toString()); + aaiExtMap.setObjectFromRequest(obj); + aaiExtMap.setObjectFromRequestType(obj.getJavaClassName()); + aaiExtMap.setObjectFromResponse(obj); + 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, request.getHeaders()); + } + + 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; + HashMap> exceptionList = new HashMap>(); + + String keyString = ""; + + Set 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)) + .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(Introspector obj, String depthParam) throws AAIException { + int depth = AAIProperties.MAXIMUM_DEPTH; + + if(depthParam == null){ + if(this.version.compareTo(Version.v9) >= 0){ + depth = 0; + } else { + depth = AAIProperties.MAXIMUM_DEPTH; + } + } else { + if (depthParam.length() > 0 && !depthParam.equals("all")){ + try { + depth = Integer.valueOf(depthParam); + } catch (Exception e) { + throw new AAIException("AAI_4016"); + } + + } + } + String maxDepth = obj.getMetadata(ObjectMetadata.MAXIMUM_DEPTH); + + int maximumDepth = AAIProperties.MAXIMUM_DEPTH; + + if(maxDepth != null){ + try { + maximumDepth = Integer.parseInt(maxDepth); + } catch(Exception ex){ + throw new AAIException("AAI_4018"); + } + } + + if(depth > maximumDepth){ + throw new AAIException("AAI_3303"); + } + + 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) || method.equals(HttpMethod.MERGE_PATCH)) { + result = true; + } + + return result; + + } + + private HashMap getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, URISyntaxException { + HashMap relatedVertices = new HashMap<>(); + List vertexChain = queryEngine.findParents(v); + for (Vertex vertex : vertexChain) { + try { + final Introspector vertexObj = serializer.getVertexProperties(vertex); + relatedVertices.put(vertexObj.getObjectId(), vertexObj); + } catch (AAIUnknownObjectException e) { + LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned"); + } + + } + + return relatedVertices; + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java new file mode 100644 index 0000000..99974ef --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java @@ -0,0 +1,143 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.retired; + +import java.util.ArrayList; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.cxf.jaxrs.ext.PATCH; + +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.restcore.RESTAPI; +import org.openecomp.aai.util.AAIConfig; + +/** + * The Class RetiredConsumer. + */ +public abstract class RetiredConsumer extends RESTAPI { + + /** + * Creates the message get. + * + * @param versionParam the version param + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @GET + @Path("/{uri:.*}") + public Response createMessageGet(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + return createMessage(versionParam, headers, info, req); + } + + /** + * Creates the message delete. + * + * @param versionParam the version param + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @DELETE + @Path("/{uri:.*}") + public Response createMessageDelete(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + return createMessage(versionParam, headers, info, req); + } + + /** + * Creates the message post. + * + * @param versionParam the version param + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @POST + @Path("/{uri:.*}") + public Response createMessagePost(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + return createMessage(versionParam, headers, info, req); + } + + @PATCH + @Path("/{uri:.*}") + public Response createMessagePatch(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + return createMessage(versionParam, headers, info, req); + } + /** + * Creates the message put. + * + * @param versionParam the version param + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + @PUT + @Path("/{uri:.*}") + public Response createMessagePut(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) { + return createMessage(versionParam, headers, info, req); + } + + + /** + * Creates the message. + * + * @param versionParam the version param + * @param headers the headers + * @param info the info + * @param req the req + * @return the response + */ + private Response createMessage(String versionParam, HttpHeaders headers, UriInfo info, HttpServletRequest req) { + AAIException e = new AAIException("AAI_3007"); + + ArrayList templateVars = new ArrayList(); + + if (templateVars.size() == 0) { + templateVars.add("PUT"); + templateVars.add(info.getPath().toString()); + templateVars.add(versionParam); + templateVars.add(AAIConfig.get("aai.default.api.version", "")); + } + + Response response = Response + .status(e.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, + templateVars)).build(); + + return response; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java new file mode 100644 index 0000000..55d9482 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.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.rest.retired; + +import javax.ws.rs.Path; + +@Path("{version: v[3-7]}") +public class V3ThroughV7Consumer extends RetiredConsumer { + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.java new file mode 100644 index 0000000..3f022a2 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.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.rest.retired; + +import javax.ws.rs.Path; + +@Path("{version: v[78]}/service-design-and-creation/named-queries") +public class V7V8NamedQueries extends RetiredConsumer { + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GenericQueryProcessor.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GenericQueryProcessor.java new file mode 100644 index 0000000..2e9e6a5 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GenericQueryProcessor.java @@ -0,0 +1,227 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.io.FileNotFoundException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +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.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.javatuples.Pair; + +import org.openecomp.aai.restcore.util.URITools; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +import org.openecomp.aai.serialization.queryformats.SubGraphStyle; + +import jersey.repackaged.com.google.common.base.Joiner; + +public abstract class GenericQueryProcessor { + + protected final Optional uri; + protected final MultivaluedMap queryParams; + protected final Optional> vertices; + protected static Pattern p = Pattern.compile("query/(.*+)"); + protected Optional gremlin; + protected final TransactionalGraphEngine dbEngine; + protected static GremlinServerSingleton gremlinServerSingleton = GremlinServerSingleton.getInstance(); + protected final boolean isGremlin; + + protected GenericQueryProcessor(Builder builder) { + this.uri = builder.getUri(); + this.dbEngine = builder.getDbEngine(); + this.vertices = builder.getVertices(); + this.gremlin = builder.getGremlin(); + this.isGremlin = builder.isGremlin(); + if (uri.isPresent()) { + queryParams = URITools.getQueryMap(uri.get()); + } else { + queryParams = new MultivaluedHashMap<>(); + } + } + + protected abstract GraphTraversal runQuery(String query, Map params); + + protected List processSubGraph(SubGraphStyle style, GraphTraversal g) { + final List resultVertices = new Vector<>(); + g.store("x"); + + if (SubGraphStyle.prune.equals(style) || SubGraphStyle.star.equals(style)) { + g.barrier().bothE(); + if (SubGraphStyle.prune.equals(style)) { + g.where(__.otherV().where(P.within("x"))); + } + g.dedup().subgraph("subGraph").cap("subGraph").map(x -> (Graph)x.get()).next().traversal().V().forEachRemaining(x -> { + resultVertices.add(x); + }); + } else { + resultVertices.addAll(g.toList()); + } + return resultVertices; + } + + public List execute(SubGraphStyle style) throws FileNotFoundException { + final List resultVertices; + + Pair> tuple = this.createQuery(); + String query = tuple.getValue0(); + Map params = tuple.getValue1(); + + if (query.equals("") && (vertices.isPresent() && vertices.get().isEmpty())) { + //nothing to do, just exit + return new ArrayList<>(); + } + GraphTraversal g = this.runQuery(query, params); + + resultVertices = this.processSubGraph(style, g); + + return resultVertices; + } + + protected Pair> createQuery() { + Map params = new HashMap<>(); + String query = ""; + if (!this.isGremlin) { + Matcher m = p.matcher(uri.get().getPath()); + String queryName = ""; + if (m.find()) { + queryName = m.group(1); + } + + for (String key : queryParams.keySet()) { + params.put(key, queryParams.getFirst(key)); + } + + query = gremlinServerSingleton.getStoredQuery(queryName); + if (query == null) { + query = ""; + } + + List ids = new ArrayList<>(); + + if (vertices.isPresent() && !vertices.get().isEmpty()) { + for (Vertex v : vertices.get()) { + ids.add(v.id()); + } + StringBuilder sb = new StringBuilder(); + sb.append("["); + sb.append(Joiner.on(",").join(ids)); + sb.append("]"); + String startPrefix = "aaiStartQuery = " + sb.toString() + " as Object[];g.V(aaiStartQuery)"; + if (!"".equals(query)) { + query = startPrefix + "." + query; + } else { + query = startPrefix; + } + } + + } else { + query = gremlin.get(); + } + + return new Pair<>(query, params); + } + + public static class Builder { + + private final TransactionalGraphEngine dbEngine; + private Optional uri = Optional.empty(); + private Optional gremlin = Optional.empty(); + private boolean isGremlin = false; + private Optional> vertices = Optional.empty(); + private QueryProcessorType processorType = QueryProcessorType.GREMLIN_SERVER; + + public Builder(TransactionalGraphEngine dbEngine) { + this.dbEngine = dbEngine; + } + + public Builder queryFrom(URI uri) { + this.uri = Optional.of(uri); + this.isGremlin = false; + return this; + } + + public Builder startFrom(Collection vertices) { + this.vertices = Optional.of(vertices); + return this; + } + + public Builder queryFrom(String gremlin) { + this.gremlin = Optional.of(gremlin); + this.isGremlin = true; + return this; + } + + public Builder processWith(QueryProcessorType type) { + this.processorType = type; + return this; + } + public TransactionalGraphEngine getDbEngine() { + return dbEngine; + } + + public Optional getUri() { + return uri; + } + + public Optional getGremlin() { + return gremlin; + } + + public boolean isGremlin() { + return isGremlin; + } + + public Optional> getVertices() { + return vertices; + } + + public QueryProcessorType getProcessorType() { + return processorType; + } + + public GenericQueryProcessor create() { + + if (this.getProcessorType().equals(QueryProcessorType.GREMLIN_SERVER)) { + return new GremlinServerImpl(this); + } else if (this.getProcessorType().equals(QueryProcessorType.LOCAL_GROOVY)) { + return new GroovyShellImpl(this); + } else { + return new GremlinServerImpl(this); + } + } + + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinGroovyShellSingleton.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinGroovyShellSingleton.java new file mode 100644 index 0000000..64159a4 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinGroovyShellSingleton.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.rest.search; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.PropertyExpression; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer; +import org.codehaus.groovy.control.customizers.ImportCustomizer; + +import groovy.lang.Binding; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import groovy.transform.TimedInterrupt; + +/** + * Creates and returns a groovy shell with the + * configuration to statically import graph classes + * + */ +public class GremlinGroovyShellSingleton { + + private final GroovyShell shell; + private GremlinGroovyShellSingleton() { + Map parameters = new HashMap<>(); + parameters.put("value", 30000); + parameters.put("unit", new PropertyExpression(new ClassExpression(ClassHelper.make(TimeUnit.class)),"MILLISECONDS")); + + ASTTransformationCustomizer custom = new ASTTransformationCustomizer(parameters, TimedInterrupt.class); + ImportCustomizer imports = new ImportCustomizer(); + imports.addStaticStars( + "org.apache.tinkerpop.gremlin.process.traversal.P" + ); + imports.addImports( + "org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__", + "org.apache.tinkerpop.gremlin.structure.T", + "org.apache.tinkerpop.gremlin.process.traversal.P"); + CompilerConfiguration config = new CompilerConfiguration(); + config.addCompilationCustomizers(custom, imports); + + this.shell = new GroovyShell(config); + } + + private static class Helper { + private static final GremlinGroovyShellSingleton INSTANCE = new GremlinGroovyShellSingleton(); + } + + public static GremlinGroovyShellSingleton getInstance() { + + return Helper.INSTANCE; + } + + /** + * @param traversal + * @param params + * @return result of graph traversal + */ + public GraphTraversal executeTraversal (String traversal, Map params) { + Binding binding = new Binding(params); + Script script = shell.parse(traversal); + script.setBinding(binding); + return (GraphTraversal) script.run(); + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerImpl.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerImpl.java new file mode 100644 index 0000000..a759b86 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerImpl.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.rest.search; + +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.tinkerpop.gremlin.driver.Client; +import org.apache.tinkerpop.gremlin.driver.Cluster; +import org.apache.tinkerpop.gremlin.driver.ResultSet; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; + +import org.openecomp.aai.util.AAIConfig; + +public class GremlinServerImpl extends GenericQueryProcessor { + + + protected GremlinServerImpl(Builder builder) { + super(builder); + } + + + @Override + protected GraphTraversal runQuery(String query, Map params) { + + //must force them into ids because of serialization issue with + //tinkerpop-3.0.1-incubating + query += ".id()"; + String rebindGraph = AAIConfig.get("aai.server.rebind", "g"); + + if(!"g".equals(rebindGraph)){ + query = query.replaceFirst("g\\.V\\(", rebindGraph + ".V("); + } + + Cluster cluster = gremlinServerSingleton.getCluster(); + Client client = cluster.connect(); + + ResultSet results = client.submit(query, params); + + + List vIds = new Vector<>(); + results.stream().forEach(x -> { + Object obj = x.getObject(); + vIds.add(obj); + }); + + client.close(); + + if (vIds.isEmpty()) { + return __.start(); + } else { + return this.dbEngine.asAdmin().getTraversalSource().V(vIds.toArray()); + } + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerSingleton.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerSingleton.java new file mode 100644 index 0000000..c54b310 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GremlinServerSingleton.java @@ -0,0 +1,130 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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 org.openecomp.aai.util.AAIConstants; +import org.openecomp.aai.util.FileWatcher; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.apache.tinkerpop.gremlin.driver.Cluster; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Date; +import java.util.Properties; +import java.util.Timer; +import java.util.TimerTask; + +public class GremlinServerSingleton { + + private static EELFLogger logger = EELFManager.getInstance().getLogger(GremlinServerSingleton.class); + + private Cluster cluster; + private boolean timerSet; + private Timer timer; + private Properties properties; + + private static class Helper { + private static final GremlinServerSingleton INSTANCE = new GremlinServerSingleton(); + } + + public static GremlinServerSingleton getInstance() { + return Helper.INSTANCE; + } + + private GremlinServerSingleton(){ + init(); + } + + /** + * Initializes the gremlin server singleton + * Loads the configuration of the gremlin server and creates a cluster + * Loads the gremlin query file into the properties object + * Then creates a file watcher to watch the file every ten seconds + * and if there is a change in the file, then reloads the file into + * the properties object + * + */ + private void init() { + + properties = new Properties(); + + try { + cluster = Cluster.build(new File(AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "gremlin-server-config.yaml")) + .maxContentLength(6537920) + .create(); + } catch (FileNotFoundException e) { + logger.error("Unable to find the file: " + e); + } + + File queryFile = new File(AAIConstants.AAI_HOME_ETC_QUERY); + + try (FileInputStream fis = new FileInputStream(queryFile)){ + properties.load(fis); + } catch (IOException e) { + logger.error("Error occurred during the processing of query file: " + e); + } + + + TimerTask task = new FileWatcher(new File(AAIConstants.AAI_HOME_ETC_QUERY)) { + @Override + protected void onChange(File file) { + File queryFile = new File(AAIConstants.AAI_HOME_ETC_QUERY); + try (FileInputStream fis = new FileInputStream(queryFile)){ + properties.load(fis); + logger.debug("File: " + file + " was changed so the cluster is rebuild for gremlin server"); + } catch (FileNotFoundException e) { + logger.error("Unable to find the file: " + e); + } catch (IOException e) { + logger.error("Error occurred during the processing of query file: " + e); + } + } + }; + + if (!timerSet) { + timerSet = true; + timer = new Timer(); + timer.schedule( task , new Date(), 10000 ); + } + + } + + public Cluster getCluster(){ + return cluster; + } + + /** + * Gets the key if the properties contains that key + * + * Purposely not checking if the property exists due + * to if you check for the property and then get the property + * Then you are going to have to synchronize the method + * + * @param key the query to check if it exists in the file + * @return string if the key exists or null if it doesn't + */ + public String getStoredQuery(String key){ + return (String) properties.get(key); + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GroovyShellImpl.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GroovyShellImpl.java new file mode 100644 index 0000000..1b64d21 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/GroovyShellImpl.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.rest.search; + +import java.util.Map; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; + +import org.openecomp.aai.restcore.search.GremlinGroovyShellSingleton; + +public class GroovyShellImpl extends GenericQueryProcessor { + + protected GroovyShellImpl(Builder builder) { + super(builder); + } + + @Override + protected GraphTraversal runQuery(String query, Map params) { + + params.put("g", this.dbEngine.asAdmin().getTraversalSource()); + + GremlinGroovyShellSingleton shell = GremlinGroovyShellSingleton.getInstance(); + + return shell.executeTraversal(query, params); + } + +} + + diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java new file mode 100644 index 0000000..f333dd8 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/ModelAndNamedQueryRestProvider.java @@ -0,0 +1,203 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.rest.search; + +import java.util.ArrayList; + +import javax.servlet.http.HttpServletRequest; +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.openecomp.aai.dbgraphmap.SearchGraph; +import org.openecomp.aai.dbmap.DBConnectionType; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.extensions.AAIExtensionMap; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.restcore.RESTAPI; +import org.openecomp.aai.util.AAIApiVersion; + +/** + * 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"; + + 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; + String rqstTm = genDate(); + ArrayList templateVars = new ArrayList(); + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + + AAIExtensionMap aaiExtMap = new AAIExtensionMap(); + aaiExtMap.setHttpHeaders(headers); + aaiExtMap.setServletRequest(req); + aaiExtMap.setApiVersion(AAIApiVersion.get()); + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + //only consider header value for search + DBConnectionType type = this.determineConnectionType("force-cache", realTime); + + SearchGraph searchGraph = new SearchGraph(); + response = searchGraph.runNamedQuery(fromAppId, transId, queryParameters, type, aaiExtMap); + + String respTm = genDate(); + logTransaction(fromAppId, transId, "GETSDNZONERESPONSE", + req.getRequestURI(), rqstTm, respTm, "", response); + + } 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)) + .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)) + .build(); + } finally { + // log success or failure + if (ex != null) { + ErrorLogHelper.logException(ex); + } + } + 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; + String rqstTm = genDate(); + ArrayList templateVars = new ArrayList(); + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + + AAIExtensionMap aaiExtMap = new AAIExtensionMap(); + aaiExtMap.setHttpHeaders(headers); + aaiExtMap.setServletRequest(req); + aaiExtMap.setApiVersion(AAIApiVersion.get()); + aaiExtMap.setFromAppId(fromAppId); + aaiExtMap.setTransId(transId); + + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + //only consider header value for search + DBConnectionType type = this.determineConnectionType("force-cache", realTime); + + SearchGraph searchGraph = new SearchGraph(); + if (action != null && action.equalsIgnoreCase("DELETE")) { + response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, type, true, aaiExtMap); + } else { + response = searchGraph.executeModelOperation(fromAppId, transId, inboundPayload, type, false, aaiExtMap); + } + String respTm = genDate(); + logTransaction(fromAppId, transId, "POSTMODELQUERYRESPONSE", + req.getRequestURI(), rqstTm, respTm, "", response); + + } 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)) + .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)) + .build(); + } finally { + // log success or failure + if (ex != null) { + ErrorLogHelper.logException(ex); + } + } + return response; + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/QueryProcessorType.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/QueryProcessorType.java new file mode 100644 index 0000000..33d7a90 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/QueryProcessorType.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.rest.search; + +public enum QueryProcessorType { + + GREMLIN_SERVER, + LOCAL_GROOVY +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java new file mode 100644 index 0000000..d6712ce --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/search/SearchProvider.java @@ -0,0 +1,269 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.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.eclipse.persistence.dynamic.DynamicEntity; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; + +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.dbgraphmap.SearchGraph; +import org.openecomp.aai.dbmap.DBConnectionType; +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.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.ErrorLogHelper; +import org.openecomp.aai.restcore.RESTAPI; +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 org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; +import org.openecomp.aai.util.AAIApiVersion; + +/** + * Implements the search subdomain in the REST API. All API calls must include + * X-FromAppId and X-TransactionId in the header. + * + + * + */ + +@Path("/{version: v2|v[789]|v1[0]|latest}/search") +public class SearchProvider extends RESTAPI { + + protected static String authPolicyFunctionName = "search"; + + 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, + @PathParam("version")String versionParam + ) { + + AAIException ex = null; + Response searchResult = null; + String fromAppId = null; + String transId = null; + String rqstTm = genDate(); + ArrayList templateVars = new ArrayList(); + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + //only consider header value for search + DBConnectionType type = this.determineConnectionType("force-cache", realTime); + final Version version; + if (versionParam.equals("latest")) { + version = AAIProperties.LATEST; + } else { + version = Version.valueOf(versionParam); + } + final ModelType factoryType = ModelType.MOXY; + Loader loader = LoaderFactory.createLoaderForVersion(factoryType, version); + TransactionalGraphEngine dbEngine = new TitanDBEngine( + QueryStyle.TRAVERSAL, + type, + loader); + DBSerializer dbSerializer = new DBSerializer(version, dbEngine, factoryType, fromAppId); + UrlBuilder urlBuilder = new UrlBuilder(version, dbSerializer); + SearchGraph searchGraph = new SearchGraph(); + searchResult = searchGraph.runGenericQuery( + headers, + startNodeType, + startNodeKeyParams, + includeNodeTypes, + depth, + dbEngine, + loader, + urlBuilder + + ); + + String respTm = genDate(); + logTransaction(fromAppId, transId, + "GETGENERICQUERYRESPONSE", req.getRequestURI(), rqstTm, respTm, + "", searchResult); + + } 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)) + .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)) + .build(); + } finally { + // log success or failure + if (ex != null){ + ErrorLogHelper.logException(ex); + } + } + + 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, + @PathParam("version")String versionParam) { + AAIException ex = null; + Response searchResult = null; + String fromAppId = null; + String transId = null; + String rqstTm = genDate(); + ArrayList templateVars = new ArrayList(); + try { + fromAppId = getFromAppId(headers); + transId = getTransId(headers); + String realTime = headers.getRequestHeaders().getFirst("Real-Time"); + //only consider header value for search + DBConnectionType type = this.determineConnectionType("force-cache", realTime); + + final Version version; + if (versionParam.equals("latest")) { + version = AAIProperties.LATEST; + } else { + version = Version.valueOf(versionParam); + } + final ModelType factoryType = ModelType.MOXY; + Loader loader = LoaderFactory.createLoaderForVersion(factoryType, version); + TransactionalGraphEngine dbEngine = new TitanDBEngine( + QueryStyle.TRAVERSAL, + type, + loader); + DBSerializer dbSerializer = new DBSerializer(version, dbEngine, factoryType, fromAppId); + UrlBuilder urlBuilder = new UrlBuilder(version, dbSerializer); + SearchGraph searchGraph = new SearchGraph(); + + searchResult = searchGraph.runNodesQuery(headers, + searchNodeType, + edgeFilterList, + filterList, + dbEngine, + loader, + urlBuilder); + + String respTm = genDate(); + logTransaction(fromAppId, transId, "GETNODESQUERYRESPONSE", + req.getRequestURI(), rqstTm, respTm, "", searchResult); + } 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)) + .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)) + .build(); + } finally { + // log success or failure + if (ex != null){ + ErrorLogHelper.logException(ex); + } + } + return searchResult; + } + + + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java new file mode 100644 index 0000000..389d296 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.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.rest.ueb; + +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.util.StoreNotificationEvent; + +/** + * The Class NotificationEvent. + */ +public class NotificationEvent { + + private Loader loader = 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 (Loader loader, Introspector eventHeader, Introspector obj) { + this.loader = loader; + this.eventHeader = eventHeader; + this.obj = obj; + } + + /** + * Trigger. + * + * @throws AAIException the AAI exception + */ + public void trigger() throws AAIException { + + StoreNotificationEvent sne = new StoreNotificationEvent(); + + sne.storeEvent(loader, eventHeader, obj); + + } + + /** + * Gets the notification version. + * + * @return the notification version + */ + public Version getNotificationVersion() { + return loader.getVersion(); + } + + /** + * 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/aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java new file mode 100644 index 0000000..397082f --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java @@ -0,0 +1,178 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.props.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.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.introspection.exceptions.AAIUnmarshallingException; +import org.openecomp.aai.parsers.uri.URIToObject; +import org.openecomp.aai.util.AAIConfig; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +/** + * The Class UEBNotification. + */ +public class UEBNotification { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(UEBNotification.class); + + 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<>(); + currentVersionLoader = LoaderFactory.createLoaderForVersion(loader.getModelType(), AAIProperties.LATEST); + urlBase = AAIConfig.get("aai.server.url.base",""); + notificationVersion = Version.valueOf(AAIConfig.get("aai.notification.current.version","v10")); + } + + + /** + * Creates the notification event. + * + * @param transactionId the X-TransactionId + * @param sourceOfTruth + * @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 transactionId, 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"; + } + + try { + Introspector eventHeader = currentVersionLoader.introspectorFromName("notification-event-header"); + URIToObject parser = new URIToObject(currentVersionLoader, uri, relatedObjects); + + String entityLink = ""; + if (uri.toString().startsWith("/")) { + entityLink = urlBase + notificationVersion + uri; + } else { + 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()); + eventHeader.setValue("id", transactionId); + + List parentList = parser.getParentList(); + parentList.clear(); + + 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()); + } + + final Introspector eventObject; + + //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(); + } + } + + final NotificationEvent event = new NotificationEvent(currentVersionLoader, eventHeader, eventObject); + events.add(event); + } catch (AAIUnknownObjectException e) { + throw new RuntimeException("Fatal error - notification-event-header object not found!"); + } catch (AAIUnmarshallingException e) { + LOGGER.error("Unmarshalling error occurred while generating UEBNotification", e); + } + } + + /** + * 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/aai-traversal/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java new file mode 100644 index 0000000..6d01435 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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 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.exceptions.AAIException; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.restcore.RESTAPI; + +/** + * The Class EchoResponse. + */ +public class EchoResponse extends RESTAPI { + + protected static String authPolicyFunctionName = "util"; + + 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; + + AAIException ex = null; + String fromAppId = null; + String transId = null; + + try { + fromAppId = getFromAppId(headers ); + transId = getTransId(headers); + } catch (AAIException e) { + ArrayList templateVars = new ArrayList(); + templateVars.add("PUT uebProvider"); + templateVars.add("addTopic"); + return Response + .status(e.getErrorObject().getHTTPResponseCode()) + .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars)) + .build(); + } + + try { + + 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)) + .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)).build(); + + } finally { + if (ex != null) { + ErrorLogHelper.logException(ex); + } + + } + + return response; + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java new file mode 100644 index 0000000..d6fcd67 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.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.rest.util; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +public class LogFormatTools { + + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern(DATE_FORMAT) + .withZone(ZoneOffset.UTC); + + public static String getCurrentDateTime() { + return DTF.format(ZonedDateTime.now()); + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java b/aai-traversal/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java new file mode 100644 index 0000000..a09a317 --- /dev/null +++ b/aai-traversal/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.encode(decode, encoding); + result = segment.equals(encode); + + return result; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/transforms/Converter.java b/aai-traversal/src/main/java/org/openecomp/aai/transforms/Converter.java new file mode 100644 index 0000000..44a0222 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/transforms/Converter.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.transforms; + +public interface Converter { + String convert(String input); +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java b/aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java new file mode 100644 index 0000000..a31da05 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.aai.transforms; + +import com.google.common.base.CaseFormat; + +public class LowerCamelToLowerHyphenConverter implements Converter { + + @Override + public String convert(String input) { + if(input == null){ + return null; + } + return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, input); + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java b/aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java new file mode 100644 index 0000000..784adbe --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.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.transforms; + +/** + * LowerHyphenToLowerCamelConverter is the converter to use + * for converting from the lower hyphen to lower camel case + *

+ * Examples: + * lower-test => lowerTest + * lower-Test => lowerTest + * lowerTest => lowerTest + * lower-test-val => lowerTestVal + *

+ * + */ +public class LowerHyphenToLowerCamelConverter implements Converter { + + /** + * Converts the dash formatted string into a camel case string + * Ensure that the capitalization is not lost during this conversion + *

+ * Loops through each character in the string + * checks if the current character is '-' and if it is then sets the + * boolean isPreviousCharDash to true and continues to the next iteration + * If the character is not '-', then checks if the previous character is dash + * If it is, then it will upper case the current character and appends to the builder + * Otherwise, it will just append the current character without any modification + * + * @param input the input string to convert to camel case + * @return a string that is converted to camel case + * if the input is null, then it returns null + */ + @Override + public String convert(String input) { + if(input == null){ + return null; + } + + int size = input.length(); + StringBuilder builder = new StringBuilder(size); + + boolean isPreviousCharDash = false; + + for(int index = 0; index < size; ++index){ + char ch = input.charAt(index); + + if(ch == '-'){ + isPreviousCharDash = true; + continue; + } + if(isPreviousCharDash){ + builder.append(Character.toUpperCase(ch)); + isPreviousCharDash = false; + } else{ + builder.append(ch); + } + } + + return builder.toString(); + } + +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/transforms/MapTraverser.java b/aai-traversal/src/main/java/org/openecomp/aai/transforms/MapTraverser.java new file mode 100644 index 0000000..7695240 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/transforms/MapTraverser.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.transforms; + + +import joptsimple.internal.Objects; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MapTraverser { + + private Converter converter; + + public MapTraverser(Converter converter){ + this.converter = converter; + } + + public Map convertKeys(Map map){ + + Objects.ensureNotNull(map); + + Map modifiedMap = new HashMap(); + convertKeys(map, modifiedMap); + + return modifiedMap; + } + + private Map convertKeys(Map original, Map modified){ + + for(Map.Entry entry : original.entrySet()){ + String key = entry.getKey(); + key = converter.convert(key); + Object value = entry.getValue(); + if(value instanceof Map){ + modified.put(key, convertKeys((Map)value, new HashMap())); + } else if(value instanceof List){ + modified.put(key, convertKeys((List) value)); + } else { + modified.put(key, value); + } + } + + return modified; + } + + public List convertKeys(List list){ + + List modifiedList = new ArrayList(); + if(list != null && list.size() > 0){ + + for(Object o : list){ + if(o instanceof Map){ + Map map = (Map) o; + modifiedList.add(convertKeys(map)); + } else if(o instanceof List){ + List l = (List) o; + modifiedList.add(convertKeys(l)); + } else { + modifiedList.add(o); + } + } + } + + return modifiedList; + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java b/aai-traversal/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java new file mode 100644 index 0000000..97b7edb --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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 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.ErrorLogHelper; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class AAIAppServletContextListener implements ServletContextListener { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIAppServletContextListener.class.getName()); + + private BrokerService broker = new BrokerService(); + + /** + * Destroys Context + * + * @param arg0 the ServletContextEvent + */ + public void contextDestroyed(ServletContextEvent arg0) { + LOGGER.info("AAIGraph shutting down"); + AAIGraph.getInstance().graphShutdown(); + LOGGER.info("AAIGraph shutdown"); + + try { + broker.stop(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Initializes Context + * + * @param arg0 the ServletContextEvent + */ + public void contextInitialized(ServletContextEvent arg0) { + System.setProperty("org.openecomp.aai.serverStarted", "false"); + LOGGER.info("***AAI Server initialization started..."); + + try { + LOGGER.info("Loading aaiconfig.properties"); + AAIConfig.init(); + + LOGGER.info("Loading error.properties"); + ErrorLogHelper.loadProperties(); + + LOGGER.info("Loading graph database"); + + AAIGraph.getInstance(); + ModelInjestor.getInstance(); + + // Jsm internal broker for aai events + broker = new BrokerService(); + broker.addConnector("tcp://localhost:61446"); + broker.setPersistent(false); + broker.setUseJmx(false); + broker.setSchedulerSupport(false); + broker.start(); + + LOGGER.info("A&AI Server initialization succcessful."); + System.setProperty("org.openecomp.aai.serverStarted", "true"); + + } catch (AAIException e) { + ErrorLogHelper.logException(e); + throw new RuntimeException("AAIException caught while initializing A&AI server", e); + } catch (IOException e) { + ErrorLogHelper.logError("AAI_4000", e.getMessage()); + throw new RuntimeException("IOException caught while initializing A&AI server", e); + } catch (Exception e) { + LOGGER.error("Unknown failure while initializing A&AI Server", e); + throw new RuntimeException("Unknown failure while initializing A&AI server", e); + } + } +} diff --git a/aai-traversal/src/main/java/org/openecomp/aai/util/RestURL.java b/aai-traversal/src/main/java/org/openecomp/aai/util/RestURL.java new file mode 100644 index 0000000..7c70929 --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/util/RestURL.java @@ -0,0 +1,704 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; + +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.springframework.web.util.UriUtils; + +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 com.google.common.base.CaseFormat; +import com.thinkaurelius.titan.core.TitanEdge; +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 + */ + + /** + * 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; + + // 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(); + } + + 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 { + 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 (depNodeTypePlural != null) + { + nodeUrl = depNodeTypePlural + "/" + depNodeType + "/"; + } + + while (keyPropI.hasNext()) { + Object nodeKey = currentNode.property(keyPropI.next()).orElse(null); + nodeUrl += RestURLEncoder.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 += RestURLEncoder.encodeURL(nodeKey) + "/"; + } else { + while (keyPropI.hasNext()) { + Object nodeKey = node.property(keyPropI.next()).orElse(null); + nodeUrl += RestURLEncoder.encodeURL(nodeKey.toString()) + "/"; + } + } + if (isCallbackurl) { + url = AAIConfig.get(AAIConstants.AAI_GLOBAL_CALLBACK_URL) + apiVersion + "/" + urlNamespace + 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 += RestURLEncoder.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 += RestURLEncoder.encodeURL(nodeKey) + "/"; + } else { + while (keyPropI.hasNext()) { + Object nodeKey = node.property(keyPropI.next()).orElse(null); + nodeUrl += RestURLEncoder.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 (hasCloudRegion) { + if (apiVerNum < 7) + urlVersion = "v7"; // or set to the latest version? + else + urlVersion = apiVersion; + } else { + if (nodeVerNum == apiVerNum || nodeVerNum < apiVerNum) + urlVersion = apiVersion; + else + urlVersion = nodeVersion; + } + url = AAIApiServerURLBase.get() + urlVersion + "/" + urlNamespace + url + nodeUrl; + //remove the trailing "/" + url = url.substring(0, url.length()-1); + 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); + } + + /* + * 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 { + + String[] ps = uri.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/aai-traversal/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java b/aai-traversal/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java new file mode 100644 index 0000000..996abba --- /dev/null +++ b/aai-traversal/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java @@ -0,0 +1,358 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.StringWriter; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.xml.bind.Marshaller; + +import org.apache.cxf.helpers.CastUtils; +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.json.JSONException; +import org.json.JSONObject; + +import org.openecomp.aai.dmaap.AAIDmaapEventJMSProducer; +import org.openecomp.aai.domain.notificationEvent.NotificationEvent; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; + +public class StoreNotificationEvent { + + private AAIDmaapEventJMSProducer messageProducer; + private String fromAppId = ""; + private String transId = ""; + + /** + * Instantiates a new store notification event. + */ + public StoreNotificationEvent() { + this.messageProducer = new AAIDmaapEventJMSProducer(); + Message inMessage = PhaseInterceptorChain.getCurrentMessage().getExchange().getInMessage(); + 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; + } + } + } + } + + /** + * 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 { + PojoUtils pu = new PojoUtils(); + String entityJson = pu.getJsonFromObject(ne); + sendToDmaapJmsQueue(entityJson); + } 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.inventory.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()); + } + + 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 { + StringWriter result = new StringWriter(); + + Marshaller marshaller = notificationJaxbContext.createMarshaller(); + marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json"); + marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, false); + marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, false); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false); + marshaller.marshal(notificationEvent, result); + + this.sendToDmaapJmsQueue(result.toString()); + + } catch (Exception e) { + throw new AAIException("AAI_7350", e); + } + } + + public void storeEvent(Loader loader, Introspector eventHeader, Introspector obj) throws AAIException { + if (obj == null) { + throw new AAIException("AAI_7350"); + } + + try { + final Introspector notificationEvent = loader.introspectorFromName("notification-event"); + + if (eventHeader.getValue("id") == null) { + eventHeader.setValue("id", genDate2() + "-" + UUID.randomUUID().toString()); + } + + if (eventHeader.getValue("timestamp") == null) { + eventHeader.setValue("timestamp", genDate()); + } + + if (eventHeader.getValue("entity-link") == null) { + eventHeader.setValue("entity-link", "UNK"); + } + + if (eventHeader.getValue("action") == null) { + eventHeader.setValue("action", "UNK"); + } + + if (eventHeader.getValue("event-type") == null) { + eventHeader.setValue("event-type", AAIConfig.get("aai.notificationEvent.default.eventType", "UNK")); + } + + if (eventHeader.getValue("domain") == null) { + eventHeader.setValue("domain", AAIConfig.get("aai.notificationEvent.default.domain", "UNK")); + } + + if (eventHeader.getValue("source-name") == null) { + eventHeader.setValue("source-name", AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK")); + } + + if (eventHeader.getValue("sequence-number") == null) { + eventHeader.setValue("sequence-number", AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK")); + } + + if (eventHeader.getValue("severity") == null) { + eventHeader.setValue("severity", AAIConfig.get("aai.notificationEvent.default.severity", "UNK")); + } + + if (eventHeader.getValue("version") == null) { + eventHeader.setValue("version", AAIConfig.get("aai.notificationEvent.default.version", "UNK")); + } + + if (notificationEvent.getValue("cambria-partition") == null) { + notificationEvent.setValue("cambria-partition", AAIConstants.UEB_PUB_PARTITION_AAI); + } + + notificationEvent.setValue("event-header", eventHeader.getUnderlyingObject()); + notificationEvent.setValue("entity", obj.getUnderlyingObject()); + + String entityJson = notificationEvent.marshal(false); + sendToDmaapJmsQueue(entityJson); + } catch (JSONException e) { + throw new AAIException("AAI_7350", e); + } catch (AAIUnknownObjectException e) { + throw new AAIException("AAI_7350", e); + } + } + + private void sendToDmaapJmsQueue(String entityString) throws JSONException { + + JSONObject entityJsonObject = new JSONObject(entityString); + + JSONObject entityJsonObjectUpdated = new JSONObject(); + JSONObject finalJson = new JSONObject(); + + JSONObject entityHeader = entityJsonObject.getJSONObject("event-header"); + String cambriaPartition = entityJsonObject.getString("cambria.partition"); + + entityJsonObject.remove("event-header"); + entityJsonObject.remove("cambria.partition"); + + entityJsonObjectUpdated.put("event-header", entityHeader); + entityJsonObjectUpdated.put("cambria.partition", cambriaPartition); + + Iterator iter = entityJsonObject.keys(); + JSONObject entity = new JSONObject(); + if (iter.hasNext()) { + entity = entityJsonObject.getJSONObject(iter.next()); + } + + entityJsonObjectUpdated.put("entity", entity); + + finalJson.put("event-topic", "AAI-EVENT"); + finalJson.put("transId", transId); + finalJson.put("fromAppId", fromAppId); + finalJson.put("fullId", ""); + finalJson.put("aaiEventPayload", entityJsonObjectUpdated); + + messageProducer.sendMessageToDefaultDestination(finalJson); + } + + /** + * 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/aai-traversal/src/main/resources/docker/Dockerfile b/aai-traversal/src/main/resources/docker/Dockerfile new file mode 100644 index 0000000..66cf412 --- /dev/null +++ b/aai-traversal/src/main/resources/docker/Dockerfile @@ -0,0 +1,85 @@ +FROM ubuntu:14.04 + +ENV DEBIAN_FRONTEND noninteractive + +ENV HTTP_PROXY ${HTTP_PROXY} +ENV HTTPS_PROXY ${HTTP_PROXY} +ENV https_proxy ${HTTP_PROXY} +ENV http_proxy ${HTTP_PROXY} + +# Setup JAVA_HOME, this is useful for docker commandline +ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64 + +# Install all the application requirements such as curl ksh and git +# Also install the chef and then remove it in one RUN command +# Because the docker files work like git commits and each command is committed +# So removing the chef in a different command will still have its in its build image +# Its good to be optimizing and removing any files that are not needed for docker images +# for the best possible performance out of your image + +RUN if [ ! -z ${HTTP_PROXY} ]; then echo "Acquire::http::proxy \"${HTTP_PROXY}\";" >> /etc/apt/apt.conf; fi && \ + if [ ! -z ${HTTP_PROXY} ]; then echo "Acquire::https::proxy \"${HTTP_PROXY}\";" >> /etc/apt/apt.conf; fi && \ + apt-get update && \ + apt-get install -y software-properties-common && \ + apt-get install --reinstall ca-certificates && \ + sudo -E add-apt-repository ppa:openjdk-r/ppa && \ + apt-get update && \ + apt-get -qq install -y openjdk-8-jre-headless git curl ksh && \ + curl -k -LO https://packages.chef.io/stable/ubuntu/14.04/chefdk_0.17.17-1_amd64.deb || \ + curl --tlsv1 -LO https://packages.chef.io/stable/ubuntu/14.04/chefdk_0.17.17-1_amd64.deb && \ + dpkg -i chefdk_0.17.17-1_amd64.deb && \ + rm chefdk_0.17.17-1_amd64.deb && \ + rm -rf /var/lib/apt/lists/* + +# Add the proper files into the docker image from your build +ADD ./opt/app /opt/app +ADD ./commonLibs/ /opt/app/commonLibs/ +ADD init-chef.sh /init-chef.sh +ADD docker-entrypoint.sh /docker-entrypoint.sh +ADD aai.sh /etc/profile.d/aai.sh + +# Expose the ports for outside linux to use +# 8446 is the important one to be used + +EXPOSE 8446 + +# Create the /var/chef if it doesn't exist +WORKDIR /var/chef + +# Create the directory structure of aai application resembling the development server +# hard-coding path to match ajsc version + +RUN chmod 755 /init-chef.sh /docker-entrypoint.sh && chmod 644 /etc/profile.d/aai.sh && \ + mkdir /opt/aaihome && \ + useradd -r -ms /bin/bash -d /opt/aaihome/aaiadmin aaiadmin && \ + mkdir -p /opt/app/${project.artifactId} && \ + chown aaiadmin:aaiadmin /opt/app/${project.artifactId} && \ + chown -R aaiadmin:aaiadmin /opt/app/${project.artifactId} && \ + mkdir -p /opt/aai/logroot && \ + chown -R aaiadmin:aaiadmin /opt/aai/logroot && \ + ln -s /opt/app/${project.artifactId}/bin scripts && \ + mkdir -p /opt/app/${project.artifactId}/extApps && chown -R aaiadmin:aaiadmin /opt/app/${project.artifactId}/extApps && \ + find /opt/app/${project.artifactId}/bin -name "*.sh" -exec chmod 755 {} + && \ + chown aaiadmin:aaiadmin /docker-entrypoint.sh && \ + chown -R aaiadmin:aaiadmin /var/chef && \ + mkdir -p /opt/aai/logroot/AAI-GQ && \ + chown aaiadmin:aaiadmin /opt/aai/logroot/AAI-GQ && \ + ln -s /opt/aai/logroot/AAI-GQ /opt/app/${project.artifactId}/logs && \ + chown -R aaiadmin:aaiadmin /opt/app/${project.artifactId}/logs + +VOLUME /opt/aai/logroot/AAI-GQ + +WORKDIR / + +USER aaiadmin + +# When the container is started this is the entrypoint script +# that docker will run. Make sure this script doesn't end abruptly +# If you want the container running even if the main application stops +# You can run a ever lasting process like tail -f /dev/null +# Or something like that at the end of the docker-entrypoint script +# So if the main application you are planning on running fails +# the docker container keeps on running forever + +ENTRYPOINT ./docker-entrypoint.sh + diff --git a/aai-traversal/src/main/resources/docker/aai.sh b/aai-traversal/src/main/resources/docker/aai.sh new file mode 100644 index 0000000..741076f --- /dev/null +++ b/aai-traversal/src/main/resources/docker/aai.sh @@ -0,0 +1,42 @@ +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +PROJECT_HOME=/opt/app/aai-traversal +export PROJECT_HOME + +JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 +export JAVA_HOME + +AAIENV=dev +export AAIENV + +PATH=/usr/lib/jvm/java-8-openjdk-amd64:$PATH + +PROJECT_OWNER=aaiadmin +PROJECT_GROUP=aaiadmin +PROJECT_UNIXHOMEROOT=/opt/aaihome +export PROJECT_OWNER PROJECT_GROUP PROJECT_UNIXHOMEROOT +umask 0022 + +export idns_api_url= +export idnscred= +export idnstenant= + + diff --git a/aai-traversal/src/main/resources/docker/commonLibs/README b/aai-traversal/src/main/resources/docker/commonLibs/README new file mode 100644 index 0000000..00e36c0 --- /dev/null +++ b/aai-traversal/src/main/resources/docker/commonLibs/README @@ -0,0 +1 @@ +// this file's presence ensures commonLibs folder is present when image is created \ No newline at end of file diff --git a/aai-traversal/src/main/resources/docker/docker-entrypoint.sh b/aai-traversal/src/main/resources/docker/docker-entrypoint.sh new file mode 100644 index 0000000..d776343 --- /dev/null +++ b/aai-traversal/src/main/resources/docker/docker-entrypoint.sh @@ -0,0 +1,34 @@ +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +cd /opt/app/aai-traversal; + +TITAN_CACHED="/opt/app/aai-traversal/bundleconfig/etc/appprops/titan-cached.properties"; +TITAN_REALTIME="/opt/app/aai-traversal/bundleconfig/etc/appprops/titan-realtime.properties"; +SERVER_HOST=${SERVER_HOST:-localhost}; +SERVER_TABLE=${SERVER_TABLE:-aaigraph-dev02}; + +sed -i 's/^storage.backend=inmemory/storage.backend=hbase/g' $TITAN_CACHED $TITAN_REALTIME; +sed -i "s/^storage.hostname=.*$/storage.hostname=${SERVER_HOST}/g" $TITAN_CACHED $TITAN_REALTIME; +sed -i "s/^storage.hbase.table=.*$/storage.hbase.table=${SERVER_TABLE}/g" $TITAN_CACHED $TITAN_REALTIME; + +/opt/app/aai-traversal/bin/createDBSchema.sh; + +java -cp ${CLASSPATH}:/opt/app/commonLibs/*:/opt/app/aai-traversal/etc:/opt/app/aai-traversal/lib/*:/opt/app/aai-traversal/extJars/logback-access-1.1.7.jar:/opt/app/aai-traversal/extJars/logback-core-1.1.7.jar:/opt/app/aai-traversal/extJars/aai-core-${AAI_CORE_VERSION}.jar -server -XX:NewSize=512m -XX:MaxNewSize=512m -XX:SurvivorRatio=8 -XX:+DisableExplicitGC -verbose:gc -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:-UseBiasedLocking -XX:ParallelGCThreads=4 -XX:LargePageSizeInBytes=128m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Dsun.net.inetaddr.ttl=180 -XX:+HeapDumpOnOutOfMemoryError -Dhttps.protocols=TLSv1.1,TLSv1.2 -DSOACLOUD_SERVICE_VERSION=1.0.1 -DAJSC_HOME=/opt/app/aai-traversal/ -DAJSC_CONF_HOME=/opt/app/aai-traversal/bundleconfig -DAJSC_SHARED_CONFIG=/opt/app/aai-traversal/bundleconfig -DAFT_HOME=/opt/app/aai-traversal -DAAI_CORE_VERSION=${AAI_CORE_VERSION} -Daai-core.version=${AAI_CORE_VERSION} -Dlogback.configurationFile=/opt/app/aai-traversal/bundleconfig/etc/logback.xml -Xloggc:/opt/app/aai-traversal/logs/ajsc-jetty/gc/graph-query_gc.log com.att.ajsc.runner.Runner context=/ port=8086 sslport=8446 diff --git a/aai-traversal/src/main/resources/docker/init-chef.sh b/aai-traversal/src/main/resources/docker/init-chef.sh new file mode 100644 index 0000000..112b0b3 --- /dev/null +++ b/aai-traversal/src/main/resources/docker/init-chef.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +############################################################################## +# Script to initialize the chef-repo branch and.chef +# +############################################################################## + +#echo "AAI_CHEF_ENV=${AAI_CHEF_ENV}" >> /etc/environment +#echo "AAI_CHEF_LOC=${AAI_CHEF_LOC}" >> /etc/environment +#touch /root/.bash_profile +chef-solo -c /var/chef/aai-data/chef-config/dev/.knife/solo.rb -j /var/chef/aai-config/cookbooks/runlist-app-server.json -E ${AAI_CHEF_ENV} + diff --git a/aai-traversal/src/main/resources/schema/UebEventLogEntry.xsd b/aai-traversal/src/main/resources/schema/UebEventLogEntry.xsd new file mode 100644 index 0000000..c679fd2 --- /dev/null +++ b/aai-traversal/src/main/resources/schema/UebEventLogEntry.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/aai-traversal/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context b/aai-traversal/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context new file mode 100644 index 0000000..8514196 --- /dev/null +++ b/aai-traversal/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context @@ -0,0 +1 @@ +{"context":{"contextClass":"ajsc.Context","contextId":"__module_ajsc_namespace_name__:__module_ajsc_namespace_version__","contextName":"__module_ajsc_namespace_name__","contextVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ Context"}} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/context/default#0.context b/aai-traversal/src/main/runtime/context/default#0.context new file mode 100644 index 0000000..d1b5ab4 --- /dev/null +++ b/aai-traversal/src/main/runtime/context/default#0.context @@ -0,0 +1 @@ +{"context":{"contextClass":"ajsc.Context","contextId":"default:0","contextName":"default","contextVersion":"0","description":"Default Context"}} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json b/aai-traversal/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json new file mode 100644 index 0000000..d0954cf --- /dev/null +++ b/aai-traversal/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json @@ -0,0 +1 @@ +{"deploymentPackage":{"Class":"ajsc.DeploymentPackage","Id":"__module.ajsc.namespace.name__:__module_ajsc_namespace_version__","namespace":"__module_ajsc_namespace_name__","namespaceVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ __module_ajsc_namespace_version__ - default description","userId":"ajsc"}} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroRole/ajscadmin.json b/aai-traversal/src/main/runtime/shiroRole/ajscadmin.json new file mode 100644 index 0000000..f5e981e --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroRole/ajscadmin.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"ajscadmin","name":"ajscadmin","permissions":"[ajscadmin:*, ajsc:*]"} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json b/aai-traversal/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json new file mode 100644 index 0000000..2dae9f5 --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:__module_ajsc_namespace_name__","name":"contextadmin:__module_ajsc_namespace_name__","permissions":"[]"} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroRole/contextadmin#default.json b/aai-traversal/src/main/runtime/shiroRole/contextadmin#default.json new file mode 100644 index 0000000..5de814e --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroRole/contextadmin#default.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:default","name":"contextadmin:default","permissions":"[]"} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroUser/ajsc.json b/aai-traversal/src/main/runtime/shiroUser/ajsc.json new file mode 100644 index 0000000..f4c7855 --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroUser/ajsc.json @@ -0,0 +1 @@ +{"shiroUserClass":"ajsc.auth.ShiroUser","shiroUserId":"ajsc","passwordHash":"9471697417008c880720ba54c6038791ad7e98f3b88136fe34f4d31a462dd27a","permissions":"[*:*]","username":"ajsc"} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json b/aai-traversal/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json new file mode 100644 index 0000000..cb8d483 --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:ajscadmin","roleId":"ajscadmin","userId":"ajsc"} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json b/aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json new file mode 100644 index 0000000..95d2361 --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:__module_ajsc_namespace_name__","roleId":"contextadmin:__module_ajsc_namespace_name__","userId":"ajsc"} \ No newline at end of file diff --git a/aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json b/aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json new file mode 100644 index 0000000..2bd5063 --- /dev/null +++ b/aai-traversal/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:default","roleId":"contextadmin:default","userId":"ajsc"} \ No newline at end of file diff --git a/aai-traversal/src/main/scripts/getTool.sh b/aai-traversal/src/main/scripts/getTool.sh new file mode 100644 index 0000000..8cdc7d1 --- /dev/null +++ b/aai-traversal/src/main/scripts/getTool.sh @@ -0,0 +1,88 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +# +# The script is called with a resource. +# It invokes a GET on the resource using curl +# Uses aaiconfig.properties for authorization type and url. + +# remove leading slash when present +RESOURCE=`echo $1 | sed "s,^/,,"` +if [ -z $RESOURCE ]; then + echo "resource parameter is missing" + echo "usage: $0 resource file [expected-failure-codes]" + exit 1 +fi +echo `date` " Starting $0 for resource $RESOURCE" + +XFROMAPPID="AAI-TOOLS" +XTRANSID=`uuidgen` + +userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) +if [ "${userid}" != "aaiadmin" ]; then + echo "You must be aaiadmin to run $0. The id used $userid." + exit 1 +fi + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-graph-query +prop_file=$PROJECT_HOME/bundleconfig/etc/appprops/aaiconfig.properties +log_dir=$PROJECT_HOME/logs/misc +today=$(date +\%Y-\%m-\%d) + +MISSING_PROP=false +RESTURL=`grep ^aai.server.url= $prop_file |cut -d'=' -f2 |tr -d "\015"` +if [ -z $RESTURL ]; then + echo "Property [aai.server.url] not found in file $prop_file" + MISSING_PROP=true +fi +USEBASICAUTH=false +BASICENABLE=`grep ^aai.tools.enableBasicAuth $prop_file |cut -d'=' -f2 |tr -d "\015"` +if [ -z $BASICENABLE ]; then + USEBASICAUTH=false +else + USEBASICAUTH=true + CURLUSER=`grep ^aai.tools.username $prop_file |cut -d'=' -f2 |tr -d "\015"` + if [ -z $CURLUSER ]; then + echo "Property [aai.tools.username] not found in file $prop_file" + MISSING_PROP=true + fi + CURLPASSWORD=`grep ^aai.tools.password $prop_file |cut -d'=' -f2 |tr -d "\015"` + if [ -z $CURLPASSWORD ]; then + echo "Property [aai.tools.password] not found in file $prop_file" + MISSING_PROP=true + fi +fi + +if [ $MISSING_PROP = false ]; then + if [ $USEBASICAUTH = false ]; then + AUTHSTRING="--cert $PROJECT_HOME/bundleconfig/etc/auth/aaiClientPublicCert.pem --key $PROJECT_HOME/bundleconfig/etc/auth/aaiClientPrivateKey.pem" + else + AUTHSTRING="-u $CURLUSER:$CURLPASSWORD" + fi + curl --request GET -sL -k $AUTHSTRING -H "X-FromAppId: $XFROMAPPID" -H "X-TransactionId: $XTRANSID" -H "Accept: application/json" $RESTURL$RESOURCE + RC=$?; +else + echo "usage: $0 resource" + RC=-1 +fi + +echo `date` " Done $0, returning $RC" +exit $RC diff --git a/aai-traversal/src/main/scripts/install/instutils.sh b/aai-traversal/src/main/scripts/install/instutils.sh new file mode 100644 index 0000000..a512606 --- /dev/null +++ b/aai-traversal/src/main/scripts/install/instutils.sh @@ -0,0 +1,724 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +ECHO=${ECHO:-echo} + +q_flags="-qq -k$$" + +show_install=${PROJECT_HOME}/install/show_install + +############################################################################ +# checkgroup groupname gid +# checks if group is already in /etc/group and if it has the right gid +# if it's not there, it adds it +# gid can be DC if you don't care +############################################################################ +checkgroup () { + ecode=0 + OFILE=/tmp/group.$$ + getent group "$1" > $OFILE + if [ $? -eq 0 ] + then + CHECKGID=$( grep "^$1:" $OFILE | cut -f3 -d: 2>/dev/null ) + CHECKGROUPPRESENT=$( grep "^$1:" $OFILE | cut -f1 -d: 2>/dev/null ) + CHECKGROUP=$( grep ":$2:" $OFILE | cut -f1 -d: 2>/dev/null ) + fi + if [ "${CHECKGID}" = "" -a "${CHECKGROUP}" = "" ] + then + ${ECHO} "Adding $1 group ..." + if [ "$2" = "DC" ] + then + groupadd $1 + else + groupadd -g $2 $1 + fi + if [ "$?" != "0" ] + then + ${ECHO} "Cannot add group $1, continuing..." + ecode=1 + fi + else + if [ "${CHECKGROUPPRESENT}" = "$1" ] + then + if [ "$2" != "DC" ] + then + if [ "${CHECKGID}" != "$2" ] + then + ${ECHO} "ERROR: $1 group added but with wrong gid \"${CHECKGID}\"; should be $2" + ecode=1 + fi + if [ "${CHECKGROUP}" != "$1" ] + then + ${ECHO} "ERROR: wrong group \"${CHECKGROUP}\" for gid $2, group should be $1" + ecode=1 + fi + else + ${ECHO} "$1 group has already been added" + fi + fi + fi + rm -f $OFILE + return ${ecode} +} + +############################################################################ +# checkuser username uid homedir shell group +# checks if the username/uid/homedir/shell combo is already in /etc/passwd +# if not, it adds it +# if the login is there and the uid belongs to a different user, it errors +# if the login is there and the shell is not correct, it errors +# uid may be DC for don't care +############################################################################ +checkuser () { + ecode=0 + OFILE=/tmp/user.$$ + getent passwd $1 > $OFILE + if [ $? -eq 0 ] + then + CHECKUID=$( grep "^$1:" $OFILE | cut -f3 -d: 2>/dev/null ) + CHECKLOGIN=$( grep ":x:$2:" $OFILE | cut -f1 -d: 2>/dev/null ) + CHECKLOGINPRESENT=$( grep "^$1:" $OFILE | cut -f1 -d: 2>/dev/null ) + CHECKSHELL=$( grep "^$1:" $OFILE | cut -f7 -d: 2>/dev/null ) + CHECKHOME=$( grep "^$1:" $OFILE | cut -f6 -d: 2>/dev/null ) + fi + + if [ ! -d $3 ] + then + mkdir -p $3 + if [ "$?" != "0" ] + then + ${ECHO} "mkdir -p $3 failed" + ecode=1 + fi + chmod -R 755 $3 + fi + if [ "${CHECKUID}" = "" -a "${CHECKLOGIN}" = "" ] + then + ${ECHO} "Adding $1 login ..." + if [ "$2" = "DC" ] + then + useradd -g $5 -d $3 -s $4 -c "$1 LOGIN" -m $1 + else + useradd -u $2 -g $5 -d $3 -s $4 -c "$1 LOGIN" -m $1 + fi + if [ "$?" != "0" ] + then + ${ECHO} "Cannot add $1 login, continuing..." + ecode=1 + fi + elif [ "${CHECKLOGINPRESENT}" = "$1" -a "$2" = "DC" -a "${CHECKSHELL}" = "$4" -a "${CHECKHOME}" = "$3" ] + then + ${ECHO} "The '$1' login has already been added to system with UID ${CHECKUID}." + + elif [ "${CHECKUID}" = "$2" -a "${CHECKLOGIN}" = "$1" -a "${CHECKSHELL}" = "$4" -a "${CHECKHOME}" = "$3" ] + then + ${ECHO} "The '$1' login has already been added to system." + else + if [ "$2" != "DC" -a "${CHECKUID}" != "$2" ] + then + ${ECHO} "ERROR: $1 login added but with wrong uid \"${CHECKUID}\"; should be $2" + ecode=1 + fi + if [ "$2" != "DC" -a "${CHECKLOGIN}" != "$1" ] + then + ${ECHO} "ERROR: wrong login \"${CHECKLOGIN}\" for uid $2, login should be $1" + ecode=1 + fi + if [ "${CHECKHOME}" != "$3" ] + then + ${ECHO} "ERROR: wrong home directory \"${CHECKHOME}\" for login $1, should be $3" + ecode=1 + fi + if [ "${CHECKSHELL}" != "$4" ] + then + ${ECHO} "ERROR: $1 login not set up with $4" + ecode=1 + fi + fi + rm -f $OFILE + return ${ecode} +} + +############################################################################ +# checkhome username homedir action +# if the user doesn't exist, it errors +# checks if the username has homedir as its home directory +# if not and action is null, it modifies it +# if not and action is mod, it modifies it +# if not and action is error, it errors +############################################################################ +checkhome () { + ecode=0 + OFILE=/tmp/user.$$ + getent passwd $1 > $OFILE + if [ $? -eq 0 ] + then + CHECKUID=$( grep "^$1:" $OFILE | cut -f3 -d: 2>/dev/null ) + CHECKGID=$( grep "^$1:" $OFILE | cut -f4 -d: 2>/dev/null ) + CHECKHOME=$( grep "^$1:" $OFILE | cut -f6 -d: 2>/dev/null ) + + if [ "${CHECKHOME}" = "$2" ] + then + if [ ! -d $2 ] + then + mkdir -p $2 + if [ "$?" != "0" ] + then + ${ECHO} "mkdir -p $2 failed" + ecode=1 + fi + chown ${CHECKUID}:${CHECKGID} $2 + chmod -R 755 $2 + fi + else + # modify the user to set the new home dir and move any current home dir to there + usermod -d $2 -m $1 + if [ "$?" != "0" ] + then + ${ECHO} "usermod -d $2 -m $1 failed" + ecode=1 + fi + fi + else + ${ECHO} "user $1 doesn't exist" + ecode=1 + fi + + rm -f $OFILE + return ${ecode} +} + +################################################################## +#checkloginsforpwds checks /etc/shadow for logins without passwords +# the first argument is a list of logins to check +################################################################## +checkloginsforpwds () { + for i in $1 + do + CHECK_LOGIN=$( grep "^${i}:" /etc/shadow | grep "!!" ) + if [ "${CHECK_LOGIN}" != "" ] + then + NOPWD="${NOPWD} ${i}" + fi + done + + if [ "${NOPWD}" != "" ] + then + ${ECHO} "" + ${ECHO} "REMINDER: The following logins must have a passwords assigned to them.\n" + ${ECHO} "##############################################################" + ${ECHO} " ${NOPWD} " + ${ECHO} "##############################################################" + ${ECHO} "" + ${ECHO} " This must be done by executing the following command:" + ${ECHO} "" + ${ECHO} " $ passwd " + ${ECHO} "" + ${ECHO} " After typing the \"passwd\" command you will be prompted for" + ${ECHO} " the password for the login." + ${ECHO} "" + fi +} + +################################################################## +# checkassignpasswords checks /etc/shadow for logins without passwords +# and then asks the user to assign one +# the first argument is a list of logins to check +################################################################## +checkassignpasswords () { + for i in $1 + do + CHECK_LOGIN=$( grep "^${i}:" /etc/shadow | grep LK ) + if [ "${CHECK_LOGIN}" != "" ] + then + ${ECHO} "Please assign a password for the '${i}' login" + passwd ${i} + ${ECHO} + fi + done +} + +############################################################################ +# copywithperms origfile destfile owner group perms [save suffix] +# copies origfile to destfile, giving destfile ownership and permssions +# from owner, group, and perms. If the sixth argument is "save", the +# original is saved in the same place with the seventh argument as the +# suffix. If the seventh arg is null, $$ is used +############################################################################ +copywithperms () { + SAVE=0 + ECODE=0 + if [ "$6" = "save" -a -f "$2" ] + then + if [ "$7" = "" ] + then + cp $2 $2.$$ + else + cp $2 $2.$7 + fi + fi + if [ -f $1 ] + then + cp $1 $2 + ECODE=$? + chown ${3}:${4} $2 + chmod $5 $2 + else + ${ECHO} "$1 is not a file. No copy done!" + fi + return ${ECODE} +} + +############################################################################ +# mkdirwithperms dirname owner group perms ifExist +# makes directory dirname , giving dirname ownership and permssions +# from owner, group, and perms. +# perms can be DC if you don't care +# ifExist can be rm, error, dontcreate +############################################################################ +mkdirwithperms () { + ECODE=0 + if [ -f $1 ] + then + ECODE=1 + ${ECHO} "$1 exists but is a file. No mkdir done!" + elif [ -d $1 ] + then + if [ "$5" = "rm" ] + then + rm -rf $1 + mkdir -p $1 + if [ "$?" != "0" ] + then + ${ECHO} "mkdir -p $1 failed" + ECODE=1 + fi + elif [ "$5" = "error" ] + then + ECODE=1 + ${ECHO} "$1 is a directory. No mkdir done!" + elif [ "$5" != "dontcreate" ] + then + mkdir -p $1 + if [ "$?" != "0" ] + then + ${ECHO} "mkdir -p $1 failed" + ECODE=1 + fi + fi + else + mkdir -p $1 + if [ "$?" != "0" ] + then + ${ECHO} "mkdir -p $1 failed" + ECODE=1 + fi + fi + if [ "${ECODE}" = "0" ] + then + chown ${2}:${3} $1 + if [ "$4" != "DC" ] + then + chmod $4 $1 + fi + fi + return ${ECODE} +} + + +############################################################################ +# chownwithperms owner group file mode +# changes the ownership and mode for the specified file +############################################################################ +chownwithperms () { + chown ${1}:${2} $3 + chmod $4 $3 +} + +verifywhosrunning () { + userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) + if [ "${userid}" != "$1" ] + then + ${ECHO} "You must be $1 to run $0" + exit 1 + fi +} + +replaceline() { + + name=$1 + value=$2 + file=$3 + + if [ -z "${file}" ] + then + ${ECHO} "replaceline: ERROR: insufficient arguments: $1 $2" >&2 + return 1 + fi + + if [ -n "$4" ] + then + ${ECHO} "replaceline: ERROR: too many arguments: $1 $2 $3 $4" >&2 + return 1 + fi + + if [ -f ${file} ] + then + grep -v "^${name}=" ${file} > ${file}.$$ + ${ECHO} "${name}=${value}" >> ${file}.$$ + mv -f ${file}.$$ ${file} + else + ${ECHO} "${name}=${value}" > ${file} + fi +} + +replaceline_with_quotes() { + + name=$1 + value=$2 + file=$3 + + if [ -z "${file}" ] + then + ${ECHO} "replaceline: ERROR: insufficient arguments: $1 $2" >&2 + return 1 + fi + + if [ -n "$4" ] + then + ${ECHO} "replaceline: ERROR: too many arguments: $1 $2 $3 $4" >&2 + return 1 + fi + + if [ -f ${file} ] + then + grep -v "^${name}=" ${file} > ${file}.$$ + ${ECHO} "${name}=\"${value}\"" >> ${file}.$$ + mv -f ${file}.$$ ${file} + else + ${ECHO} "${name}=\"${value}\"" > ${file} + fi +} + +# this deleteline will not actually delete the entry +# but only delete the value leaving the name= +# when siteconf.pl went from Boilerplate to Fillin, +# we changed this because Fillin can handle null values. + +deleteline() { + + name=$1 + file=$2 + + if [ -z "${file}" ] + then + ${ECHO} "deleteline: ERROR: insufficient arguments" >&2 + return 1 + fi + + if [ -f ${file} ] + then + cp ${file} ${file}.$$ + lno=$( grep -n "^${name}=" ${file} | cut -d: -f1 ) + if [ "${lno}" != "" ] + then + sed "${lno}d" ${file} > ${file}.$$ + fi + ${ECHO} "${name}=" >> ${file}.$$ + mv -f ${file}.$$ ${file} + else + ${ECHO} "${name}=" > ${file} + fi +} + +# dropline will drop the line from the file +# unlike the deleteline function above + +dropline() { + + name=$1 + file=$2 + + if [ -z "${file}" ] + then + ${ECHO} "dropline: ERROR: insufficient arguments" >&2 + return 1 + fi + + if [ -f ${file} ] + then + grep -v "^${name}=" ${file} > ${file}.$$ + mv -f ${file}.$$ ${file} + fi +} + +pause_install() { + + if [ "${Pause}" = "1" ] + then + if ${chkyn} -y "Continue with ${Itype}?" + then + return 0 + else + ${ECHO} "${PNAME}: quitting" >&2 + exit 1 + fi + fi +} + +get_ITYPE() { + ITYPE=$( ${chkyn} -fer ${q_flags} -h\? ${ITYPE:+-D"${ITYPE}"} -H \ +" If you are doing a fresh install, answer 'I' or answer 'U' for upgrade." \ +"Is this a fresh 'install' or 'upgrade' (I or U):${ITYPE:+ [${ITYPE}]}" \ + '^[IU]$' \ +'*** ERROR *** Entry must be I or U.' ) +} + + +### +# Change an /etc/group entry to allow a give user to change group into it. +# arg1 = comma-sep group list (e.g., sylantro,other) +# arg2 = user +### +addUserToGroup() +{ + if [ -z "$1" -o -z "$2" ] + then + ${ECHO} "addUserToGroup failed, need two args, group and user" + return 1 + else + usermod -G $1 $2 + fi + return 0 +} + +################### BACKUP AND RESTORE METHODS ######################## +################### VARIABLES ########################## +################### VARIABLES ########################## +################### VARIABLES ########################## +################### VARIABLES ########################## + +NO_FILE_INDICATOR="__NO_PREVIOUS_FILE__" +SAVE_SUFFIX=${Project}save + +################### SUBROUTINES ########################## +################### SUBROUTINES ########################## +################### SUBROUTINES ########################## +################### SUBROUTINES ########################## +################### SUBROUTINES ########################## + +############################################################################## +# Purpose: make a backup copy of a file in such a way that the backup +# won't be lost by re-running your script PLUS give you a predictable name +# for the most recent back up to use when you roll back. +# +# Input: +# - Arg1 = file to back up +# +# Requirement: +# - Remove $1.save before calling this function or else a copy won't be made. +# - Make sure to set the value of env value TODAY to use as a suffix. +# +# Description: +# Copy $1 to $1.${SAVE_SUFFIX}.${TODAY}, then link that to $1.save. +# +############################################################################## +make_backup_copy () +{ + if [ -z "${TODAY}" ] + then + ${ECHO} "make_backup_copy - TODAY variable is unset" >&2 + return 1 + fi + + if [ -f $1.${SAVE_SUFFIX}.${TODAY} -a -h $1.save ] + then + ${ECHO} "Note: backup already exists for $1" + else + # if existing file doesn't exist, set up for later delete by rollback + if [ ! -f $1 -a ! -h $1 ] + then + ${ECHO} ${NO_FILE_INDICATOR} > $1 + fi + cp -p $1 $1.${SAVE_SUFFIX}.${TODAY} + ln -s $1.${SAVE_SUFFIX}.${TODAY} $1.save + fi +} + +################################################################################ +# Purpose: Find the actual file that belongs to $1, which can be a symbolic +# link. +# +# Input: +# - Arg1 = path to file or link +# - Arg2 = true if you want _SRCFILE to be null if no actual file is +# found. If Arg2 is NOT true, then _SRCFILE is set to Arg1. +# +# Side Effect: +# Sets value of _SRCFILE variable +################################################################################ +find_source_file () +{ + if [ -z "$1" ] + then + ${ECHO} "find_source_file - needs at least one argument" >&2 + return 1 + fi + + ls -l $1 > /tmp/tls$$ + cat /tmp/tls$$ | sed 's/ */ /g' |cut -f11 > /tmp/cuts$$ + _SRCFILE=$( cat /tmp/cuts$$ ) + + if [ "$_SRCFILE" = "" ] + then + if [ "$2" != "true" ] + then + _SRCFILE=$1 + fi + fi + rm -f /tmp/tls$$ /tmp/cuts$$ +} + +####################################################################### +# Purpose: Expands template file using data in COPT variable. +# Diffs expanded template against existing file and installs if different. +# If arg5 = true, sets _config_changes=1 so you know that changes were installed +# +# Makes its own backup copy using make_backup_copy. +# Does install if different using install_if_different. +# +# Input: +# Arg1 = template path without .tmpl extension +# Arg2 = install path +# Arg3 = owner and group (e.g., root:other) +# Arg4 = permissions (e.g., 750) +# Arg5 = true/false, if expanded file is different than installed . +# Set _config_changes to 1 if Arg5 is true. Otherwise, don't touch +# _config_changes +# +# Requirement: set COPT to the value of the -c option to siteconf.pl +# +# Side Effect: sets _config_changes=1 if changes were installed +####################################################################### +install_from_template () +{ + if [ -z "${COPT}" ] + then + ${ECHO} "install_from_template - COPT is unset" >&2 + return 1 + fi + + TMPL=$( basename ${1} ) + OFILE=/tmp/${TMPL} + if [ -f ${1}.tmpl ] + then + + ${PROJECT_HOME}/bin/siteconf.pl -t ${1}.tmpl -c ${COPT} -o ${OFILE} + install_if_different ${OFILE} ${2} ${3} ${4} ${5} + + else + ${ECHO} "install_from_template: ERROR: Missing ${TMPL}.tmpl" >&2 + fi + rm -f ${OFILE} +} + + +####################################################################### +# Purpose: Copies source to destination if the two are different. +# If arg5 = true, sets _config_changes=1 so you know that changes were installed +# +# Makes its own backup copy using make_backup_copy. +# +# Input: +# Arg1 = source path +# Arg2 = install path +# Arg3 = owner and group (e.g., root:other) +# Arg4 = permissions (e.g., 750) +# Arg5 = true/false, if expanded file is different than installed . +# Set _config_changes to 1 if Arg5 is true. Otherwise, don't touch +# _config_changes +# +# Side Effect: sets _config_changes=1 if changes were installed +####################################################################### +install_if_different() +{ + # Take backup before changing. + # Only change if different. + if [ -f ${2} ] + then + diff ${1} ${2} > /dev/null + diffrc=$? + if [ "${diffrc}" != "0" ] + then + ${ECHO} "Installing ${2}" + make_backup_copy ${2} + mv -f ${1} ${2} + chown ${3} ${2} + chmod ${4} ${2} + if [ "${5}" = "true" ] + then + _config_changes=1 + fi + fi + else + # creates backup containing ${NO_FILE_INDICATOR} for rollback removal + make_backup_copy ${2} + mv -f ${1} ${2} + chown ${3} ${2} + chmod ${4} ${2} + if [ "${5}" = "true" ] + then + _config_changes=1 + fi + fi +} +################################################################### +# Purpose: rollback a file whose backup was made with make_backup_copy +# +# Input: +# Arg1 is path of installed file. Subroutine will look for ${1}.save +# Arg2 = true/false, if expanded file is different than installed, +# set _config_changes to 1 if Arg2 is true. Otherwise, don't touch +# _config_changes +# +# Side Effect: sets _config_changes=1 if changes were rolled back +################################################################### +rollback_from_save () +{ + if [ -f ${1}.save -o -h ${1}.save ] + then + find_source_file ${1}.save false + ${ECHO} "rollback_from_save: rolling back to $( basename ${_SRCFILE} )" + grep ${NO_FILE_INDICATOR} ${_SRCFILE} > /dev/null + if [ $? -eq 0 ] + then + rm -f ${_SRCFILE} ${1} + else + mv -f ${_SRCFILE} ${1} + fi + if [ "${2}" = "true" ] + then + _config_changes=1 + fi + rm -f ${1}.save + fi +} diff --git a/aai-traversal/src/main/scripts/install/siteconf.pl b/aai-traversal/src/main/scripts/install/siteconf.pl new file mode 100644 index 0000000..d035851 --- /dev/null +++ b/aai-traversal/src/main/scripts/install/siteconf.pl @@ -0,0 +1,100 @@ +#!/usr/bin/perl +# CC_ID_SITECONF_PL[] = "@(#)/vobs/waas/src/oam/siteconf.pl@@/main/4" + +#.Description +# This perl script takes as input template file, +# and one or more configuration files. It uses the values in the +# configuration files as substitutions for the matching tags in the template +# file. + +#.Constraints +# The input files must be readable by the script. + +#.See Also +# + +use Getopt::Std; + +local $dbg=0; + +getopts ('dt:c:'); + +if ($opt_d) { + $dbg=$opt_d; +} + +if ($dbg) { + print STDERR "opt_d=$opt_d\n"; + print STDERR "opt_t=$opt_t\n"; + print STDERR "opt_c=$opt_c\n"; +} + +### +# Print usage if no arguments passed +if (! $opt_t) { + print STDERR "Usage: $0 -t templatefile -c configfilelist\n"; + exit (1); +} + +# process the template file variable +if ($opt_t) { + if (! -r $opt_t) { + print STDERR "Error: Can't read template file $opt_t\n"; + exit (2); + } + $templatefile = $opt_t; +} +else { + print STDERR "Error: You must enter the template file name\n"; + exit (2); +} + +### +# Global error flag for return code when exiting +$err = 0; + +$configlist = ''; +if ($opt_c) { + $configlist = $opt_c; +} + +# process the site configuration file variable +if ($configlist) { + @siteary = split /,/, $configlist; +} + +# Add PROJECT_HOME to Conf dictionary +$Conf{'PROJECT_HOME'} = $ENV{'PROJECT_HOME'}; + +foreach $arg (@siteary) { + if ($dbg) { print STDERR "Opening $arg\n" } + + open(CONF, $arg) || die $!, ", '$arg'\n"; + + while () { + #1 while chomp(); + $_ =~ s/[\r\n]$//g; # strip newlines and dos-injected carriage returns + if ( /=/ ) { + ($attr,$value) = split(/=/,$_,2); + $value =~ s/\$PHOME/$ENV{'PROJECT_HOME'}/; + $value =~ s/\$PROJECT_HOME/$ENV{'PROJECT_HOME'}/; + $Conf{$attr} = $value; + } + } + + close CONF; +} + +if ($dbg) { print STDERR "Expanding $templatefile\n" } + +# Expand a config file + +open(TEMPLATE, $templatefile) || die $!, ", '$templatefile'\n"; +while (