@itentialopensource/adapter-nokia_nsp_network_management 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.js +18 -0
  3. package/.jshintrc +3 -0
  4. package/AUTH.md +38 -0
  5. package/BROKER.md +211 -0
  6. package/CALLS.md +206 -0
  7. package/CHANGELOG.md +9 -0
  8. package/CODE_OF_CONDUCT.md +43 -0
  9. package/CONTRIBUTING.md +13 -0
  10. package/ENHANCE.md +69 -0
  11. package/LICENSE +201 -0
  12. package/PROPERTIES.md +646 -0
  13. package/README.md +343 -0
  14. package/SUMMARY.md +9 -0
  15. package/SYSTEMINFO.md +22 -0
  16. package/TAB1.md +14 -0
  17. package/TAB2.md +321 -0
  18. package/TROUBLESHOOT.md +47 -0
  19. package/adapter.js +11110 -0
  20. package/adapterBase.js +1452 -0
  21. package/entities/.generic/action.json +214 -0
  22. package/entities/.generic/schema.json +28 -0
  23. package/entities/.system/action.json +52 -0
  24. package/entities/.system/mockdatafiles/getToken-default.json +3 -0
  25. package/entities/.system/mockdatafiles/healthcheck-default.json +3 -0
  26. package/entities/.system/schema.json +19 -0
  27. package/entities/.system/schemaTokenReq.json +53 -0
  28. package/entities/.system/schemaTokenResp.json +31 -0
  29. package/entities/AddressPool/action.json +65 -0
  30. package/entities/AddressPool/mockdatafiles/getIPv4AddressPool-default.json +47 -0
  31. package/entities/AddressPool/mockdatafiles/obtainValueFromPool-default.json +23 -0
  32. package/entities/AddressPool/schema.json +32 -0
  33. package/entities/AuditAndAlignment/action.json +165 -0
  34. package/entities/AuditAndAlignment/mockdatafiles/alignConfigurationDeployment-default.json +6 -0
  35. package/entities/AuditAndAlignment/mockdatafiles/alignConfigurationTemplateAllDeployments-default.json +7 -0
  36. package/entities/AuditAndAlignment/mockdatafiles/alignConfigurationTemplateMisalignedDeployments-default.json +7 -0
  37. package/entities/AuditAndAlignment/mockdatafiles/auditDeployment-default.json +7 -0
  38. package/entities/AuditAndAlignment/mockdatafiles/auditNodeDeployments-default.json +6 -0
  39. package/entities/AuditAndAlignment/mockdatafiles/auditTemplate-default.json +7 -0
  40. package/entities/AuditAndAlignment/mockdatafiles/checkAuditStatusCount-default.json +15 -0
  41. package/entities/AuditAndAlignment/mockdatafiles/getAuditDetails-default.json +9 -0
  42. package/entities/AuditAndAlignment/schema.json +26 -0
  43. package/entities/BaselineOperationsRestconfAPI/action.json +207 -0
  44. package/entities/BaselineOperationsRestconfAPI/mockdatafiles/createBaselineDetector-default.json +35 -0
  45. package/entities/BaselineOperationsRestconfAPI/mockdatafiles/getAllBaselines-default.json +44 -0
  46. package/entities/BaselineOperationsRestconfAPI/mockdatafiles/getBaseline-default.json +24 -0
  47. package/entities/BaselineOperationsRestconfAPI/mockdatafiles/getBaselineDetector-default.json +15 -0
  48. package/entities/BaselineOperationsRestconfAPI/mockdatafiles/patchBaselineDetector-default.json +13 -0
  49. package/entities/BaselineOperationsRestconfAPI/schema.json +39 -0
  50. package/entities/Brownfield/action.json +24 -0
  51. package/entities/Brownfield/mockdatafiles/discoverDeployments-default.json +7 -0
  52. package/entities/Brownfield/schema.json +19 -0
  53. package/entities/ConfigurationDeployments/action.json +207 -0
  54. package/entities/ConfigurationDeployments/mockdatafiles/createDeployment-default.json +7 -0
  55. package/entities/ConfigurationDeployments/mockdatafiles/createPortGroup-default.json +18 -0
  56. package/entities/ConfigurationDeployments/mockdatafiles/createPortGroupDirectory-default.json +16 -0
  57. package/entities/ConfigurationDeployments/mockdatafiles/deleteDeployments-default.json +7 -0
  58. package/entities/ConfigurationDeployments/mockdatafiles/getDeployments-default.json +322 -0
  59. package/entities/ConfigurationDeployments/mockdatafiles/getPortGroupFDN-default.json +18 -0
  60. package/entities/ConfigurationDeployments/mockdatafiles/getSpecificDeployment-default.json +43 -0
  61. package/entities/ConfigurationDeployments/mockdatafiles/replaceDeployment-default.json +7 -0
  62. package/entities/ConfigurationDeployments/mockdatafiles/updateDeploymentConfiguration-default.json +7 -0
  63. package/entities/ConfigurationDeployments/schema.json +28 -0
  64. package/entities/ConfigurationTemplates/action.json +85 -0
  65. package/entities/ConfigurationTemplates/mockdatafiles/createTemplate-default.json +4 -0
  66. package/entities/ConfigurationTemplates/mockdatafiles/getTemplates-default.json +195 -0
  67. package/entities/ConfigurationTemplates/schema.json +22 -0
  68. package/entities/DataTablesRetention/action.json +86 -0
  69. package/entities/DataTablesRetention/mockdatafiles/getBaselineAgeoutPolicySettings-default.json +22 -0
  70. package/entities/DataTablesRetention/mockdatafiles/getIndicatorAgeoutPolicySettings-default.json +16 -0
  71. package/entities/DataTablesRetention/schema.json +22 -0
  72. package/entities/IETFL2Model/action.json +67 -0
  73. package/entities/IETFL2Model/mockdatafiles/getL2TopologyAttributes-default.json +5 -0
  74. package/entities/IETFL2Model/mockdatafiles/getL2TopologyNodeTerminationPoints-default.json +69 -0
  75. package/entities/IETFL2Model/schema.json +21 -0
  76. package/entities/IETFL3Model/action.json +277 -0
  77. package/entities/IETFL3Model/mockdatafiles/getAllNodesInANetwork-default.json +207 -0
  78. package/entities/IETFL3Model/mockdatafiles/getL3TopologyAttribute-default.json +8 -0
  79. package/entities/IETFL3Model/mockdatafiles/getNetworkType-default.json +7 -0
  80. package/entities/IETFL3Model/mockdatafiles/getSpecificLinkInANetwork-default.json +67 -0
  81. package/entities/IETFL3Model/mockdatafiles/getSpecificNetwork-default.json +498 -0
  82. package/entities/IETFL3Model/mockdatafiles/getSpecificNodeInANetwork-default.json +56 -0
  83. package/entities/IETFL3Model/mockdatafiles/getSpecificTerminationPointsOfANode-default.json +17 -0
  84. package/entities/IETFL3Model/mockdatafiles/getSupportingLink-default.json +8 -0
  85. package/entities/IETFL3Model/mockdatafiles/getSupportingNetwork-default.json +7 -0
  86. package/entities/IETFL3Model/mockdatafiles/getSupportingTerminationPoint-default.json +9 -0
  87. package/entities/IETFL3Model/mockdatafiles/l3GETSRTopologyLinkAttributes-default.json +41 -0
  88. package/entities/IETFL3Model/mockdatafiles/l3GETSRTopologyNodeAttributes-default.json +16 -0
  89. package/entities/IETFL3Model/schema.json +42 -0
  90. package/entities/IETFLogicalInventoryRestconfAPI/action.json +235 -0
  91. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkInterfacesConfig-default.json +14 -0
  92. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkInterfacesUnnumbered-default.json +28 -0
  93. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkInterfacesUnnumberedIntf-default.json +21 -0
  94. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkSubInterfacesConfig-default.json +16 -0
  95. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkSubInterfacesIPv4Addresses-default.json +39 -0
  96. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkSubInterfacesIPv6Addresses-default.json +38 -0
  97. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveNetworkSubInterfacesState-default.json +15 -0
  98. package/entities/IETFLogicalInventoryRestconfAPI/mockdatafiles/retrieveResyncPolicyNodeVersionEntity-default.json +797 -0
  99. package/entities/IETFLogicalInventoryRestconfAPI/schema.json +51 -0
  100. package/entities/IETFSAPTopology/action.json +67 -0
  101. package/entities/IETFSAPTopology/mockdatafiles/getIETFNetworkFromSpecificNode-default.json +483 -0
  102. package/entities/IETFSAPTopology/mockdatafiles/getSAPNetwork-default.json +9 -0
  103. package/entities/IETFSAPTopology/mockdatafiles/getSAPsOnASpecificNodeOfSpecificServiceType-default.json +153 -0
  104. package/entities/IETFSAPTopology/schema.json +21 -0
  105. package/entities/IndicatorRules/action.json +106 -0
  106. package/entities/IndicatorRules/mockdatafiles/getAllIndicatorRules-default.json +818 -0
  107. package/entities/IndicatorRules/mockdatafiles/getSpecificIndicatorRule-default.json +119 -0
  108. package/entities/IndicatorRules/schema.json +23 -0
  109. package/entities/IndicatorTemplates/action.json +106 -0
  110. package/entities/IndicatorTemplates/mockdatafiles/avgCPUAllNodesAllActions-default.json +105 -0
  111. package/entities/IndicatorTemplates/mockdatafiles/getAllIndicatorTemplates-default.json +512 -0
  112. package/entities/IndicatorTemplates/mockdatafiles/getSpecificIndicatorTemplate-default.json +88 -0
  113. package/entities/IndicatorTemplates/mockdatafiles/uPDATEIndicatorTemplate-default.json +48 -0
  114. package/entities/IndicatorTemplates/schema.json +23 -0
  115. package/entities/Intent/action.json +105 -0
  116. package/entities/Intent/mockdatafiles/getIntent-default.json +161 -0
  117. package/entities/Intent/mockdatafiles/synchronizeIntent-default.json +6 -0
  118. package/entities/Intent/schema.json +23 -0
  119. package/entities/IntentTypeManagement/action.json +65 -0
  120. package/entities/IntentTypeManagement/mockdatafiles/getIntentTypes-default.json +482 -0
  121. package/entities/IntentTypeManagement/mockdatafiles/importIntentTypeFromIntentManager-default.json +6 -0
  122. package/entities/IntentTypeManagement/mockdatafiles/removeIntentType-default.json +7 -0
  123. package/entities/IntentTypeManagement/schema.json +21 -0
  124. package/entities/LogicalInventoryRestconfAPI/action.json +107 -0
  125. package/entities/LogicalInventoryRestconfAPI/mockdatafiles/nspInventoryFindWithFilter-default.json +528 -0
  126. package/entities/LogicalInventoryRestconfAPI/mockdatafiles/retrieveResyncPolicy-default.json +4189 -0
  127. package/entities/LogicalInventoryRestconfAPI/mockdatafiles/retrieveResyncPolicyNEAndVersionSpecific-default.json +1083 -0
  128. package/entities/LogicalInventoryRestconfAPI/mockdatafiles/retrieveResyncPollingPolicyNESpecific-default.json +1113 -0
  129. package/entities/LogicalInventoryRestconfAPI/schema.json +34 -0
  130. package/entities/ManageZTPListFromDeviceAdministrator/action.json +85 -0
  131. package/entities/ManageZTPListFromDeviceAdministrator/mockdatafiles/getZTPListFromDeviceAdministrator-default.json +114 -0
  132. package/entities/ManageZTPListFromDeviceAdministrator/schema.json +33 -0
  133. package/entities/RouterNECorrelationMappingService/action.json +147 -0
  134. package/entities/RouterNECorrelationMappingService/mockdatafiles/getCorrelationPolicy-default.json +38 -0
  135. package/entities/RouterNECorrelationMappingService/mockdatafiles/getRouterNeMapping-default.json +32 -0
  136. package/entities/RouterNECorrelationMappingService/mockdatafiles/getSpecificMappingPolicy-default.json +32 -0
  137. package/entities/RouterNECorrelationMappingService/schema.json +47 -0
  138. package/entities/TemplateMigration/action.json +44 -0
  139. package/entities/TemplateMigration/mockdatafiles/cloneTemplate-default.json +7 -0
  140. package/entities/TemplateMigration/mockdatafiles/migrateDeployments-default.json +7 -0
  141. package/entities/TemplateMigration/schema.json +20 -0
  142. package/entities/UploadMappingFiles/action.json +45 -0
  143. package/entities/UploadMappingFiles/mockdatafiles/getIETFMappingFiles-default.json +953 -0
  144. package/entities/UploadMappingFiles/schema.json +31 -0
  145. package/error.json +190 -0
  146. package/metadata.json +61 -0
  147. package/package.json +81 -0
  148. package/pronghorn.json +5141 -0
  149. package/propertiesDecorators.json +14 -0
  150. package/propertiesSchema.json +1666 -0
  151. package/refs?service=git-upload-pack +0 -0
  152. package/report/creationReport.json +657 -0
  153. package/report/update-postman.json-OpenApi3Json.json +112049 -0
  154. package/report/updateReport1718639512342.json +120 -0
  155. package/sampleProperties.json +268 -0
  156. package/test/integration/adapterTestBasicGet.js +83 -0
  157. package/test/integration/adapterTestConnectivity.js +142 -0
  158. package/test/integration/adapterTestIntegration.js +3836 -0
  159. package/test/unit/adapterBaseTestUnit.js +1024 -0
  160. package/test/unit/adapterTestUnit.js +5403 -0
  161. package/utils/adapterInfo.js +206 -0
  162. package/utils/addAuth.js +94 -0
  163. package/utils/artifactize.js +146 -0
  164. package/utils/basicGet.js +50 -0
  165. package/utils/checkMigrate.js +63 -0
  166. package/utils/entitiesToDB.js +179 -0
  167. package/utils/findPath.js +74 -0
  168. package/utils/methodDocumentor.js +273 -0
  169. package/utils/modify.js +152 -0
  170. package/utils/packModificationScript.js +35 -0
  171. package/utils/patches2bundledDeps.js +90 -0
  172. package/utils/pre-commit.sh +32 -0
  173. package/utils/removeHooks.js +20 -0
  174. package/utils/setup.js +33 -0
  175. package/utils/taskMover.js +309 -0
  176. package/utils/tbScript.js +239 -0
  177. package/utils/tbUtils.js +489 -0
  178. package/utils/testRunner.js +298 -0
  179. package/utils/troubleshootingAdapter.js +193 -0
@@ -0,0 +1,953 @@
1
+ {
2
+ "nsp-yang-mapping-converter:nsp-yang-mapping-converter": {
3
+ "@": {
4
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter",
5
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter"
6
+ },
7
+ "tracking-handler": [
8
+ {
9
+ "@": {
10
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler",
11
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler']",
12
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
13
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
14
+ },
15
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
16
+ "version": "2.0.2",
17
+ "java-code": [
18
+ {
19
+ "@": {
20
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler/java-code",
21
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler']/java-code[page-number='1']",
22
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
23
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
24
+ },
25
+ "page-number": 1,
26
+ "page": "/**\n * ***************************************************************************\n *\n * $RCSfile$\n *\n * <Your Name Here>\n *\n * ***************************************************************************\n *\n * $Revision$\n *\n * $Id$\n *\n * ***************************************************************************\n *\n * Copyright (c) 2022 NOKIA Inc. All Rights Reserved. Please read the associated COPYRIGHTS file for more details.\n *\n * ***************************************************************************\n */\npackage com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.alu.nms.common.util.model.ModelFdn;\nimport com.google.common.net.InetAddresses;\nimport com.google.common.primitives.Ints;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport com.nokia.nsp.md.common.notif.ObjectCreation;\nimport com.nokia.nsp.md.common.notif.ObjectDeletion;\nimport com.nokia.nsp.md.common.notif.ObjectModification;\nimport com.nokia.nsp.md.common.notif.ObjectReplacement;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.ICustomHandler;\nimport com.nokia.nsp.md.converter.yang.plugin.common.IHandleDeleteTracking;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\n\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nsp.md.db.yang.api.config.YangDBConfig;\nimport com.nokia.nsp.md.db.yang.spi.DBType;\nimport com.nokia.nsp.md.ifg.yang.api.Field;\nimport com.nokia.nsp.md.ifg.yang.api.Fields;\nimport com.nokia.nsp.md.ifg.yang.api.YangException;\nimport com.nokia.nsp.md.restconf.client.api.IRestConfClient;\nimport com.nokia.nspos.persistence.api.IDB;\nimport com.nokia.nspos.persistence.impl.db.transaction.DBRuntimeException;\nimport com.nokia.nspos.persistence.impl.db.transaction.ITransactionContext;\nimport com.nokia.nspos.persistence.impl.db.transaction.Transactor;\nimport com.nokia.nspos.persistence.impl.db.util.ModelFdnUtil;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\n@SuppressFBWarnings({\"BX_UNBOXING_IMMEDIATELY_REBOXED\", \"DM_NUMBER_CTOR\", \"BX_UNBOXING_IMMEDIATELY_REBOXED\", \"NP_ALWAYS_NULL\", \"NP_LOAD_OF_KNOWN_NULL_VALUE\"})\npublic class L3UnicastTopologyHandler implements ICustomHandler, IHandleDeleteTracking\n{\n private static final Logger handleSrcClassLogger = LoggerFactory.getLogger(L3UnicastTopologyHandler.class.getName() + \".handleSrcClass\");\n private static final Logger handleUpdateLogger = LoggerFactory.getLogger(L3UnicastTopologyHandler.class.getName() + \".handleUpdate\");\n private static final Logger logger = LoggerFactory.getLogger(L3UnicastTopologyHandler.class.getName());\n\n private static String NETWORKS_PATH = \"/ietf-network:networks\";\n private static String L3_NETWORK_PATH = NETWORKS_PATH + \"/network[network-id='%s']\";\n private static final String LINK_PATH_PREFIX = \"/ietf-network-topology:link\";\n private static final String LINK_PATH = LINK_PATH_PREFIX + \"[link-id='%s']\";\n private static final String NODE_PATH = \"/node[node-id='%s']\";\n private static final String TP_PATH = \"/ietf-network-topology:termination-point[tp-id='%s']\";\n\n private static final String TP_TYPE = \"ietf-network-topology:termination-point\";\n private static final String LINK_TYPE = \"ietf-network-topology:link\";\n private static final String NETWORK_CLASS_PATH =\"ietf-network:/networks/network\";\n private static final String NODE_CLASS_PATH = NETWORK_CLASS_PATH + \"/node\";\n private static final String LINK_CLASS_PATH = NETWORK_CLASS_PATH + \"/\" + LINK_TYPE;\n private static final String SR_MPLS_TYPE = \"ietf-sr-mpls-topology:sr-mpls\";\n\n private static final String NETWORK_ID = \"network-id\";\n private static final String NODE_ID = \"node-id\";\n private static final String LINK_ID = \"link-id\";\n private static final String TP_ID = \"tp-id\";\n private static final String NAME = \"name\";\n private static final String ROUTER_ID = \"router-id\";\n private static final String IP_ADDRESS = \"ip-address\";\n private static final String ID = \"id\";\n private static final String PREFIX = \"prefix\";\n private static final String MSDS = \"msds\";\n private static final String SIDS = \"sids\";\n private static final String MSD_TYPE = \"msd-type\";\n private static final String MSD_VALUE= \"msd-value\";\n private static final String VALUE_TYPE= \"value-type\";\n private static final String SID= \"sid\";\n private static final String ADDRESS_FAMILY= \"address-family\";\n private static final String IS_ELG_PROT= \"is-eligible-for-protection\";\n private static final String IS_LOCAL= \"is-local\";\n private static final String IS_PART_SET= \"is-part-of-set\";\n private static final String IS_PERS= \"is-persistent\";\n private static final String IS_ON_LAN= \"is-on-lan\";\n private static final String WEIGHT= \"weight\";\n private static final String SUBNET = \"subnet\";\n private static final String NODE_TYPE = \"node-type\";\n\n private static final String IETF_NETWORK_PATH = NETWORKS_PATH + \"/network\";\n\n private static final String NSP_SERVICE_IGP_LAYER_PATH = \"/nsp-service:services/igp-layer\";\n private static final String NSP_SERVICE_ADMIN_DOMAIN_PATH = NSP_SERVICE_IGP_LAYER_PATH + \"/admin-domain[name='%s']\";\n private static final String NSP_SERVICE_ROUTING_INS_PATH = \"/routing-instance[id='%s']\";\n private static final String NSP_SERVICE_SUBNET_PATH = \"/subnet[id='%s']\";\n private static final String NSP_SERVICE_LINK_PATH = NSP_SERVICE_IGP_LAYER_PATH + \"/ip-links[name='%s']\";\n private static final String NSP_SERVICE_GENERIC_PREFIX = NSP_SERVICE_IGP_LAYER_PATH + \"/admin-domain/routing-instance/prefix\";\n\n private static final String CREATE = \"CREATE\";\n private static final String UPDATE = \"UPDATE\";\n private static final String DELETE = \"DELETE\";\n\n private static final String L2_NETWORK_ID = \"L2Topology\";\n private static final String L2_NETWORK_PATH = String.format(L3_NETWORK_PATH, L2_NETWORK_ID);\n private static final String NETWORK_REF = \"network-ref\";\n private static final String NODE_REF = \"node-ref\";\n private static final String TP_REF = \"tp-ref\";\n private static final String LINK_REF = \"link-ref\";\n\n private static final String SUBINTERFACE_FILTER = \"/nsp-network:network/node[node-id='%s']/node-root/\" +\n \"openconfig-interfaces:interfaces/interface/subinterfaces/subinterface\";\n private static final String SUBINTERFACE_UNNUM_FILTER = \"[index='%s']\";\n private static final String SUPPORTING_NETWORK = \"supporting-network\";\n private static final String SUPPORTING_NODE = \"supporting-node\";\n private static final String SUPPORTING_TP = \"supporting-termination-point\";\n private static final String SUPPORTING_LINK = \"supporting-link\";\n\n private static final String ADMIN_DOMAIN_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain\";\n private static final String ADMIN_DOMAIN_FIELDS = \"name\";\n private static final String IP_LINK_SRC_PATH = \"nsp-service:/services/igp-layer/ip-links\";\n private static final String IP_LINK_FIELDS = \"admin-domains;protocol;name;destination-node;source-node;ip-address;\" +\n \"cost;te-metric;latency;opposite-link;isis-level;bw;available-bw;un-resv-bw;one-way-min-delay;one-way-max-delay;\" +\n \"srg-labels;sids\";\n private static final String ROUTING_INSTANCE_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain/routing-instance\";\n private static final String ROUTING_INSTANCE_FIELDS = \"node-type;protocols;id;name;router/ne;router-id;\" +\n \"prefix(ip-address;metric);msds\";\n private static final String SUBNET_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain/subnet\";\n private static final String SUBNET_FIELDS = \"node-type;protocol;id;name;dr-ip-address\";\n private static final String PREFIX_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain/routing-instance/prefix\";\n\n public static final boolean TE_TOPOLOGY_ENABLED = true;\n private static final String TIME_FIELD_LAST_MODIFIED = \"lastModifiedTime\";\n\n private List<String> srcClasses = new ArrayList<> (Arrays.asList(\n \"nsp-service:/services/igp-layer/admin-domain\",\n \"nsp-service:/services/igp-layer/admin-domain/routing-instance\",\n \"nsp-service:/services/igp-layer/admin-domain/routing-instance/prefix\",\n \"nsp-service:/services/igp-layer/admin-domain/subnet\",\n \"nsp-service:/services/igp-layer/ip-links\"\n ));\n\n private static Map<String, Set<String>> supportingNodeMap = new ConcurrentHashMap();\n private static Map<String, String> supportingTpMap = new ConcurrentHashMap();\n private static Map<String, String> supportingLinkMap = new ConcurrentHashMap();\n private static Map<String, String> oppLinkMap = new ConcurrentHashMap();\n\n private ScheduledExecutorService correlationService;\n private ThreadPoolExecutor correlationWorker;\n private static Map<String, L2TpCreateTask> l2TpCreateEvents = new ConcurrentHashMap();\n private static Map<String, L2TpDeleteTask> l2TpDeleteEvents = new ConcurrentHashMap();\n private static Map<String, L2LinkCreateTask> l2LinkCreateEvents = new ConcurrentHashMap();\n private static Map<String, L2LinkDeleteTask> l2LinkDeleteEvents = new ConcurrentHashMap();\n\n public L3UnicastTopologyHandler() {\n try {\n YangPluginMdConverterProvider mdConverterFw = YangPluginMdConverterProvider.getInstance();\n IMdConverterFw converterFw = mdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n populateSuportingNodeMap(yangDB);\n populateSuportingTpMap(yangDB);\n populateSuportingLinkMap(yangDB);\n correlationWorker = new ThreadPoolExecutor(\n 1, 2, 5L, TimeUnit.MINUTES, new LinkedBlockingQueue<>(),\n new ThreadFactoryBuilder().setNameFormat(\"L3-correlaion-worker-%d\").build());\n correlationWorker.allowCoreThreadTimeOut(true);\n }\n catch (Exception e) {\n logger.warn(\"Could not populate the correlation cache\");\n }\n }\n\n void handleL2CreateEvent(ObjectCreation aInObjectNotification, IMdConverterFw aInMdConverterFw) {\n String instanceId = aInObjectNotification.getInstanceId();\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - handleL2CreateEvent - {}\", instanceId);\n }\n if(instanceId.contains(L2_NETWORK_PATH)) {\n if (instanceId.equals(L2_NETWORK_PATH)) {\n QueryParameters qp = getFilteredQueryParameters(NETWORK_ID);\n qp.setDepth(2);\n List<IYangObject> l3NetworkObjList = yangDB.getMany(IETF_NETWORK_PATH, qp);\n if(l3NetworkObjList != null && !l3NetworkObjList.isEmpty()) {\n for(IYangObject l3NetworkObj : l3NetworkObjList) {\n String networkId = (String) l3NetworkObj.get(NETWORK_ID);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - NETWORK ID : {}\", networkId);\n }\n if(networkId != null && (networkId.contains(\"-ospf\") || networkId.contains(\"-isis\"))) {\n String supportingNetworkIdentifier = String.format(L3_NETWORK_PATH, networkId) + \"/\" + SUPPORTING_NETWORK;\n if(!yangDB.exists(supportingNetworkIdentifier)) {\n logger.debug(\"L3 - createSupportingNetwork {}\", instanceId);\n createSupportingNetwork(yangDB, getFilteredQueryParameters(null), networkId, instanceId);\n }\n }\n }\n }\n } else if (instanceId.contains(TP_TYPE)) {\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n String port = StringUtils.substringBetween(instanceId, \"[tp-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n if (l2TpCreateEvents.containsKey(neId)) {\n L2TpCreateTask l2TpTask = l2TpCreateEvents.get(neId);\n if(l2TpDeleteEvents.containsKey(neId) && l2TpDeleteEvents.get(neId).portsToDelete.contains(port)) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} not added to the queue {} as it was in the list to be removed\", port, neId);\n }\n l2TpDeleteEvents.get(neId).portsToDelete.remove(port);\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} added to the queue {} \", port, neId);\n }\n l2TpTask.portsToAdd.put(port, 1);\n }\n } else {\n L2TpCreateTask tpTask = new L2TpCreateTask(neId, port, aInMdConverterFw);\n l2TpCreateEvents.put(neId, tpTask);\n }\n synchronized (this) {\n if (correlationService == null || correlationService.isShutdown()) {\n logger.debug(\"L3 - L2 - Correlation - correlationService has been started that will run periodically until correlation is complete\");\n correlationService = Executors.newScheduledThreadPool(1,\n new ThreadFactoryBuilder().setNameFormat(\"L3-CorrelationHandler-to-L2\").build());\n correlationService.scheduleAtFixedRate(() -> correlateTpsAndLinks(), 2, 2, TimeUnit.MINUTES);\n }\n }\n }\n } else if (instanceId.contains(\"/node\")) {\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - NE ID - {}\", neId);\n }\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n for(List<String> router: routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n String supportingNodeIden = nodeIdentifer + \"/\" + SUPPORTING_NODE;\n if(!yangDB.exists(supportingNodeIden) && yangDB.exists(nodeIdentifer)) {\n logger.debug(\"L3 - createSupportingNode {}\", instanceId);\n createSupportingNode(yangDB, getFilteredQueryParameters(null), networkId, router.get(0), instanceId, nodeIdentifer);\n }\n }\n }\n } else if(instanceId.contains(LINK_TYPE)) {\n if(!l2LinkCreateEvents.containsKey(instanceId)) {\n L2LinkCreateTask l2LinkCreateTask = new L2LinkCreateTask(instanceId, aInMdConverterFw);\n l2LinkCreateEvents.put(instanceId, l2LinkCreateTask);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - links to correlate: {}\", l2LinkCreateEvents.keySet());\n }\n startCorrelationService();\n }\n }\n }\n }\n\n List<String> getTpDetails(String[] tpDetails, IYangDB yangDB, IMdConverterFw aInMdConverterFw, List<String> aInNetworkDetails) {\n List<String> l3SourceTps = new ArrayList<>();\n if(tpDetails != null && tpDetails.length == 2) {\n String sourceNeId = tpDetails[0];\n String sourcePort = tpDetails[1];\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, sourceNeId);\n if(routers == null) {\n return l3SourceTps;\n }\n for(List<String> router: routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n if(aInNetworkDetails != null) {\n aInNetworkDetails.add(networkId);\n }\n QueryParameters qp = getFilteredQueryParameters(\"tp-id;\" + SUPPORTING_TP);\n qp.setDepth(2);\n List<IYangObject> tpList = yangDB.getMany(nodeIdentifer + \"/\" + TP_TYPE, qp);\n if(tpList != null && !tpList.isEmpty()) {\n for(IYangObject tp : tpList) {\n String tpId = (String) tp.get(\"tp-id\");\n String portName = null;\n if(tp.get(SUPPORTING_TP) == null || ((List<IYangObject>) tp.get(SUPPORTING_TP)).isEmpty()) {\n portName = getPortDetailsFromDb(tpId, yangDB, sourceNeId);\n if (portName == null) {\n //try to get the details via openconfig restconf. It works for mdm managed nodes\n portName = getSubInterfaces(sourceNeId, aInMdConverterFw, tpId);\n }\n }\n else {\n List<IYangObject> supportingTp = (List<IYangObject>) tp.get(SUPPORTING_TP);\n String tpRef = (String) supportingTp.get(0).get(TP_REF);\n portName = StringUtils.substringBetween(tpRef, \"[tp-id='\", \"']\");\n }\n if(portName != null && portName.equals(sourcePort)) {\n l3SourceTps.add(router.get(0) + \":\" + tpId);\n }\n }\n }\n }\n }\n return l3SourceTps;\n }\n\n void handleL2DeleteEvent(ObjectDeletion aInObjectNotification, IMdConverterFw aInMdConverterFw) {\n String instanceId = aInObjectNotification.getInstanceId();\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - handleL2DeleteEvent - {}\", instanceId);\n }\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n\n if(instanceId.contains(L2_NETWORK_PATH)) {\n if (instanceId.equals(L2_NETWORK_PATH)) {\n QueryParameters qp = getFilteredQueryParameters(NETWORK_ID);\n qp.setDepth(2);\n List<IYangObject> l3NetworkObjList = yangDB.getMany(IETF_NETWORK_PATH, qp);\n if(l3NetworkObjList != null && !l3NetworkObjList.isEmpty()) {\n for(IYangObject l3NetworkObj : l3NetworkObjList) {\n String networkId = (String) l3NetworkObj.get(NETWORK_ID);\n if(networkId != null && (networkId.contains(\"-ospf\") || networkId.contains(\"-isis\"))) {\n String supportingNetworkIdentifier = String.format(L3_NETWORK_PATH, networkId) + \"/\" + SUPPORTING_NETWORK;\n if(yangDB.exists(supportingNetworkIdentifier)) {\n updateInDb(yangDB, null, supportingNetworkIdentifier, null, null, DELETE, null, qp);\n }\n }\n }\n }\n } else if (instanceId.contains(TP_TYPE)) {\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n String port = StringUtils.substringBetween(instanceId, \"[tp-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n if (l2TpDeleteEvents.containsKey(neId)) {\n L2TpDeleteTask l2TpTask = l2TpDeleteEvents.get(neId);\n if(l2TpCreateEvents.containsKey(neId) && l2TpCreateEvents.get(neId).portsToAdd.containsKey(port)) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} not added to the delete queue {} as it was in the list to be added\", port, neId);\n }\n l2TpCreateEvents.get(neId).portsToAdd.remove(port);\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} added to the delete queue {} \", port, neId);\n }\n l2TpTask.portsToDelete.add(port);\n }\n } else {\n L2TpDeleteTask tpTask = new L2TpDeleteTask(neId, port, aInMdConverterFw);\n l2TpDeleteEvents.put(neId, tpTask);\n }\n if(logger.isDebugEnabled()) {\n logger.debug(l2TpDeleteEvents.keySet().toString());\n }\n startCorrelationService();\n }\n } else if (instanceId.contains(\"/node\")) {\n if(supportingNodeMap.containsKey(instanceId)) {\n for (String nodeIden : supportingNodeMap.get(instanceId)) {\n String supportingNodeIden = nodeIden + \"/\" + SUPPORTING_NODE;\n if (yangDB.exists(supportingNodeIden)) {\n logger.debug(\"L3 - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(yangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n String supportingTpIden = nodeIden + \"/\" + TP_TYPE + \"/\" + SUPPORTING_TP;\n if(yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTps on node {}\", supportingNodeIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n supportingTpMap.entrySet().removeIf(entry -> entry.getKey().startsWith(instanceId));\n }\n }\n }\n supportingNodeMap.remove(instanceId);\n return;\n }\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n if(routers != null) {\n for (List<String> router : routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n String supportingNodeIden = nodeIdentifer + \"/\" + SUPPORTING_NODE;\n if (yangDB.exists(supportingNodeIden)) {\n logger.debug(\"L3 - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(yangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n } else if(instanceId.contains(LINK_TYPE)) {\n if(!l2LinkDeleteEvents.containsKey(instanceId)) {\n L2LinkDeleteTask l2LinkDeleteTask = new L2LinkDeleteTask(instanceId, aInMdConverterFw);\n l2LinkDeleteEvents.put(instanceId, l2LinkDeleteTask);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - links to delete correlation: {}\", l2LinkDeleteEvents.keySet());\n }\n startCorrelationService();\n }\n }\n }\n }\n\n private void deleteL2SupportingTps(List<String> portsToDelete, String neId, IYangDB yangDB) {\n List<String> deletedPorts = new ArrayList<>();\n for(String port : portsToDelete) {\n String instanceId = L2_NETWORK_PATH + String.format(NODE_PATH, neId) + String.format(TP_PATH, port);\n if (supportingTpMap.containsKey(instanceId)) {\n String supportingTpIden = supportingTpMap.get(instanceId) + \"/\" + SUPPORTING_TP;\n if (yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTp {}\", supportingTpIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n supportingTpMap.remove(instanceId);\n deletedPorts.add(port);\n }\n }\n\n portsToDelete.removeAll(deletedPorts);\n if(portsToDelete.isEmpty()) {\n return;\n }\n\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n if(routers != null) {\n for (List<String> router : routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n QueryParameters qp = getFilteredQueryParameters(\"tp-id;\" + SUPPORTING_TP);\n qp.setDepth(2);\n List<IYangObject> tpList = yangDB.getMany(nodeIdentifer + \"/\" + TP_TYPE, qp);\n if (tpList != null && !tpList.isEmpty()) {\n for (IYangObject tp : tpList) {\n if (tp.get(SUPPORTING_TP) != null) {\n String supportingTpRef = (String) ((IYangObject) ((List) tp.get(SUPPORTING_TP)).get(0)).get(TP_REF);\n String port = StringUtils.substringBetween(supportingTpRef, \"[tp-id='\", \"']\");\n if (portsToDelete.contains(port)) {\n String tpId = (String) tp.get(TP_ID);\n String tpIden = nodeIdentifer + String.format(TP_PATH, tpId);\n String supportingTpIden = tpIden + \"/\" + SUPPORTING_TP;\n if (yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTp {}\", supportingTpIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n portsToDelete.remove(port);\n }\n }\n }\n }\n }\n }\n }\n\n private void correlateTpsAndLinks() {\n\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Running routine correlation task\");\n }\n Map<String, L2TpCreateTask> l2TpCreateTaskMap =new HashMap<>(l2TpCreateEvents);\n l2TpCreateEvents.clear();\n Map<String, L2TpDeleteTask> l2TpDeleteTaskMap =new HashMap<>(l2TpDeleteEvents);\n l2TpDeleteEvents.clear();\n Map<String, L2LinkCreateTask> l2LinkCreateTaskMap =new HashMap<>(l2LinkCreateEvents);\n l2LinkCreateEvents.clear();\n Map<String, L2LinkDeleteTask> l2LinkDeleteTaskMap =new HashMap<>(l2LinkDeleteEvents);\n l2LinkDeleteEvents.clear();\n\n if(!l2TpCreateTaskMap.isEmpty()) {\n for(L2TpCreateTask l2TpTask : l2TpCreateTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate ports creation on {}\", l2TpTask.neId);\n correlationWorker.execute(l2TpTask);\n }\n }\n\n if(!l2TpDeleteTaskMap.isEmpty()) {\n for(L2TpDeleteTask l2TpTask : l2TpDeleteTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate ports deletion on {}\", l2TpTask.neId);\n correlationWorker.execute(l2TpTask);\n }\n }\n\n if(!l2LinkCreateTaskMap.isEmpty()) {\n for(L2LinkCreateTask l2LinkTask : l2LinkCreateTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate link creation {}\", l2LinkTask.linkId);\n correlationWorker.execute(l2LinkTask);\n }\n }\n\n if(!l2LinkDeleteTaskMap.isEmpty()) {\n for(L2LinkDeleteTask l2LinkTask : l2LinkDeleteTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate link deletion {}\", l2LinkTask.linkId);\n correlationWorker.execute(l2LinkTask);\n }\n }\n\n if(l2TpCreateEvents.isEmpty() && l2TpDeleteEvents.isEmpty()\n && l2LinkCreateEvents.isEmpty() && l2LinkDeleteEvents.isEmpty()) {\n logger.debug(\"L3 - correlationService is shutdown\");\n correlationService.shutdown();\n }\n\n }\n\n @Override\n public int readSrcObjectDepth(String aInSrcClassPath) {\n if(aInSrcClassPath.equals(ROUTING_INSTANCE_SRC_PATH)) {\n return 3;\n }\n else {\n return 2;\n }\n }\n\n @Override\n public Fields srcFilterFieldsToInclude(String aInSrcClassPath) {\n if(aInSrcClassPath.equals(ADMIN_DOMAIN_SRC_PATH)) {\n return Fields.parse(ADMIN_DOMAIN_FIELDS);\n }\n else if(aInSrcClassPath.equals(IP_LINK_SRC_PATH)) {\n return Fields.parse(IP_LINK_FIELDS);\n }\n else if(aInSrcClassPath.equals(ROUTING_INSTANCE_SRC_PATH)) {\n return Fields.parse(ROUTING_INSTANCE_FIELDS);\n }\n else if(aInSrcClassPath.equals(SUBNET_SRC_PATH)) {\n return Fields.parse(SUBNET_FIELDS);\n }\n else {\n return null;\n }\n }\n\n @Override\n public void handlePostResyncDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n //this method is called after the fwk deletes the object. extra post processing logics like cleaning up routing instances/tp.\n if(logger.isDebugEnabled()) {\n logger.debug(\"POST RE-SYNC DELETE - aInSrcClass:{}, aInSyncClass:{}\", aInSrcClass, aInSyncClass);\n }\n }\n\n @Override\n public void handleTrackedDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, String aInIdentifier, Map<String, Object> aInData, YangPluginMdConverterProvider aInYangPlugin)\n {\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInIdentifier:{}, aInData:{}\", aInSrcClass, aInSyncClass, aInIdentifier, aInData);\n }\n IMdConverterFw converterFw = aInYangPlugin.getiMdConverterFw();\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n IYangDB yangDB = converterFw.getIYangDB();\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInSrcClass.getSrcClassPath().equals(IP_LINK_SRC_PATH)) {\n Map<String, Object> linkObj = new HashMap<>();\n linkObj.put(NAME, StringUtils.substringBetween(aInIdentifier, \"ip-links[name='\", \"'\"));\n logger.debug(\"L3 - handleTrackedDelete - DELETING LINK - {} \", aInIdentifier);\n deleteLink(yangDB, qp, linkObj, dbConfig, null);\n }\n else if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n String ipAddress = StringUtils.substringBetween(aInIdentifier, \"prefix[ip-address='\", \"'\");\n logger.debug(\"L3 - handleTrackedDelete - DELETING PREFIX {}, {} \", aInIdentifier, ipAddress);\n deletePrefix(yangDB, qp, aInIdentifier, ipAddress);\n }\n else if(aInSrcClass.getSrcClassPath().equals(SUBNET_SRC_PATH)) {\n String networkId = extractAdminDomain(aInIdentifier) + \"-\" + aInData.get(\"protocols\");\n logger.debug(\"L3 - handleTrackedDelete - DELETING SUBNET - {}, {} \", aInIdentifier, networkId);\n deleteNode(yangDB, qp, aInData, dbConfig, networkId, null);\n }\n else if(aInSrcClass.getSrcClassPath().equals(ADMIN_DOMAIN_SRC_PATH)) {\n String adminDomain = StringUtils.substringBetween(aInIdentifier, \"admin-domain[name='\", \"'\");\n IYangObject yangObj = new YangObject();\n yangObj.setProperty(NAME, adminDomain);\n logger.debug(\"L3 - handleTrackedDelete - DELETING NETWORK - {} \", aInIdentifier);\n deleteNetwork(yangDB, qp, yangObj);\n }\n }\n\n\n public void handleResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInExistingObject,\n String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n if(handleSrcClassLogger.isDebugEnabled()) {\n handleSrcClassLogger.debug(\"---------------------------------------------------------RE-SYNC----------------------------------------------------------------------\");\n handleSrcClassLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n }\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n\n if (aInSyncClass.getDestClassPath().equals(NETWORK_CLASS_PATH)) {\n handleSrcClassLogger.debug(\"L3 - RESYNC NETWORK - {}\", aInSrcObject.get(NAME) );\n createL3Network(aInSrcObject, yangDB, dbConfig, converterFw);\n }\n else if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n Map<String, Object> srcObject = aInSrcObject.asMap();\n handleSrcClassLogger.debug(\"L3 - RESYNC NODE - {}\", srcObject.get(ID));\n String networkId = getNetworkIdFromMeta(yangDB, srcObject);\n if(networkId == null) {\n return;\n }\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n //could be routing instance or subnet.\n if(yangDB.exists(networkPathIdentifier, qp)) {\n if (srcObject.get(NODE_TYPE).equals(SUBNET)) {\n if(handleSrcClassLogger.isDebugEnabled()) {\n handleSrcClassLogger.debug(\"L3 - SUBNET\");\n }\n createSubnet(srcObject, yangDB, dbConfig, networkId, null);\n } else {\n if(handleSrcClassLogger.isDebugEnabled()) {\n handleSrcClassLogger.debug(\"L3 - NODE\");\n }\n createRoutingInstance(srcObject, yangDB, networkId);\n }\n }\n else {\n handleSrcClassLogger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", srcObject.get(ID));\n }\n\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n Map<String, Object> srcObject = aInSrcObject.asMap();\n handleSrcClassLogger.debug(\"L3 - RESYNC LINK - {}\", srcObject.get(NAME));\n String networkId = getNetworkIdFromLink((List<String>) srcObject.get(\"admin-domains\"), (String) srcObject.get(\"protocol\"));\n if(networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n if (yangDB.exists(networkPathIdentifier, qp)) {\n createLink(srcObject, yangDB, converterFw, networkId, false, null);\n }\n else {\n handleSrcClassLogger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", srcObject.get(NAME));\n }\n }\n }\n }\n\n @Override\n public void handleCreateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectCreation aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n\n if(aInEvent.getInstanceId().contains(L2_NETWORK_PATH)) {\n handleL2CreateEvent(aInEvent, converterFw);\n return;\n }\n\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n if(logger.isDebugEnabled()) {\n logger.debug(\"---------------------------------------------------CREATION---------------------------------------------------------------------------\");\n }\n IYangDB yangDB = converterFw.getIYangDB();\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n if (aInSyncClass.getDestClassPath().equals(NETWORK_CLASS_PATH)) {\n logger.debug(\"L3 - CREATE NETWORK\");\n createL3Network(aInEvent.getEntity(), yangDB, dbConfig, converterFw);\n }\n else if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n logger.debug(\"L3 - CREATE PREFIX\");\n createPrefix(yangDB, getFilteredQueryParameters(null), aInEvent);\n }\n else {\n logger.debug(\"L3 - CREATE NODE\");\n Map<String, Object> srcObject = aInEvent.getEntity().asMap();\n String id = (String) srcObject.get(ID);\n String adminDomain = getAdminDomainFromMeta(srcObject);\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += srcObject.get(NODE_TYPE).equals(SUBNET) ? String.format(NSP_SERVICE_SUBNET_PATH, id)\n : String.format(NSP_SERVICE_ROUTING_INS_PATH, id);\n QueryParameters qp = srcObject.get(NODE_TYPE).equals(SUBNET) ?\n getFilteredQueryParameters(\"node-type;protocol;id;name;dr-ip-address\") :\n getFilteredQueryParameters(\"node-type;protocols;id;name;router/ne;router-id;prefix(ip-address;metric)\");\n //IYangObject nodeObj = yangDB.getSingle(nspServiceNodeIden, qp);\n //GetMany for debug\n qp.setLimit(2);\n List<IYangObject> nodeObjs = yangDB.getMany(nspServiceNodeIden, qp);\n IYangObject nodeObj=null;\n if(nodeObjs.size()>0){\n nodeObj=nodeObjs.get(0);\n }\n if(nodeObjs.size()>1){\n logger.error(\"More than one object returned for path: {}\", nspServiceNodeIden);\n }\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(yangDB, nodeMap);\n if(networkId == null) {\n return;\n }\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n qp = getFilteredQueryParameters(null);\n //could be routing instance or subnet.\n if (yangDB.exists(networkPathIdentifier, qp)) {\n if (nodeMap.get(NODE_TYPE).equals(SUBNET)) {\n if (logger.isDebugEnabled()) {\n logger.debug(\"L3 - CREATE SUBNET\");\n }\n createSubnet(nodeMap, yangDB, dbConfig, networkId, null);\n } else {\n if (logger.isDebugEnabled()) {\n logger.debug(\"L3 - CREATE ROUTING-INSTANCE\");\n }\n createRoutingInstance(nodeMap, yangDB, networkId);\n }\n }\n } else {\n logger.warn(\"L3 - Not found: \" + nspServiceNodeIden);\n }\n }\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n logger.debug(\"L3 - CREATE LINK\");\n String name = (String) aInEvent.getEntity().get(NAME);\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n QueryParameters qp = getFilteredQueryParameters(IP_LINK_FIELDS);\n IYangObject linkObj = yangDB.getSingle(nspServiceIpLinkIden, qp);\n\n if(linkObj != null) {\n String networkId = getNetworkIdFromLink((List<String>) linkObj.get(\"admin-domains\"), (String) linkObj.get(\"protocol\"));\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if (yangDB.exists(networkPathIdentifier, qp)) {\n createLink(linkObj.asMap(), yangDB, converterFw, networkId, true, null);\n } else {\n logger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", linkObj.get(NAME));\n }\n }\n }\n }\n }\n\n void createL3Network(IYangObject aInSrcObject, IYangDB aInYangDB, YangDBConfig aInDbConfig, IMdConverterFw aInConverterFw) {\n\n String adminDomain = (String) aInSrcObject.get(NAME);\n if(\"UnknownDomain\".equals(adminDomain)) {\n return;\n }\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInSrcObject != null) {\n String networkId = getNetworkId(aInYangDB, aInSrcObject);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n try {\n if (!aInYangDB.exists(networkPathIdentifier, qp)) {\n logger.debug(\"L3 - creating new network: {}\", networkId);\n qp = getFilteredQueryParameters(null);\n\n IYangObject l3NetworkObj = new YangObject();\n l3NetworkObj.setProperty(NETWORK_ID, networkId);\n IYangObject networkTypesObj = new YangObject();\n IYangObject l3UnicastNwObj = new YangObject();\n l3UnicastNwObj.setProperty(SR_MPLS_TYPE, new YangObject());\n networkTypesObj.setProperty(\"ietf-l3-unicast-topology:l3-unicast-topology\", l3UnicastNwObj);\n l3NetworkObj.setProperty(\"network-types\", networkTypesObj);\n\n YangObject topologyAttrObj = new YangObject();\n topologyAttrObj.setProperty(\"name\", aInSrcObject.get(NAME));\n l3NetworkObj.setProperty(\"ietf-l3-unicast-topology:l3-topology-attributes\", topologyAttrObj);\n\n updateInDb(aInYangDB, l3NetworkObj, \"\", NETWORKS_PATH, \"network\", CREATE, null, qp);\n\n\n //create supporting-network\n String supportingNetworkRef = getSupportingNetworkRef(aInYangDB, qp);\n if(supportingNetworkRef != null) {\n createSupportingNetwork(aInYangDB, qp, networkId, supportingNetworkRef);\n }\n /* resync is based on equipment.networkelement table and so if there are no corresponding NEs\n discovered for the routers, we wouldn't get any nodes. so it is important (at least for now) to\n get the network and build the nodes from that info instead of relying on the node resync events.\n */\n// createRoutingInstances(aInSrcObject.get(\"routing-instance\"), aInYangDB, networkId);\n// createSubnets(aInSrcObject.get(\"subnet\"), aInYangDB, aInDbConfig, networkId);\n } else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - network exists already - {} \", networkId);\n }\n }\n } catch (Exception e) {\n logger.error(\"L3 - Exception when creating IETF L3 network: \" + networkId, e);\n return;\n }\n\n //create TE Network\n String teNetworkRef = createTeNetwork(networkId, aInYangDB);\n if(teNetworkRef != null) {\n createTeNetworkRef(aInYangDB, getFilteredQueryParameters(null), networkId, teNetworkRef);\n }\n }\n }\n }\n\n String createTeNetwork(String networkId, IYangDB aInYangDB) {\n if(!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n String teNetworkId = getTeNetworkId(networkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n try {\n if (!aInYangDB.exists(teNetworkPathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new network: {}\", teNetworkId);\n\n IYangObject networkObj = new YangObject();\n networkObj.setProperty(NETWORK_ID, teNetworkId);\n IYangObject networkTypesObj = new YangObject();\n IYangObject packetTypesObj = new YangObject();\n packetTypesObj.setProperty(\"ietf-te-topology-packet:packet\", new YangObject());\n networkTypesObj.setProperty(\"ietf-te-topology:te-topology\", packetTypesObj);\n networkObj.setProperty(\"network-types\", networkTypesObj);\n\n YangObject topologyProviderIdObj = new YangObject();\n topologyProviderIdObj.setProperty(\"topology-id\", \"\");\n topologyProviderIdObj.setProperty(\"client-id\", 0);\n topologyProviderIdObj.setProperty(\"provider-id\", 0);\n networkObj.setProperty(\"ietf-te-topology:te-topology-identifier\", topologyProviderIdObj);\n\n updateInDb(aInYangDB, networkObj, \"\", NETWORKS_PATH, \"network\", CREATE, null, qp);\n return teNetworkPathIdentifier;\n } else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"TE Topology - network exists already - {} \", teNetworkId);\n }\n }\n } catch (Exception e) {\n logger.error(\"TE Topology - Exception when creating TE network object {}: {}\", teNetworkId, e);\n }\n return null;\n }\n\n void createSubnets(Object aInSubnets, IYangDB aInYangDB, YangDBConfig aInDbConfig, String networkId) {\n\n if (aInSubnets != null && ((List) aInSubnets).size() > 0) {\n List<IYangObject> subnets = (List<IYangObject>) aInSubnets;\n for (IYangObject subnet : subnets) {\n createSubnet(subnet.asMap(), aInYangDB, aInDbConfig, networkId, null);\n }\n }\n }\n\n\n void createSubnet(Map<String,Object> aInSubnet, IYangDB aInYangDB, YangDBConfig aInDbConfig, String networkId, String aInRouterId) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String systemId = getSubnetSystemId((String) aInSubnet.get(NAME));\n String routerId = aInRouterId;\n if(routerId == null) {\n if (systemId.contains(\"dr\")) {\n routerId = (String) aInSubnet.get(\"dr-ip-address\");\n }\n routerId = routerId == null ? InetAddresses.isInetAddress(systemId) ? systemId : getSubnetNodeIdFromDB(aInDbConfig, systemId, networkId) : routerId;\n if (routerId == null) {\n logger.error(\"Couldn't create the subnet node because router-id is null for {}\", systemId);\n return;\n }\n }\n String nodeId = routerId +\"-\"+getSubnetPsnId((String) aInSubnet.get(NAME));\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n\n if (!aInYangDB.exists(nodePathIdentifier, qp)) {\n logger.debug(\"L3 - creating new subnet: {} on {}\", nodeId, networkId);\n IYangObject nodeObj = new YangObject();\n nodeObj.setProperty(NETWORK_ID, networkId);\n nodeObj.setProperty(NODE_ID, nodeId);\n IYangObject nodeAttrObj = new YangObject();\n nodeAttrObj.setProperty(NETWORK_ID, networkId);\n nodeAttrObj.setProperty(NAME, aInSubnet.get(NAME));\n nodeAttrObj.setProperty(ROUTER_ID, Arrays.asList(new String[]{nodeId}));\n nodeAttrObj.setProperty(\"flag\", Collections.singletonList(\"nsp-ietf-network-topology:subnet\"));\n nodeObj.setProperty(\"ietf-l3-unicast-topology:l3-node-attributes\", nodeAttrObj);\n logger.debug(\"L3 - createSubnet - {}\", networkPathIdentifier);\n updateInDb(aInYangDB, nodeObj, \"\", networkPathIdentifier, \"node\", CREATE, null, qp);\n }\n\n //create TE network subnet\n String teNodeRef = createTeNode(networkId, aInYangDB, nodeId, routerId);\n if(teNodeRef != null) {\n String teNetworkRef = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId));\n createTeNodeRef(aInYangDB, getFilteredQueryParameters(null), networkId, nodeId, teNetworkRef, teNodeRef);\n }\n }\n\n String createTeNode(String networkId,IYangDB aInYangDB, String nodeId, String teNodeId) {\n if(!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n String teNetworkId = getTeNetworkId(networkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n\n String teNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, nodeId);\n\n if (!aInYangDB.exists(teNodePathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new node: {} on {}\", nodeId, teNetworkId);\n IYangObject nodeObj = new YangObject();\n nodeObj.setProperty(NETWORK_ID, teNetworkId);\n nodeObj.setProperty(NODE_ID, nodeId);\n nodeObj.setProperty(\"te-node-id\", teNodeId);\n logger.debug(\"L3 - createTeNode - {}\", teNetworkPathIdentifier);\n updateInDb(aInYangDB, nodeObj, \"\", teNetworkPathIdentifier, \"node\", CREATE, null, qp);\n return teNodePathIdentifier;\n }\n return null;\n }\n\n\n void createRoutingInstances(Object aInRoutingInstances, IYangDB aInYangDB, String networkId) {\n\n if (aInRoutingInstances != null && ((List) aInRoutingInstances).size() > 0) {\n List<IYangObject> routingInstances = (List<IYangObject>) aInRoutingInstances;\n for (IYangObject routingInstance : routingInstances) {\n createRoutingInstance(routingInstance.asMap(), aInYangDB, networkId);\n }\n }\n }\n\n void createRoutingInstance(Map<String,Object> aInRoutingInstance, IYangDB aInYangDB, String networkId) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodeId = (String) aInRoutingInstance.get(ID);\n String routerId = (String) aInRoutingInstance.get(ROUTER_ID);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n\n if (!aInYangDB.exists(nodePathIdentifier, qp)) {\n logger.debug(\"L3 - creating new routing instance: {} on {}\", nodeId, networkId);\n IYangObject nodeObj = new YangObject();\n nodeObj.setProperty(NETWORK_ID, networkId);\n nodeObj.setProperty(NODE_ID, nodeId);\n IYangObject nodeAttrObj = new YangObject();\n nodeAttrObj.setProperty(NETWORK_ID, networkId);\n nodeAttrObj.setProperty(NAME, aInRoutingInstance.get(NAME));\n nodeAttrObj.setProperty(ROUTER_ID, Arrays.asList(new String[]{routerId}));\n nodeAttrObj.setProperty(\"flag\", Collections.singletonList(\"nsp-ietf-network-topology:routing-instance\"));\n nodeObj.setProperty(\"ietf-l3-unicast-topology:l3-node-attributes\", nodeAttrObj);\n\n updateInDb(aInYangDB, nodeObj, \"\", networkPathIdentifier, \"node\", CREATE, null, qp);\n\n //create supporting-node\n Map routerDetails = (Map) aInRoutingInstance.get(\"router\");\n if(routerDetails != null && routerDetails.containsKey(\"ne\")) {\n String neId = extractNeId((String) routerDetails.get(\"ne\"));\n if(neId != null) {\n String supportingNodeRef = getSupportingNodeRef(aInYangDB, qp, neId);\n if(supportingNodeRef != null) {\n String supportingNodeIden = nodePathIdentifier + \"/\" + SUPPORTING_NODE;\n if(!aInYangDB.exists(supportingNodeIden, qp)) {\n createSupportingNode(aInYangDB, qp, networkId, nodeId, supportingNodeRef, nodePathIdentifier);\n }\n }\n }\n }\n\n //create prefixes\n List<Map<String,Object>> prefixes = (List) aInRoutingInstance.get(PREFIX);\n if(prefixes != null) {\n Set<String> prefixSet = new HashSet<>();\n for (Map<String, Object> prefix : prefixes) {\n if (!prefixSet.contains(prefix.get(IP_ADDRESS))) {\n prefixSet.add((String) prefix.get(IP_ADDRESS));\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, prefix.get(IP_ADDRESS));\n prefixObj.setProperty(\"metric\", prefix.get(\"metric\"));\n updateInDb(aInYangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, qp);\n }\n }\n }\n\n //create sr mpls MSDs\n List<Map<String,Object>> msds = (List) aInRoutingInstance.get(MSDS);\n if(msds != null) {\n IYangObject srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, networkId);\n srMplsObj.setProperty(NODE_ID, nodeId);\n\n IYangObject msdObj = new YangObject();\n msdObj.setProperty(NETWORK_ID, networkId);\n msdObj.setProperty(NODE_ID, nodeId);\n srMplsObj.setProperty(MSDS, msdObj);\n\n String nodeAttrIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\";\n updateInDb(aInYangDB, srMplsObj, \"\", nodeAttrIden, SR_MPLS_TYPE, CREATE, null, qp);\n\n for(Map<String, Object> msd : msds) {\n IYangObject nodeMsdObj = new YangObject();\n nodeMsdObj.setProperty(NETWORK_ID, networkId);\n nodeMsdObj.setProperty(NODE_ID, nodeId);\n nodeMsdObj.setProperty(MSD_TYPE, msd.get(MSD_TYPE));\n nodeMsdObj.setProperty(MSD_VALUE, msd.get(MSD_VALUE));\n updateInDb(aInYangDB, nodeMsdObj, \"\", nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"node-msd\", CREATE, null, qp);\n }\n }\n }\n else {\n /** there could be updates during resync.\n * prefix (L3) and msd (SR MPLS) could have been updated or created */\n\n List<Map<String,Object>> prefixes = (List) aInRoutingInstance.get(PREFIX);\n if(prefixes != null) {\n Set<String> prefixSet = new HashSet<>();\n for (Map<String, Object> prefix : prefixes) {\n String ipAddress = (String) prefix.get(IP_ADDRESS);\n if(!prefixSet.contains(prefix.get(IP_ADDRESS))) {\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n QueryParameters queryParameters = getFilteredQueryParameters(null);\n if (aInYangDB.exists(prefixPathIden, queryParameters)) {\n //update\n logger.debug(\"L3 - handleResync - prefix - UPDATE {}\", prefixPathIden);\n IYangObject prefixObj = aInYangDB.getSingle(prefixPathIden, queryParameters);\n if (prefixObj != null) {\n int metric = (int) prefix.get(\"metric\");\n prefixObj.setProperty(\"metric\", metric);\n updateInDb(aInYangDB, prefixObj, prefixPathIden, null, null, UPDATE, null, queryParameters);\n }\n } else {\n logger.debug(\"L3 - handleResync - prefix - CREATE {}\", prefixPathIden);\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, prefix.get(IP_ADDRESS));\n prefixObj.setProperty(\"metric\", prefix.get(\"metric\"));\n updateInDb(aInYangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, qp);\n }\n prefixSet.add((String) prefix.get(IP_ADDRESS));\n }\n }\n }\n\n List<Map<String,Object>> msds = (List) aInRoutingInstance.get(MSDS);\n if(msds != null) {\n //copy code from updateMsds\n updateMsd(aInYangDB, nodeId, aInRoutingInstance, networkId);\n }\n\n //create supporting-node\n Map routerDetails = (Map) aInRoutingInstance.get(\"router\");\n if(routerDetails != null && routerDetails.containsKey(\"ne\")) { //check this for unmanaged NE\n String neId = extractNeId((String) routerDetails.get(\"ne\"));\n if(logger.isDebugEnabled()) {\n logger.debug(\"*********** - NE {} {}\", neId, routerDetails.get(\"ne\"));\n }\n if(neId != null) {\n String supportingNodeRef = getSupportingNodeRef(aInYangDB, qp, neId);\n if(supportingNodeRef != null) {\n String supportingNodeIden = nodePathIdentifier + \"/\" + SUPPORTING_NODE;\n if(!aInYangDB.exists(supportingNodeIden, qp)) {\n logger.debug(\"L3 - Resync Node - createSupportingNode {}\", supportingNodeIden);\n createSupportingNode(aInYangDB, qp, networkId, nodeId, supportingNodeRef, nodePathIdentifier);\n }\n }\n }\n else {\n //NE could have been unmanaged\n if(logger.isDebugEnabled()) {\n logger.debug(\"*********** - Trying to delete supporting node {}\", nodePathIdentifier);\n }\n String supportingNodeIden = nodePathIdentifier + \"/\" + SUPPORTING_NODE;\n if (aInYangDB.exists(supportingNodeIden)) {\n IYangObject supportingNodeObj = aInYangDB.getSingle(supportingNodeIden, getFilteredQueryParameters(null));\n String l2NodeRef = (String) supportingNodeObj.get(\"node-ref\");\n if(supportingNodeMap.containsKey(l2NodeRef)) {\n for (String nodeIden : supportingNodeMap.get(l2NodeRef)) {\n if(nodeIden.equals(nodePathIdentifier)) {\n logger.debug(\"L3 - Resync Node - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(aInYangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n else {\n supportingNodeIden = nodeIden + \"/\" + SUPPORTING_NODE;\n if (aInYangDB.exists(supportingNodeIden)) {\n logger.debug(\"L3 - Resync Node - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(aInYangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n supportingNodeMap.remove(l2NodeRef);\n }\n else {\n logger.debug(\"L3 - handleResync - delete supporting node {}\", supportingNodeIden);\n updateInDb(aInYangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n\n }\n\n //create te node\n\n String teNodeRef = createTeNode(networkId, aInYangDB, nodeId, nodeId);\n if(teNodeRef != null) {\n String teNetworkRef = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId));\n createTeNodeRef(aInYangDB, getFilteredQueryParameters(null), networkId, nodeId, teNetworkRef, teNodeRef);\n }\n }\n\n boolean createTerminationPoint(IYangDB aInYangDB, String aInNodeIdentifier, IMdConverterFw aInConverterFw, String aInTpIdentifier,\n String aInNetworkId, String aInNodeId, String aInTpId, List<String> aInTpDetails) {\n QueryParameters qp = getFilteredQueryParameters(null);\n\n if(aInYangDB.exists(aInNodeIdentifier, qp)) {\n String neId = getNeIdFromRouterId(aInYangDB, aInNetworkId, aInNodeId);\n String portName = null;\n if(neId != null) {\n portName = getPortDetailsFromDb(aInTpId, aInYangDB, neId);\n if (portName == null) {\n //try to get the details via openconfig restconf. It works for mdm managed nodes\n portName = getSubInterfaces(neId, aInConverterFw, aInTpId);\n if(portName == null) {\n logger.warn(\"Couldn't find L2 port on the NE-ID:{} for the L3 TP-ID: {}. \" +\n \"So correlation is not established.\", neId, aInTpId);\n }\n }\n }\n if(!aInYangDB.exists(aInTpIdentifier, qp)) {\n IYangObject tpObj = new YangObject();\n tpObj.setProperty(NETWORK_ID, aInNetworkId);\n tpObj.setProperty(NODE_ID, aInNodeId);\n tpObj.setProperty(TP_ID, aInTpId);\n IYangObject tpAttrObj = new YangObject();\n tpAttrObj.setProperty(NETWORK_ID, aInNetworkId);\n tpAttrObj.setProperty(NODE_ID, aInNodeId);\n tpAttrObj.setProperty(TP_ID, aInTpId);\n if(aInTpId.contains(\"%\")) {\n int unnumbered = Integer.parseInt(aInTpId.split(\"%\")[1]);\n tpAttrObj.setProperty(\"unnumbered-id\", unnumbered);\n } else{\n try{\n int unnumbered = Integer.parseInt(aInTpId);\n tpAttrObj.setProperty(\"unnumbered-id\", unnumbered);\n }\n catch(NumberFormatException e) {\n tpAttrObj.setProperty(IP_ADDRESS, Arrays.asList(new String[]{aInTpId}));\n }\n }\n tpObj.setProperty(\"ietf-l3-unicast-topology:l3-termination-point-attributes\", tpAttrObj);\n\n updateInDb(aInYangDB, tpObj, \"\", aInNodeIdentifier, TP_TYPE, CREATE, null, qp);\n\n if(neId != null && portName != null) {\n String supportingTpRef = getSupportingTpRef(aInYangDB, qp, neId, portName);\n if (supportingTpRef != null) {\n String supportingTpIden = aInTpIdentifier + \"/\" + SUPPORTING_TP;\n if(!aInYangDB.exists(supportingTpIden, qp)) {\n createSupportingTp(aInYangDB, qp, aInNetworkId, aInNodeId, aInTpId, neId, supportingTpRef, aInTpIdentifier);\n }\n }\n }\n }\n else {\n // supporting port could have been created/deleted.\n // node could have been managed/unmanaged.\n String supportingTpIden = aInTpIdentifier + \"/\" + SUPPORTING_TP;\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - SUPPORTING TP UPDATE {} {} \", neId, portName);\n }\n if(neId != null) {\n if(portName != null) {\n // ne could have been managed or port could have been created\n String supportingTpRef = getSupportingTpRef(aInYangDB, qp, neId, portName);\n if (supportingTpRef != null) {\n if(!aInYangDB.exists(supportingTpIden, qp)) {\n logger.debug(\"L3 - RESYNC TP - createSupportingTp {} , {}\", supportingTpIden, supportingTpRef);\n createSupportingTp(aInYangDB, qp, aInNetworkId, aInNodeId, aInTpId, neId, supportingTpRef, aInTpIdentifier);\n }\n }\n }\n else {\n // port could have been deleted\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - PORT IS NULL - TRYING TO DELETE SUPPORTING TP {} \", supportingTpIden);\n }\n deleteSupportingTp(supportingTpIden, aInYangDB);\n }\n }\n else { //ne id will be null if the ne is unmanaged.\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - NE IS NULL - TRYING TO DELETE SUPPORTING TP {} \", supportingTpIden);\n }\n deleteSupportingTp(supportingTpIden, aInYangDB);\n }\n }\n if(neId != null && portName != null) {\n aInTpDetails.add(neId);\n aInTpDetails.add(portName);\n }\n return true;\n } else {\n logger.warn(\"L3 - Couldn't create termination point \" + aInTpIdentifier + \" because node doesn't exist - \" + aInNodeIdentifier);\n return false;\n }\n }\n\n String createTeTerminationPoint(String aInNetworkId, IYangDB aInYangDB, String aInNodeId, String aInTpId) {\n if(!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n String teNetworkId = getTeNetworkId(aInNetworkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n\n String teNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, aInNodeId);\n String teTPPathIdentifier = teNodePathIdentifier + String.format(TP_PATH, aInTpId);\n\n if (aInYangDB.exists(teNodePathIdentifier,qp) && !aInYangDB.exists(teTPPathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new TP: {} on {}\", aInTpId, aInNodeId);\n IYangObject tpObj = new YangObject();\n tpObj.setProperty(NETWORK_ID, teNetworkId);\n tpObj.setProperty(NODE_ID, aInNodeId);\n tpObj.setProperty(TP_ID, aInTpId);\n if(aInTpId.contains(\"%\")) {\n tpObj.setProperty(\"te-tp-id\", aInTpId.split(\"%\")[1]);\n }\n else {\n tpObj.setProperty(\"te-tp-id\", aInTpId);\n }\n\n updateInDb(aInYangDB, tpObj, \"\", teNodePathIdentifier, TP_TYPE, CREATE, null, qp);\n\n //update the L3 to TE ref.\n createTeTpRef(aInYangDB, getFilteredQueryParameters(null), aInNetworkId, aInNodeId, aInTpId, teNetworkPathIdentifier, teNodePathIdentifier, teTPPathIdentifier);\n return teTPPathIdentifier;\n }\n return null;\n }\n\n void createLink(Map<String,Object> aInLink, IYangDB aInYangDB, IMdConverterFw aInConverterFw, String networkId, boolean aInCheckOppLink, String aInDstTpId) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n logger.debug(\"Creating Link {}, \", aInLink.get(NAME));\n Map<String, String> srcNode = getLinkNodeDetails((String) aInLink.get(\"source-node\"));\n Map<String, String> dstNode = getLinkNodeDetails((String) aInLink.get(\"destination-node\"));\n if(srcNode.isEmpty() || dstNode.isEmpty()) {\n logger.warn(\"L3 - parsing error to get src node / dst node on the link {}\", aInLink.entrySet().toString());\n return;\n }\n String srcNodeId = srcNode.get(ID);\n String dstNodeId = dstNode.get(ID);\n String srcTpId = (String) aInLink.get(IP_ADDRESS);\n String dstTpId = null;\n\n if(aInDstTpId != null) {\n dstTpId = aInDstTpId;\n }\n else {\n if (srcNode.get(NODE_TYPE).equals(SUBNET)) {\n IYangObject nodeObj = aInYangDB.getSingle((String) aInLink.get(\"source-node\"),\n getFilteredQueryParameters(\"name;dr-ip-address\"));\n\n if (nodeObj != null) {\n String subnetNodeId = (String) nodeObj.get(\"dr-ip-address\");\n if(subnetNodeId == null || subnetNodeId.isEmpty()) {\n srcNodeId = (String) nodeObj.get(NAME);\n String systemId = getSubnetSystemId(srcNodeId);\n subnetNodeId = InetAddresses.isInetAddress(systemId) ? systemId :\n getSubnetNodeIdFromDB(aInConverterFw.getYangDBConfig(), systemId, networkId);\n }\n srcNodeId = subnetNodeId == null ? srcNodeId : subnetNodeId + \"-\" + getSubnetPsnId(srcNodeId);\n dstTpId = srcTpId;\n }\n else {\n logger.warn(\"L3 - CreateLink - SUBNET IS NOT IN DB\" + aInLink.get(\"source-node\"));\n }\n\n } else if (dstNode.get(NODE_TYPE).equals(SUBNET)) {\n IYangObject nodeObj = aInYangDB.getSingle((String) aInLink.get(\"destination-node\"),\n getFilteredQueryParameters(\"name;dr-ip-address\"));\n\n if (nodeObj != null) {\n String subnetNodeId = (String) nodeObj.get(\"dr-ip-address\");\n if(subnetNodeId == null || subnetNodeId.isEmpty()) {\n dstNodeId = (String) nodeObj.get(NAME);\n String systemId = getSubnetSystemId(dstNodeId);\n subnetNodeId = InetAddresses.isInetAddress(systemId) ? systemId :\n getSubnetNodeIdFromDB(aInConverterFw.getYangDBConfig(), systemId, networkId);\n }\n dstNodeId = subnetNodeId == null ? dstNodeId : subnetNodeId + \"-\" + getSubnetPsnId(dstNodeId);\n dstTpId = srcTpId;\n }\n else {\n logger.warn(\"L3 - CreateLink - SUBNET IS NOT IN DB\" + aInLink.get(\"destination-node\"));\n }\n }\n\n dstTpId = dstTpId == null ? getTerminationPointId((String) aInLink.get(\"opposite-link\"), aInYangDB, networkId) : dstTpId;\n }\n if(dstTpId == null) {\n logger.warn(\"L3 - couldn't find opposite L3 link and destination TP for {} on {}\", aInLink.get(NAME), networkId);\n oppLinkMap.put(srcNodeId + \":\" + srcTpId + \"--\" + dstNodeId, aInLink.get(NAME).toString());\n return;\n }\n String isisLevel = aInLink.get(\"protocol\").equals(\"isis\") ? (String) aInLink.get(\"isis-level\") : null;\n String linkId = getLinkId(srcNodeId, dstNodeId, srcTpId, dstTpId, isisLevel);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n\n if (!aInYangDB.exists(linkPathIdentifier, qp)) {\n logger.debug(\"creating new L3 link: {} on {}\", linkId, networkId);\n IYangObject linkObj = new YangObject();\n linkObj.setProperty(NETWORK_ID, networkId);\n linkObj.setProperty(LINK_ID, linkId);\n IYangObject linkAttrObj = new YangObject();\n linkAttrObj.setProperty(NETWORK_ID, networkId);\n linkAttrObj.setProperty(NAME, aInLink.get(NAME));\n linkAttrObj.setProperty(\"metric1\", aInLink.get(\"cost\"));\n linkAttrObj.setProperty(\"metric2\", aInLink.get(\"te-metric\"));\n linkAttrObj.setProperty(\"flag\", Collections.singletonList(\"nsp-ietf-network-topology:igp\"));\n linkObj.setProperty(\"ietf-l3-unicast-topology:l3-link-attributes\", linkAttrObj);\n\n //source-node\n\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, srcNodeId);\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, srcTpId);\n List<String> srcTpDetails = new ArrayList<>();\n if(!createTerminationPoint(aInYangDB, srcNodeIdentifier, aInConverterFw, srcNodeTPIdentifier, networkId, srcNodeId, srcTpId, srcTpDetails))\n {\n logger.warn(\"L3 - Termination point creation failed {}, {}\", srcNodeIdentifier, srcNodeTPIdentifier);\n return;\n }\n YangObject srcObj = new YangObject();\n srcObj.setProperty(NETWORK_ID, networkId);\n srcObj.setProperty(LINK_ID, linkId);\n srcObj.setProperty(\"source-node\", srcNodeIdentifier);\n srcObj.setProperty(\"source-tp\", srcNodeTPIdentifier);\n linkObj.setProperty(\"source\", srcObj);\n\n //destination-node\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, dstNodeId);\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, dstTpId);\n List<String> dstTpDetails = new ArrayList<>();\n if(!createTerminationPoint(aInYangDB, dstNodeIdentifier, aInConverterFw, dstNodeTPIdentifier, networkId, dstNodeId, dstTpId, dstTpDetails))\n {\n logger.warn(\"L3 - Termination point creation failed {}, {}\", dstNodeIdentifier, dstNodeTPIdentifier);\n return;\n }\n YangObject dstObj = new YangObject();\n dstObj.setProperty(NETWORK_ID, networkId);\n dstObj.setProperty(LINK_ID, linkId);\n dstObj.setProperty(\"dest-node\", dstNodeIdentifier);\n dstObj.setProperty(\"dest-tp\", dstNodeTPIdentifier);\n linkObj.setProperty(\"destination\", dstObj);\n\n updateInDb(aInYangDB, linkObj, \"\", networkPathIdentifier, LINK_TYPE, CREATE, null, qp);\n\n //create sr mpls MSDs and SIDs\n List<Map<String,Object>> msds = (List) aInLink.get(MSDS);\n List<Map<String,Object>> sids = (List) aInLink.get(SIDS);\n\n if(msds != null || sids != null) {\n IYangObject srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, networkId);\n srMplsObj.setProperty(LINK_ID, linkId);\n if(msds != null) {\n IYangObject msdObj = new YangObject();\n msdObj.setProperty(NETWORK_ID, networkId);\n msdObj.setProperty(LINK_ID, linkId);\n srMplsObj.setProperty(MSDS, msdObj);\n }\n\n if(sids != null) {\n IYangObject sidObject = new YangObject();\n sidObject.setProperty(NETWORK_ID, networkId);\n sidObject.setProperty(LINK_ID, linkId);\n srMplsObj.setProperty(SIDS, sidObject);\n }\n\n String linkAttrIden = linkPathIdentifier + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n updateInDb(aInYangDB, srMplsObj, \"\", linkAttrIden, SR_MPLS_TYPE, CREATE, null, qp);\n\n if(msds != null) {\n for (Map<String, Object> msd : msds) {\n IYangObject nodeMsdObj = new YangObject();\n nodeMsdObj.setProperty(NETWORK_ID, networkId);\n nodeMsdObj.setProperty(LINK_ID, linkId);\n nodeMsdObj.setProperty(MSD_TYPE, msd.get(MSD_TYPE));\n nodeMsdObj.setProperty(MSD_VALUE, msd.get(MSD_VALUE));\n updateInDb(aInYangDB, nodeMsdObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"link-msd\", CREATE, null, qp);\n }\n }\n\n if(sids != null) {\n Set<String> existingSids = new HashSet<>();\n for (Map<String, Object> sid : sids) {\n IYangObject nodeSidObj = new YangObject();\n nodeSidObj.setProperty(NETWORK_ID, networkId);\n nodeSidObj.setProperty(LINK_ID, linkId);\n nodeSidObj.setProperty(VALUE_TYPE, sid.get(VALUE_TYPE));\n nodeSidObj.setProperty(SID, sid.get(SID));\n nodeSidObj.setProperty(ADDRESS_FAMILY, sid.get(ADDRESS_FAMILY));\n nodeSidObj.setProperty(IS_ELG_PROT, sid.get(IS_ELG_PROT));\n nodeSidObj.setProperty(IS_LOCAL, sid.get(IS_LOCAL));\n nodeSidObj.setProperty(IS_PART_SET, sid.get(IS_PART_SET));\n nodeSidObj.setProperty(IS_PERS, sid.get(IS_PERS));\n nodeSidObj.setProperty(IS_ON_LAN, sid.get(IS_ON_LAN));\n nodeSidObj.setProperty(WEIGHT, sid.get(WEIGHT));\n\n String sidKey = sid.get(VALUE_TYPE).toString() +\"-\"+ sid.get(SID);\n if(!existingSids.contains(sidKey)) {\n updateInDb(aInYangDB, nodeSidObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids\", \"sid\", CREATE, null, qp);\n existingSids.add(sidKey);\n }\n }\n }\n }\n\n //supporting link\n\n if(!srcTpDetails.isEmpty() && srcTpDetails.size() >= 2 && !dstTpDetails.isEmpty() && dstTpDetails.size() >=2) {\n String supportingLinkRef = getSupportingLinkRef(aInYangDB, qp,\n getLinkId(srcTpDetails.get(0), dstTpDetails.get(0), srcTpDetails.get(1), dstTpDetails.get(1), null));\n if (supportingLinkRef != null) {\n String supportingLinkIden = linkPathIdentifier + \"/\" + SUPPORTING_LINK;\n if(!aInYangDB.exists(supportingLinkIden, qp)) {\n createSupportingLink(aInYangDB, qp, networkId, linkId, supportingLinkRef, linkPathIdentifier);\n }\n }\n }\n }\n else {\n // link properties could have got updated.resync the updatable properties\n\n IYangObject ietfLinkObj = aInYangDB.getSingle(linkPathIdentifier, qp);\n if (ietfLinkObj != null) {\n logger.debug(\"L3 - RESYNC LINK - updating link: {} on {}\", linkId, networkId);\n IYangObject linkAttrObj = (YangObject) ietfLinkObj.get(\"ietf-l3-unicast-topology:l3-link-attributes\");\n linkAttrObj.setProperty(\"metric1\", aInLink.get(\"cost\"));\n linkAttrObj.setProperty(\"metric2\", aInLink.get(\"te-metric\"));\n ietfLinkObj.setProperty(\"ietf-l3-unicast-topology:l3-link-attributes\", linkAttrObj);\n ietfLinkObj.removeProperty(SUPPORTING_LINK);\n updateInDb(aInYangDB, ietfLinkObj, linkPathIdentifier, null, null, UPDATE, null, getFilteredQueryParameters(null));\n }\n\n if(aInLink.get(SIDS) != null) {\n updateSid(aInYangDB, qp, aInLink, linkPathIdentifier, networkId, linkId);\n }\n\n // update supporting link.\n\n //source-node\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, srcNodeId);\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, srcTpId);\n List<String> srcTpDetails = new ArrayList<>();\n createTerminationPoint(aInYangDB, srcNodeIdentifier, aInConverterFw, srcNodeTPIdentifier, networkId, srcNodeId, srcTpId, srcTpDetails);\n\n //destination-node\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, dstNodeId);\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, dstTpId);\n List<String> dstTpDetails = new ArrayList<>();\n createTerminationPoint(aInYangDB, dstNodeIdentifier, aInConverterFw, dstNodeTPIdentifier, networkId, dstNodeId, dstTpId, dstTpDetails);\n\n String supportingLinkIden = linkPathIdentifier + \"/\" + SUPPORTING_LINK;\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - SUPPORTING TP UPDATE {} {} \", supportingLinkIden, !srcTpDetails.isEmpty() && srcTpDetails.size() >= 2 && !dstTpDetails.isEmpty() && dstTpDetails.size() >= 2);\n }\n if(!srcTpDetails.isEmpty() && srcTpDetails.size() >= 2 && !dstTpDetails.isEmpty() && dstTpDetails.size() >=2) {\n String supportingLinkRef = getSupportingLinkRef(aInYangDB, qp,\n getLinkId(srcTpDetails.get(0), dstTpDetails.get(0), srcTpDetails.get(1), dstTpDetails.get(1), null));\n if (supportingLinkRef != null) {\n if(!aInYangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - RESYNC LINK - CREATING SUPPORTING LINK {} \", supportingLinkIden);\n createSupportingLink(aInYangDB, qp, networkId, linkId, supportingLinkRef, linkPathIdentifier);\n }\n else if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - SUPPORTING LINK EXISTS {} \", supportingLinkIden);\n }\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 TRYING TO DELETE SUPPORTING LINK {} \", supportingLinkIden);\n }\n deleteSupportingLink(supportingLinkIden, aInYangDB);\n }\n\n }\n else if(aInYangDB.exists(supportingLinkIden, qp)) {\n //delete supporting link ref\n logger.debug(\"*********** - L3 TRYING TO DELETE SUPPORTING LINK {} \", supportingLinkIden);\n deleteSupportingLink(supportingLinkIden, aInYangDB);\n }\n }\n\n createTeLink(networkId, aInYangDB, aInLink, linkId, srcNodeId, srcTpId, dstNodeId, dstTpId);\n\n // Sometimes during eventing, it happens that both the link is not in dmodel and so we failed to create the opp link earlier.\n // so this is our second chance\n if(aInCheckOppLink) {\n String[] idSplits = linkId.split(\"--\");\n String[] dstSplit = idSplits[0].split(\":\");\n if(oppLinkMap.containsKey(idSplits[1] + \"--\" + dstSplit[0])) {\n String name = oppLinkMap.remove(idSplits[1] + \"--\" + dstSplit[0]);\n String oppLinkId = getOppIetfLinkId(linkId);\n String oppLinkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, oppLinkId);\n if (!aInYangDB.exists(oppLinkPathIdentifier, getFilteredQueryParameters(null))) {\n //create the opposite link\n logger.debug(\"L3 - CREATING OPP LINK with name: {} \", name);\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n IYangObject linkObj = aInYangDB.getSingle(nspServiceIpLinkIden, getFilteredQueryParameters(IP_LINK_FIELDS));\n\n if (linkObj != null) {\n createLink(linkObj.asMap(), aInYangDB, aInConverterFw, networkId, false, dstSplit[1]);\n }\n }\n }\n }\n }\n\n String createTeLink(String aInNetworkId, IYangDB aInYangDB, Map<String,Object> aInLink, String aInLinkId,\n String aInSrcNodeId, String aInSrcTpId, String aInDstNodeId, String aInDstTpId) {\n if (!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n\n createTeTerminationPoint(aInNetworkId, aInYangDB, aInSrcNodeId, aInSrcTpId);\n createTeTerminationPoint(aInNetworkId, aInYangDB, aInDstNodeId, aInDstTpId);\n\n String teNetworkId = getTeNetworkId(aInNetworkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n\n String teSrcNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, aInSrcNodeId);\n String teSrcTPPathIdentifier = teSrcNodePathIdentifier + String.format(TP_PATH, aInSrcTpId);\n\n String teDstNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, aInDstNodeId);\n String teDstTPPathIdentifier = teDstNodePathIdentifier + String.format(TP_PATH, aInDstTpId);\n\n String teLinkPathIdentifier = teNetworkPathIdentifier + String.format(LINK_PATH, aInLinkId);\n\n if (!aInYangDB.exists(teLinkPathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new Link: {} on {}\", aInLinkId, teNetworkId);\n IYangObject linkObj = new YangObject();\n linkObj.setProperty(NETWORK_ID, teNetworkId);\n linkObj.setProperty(LINK_ID, aInLinkId);\n YangObject srcObj = new YangObject();\n srcObj.setProperty(NETWORK_ID, teNetworkId);\n srcObj.setProperty(LINK_ID, aInLinkId);\n srcObj.setProperty(\"source-node\", teSrcNodePathIdentifier);\n srcObj.setProperty(\"source-tp\", teSrcTPPathIdentifier);\n linkObj.setProperty(\"source\", srcObj);\n\n YangObject dstObj = new YangObject();\n dstObj.setProperty(NETWORK_ID, teNetworkId);\n dstObj.setProperty(LINK_ID, aInLinkId);\n dstObj.setProperty(\"dest-node\", teDstNodePathIdentifier);\n dstObj.setProperty(\"dest-tp\", teDstTPPathIdentifier);\n linkObj.setProperty(\"destination\", dstObj);\n\n IYangObject teObj = new YangObject();\n IYangObject linkAttrObj = new YangObject();\n linkAttrObj.setProperty(NETWORK_ID, teNetworkId);\n linkAttrObj.setProperty(LINK_ID, aInLinkId);\n linkAttrObj.setProperty(\"te-default-metric\", aInLink.get(\"te-metric\"));\n linkAttrObj.setProperty(\"te-delay-metric\", aInLink.get(\"latency\"));\n linkAttrObj.setProperty(\"te-igp-metric\", aInLink.get(\"cost\"));\n\n if(aInLink.get(\"bw\") != null) {\n\n IYangObject maxLinkBandwidth = new YangObject();\n maxLinkBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxLinkBandwidth.setProperty(LINK_ID, aInLinkId);\n IYangObject maxLinkTeBandwidth = new YangObject();\n maxLinkTeBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxLinkTeBandwidth.setProperty(LINK_ID, aInLinkId);\n // convert kilo bits to bytes and then to IEEE 754 format.\n maxLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes((Long) aInLink.get(\"bw\")))));\n maxLinkBandwidth.setProperty(\"te-bandwidth\", maxLinkTeBandwidth);\n\n IYangObject maxResvLinkBandwidth = new YangObject();\n maxResvLinkBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxResvLinkBandwidth.setProperty(LINK_ID, aInLinkId);\n IYangObject maxResvLinkTeBandwidth = new YangObject();\n maxResvLinkTeBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxResvLinkTeBandwidth.setProperty(LINK_ID, aInLinkId);\n maxResvLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes((Long) aInLink.get(\"bw\")))));\n maxResvLinkBandwidth.setProperty(\"te-bandwidth\", maxResvLinkTeBandwidth);\n\n linkAttrObj.setProperty(\"max-link-bandwidth\", maxLinkBandwidth);\n linkAttrObj.setProperty(\"max-resv-link-bandwidth\", maxResvLinkBandwidth);\n }\n\n IYangObject tesrlgs = new YangObject();\n tesrlgs.setProperty(\"value\", aInLink.get(\"srg-labels\"));\n linkAttrObj.setProperty(\"te-srlgs\", tesrlgs);\n\n IYangObject performanceMetricsOneWay = new YangObject();\n performanceMetricsOneWay.setProperty(NETWORK_ID, teNetworkId);\n performanceMetricsOneWay.setProperty(LINK_ID, aInLinkId);\n performanceMetricsOneWay.setProperty(\"one-way-delay\", aInLink.get(\"latency\"));\n performanceMetricsOneWay.setProperty(\"one-way-min-delay\", aInLink.get(\"one-way-min-delay\"));\n performanceMetricsOneWay.setProperty(\"one-way-max-delay\", aInLink.get(\"one-way-max-delay\"));\n if(aInLink.get(\"available-bw\") != null) {\n performanceMetricsOneWay.setProperty(\"one-way-utilized-bandwidth\", String.format(\"%a\",\n Float.valueOf(convertKiloBitstoBytes((Long) aInLink.get(\"available-bw\")))));\n }\n linkAttrObj.setProperty(\"ietf-te-topology-packet:performance-metrics-one-way\", performanceMetricsOneWay);\n linkAttrObj.setProperty(NAME, aInLink.get(NAME));\n\n teObj.setProperty(\"te-link-attributes\", linkAttrObj);\n teObj.setProperty(NETWORK_ID, teNetworkId);\n teObj.setProperty(LINK_ID, aInLinkId);\n linkObj.setProperty(\"ietf-te-topology:te\", teObj);\n\n updateInDb(aInYangDB, linkObj, \"\", teNetworkPathIdentifier, LINK_TYPE, CREATE, null, qp);\n createTeLinkRef(aInYangDB, getFilteredQueryParameters(null), aInNetworkId, aInLinkId, teNetworkPathIdentifier, teLinkPathIdentifier);\n\n for(int i = 0 ; i <= 7 ; i++) {\n IYangObject maxUnResvBandwidth = new YangObject();\n maxUnResvBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxUnResvBandwidth.setProperty(LINK_ID, aInLinkId);\n maxUnResvBandwidth.setProperty(\"priority\", i);\n IYangObject maxUnResvTeBandwidth = new YangObject();\n maxUnResvTeBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxUnResvTeBandwidth.setProperty(LINK_ID, aInLinkId);\n maxUnResvTeBandwidth.setProperty(\"priority\", i);\n Long unResvBw = (Long) aInLink.get(\"un-resv-bw\");\n unResvBw = unResvBw == null ? 0 : unResvBw;\n maxUnResvTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes(unResvBw))));\n maxUnResvBandwidth.setProperty(\"te-bandwidth\", maxUnResvTeBandwidth);\n updateInDb(aInYangDB, maxUnResvBandwidth, \"\", teLinkPathIdentifier + \"/ietf-te-topology:te/te-link-attributes\" , \"unreserved-bandwidth\", CREATE, null, qp);\n }\n return teLinkPathIdentifier;\n }\n else {\n //TE link could have got updated. resync the properties.\n if(updateTeLink(aInYangDB, qp, aInLink, teLinkPathIdentifier, teNetworkId, aInLinkId, true)) {\n updateTeLinkPriority(aInYangDB, aInLink, teLinkPathIdentifier);\n }\n }\n return null;\n }\n\n long convertKiloBitstoBytes(long aInBW) {\n return aInBW * 125;\n }\n\n private void createPrefix(IYangDB aInYangDB, QueryParameters aInQp, ObjectCreation aInEvent) {\n\n String instanceId = aInEvent.getInstanceId();\n String adminDomain = extractAdminDomain(instanceId);\n String nodeId = StringUtils.substringBetween(instanceId, \"routing-instance[id='\", \"'\");\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String ipAddress = (String) aInEvent.getEntity().get(IP_ADDRESS);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n if (aInYangDB.exists(nodePathIdentifier) && !aInYangDB.exists(prefixPathIden, aInQp)) {\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, ipAddress);\n prefixObj.setProperty(\"metric\", aInEvent.getEntity().get(\"metric\"));\n updateInDb(aInYangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, aInQp);\n }\n }\n }\n }\n\n public void handleUpdateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectModification aInEvent,\n String aInNeId, YangPluginMdConverterProvider aInMdResyncFw)\n {\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------UPDATE---------------------------------------------------------------------------\");\n }\n\n IMdConverterFw converterFw = aInMdResyncFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n logger.debug(\"L3 - handleUpdateEvent - UPDATE PREFIX\");\n updatePrefix(yangDB, getFilteredQueryParameters(null), aInEvent);\n }\n else {\n boolean isValidSrMplsUpdate = false;\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n if(MSDS.equals(change.getName())) {\n logger.debug(\"L3 - handleUpdateEvent - node MSD update\");\n Map<String, Object> node = aInEvent.getEntity().asMap();\n updateMsd(yangDB, StringUtils.substringBetween(aInEvent.getInstanceId(),\n \"routing-instance[id='\", \"'\"), node, getNetworkIdFromMeta(yangDB, node));\n }\n else if(ID.equals(change.getName())) {\n logger.debug(\"L3 - handleUpdateEvent - node ID update\");\n updateNodeAndLinks(yangDB, change.getOldValue().toString(), change.getNewValue().toString(),\n aInEvent.getInstanceId(), converterFw);\n }\n }\n }\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n logger.debug(\"L3 - handleUpdateEvent - UPDATE LINK\");\n updateLink(yangDB, aInEvent, converterFw);\n }\n }\n\n private void updateNodeAndLinks(IYangDB aInYangDB, String aInOldRouterId, String aInNewRouterId, String aInInstanceId,\n IMdConverterFw aInConverterFw) {\n /*Router-id has changed due to correlation.\n 1. delete the old node/tps/links and subnet node if any.\n 2. create new node and the links, tps, etc.\n */\n YangDBConfig dbConfig = aInConverterFw.getYangDBConfig();\n String adminDomain = extractAdminDomain(aInInstanceId);\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, aInNewRouterId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols;id;name;router/ne;router-id;prefix(ip-address;metric)\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n //There can be more than one nodes in IETF as there can be subnets on that node\n List<Object> nodeIds = getNodeIds(aInYangDB, aInOldRouterId, networkId);\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> nodes: {}\", nodeIds.toString());\n }\n List<String> linkNames = new ArrayList<>();\n Map<String,String> subnetNames = new HashMap<>();\n if(CollectionUtils.isNotEmpty(nodeIds)) {\n nodeIds.forEach(node -> {\n String nodeId = node.toString();\n //get the links that originate or end on this nodeId\n List<Map<String,Object>> linkList = getLinkDetails(aInYangDB, nodeId, networkId);\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> links : {}\", linkList.toString());\n }\n if(CollectionUtils.isNotEmpty(linkList)) {\n linkList.forEach(linkMap -> {\n Object[] linkObj = new Object[2];\n linkObj[0] = linkMap.get(LINK_ID);\n linkObj[1] = networkId;\n List<Object> linkObjList = new ArrayList<>();\n linkObjList.add(linkObj);\n deleteLink(aInYangDB, getFilteredQueryParameters(null), linkMap, dbConfig, linkObjList);\n linkNames.add(linkMap.get(NAME).toString());\n });\n }\n if(nodeId.contains(\"psn\")) {\n List<Object> subnetName = getSubnetName(aInYangDB, nodeId, networkId);\n if(CollectionUtils.isNotEmpty(subnetName)) {\n subnetNames.put(nodeId, subnetName.get(0).toString());\n }\n }\n deleteNode(aInYangDB, getFilteredQueryParameters(null), null, dbConfig, networkId, nodeId);\n });\n }\n\n //Now create the new node and the links..\n nodeIds.forEach(nodeId -> {\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> creating equivalent node for {}\", nodeId);\n }\n\n if(nodeId.toString().contains(\"psn\")) {\n Map<String, Object> subnetMap = new HashMap<>();\n subnetMap.put(NAME, subnetNames.get(nodeId));\n createSubnet(nodeMap, aInYangDB, dbConfig, networkId, aInNewRouterId);\n }\n else {\n createRoutingInstance(nodeMap, aInYangDB, networkId);\n }\n });\n\n QueryParameters linkQp = getFilteredQueryParameters(IP_LINK_FIELDS);\n //create links and tps.\n linkNames.forEach(name -> {\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> creating link : {}\", name);\n }\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n IYangObject linkObj = aInYangDB.getSingle(nspServiceIpLinkIden, linkQp);\n\n if(linkObj != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if (aInYangDB.exists(networkPathIdentifier, qp)) {\n createLink(linkObj.asMap(), aInYangDB, aInConverterFw, networkId, true, null);\n return;\n } else {\n logger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", name);\n }\n }\n });\n }\n }\n }\n\n private List<Object> getNodeIds(IYangDB aInYangDb, String aInNodeId, String aInNetworkId)\n {\n return execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT n.nodeId FROM ietf.ietf_network_networks_network_node n WHERE n.networkId = \" +\n \":networkId AND n.nodeId LIKE :pattern\")\n .setParameter(\"networkId\", aInNetworkId)\n .setParameter(\"pattern\", aInNodeId + \"%\")\n .getResultList());\n\n }\n\n private List<Map<String,Object>> getLinkDetails(IYangDB aInYangDb, String aInNodeId, String aInNetworkId)\n {\n List<Object[]> linkDetails = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT la.linkId, la.name FROM ietf.ietf_241652239nk_ietf_l3_unicast_topology_l3_link_attributes la\" +\n \" WHERE la.networkId = :networkId AND la.linkId LIKE :linkId\")\n .setParameter(\"networkId\", aInNetworkId)\n .setParameter(\"linkId\", \"%\" + aInNodeId + \":%\")\n .getResultList());\n\n List<Map<String,Object>> linkList = new ArrayList<>();\n if(CollectionUtils.isNotEmpty(linkDetails)) {\n linkDetails.forEach(obj -> {\n Map<String,Object> linkMap = new HashMap<>();\n linkMap.put(LINK_ID, obj[0]);\n linkMap.put(NAME, obj[1]);\n linkList.add(linkMap);\n });\n }\n\n return linkList;\n\n }\n\n private List<Object> getSubnetName(IYangDB aInYangDb, String aInNodeId, String aInNetworkId)\n {\n return execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT n.name FROM ietf.ietf_220877889de_ietf_l3_unicast_topology_l3_node_attributes n WHERE n.networkId = \" +\n \":networkId AND n.nodeId = :nodeId\")\n .setParameter(\"networkId\", aInNetworkId)\n .setParameter(\"nodeId\", aInNodeId)\n .getResultList());\n\n }\n\n private void updatePrefix(IYangDB aInYangDB, QueryParameters aInQp, ObjectModification aInEvent) {\n\n //if the changed property is not one of the properties that could change, ignore the event.\n\n Set<String> updateableAttributes = new HashSet<>(Arrays.asList(\"metric\"));\n Map<String, Object> prefix = aInEvent.getEntity().asMap();\n boolean isValidUpdate = false;\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n if (updateableAttributes.contains(change.getName())) {\n isValidUpdate = true;\n break;\n }\n }\n\n if(isValidUpdate) {\n String instanceId = aInEvent.getInstanceId();\n String adminDomain = extractAdminDomain(instanceId);\n String nodeId = StringUtils.substringBetween(instanceId, \"routing-instance[id='\", \"'\");\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String ipAddress = (String) prefix.get(IP_ADDRESS);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n IYangObject prefixObj = aInYangDB.getSingle(prefixPathIden, aInQp);\n if (prefixObj != null) {\n int metric = (int) prefix.get(\"metric\");\n prefixObj.setProperty(\"metric\", metric);\n updateInDb(aInYangDB, prefixObj, prefixPathIden, null, null, UPDATE, null, aInQp);\n }\n }\n }\n\n }\n }\n\n private void updateMsd(IYangDB aInYangDB, String aInNodeId, Map<String,Object> aInNode, String aInNetworkId) {\n\n if (aInNode != null && aInNetworkId != null) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, aInNodeId);\n String nodeAttrIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\";\n IYangObject srMplsObj = aInYangDB.getSingle(nodeAttrIden + \"/\" + SR_MPLS_TYPE);\n Map<String, IYangObject> existingMsds = new HashMap<>();\n if(srMplsObj != null) {\n Collection<IYangObject> msdsList = ((IYangObject)srMplsObj.getProperty(MSDS)).getProperty(\"node-msd\");\n\n if(msdsList != null && !msdsList.isEmpty()) {\n for(IYangObject msd : msdsList) {\n String[] msdIden = msd.get(MSD_TYPE).toString().split(\":\");\n existingMsds.put(msdIden.length == 2 ? msdIden[1]:msdIden[0], msd);\n }\n }\n }\n\n List<Map> currentMsds = ((List)aInNode.get(MSDS));\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - EXISTING IETF MSDs - {}\", existingMsds.keySet().toString());\n logger.debug(\"L3 - CURRENT NSP MSDs - {}\", currentMsds.toString());\n }\n if(currentMsds == null || currentMsds.isEmpty()) {\n if(srMplsObj != null) {\n //delete the sr-mpls type.\n logger.debug(\"L3 - Update Node - delete msd sr mpls {}\", nodeAttrIden);\n updateInDb(aInYangDB, null, nodeAttrIden + \"/\" + SR_MPLS_TYPE, null, null, DELETE, null, qp);\n }\n }\n else {\n\n for(Map msd : currentMsds) {\n String msdKey = msd.get(MSD_TYPE).toString();\n if(!existingMsds.containsKey(msdKey) && srMplsObj != null) {\n //creation\n IYangObject newMsdObj = getMsdYangObject(new YangObject(), msd, aInNetworkId, aInNodeId);\n updateInDb(aInYangDB, newMsdObj, \"\", nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"node-msd\", CREATE, null, qp);\n logger.debug(\"L3 - Update Node - create msd {}, {}\", msdKey, nodeAttrIden);\n }\n else if(!existingMsds.containsKey(msdKey) && srMplsObj == null) {\n srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, aInNetworkId);\n srMplsObj.setProperty(NODE_ID, aInNodeId);\n\n IYangObject msdObj = new YangObject();\n msdObj.setProperty(NETWORK_ID, aInNetworkId);\n msdObj.setProperty(NODE_ID, aInNodeId);\n srMplsObj.setProperty(MSDS, msdObj);\n\n updateInDb(aInYangDB, srMplsObj, \"\", nodeAttrIden, SR_MPLS_TYPE, CREATE, null, qp);\n\n IYangObject newMsdObj = getMsdYangObject(new YangObject(), msd, aInNetworkId, aInNodeId);\n updateInDb(aInYangDB, newMsdObj, \"\", nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"node-msd\", CREATE, null, qp);\n logger.debug(\"L3 - Update Node - create msd {}, {}\", msdKey, nodeAttrIden);\n }\n else {\n //update\n IYangObject aInTargetMsd = existingMsds.get(msdKey);\n aInTargetMsd.setProperty(MSD_VALUE, msd.get(MSD_VALUE));\n logger.debug(\"L3 - Update Node - update msd {}, {}\", msdKey, nodeAttrIden);\n updateInDb(aInYangDB, srMplsObj, nodeAttrIden + \"/\" + SR_MPLS_TYPE, null, null, UPDATE, null, getFilteredQueryParameters(null));\n existingMsds.remove(msdKey);\n }\n }\n if(!existingMsds.isEmpty()) {\n //deletion\n for(IYangObject deleteMsd : existingMsds.values()) {\n String msdPath = String.format(nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds/node-msd[msd-type='%s']\",\n deleteMsd.get(MSD_TYPE));\n logger.debug(\"L3 - Update Node - delete msd {}\", msdPath);\n updateInDb(aInYangDB, null, msdPath, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n }\n\n private IYangObject getMsdYangObject(IYangObject aInTargetMsd, Map aInSourceMsd, String aInNetworkId, String aInNodeId) {\n aInTargetMsd.setProperty(NETWORK_ID, aInNetworkId);\n aInTargetMsd.setProperty(LINK_ID, aInNodeId);\n aInTargetMsd.setProperty(MSD_TYPE, aInSourceMsd.get(MSD_TYPE));\n aInTargetMsd.setProperty(MSD_VALUE, aInSourceMsd.get(MSD_VALUE));\n return aInTargetMsd;\n }\n\n private void updateLink(IYangDB aInYangDB, ObjectModification aInEvent, IMdConverterFw aInConverterFw) {\n\n //if the changed property is not one of the properties that could change, ignore the event.\n\n Set<String> updateableAttributes = new HashSet<>(Arrays.asList(\"te-metric\", \"cost\"));\n Set<String> updateableTeAttributes = new HashSet<>(Arrays.asList(\"te-metric\", \"cost\", \"latency\", \"isis-level\",\n \"bw\", \"available-bw\", \"one-way-min-delay\", \"one-way-max-delay\", \"srg-labels\"));\n Set<String> updatableSrMplsAttributes = new HashSet<>(Arrays.asList(SIDS));\n Map<String, Object> link = aInEvent.getEntity().asMap();\n boolean isValidLinkUpdate = false;\n boolean isValidTeLinkUpdate = false;\n boolean isValidPriorityUpdate = false;\n boolean isValidIpUpdate = false;\n boolean isValidSrMplsUpdate = false;\n\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n isValidLinkUpdate = updateableAttributes.contains(change.getName());\n isValidSrMplsUpdate = updatableSrMplsAttributes.contains(change.getName());\n }\n if(TE_TOPOLOGY_ENABLED) {\n isValidTeLinkUpdate = aInEvent.getChanges().size() == 1; // srlg changes are coming as empty.\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n if (\"un-resv-bw\".equals(change.getName())) {\n isValidPriorityUpdate = true;\n }\n if (updateableTeAttributes.contains(change.getName())) {\n isValidTeLinkUpdate = true;\n }\n isValidIpUpdate = \"ip-address\".equals(change.getName());\n }\n }\n\n // if ip-address is changed, the link needs to be created.\n if(isValidIpUpdate) {\n logger.debug(\"L3 - CREATE LINK FROM IP-ADDRESS UPDATE\");\n String name = (String) link.get(NAME);\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n QueryParameters qp = getFilteredQueryParameters(IP_LINK_FIELDS);\n IYangObject linkObj = aInYangDB.getSingle(nspServiceIpLinkIden, qp);\n\n if(linkObj != null) {\n String networkId = getNetworkIdFromLink((List<String>) linkObj.get(\"admin-domains\"), (String) linkObj.get(\"protocol\"));\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if (aInYangDB.exists(networkPathIdentifier, qp)) {\n createLink(linkObj.asMap(), aInYangDB, aInConverterFw, networkId, true, null);\n return;\n } else {\n logger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", linkObj.get(NAME));\n }\n }\n }\n }\n\n if(isValidLinkUpdate || isValidTeLinkUpdate || isValidPriorityUpdate || isValidSrMplsUpdate) {\n String name = (String) link.get(NAME);\n List<Object> linkDetails = getLinkFromDb(name, aInConverterFw.getYangDBConfig());\n if(linkDetails != null && !linkDetails.isEmpty()) {\n String linkId = ((Object[])linkDetails.get(0))[0].toString();\n String networkId = ((Object[])linkDetails.get(0))[1].toString();\n if(isValidLinkUpdate || isValidSrMplsUpdate) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n if(isValidLinkUpdate) {\n IYangObject ietfLinkObj = aInYangDB.getSingle(linkPathIdentifier, qp);\n if (ietfLinkObj != null) {\n logger.debug(\"L3 - updating link: {} on {}\", linkId, networkId);\n IYangObject linkAttrObj = (YangObject) ietfLinkObj.get(\"ietf-l3-unicast-topology:l3-link-attributes\");\n linkAttrObj.setProperty(\"metric1\", link.get(\"cost\"));\n linkAttrObj.setProperty(\"metric2\", link.get(\"te-metric\"));\n ietfLinkObj.setProperty(\"ietf-l3-unicast-topology:l3-link-attributes\", linkAttrObj);\n ietfLinkObj.removeProperty(SUPPORTING_LINK);\n updateInDb(aInYangDB, ietfLinkObj, linkPathIdentifier, null, null, UPDATE, null, getFilteredQueryParameters(null));\n } else {\n logger.debug(\"L3 - LINK changes ignored - link doesn't exist. {}\", linkPathIdentifier);\n }\n }\n\n if(isValidSrMplsUpdate) {\n updateSid(aInYangDB, qp, link, linkPathIdentifier, networkId, linkId);\n }\n }\n\n //Update TE Properties\n if(TE_TOPOLOGY_ENABLED && (isValidTeLinkUpdate || isValidPriorityUpdate)) {\n String teNetworkId = getTeNetworkId(networkId);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n if(updateTeLink(aInYangDB, qp, link, linkPathIdentifier, teNetworkId, linkId, isValidPriorityUpdate)) {\n if (isValidPriorityUpdate) {\n updateTeLinkPriority(aInYangDB, link, linkPathIdentifier);\n }\n }\n }\n }\n }\n else {\n handleUpdateLogger.debug(\"L3 - LINK changes ignored - {} on {} \", aInEvent.getChanges(), link.toString());\n }\n }\n\n private boolean updateTeLink(IYangDB aInYangDB, QueryParameters aInQp, Map<String, Object> aInLink, String aInLinkPathIdentifier,\n String aInTeNetworkId, String aInLinkId, boolean isValidPriorityUpdate) {\n IYangObject ietfTeLinkObj = aInYangDB.getSingle(aInLinkPathIdentifier, aInQp);\n if (ietfTeLinkObj != null) {\n logger.debug(\"L3 - updating TE link: {} on {}\", aInLinkId, aInTeNetworkId);\n IYangObject teObj = (YangObject) ietfTeLinkObj.get(\"ietf-te-topology:te\");\n IYangObject linkAttrObj = (YangObject) teObj.get(\"te-link-attributes\");\n linkAttrObj.setProperty(\"te-default-metric\", aInLink.get(\"te-metric\"));\n linkAttrObj.setProperty(\"te-delay-metric\", aInLink.get(\"latency\"));\n linkAttrObj.setProperty(\"te-igp-metric\", aInLink.get(\"cost\"));\n if(aInLink.get(\"bw\") != null) {\n IYangObject maxLinkBandwidth = (YangObject) linkAttrObj.get(\"max-link-bandwidth\");\n IYangObject maxLinkTeBandwidth = (YangObject) maxLinkBandwidth.get(\"te-bandwidth\");\n // convert kilo bits to bytes and then to IEEE 754 format.\n maxLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(\n convertKiloBitstoBytes(aInLink.get(\"bw\") instanceof Integer ? (Integer) aInLink.get(\"bw\") :\n (Long) aInLink.get(\"bw\")))));\n maxLinkBandwidth.setProperty(\"te-bandwidth\", maxLinkTeBandwidth);\n\n IYangObject maxResvLinkBandwidth = (YangObject) linkAttrObj.get(\"max-link-bandwidth\");\n IYangObject maxResvLinkTeBandwidth = (YangObject) maxResvLinkBandwidth.get(\"te-bandwidth\");\n maxResvLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(\n convertKiloBitstoBytes(aInLink.get(\"bw\") instanceof Integer ? (Integer) aInLink.get(\"bw\") :\n (Long) aInLink.get(\"bw\")))));\n maxResvLinkBandwidth.setProperty(\"te-bandwidth\", maxResvLinkTeBandwidth);\n linkAttrObj.setProperty(\"max-link-bandwidth\", maxLinkBandwidth);\n linkAttrObj.setProperty(\"max-resv-link-bandwidth\", maxResvLinkBandwidth);\n }\n IYangObject tesrlgs = (YangObject) linkAttrObj.get(\"te-srlgs\");\n tesrlgs.setProperty(\"value\", aInLink.get(\"srg-labels\"));\n\n linkAttrObj.setProperty(\"te-srlgs\", tesrlgs);\n\n\n\n IYangObject performanceMetricsOneWay = (YangObject) linkAttrObj.get(\"ietf-te-topology-packet:performance-metrics-one-way\");\n performanceMetricsOneWay.setProperty(\"one-way-delay\", aInLink.get(\"latency\"));\n performanceMetricsOneWay.setProperty(\"one-way-min-delay\", aInLink.get(\"one-way-min-delay\"));\n performanceMetricsOneWay.setProperty(\"one-way-max-delay\", aInLink.get(\"one-way-max-delay\"));\n if(aInLink.get(\"available-bw\") != null) {\n performanceMetricsOneWay.setProperty(\"one-way-utilized-bandwidth\", String.format(\"%a\",\n Float.valueOf(convertKiloBitstoBytes(\n aInLink.get(\"available-bw\") instanceof Integer ?\n (Integer) aInLink.get(\"available-bw\") : (Long) aInLink.get(\"available-bw\")))));\n }\n linkAttrObj.setProperty(\"ietf-te-topology-packet:performance-metrics-one-way\", performanceMetricsOneWay);\n linkAttrObj.setProperty(NAME, aInLink.get(NAME));\n if (!isValidPriorityUpdate) {\n linkAttrObj.removeProperty(\"unreserved-bandwidth\");\n }\n teObj.setProperty(\"te-link-attributes\", linkAttrObj);\n ietfTeLinkObj.setProperty(\"ietf-te-topology:te\", teObj);\n updateInDb(aInYangDB, ietfTeLinkObj, aInLinkPathIdentifier, null, null, UPDATE, null, getFilteredQueryParameters(null));\n return true;\n }\n else {\n if (logger.isDebugEnabled()) {\n logger.debug(\"L3 - TE LINK changes ignored - link doesn't exist. {}\", aInLinkPathIdentifier);\n }\n }\n return false;\n }\n\n private void updateTeLinkPriority(IYangDB aInYangDB, Map<String, Object> aInLink, String aInLinkPathIdentifier) {\n String teUnResvBwPathIdentifier = aInLinkPathIdentifier + \"/ietf-te-topology:te/te-link-attributes/unreserved-bandwidth\";\n List<IYangObject> teUnResvBwObjList = aInYangDB.getMany(teUnResvBwPathIdentifier, getFilteredQueryParameters(null));\n if (teUnResvBwObjList != null && !teUnResvBwObjList.isEmpty()) {\n for (IYangObject teUnResvBwObj : teUnResvBwObjList) {\n IYangObject maxUnResvTeBandwidth = (YangObject) teUnResvBwObj.get(\"te-bandwidth\");\n Long unResvBw = aInLink.get(\"un-resv-bw\") instanceof Integer ?\n new Long((Integer)aInLink.get(\"un-resv-bw\")) : (Long) aInLink.get(\"un-resv-bw\") ;\n unResvBw = unResvBw == null ? 0 : unResvBw;\n maxUnResvTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes(unResvBw))));\n teUnResvBwObj.setProperty(\"te-bandwidth\", maxUnResvTeBandwidth);\n updateInDb(aInYangDB, teUnResvBwObj, teUnResvBwPathIdentifier + String.format(\"[priority='%s']\",\n teUnResvBwObj.get(\"priority\")), null, null, UPDATE, null, getFilteredQueryParameters(null));\n }\n }\n }\n\n private void updateSid(IYangDB aInYangDB, QueryParameters aInQp, Map<String, Object> aInLink, String aInLinkPathIdentifier,\n String aInNetworkId, String aInLinkId) {\n String linkAttrIden = aInLinkPathIdentifier + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n IYangObject srMplsObj = aInYangDB.getSingle(linkAttrIden + \"/\" + SR_MPLS_TYPE);\n Map<String, IYangObject> existingSids = new HashMap<>();\n if(srMplsObj != null) {\n Collection<IYangObject> sidsList = ((IYangObject)srMplsObj.getProperty(SIDS)).getProperty(SID);\n\n if(sidsList != null && !sidsList.isEmpty()) {\n for(IYangObject sid : sidsList) {\n String sidKey = sid.get(VALUE_TYPE).toString() +\"-\"+ sid.get(SID);\n existingSids.put(sidKey, sid);\n }\n }\n }\n\n List<Map> currentSids = ((List)aInLink.get(SIDS));\n if(logger.isDebugEnabled()) {\n logger.debug(\"EXISTING IETF SIDS - {}\", existingSids.keySet().toString());\n logger.debug(\"CURRENT NSP SIDS - {}\", currentSids.toString());\n }\n if(currentSids == null || currentSids.isEmpty()) {\n if(srMplsObj != null) {\n //delete the sr-mpls type.\n logger.debug(\"L3 - Update Link - delete sid sr mpls {}\", linkAttrIden);\n updateInDb(aInYangDB, null, linkAttrIden + \"/\" + SR_MPLS_TYPE, null, null, DELETE, null, aInQp);\n }\n }\n else {\n\n for(Map sid : currentSids) {\n String sidKey = sid.get(VALUE_TYPE).toString() +\"-\"+ sid.get(SID);\n if(!existingSids.containsKey(sidKey) && srMplsObj != null) {\n //creation\n IYangObject newSidObj = getSidYangObject(new YangObject(), sid, aInNetworkId, aInLinkId);\n updateInDb(aInYangDB, newSidObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids\", \"sid\", CREATE, null, aInQp);\n logger.debug(\"L3 - Update Link - sid added to existing sids {}, {}\", sidKey, linkAttrIden);\n }\n else if(!existingSids.containsKey(sidKey) && srMplsObj == null) {\n srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, aInNetworkId);\n srMplsObj.setProperty(LINK_ID, aInLinkId);\n\n IYangObject sidObj = new YangObject();\n sidObj.setProperty(NETWORK_ID, aInNetworkId);\n sidObj.setProperty(LINK_ID, aInLinkId);\n srMplsObj.setProperty(SIDS, sidObj);\n\n updateInDb(aInYangDB, srMplsObj, \"\", linkAttrIden, SR_MPLS_TYPE, CREATE, null, aInQp);\n\n IYangObject newSidObj = getSidYangObject(new YangObject(), sid, aInNetworkId, aInLinkId);\n updateInDb(aInYangDB, newSidObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids\", \"sid\", CREATE, null, aInQp);\n logger.debug(\"L3 - Update Link - create sid {}, {}\", sidKey, linkAttrIden);\n }\n else {\n //update\n IYangObject aInTargetSid = existingSids.get(sidKey);\n aInTargetSid.setProperty(ADDRESS_FAMILY, sid.get(ADDRESS_FAMILY));\n aInTargetSid.setProperty(IS_ELG_PROT, sid.get(IS_ELG_PROT));\n aInTargetSid.setProperty(IS_LOCAL, sid.get(IS_LOCAL));\n aInTargetSid.setProperty(IS_PART_SET, sid.get(IS_PART_SET));\n aInTargetSid.setProperty(IS_PERS, sid.get(IS_PERS));\n aInTargetSid.setProperty(IS_ON_LAN, sid.get(IS_ON_LAN));\n aInTargetSid.setProperty(WEIGHT, sid.get(WEIGHT));\n logger.debug(\"L3 - Update Link - update sid {}, {}\", sidKey, linkAttrIden);\n updateInDb(aInYangDB, srMplsObj, linkAttrIden + \"/\" + SR_MPLS_TYPE, null, null, UPDATE, null, getFilteredQueryParameters(null));\n existingSids.remove(sidKey);\n }\n }\n if(!existingSids.isEmpty()) {\n //deletion\n for(IYangObject deleteSid : existingSids.values()) {\n String sidPath = String.format(linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids/sid[value-type='%s'][sid='%s']\",\n deleteSid.get(VALUE_TYPE), deleteSid.get(SID));\n logger.debug(\"L3 - Update Link - delete sid {}\", sidPath);\n updateInDb(aInYangDB, null, sidPath, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n\n private IYangObject getSidYangObject(IYangObject aInTargetSid, Map aInSourceSid, String aInNetworkId, String aInLinkId) {\n aInTargetSid.setProperty(NETWORK_ID, aInNetworkId);\n aInTargetSid.setProperty(LINK_ID, aInLinkId);\n aInTargetSid.setProperty(VALUE_TYPE, aInSourceSid.get(VALUE_TYPE));\n aInTargetSid.setProperty(SID, aInSourceSid.get(SID));\n aInTargetSid.setProperty(ADDRESS_FAMILY, aInSourceSid.get(ADDRESS_FAMILY));\n aInTargetSid.setProperty(IS_ELG_PROT, aInSourceSid.get(IS_ELG_PROT));\n aInTargetSid.setProperty(IS_LOCAL, aInSourceSid.get(IS_LOCAL));\n aInTargetSid.setProperty(IS_PART_SET, aInSourceSid.get(IS_PART_SET));\n aInTargetSid.setProperty(IS_PERS, aInSourceSid.get(IS_PERS));\n aInTargetSid.setProperty(IS_ON_LAN, aInSourceSid.get(IS_ON_LAN));\n aInTargetSid.setProperty(WEIGHT, aInSourceSid.get(WEIGHT));\n return aInTargetSid;\n }\n\n public void handleDeleteEvent(SrcClass aInSrcClass,SyncClass aInSyncClass, ObjectDeletion aInEvent,\n String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n\n if(aInEvent.getInstanceId().contains(L2_NETWORK_PATH)) {\n handleL2DeleteEvent(aInEvent, converterFw);\n return;\n }\n\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------DELETE---------------------------------------------------------------------------\");\n }\n\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n IYangDB yangDB = converterFw.getIYangDB();\n\n QueryParameters qp = getFilteredQueryParameters(null);\n Map<String, Object> srcObject = aInEvent.getEntity().asMap();\n Map<String, Object> meta = (Map) srcObject.get(\"@\");\n if(meta == null) {\n logger.warn(\"L3 - meta details are missing on the event\");\n }\n else if(((String) meta.get(\"nsp-model:identifier\")).contains(NETWORKS_PATH) &&\n !((String) meta.get(\"nsp-model:identifier\")).contains(L2_NETWORK_PATH))\n {\n if (logger.isDebugEnabled())\n {\n logger.debug(\"L3 - DELETE IGNORED {}\", meta.get(\"nsp-model:identifier\"));\n }\n return; //sometimes the srcobject has ietf object details\n }\n\n if (aInSyncClass.getDestClassPath().equals(NETWORK_CLASS_PATH)) {\n\n logger.debug(\"L3 - DELETE NETWORK\");\n deleteNetwork(yangDB, qp, aInEvent.getEntity());\n }\n else if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n logger.debug(\"L3 - DELETE PREFIX\");\n String instanceId = aInEvent.getInstanceId();\n String ipAddress = (String) aInEvent.getEntity().get(IP_ADDRESS);\n deletePrefix(yangDB, getFilteredQueryParameters(null), instanceId, ipAddress);\n }\n else {\n logger.debug(\"L3 - DELETE NODE\");\n deleteNode(yangDB, qp, srcObject, dbConfig, null, null);\n }\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n\n logger.debug(\"L3 - DELETE LINK\");\n deleteLink(yangDB, qp, srcObject, dbConfig, null);\n }\n }\n\n private void deleteNetwork(IYangDB aInYangDB, QueryParameters aInQp, IYangObject aInSrcObject) {\n String networkId = getNetworkId(aInYangDB, aInSrcObject);\n if(networkId == null) {\n //it could be one of isis or ospf.\n String adminDomain = (String) aInSrcObject.get(NAME);\n String ospfNetworkId = adminDomain + \"-ospf\";\n String ospfNetworkPathIdentifier = String.format(L3_NETWORK_PATH, ospfNetworkId);\n if(aInYangDB.exists(ospfNetworkPathIdentifier, aInQp))\n {\n networkId = ospfNetworkId;\n }\n\n String isisNetworkId = adminDomain + \"-isis\";\n String isisNetworkPathIdentifier = String.format(L3_NETWORK_PATH, isisNetworkId);\n if(aInYangDB.exists(isisNetworkPathIdentifier, aInQp)) {\n // exit if both ospf and isis exists for the same admin domain\n networkId = networkId == null ? isisNetworkId : null;\n }\n }\n\n if(networkId != null) {\n logger.debug(\"L3 - DELETING NETWORK {}\", networkId);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n updateInDb(aInYangDB, null, networkPathIdentifier, networkId, null, DELETE, null, aInQp);\n if(TE_TOPOLOGY_ENABLED) {\n String teNetworkId = getTeNetworkId(networkId);\n logger.debug(\"L3 - DELETING NETWORK {}\", teNetworkId);\n updateInDb(aInYangDB, null, String.format(L3_NETWORK_PATH, teNetworkId), teNetworkId, null, DELETE, null, aInQp);\n }\n }\n else {\n logger.warn(\"L3 - DELETING NETWORK - for admin domain {} failed. Couldn't find the right IETF network.\", aInSrcObject.get(NAME));\n }\n }\n\n private void deleteNode(IYangDB aInYangDB, QueryParameters aInQp, Map<String,Object> aInSrcObject,\n YangDBConfig dbConfig, String aInNetworkId, String aInNodeId) {\n String networkId = aInNetworkId == null ? getNetworkIdFromMeta(aInYangDB, aInSrcObject) : aInNetworkId;\n if(networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if(aInYangDB.exists(networkPathIdentifier, aInQp)) {\n String nodeId = aInNodeId;\n if(nodeId == null && SUBNET.equals(aInSrcObject.get(NODE_TYPE))) {\n String routerId = null;\n String systemId = getSubnetSystemId((String) aInSrcObject.get(NAME));\n if(systemId != null && systemId.contains(\"dr\")) {\n routerId = (String) aInSrcObject.get(\"dr-ip-address\");\n }\n routerId = routerId == null ? InetAddresses.isInetAddress(systemId) ? systemId : getSubnetNodeIdFromDB(dbConfig, systemId, networkId) : routerId;\n if(routerId == null) {\n logger.error(\"L3 - deleteNode - Couldn't delete the subnet node because router-id is null for {}\", systemId);\n return;\n }\n nodeId = routerId +\"-\"+getSubnetPsnId((String) aInSrcObject.get(NAME));\n }\n else if(nodeId == null) {\n nodeId = (String) aInSrcObject.get(ID);\n }\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n logger.debug(\"Deleting L3 node: {}\", nodePathIdentifier);\n updateInDb(aInYangDB, null, nodePathIdentifier, null, null, DELETE, null, aInQp);\n if(TE_TOPOLOGY_ENABLED) {\n String teNodePathIdentfier = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId)) + String.format(NODE_PATH, nodeId);\n if (aInYangDB.exists(teNodePathIdentfier, aInQp)) {\n logger.debug(\"Deleting TE node: {}\", teNodePathIdentfier);\n updateInDb(aInYangDB, null, teNodePathIdentfier, null, null, DELETE, null, aInQp);\n }\n }\n }\n }\n }\n\n private void deletePrefix(IYangDB aInYangDB, QueryParameters aInQp, String aInInstanceId, String aInIpAddress) {\n\n String adminDomain = extractAdminDomain(aInInstanceId);\n String nodeId = StringUtils.substringBetween(aInInstanceId, \"routing-instance[id='\", \"'\");\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + aInIpAddress + \"']\";\n if (aInYangDB.exists(prefixPathIden, aInQp)) {\n updateInDb(aInYangDB, null, prefixPathIden, null, null, DELETE, null, aInQp);\n }\n }\n }\n }\n\n private void deleteLink(IYangDB aInYangDB, QueryParameters aInQp, Map<String,Object> aInLink, YangDBConfig aInDbConfig,\n List<Object> aInLinkDetails) {\n String name = (String) aInLink.get(NAME);\n List<Object> linkDetails = CollectionUtils.isEmpty(aInLinkDetails) ? getLinkFromDb(name, aInDbConfig) : aInLinkDetails;\n if(linkDetails != null && !linkDetails.isEmpty()) {\n String linkId = ((Object[])linkDetails.get(0))[0].toString();\n String networkId = ((Object[])linkDetails.get(0))[1].toString();\n\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n logger.debug(\"L3 - deleteLink {}\", linkPathIdentifier);\n updateInDb(aInYangDB, null, linkPathIdentifier, null, null, DELETE, null, aInQp);\n\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId));\n //delete TE link\n if(TE_TOPOLOGY_ENABLED) {\n String teLinkPathIdentifier = teNetworkPathIdentifier + String.format(LINK_PATH, linkId);\n logger.debug(\"L3 - deleteLink {}\", teLinkPathIdentifier);\n updateInDb(aInYangDB, null, teLinkPathIdentifier, null, null, DELETE, null, aInQp);\n }\n //can delete source tp and destination tp?\n String oppLinkId = getOppIetfLinkId(linkId);\n String oppLinkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, oppLinkId);\n if (!aInYangDB.exists(oppLinkPathIdentifier, aInQp)) {\n // no other link is using the same source and destination. delete the TPs.\n List<String> linkObjIds = getLinkObjIds(linkId);\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(0));\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, linkObjIds.get(1));\n if(canDeleteTp(aInYangDB, \"%\" + linkObjIds.get(0) + \":\" + linkObjIds.get(1) + \"%\", networkId)) {\n deleteTerminationPoint(aInYangDB, aInQp, srcNodeIdentifier, srcNodeTPIdentifier);\n\n // delete TE src termination point\n if (TE_TOPOLOGY_ENABLED) {\n String teSrcNodeIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(0));\n String teSrcNodeTPIdentifier = teSrcNodeIdentifier + String.format(TP_PATH, linkObjIds.get(1));\n deleteTerminationPoint(aInYangDB, aInQp, teSrcNodeIdentifier, teSrcNodeTPIdentifier);\n }\n }\n\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(2));\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, linkObjIds.get(3));\n if(canDeleteTp(aInYangDB, \"%\" + linkObjIds.get(2) + \":\" + linkObjIds.get(3) + \"%\", networkId)) {\n deleteTerminationPoint(aInYangDB, aInQp, dstNodeIdentifier, dstNodeTPIdentifier);\n\n // delete TE dst termination point\n if (TE_TOPOLOGY_ENABLED) {\n String teDstNodeIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(2));\n String teDstNodeTPIdentifier = teDstNodeIdentifier + String.format(TP_PATH, linkObjIds.get(3));\n deleteTerminationPoint(aInYangDB, aInQp, teDstNodeIdentifier, teDstNodeTPIdentifier);\n }\n }\n //check whether the nodes has any more tps. if not delete the nodes as well.\n// validateNode(aInYangDB, aInQp, srcNodeIdentifier, networkId);\n// validateNode(aInYangDB, aInQp, dstNodeIdentifier, networkId);\n }\n }\n }\n\n @Override\n public void handleReplaceEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectReplacement aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------REPLACE------------------------------------------------------------------\");\n }\n\n// void validateNode(IYangDB aInYangDB, QueryParameters aInQp, String aInNodeIdentifier, String networkId) {\n// handleDeleteLogger.debug(\"VALIDATING NODE\");\n// IYangObject nodeObj = aInYangDB.getSingle(aInNodeIdentifier, aInQp);\n// if(nodeObj != null) {\n// List tp = (List) nodeObj.get(\"ietf-network-topology:termination-point\");\n// if(tp.isEmpty()) {\n// handleDeleteLogger.debug(\"VALIDATING NODE - NO MORE TP. SO DELETING IT\");\n// updateInDb(aInYangDB, null, aInNodeIdentifier, null, null, DELETE, null, aInQp);\n// }\n// }\n// }\n\n private void deleteTerminationPoint(IYangDB aInYangDB, QueryParameters aInQp, String aInSrcNodeIdentifier, String aInSrcNodeTPIdentifier) {\n if(aInYangDB.exists(aInSrcNodeIdentifier, aInQp)) {\n logger.debug(\"deleteTerminationPoint {}\", aInSrcNodeTPIdentifier);\n updateInDb(aInYangDB, null, aInSrcNodeTPIdentifier, null, null, DELETE, null, aInQp);\n }\n }\n\n public void handlePartialResync(SrcClass aInSrcClass, SyncClass aInSyncClass, long aInFromTime, String aInNeId, YangPluginMdConverterProvider aInYangPlugin) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------handlePartialResync-----------------------------------------------------------\");\n }\n\n IMdConverterFw converterFw = aInYangPlugin.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n logger.debug(\"L3 - handlePartialResync - UPDATE PREFIX after {}\", aInFromTime);\n partialResyncPrefix(yangDB, aInFromTime);\n }\n }\n\n void partialResyncPrefix(IYangDB yangDB, long aInFromTime) {\n //get the prefixes that have changed after the timestamp.\n QueryParameters qp = getFilteredQueryParameters(null);\n qp.setTimeField(TIME_FIELD_LAST_MODIFIED);\n qp.setTimeFrom(aInFromTime);\n List<IYangObject> prefixList = yangDB.getMany(NSP_SERVICE_GENERIC_PREFIX, qp);\n if (prefixList != null && !prefixList.isEmpty()) {\n prefixList.stream().forEach(prefix -> {\n Map<String, Object> meta = (Map) prefix.asMap().get(\"@\"); //need to convert it to map to get the identifier\n String identifier = (String) meta.get(\"nsp-model:identifier\");\n String adminDomain = extractAdminDomain(identifier);\n if(\"UnknownDomain\".equals(adminDomain) || adminDomain == null) {\n return;\n }\n String nodeId = StringUtils.substringBetween(identifier, \"routing-instance[id='\", \"'\");\n String nodePath = extractNodePathFromPrefixPath(identifier);\n IYangObject node = yangDB.getSingle(nodePath, getFilteredQueryParameters(\"protocols\"));\n if(node != null) {\n String protocol = null;\n Collection<String> protocols = (Collection) node.get(\"protocols\");\n for (String p : protocols) {\n if(isValidProtocol(p)) {\n protocol = p;\n break;\n }\n }\n if(protocol == null) {\n return;\n }\n String networkId = adminDomain + \"-\" + protocol;\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String ipAddress = (String) prefix.get(IP_ADDRESS);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n QueryParameters queryParameters = getFilteredQueryParameters(null);\n if(yangDB.exists(prefixPathIden, queryParameters)) {\n //update\n logger.debug(\"L3 - handlePartialResync - prefix - UPDATE {}\", prefixPathIden);\n IYangObject prefixObj = yangDB.getSingle(prefixPathIden, queryParameters);\n if (prefixObj != null) {\n int metric = (int) prefix.get(\"metric\");\n prefixObj.setProperty(\"metric\", metric);\n updateInDb(yangDB, prefixObj, prefixPathIden, null, null, UPDATE, null, queryParameters);\n }\n }\n else if (yangDB.exists(nodePathIdentifier)){\n //create\n logger.debug(\"L3 - handlePartialResync - prefix - CREATE {}\", prefixPathIden);\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, ipAddress);\n prefixObj.setProperty(\"metric\", prefix.get(\"metric\"));\n updateInDb(yangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, queryParameters);\n\n }\n }\n });\n }\n\n }\n\n private void updateInDb(IYangDB yangDB, IYangObject aInYangObject, String aInXPath, String aInParentPath,\n String aInChildType, String aInAction, ExecutionContext aInExecCtx, QueryParameters aInQp) {\n\n if (null != aInExecCtx) {\n aInQp.setIExecutionContext(aInExecCtx);\n }\n\n if (null != aInAction) {\n if (CREATE.equals(aInAction)) {\n yangDB.createChild(aInParentPath, aInChildType, aInYangObject, aInQp);\n } else if (\"UPDATE\".equals(aInAction)) {\n yangDB.update(aInXPath, aInYangObject, aInQp);\n } else {\n yangDB.delete(aInXPath, aInQp);\n }\n }\n }\n\n List<String> getLinkObjIds(String aInLinkId) {\n String[] idSplits = aInLinkId.split(\"--\");\n String[] srcNodeSplits = idSplits[0].split(\":\");\n String[] dstNodeSplits = idSplits[1].split(\":\");\n List<String> linkObjIds = new ArrayList<>();\n linkObjIds.add(srcNodeSplits[0]);\n linkObjIds.add(srcNodeSplits[1]);\n linkObjIds.add(dstNodeSplits[0]);\n linkObjIds.add(dstNodeSplits[1]);\n return linkObjIds;\n }\n\n String getOppIetfLinkId(String aInLinkId) {\n String[] idSplits = aInLinkId.split(\"--\");\n String oppLinkId = idSplits[1] + \"--\" + idSplits[0];\n oppLinkId += (idSplits.length == 3) ? \"--\" + idSplits[2] : \"\";\n return oppLinkId;\n }\n\n// String getSubnetRouterId(String aInNodeId) {\n// return aInNodeId.split(\"-psn\")[0];\n// }\n\n String getSubnetPsnId(String aInSubnetId) {\n int fromIndex = aInSubnetId.indexOf(\"psn\");\n if(fromIndex != -1 ) {\n return(aInSubnetId.substring(fromIndex));\n }\n return aInSubnetId;\n }\n\n String getSubnetSystemId(String aInSubnetId) {\n int toIndex = aInSubnetId.indexOf(\"-psn\");\n if(toIndex != -1 ) {\n return(aInSubnetId.substring(0, toIndex));\n }\n\n return aInSubnetId;\n }\n\n String getLinkId(String aInSrcNodeId, String aInDstNodeId, String aInSrcTpId, String aInDstTpId, String aInIsisLevel) {\n String linkId = aInSrcNodeId + \":\" + aInSrcTpId + \"--\" + aInDstNodeId + \":\" + aInDstTpId;\n if(aInIsisLevel != null) {\n linkId = linkId + \"--\" + aInIsisLevel;\n }\n return linkId;\n }\n\n String getTerminationPointId( String aInOppLinkIdentifier, IYangDB aInYangDB, String aInNetworkId) {\n logger.debug(\"Getting opposite link {}\", aInOppLinkIdentifier);\n String dstTpId = null;\n if(aInOppLinkIdentifier != null) {\n QueryParameters qp = getFilteredQueryParameters(IP_ADDRESS);\n List<IYangObject> oppLinkObjList = aInYangDB.getMany(aInOppLinkIdentifier, qp);\n if(oppLinkObjList != null && !oppLinkObjList.isEmpty()) {\n IYangObject oppLinkObj = oppLinkObjList.get(0);\n dstTpId = (String) oppLinkObj.get(IP_ADDRESS);\n }\n }\n return dstTpId;\n }\n\n Map<String,String> getLinkNodeDetails(String node) {\n Map<String, String> nodeDetails = new HashMap<>();\n if(node != null) {\n String[] pathSplit = node.split(\"/\");\n if (pathSplit.length > 0) {\n String[] nodeSplit = pathSplit[pathSplit.length - 1].split(\"id=\");\n if (nodeSplit.length > 1) {\n nodeDetails.put(NODE_TYPE, nodeSplit[0].substring(0, nodeSplit[0].length() - 1));\n nodeDetails.put(ID, nodeSplit[1].split(\"'\")[1]);\n }\n }\n }\n return nodeDetails;\n }\n\n String extractAdminDomain(String identifier) {\n int fromIndex = identifier.indexOf(\"/admin-domain[name='\");\n int toIndex = identifier.indexOf(\"'\", fromIndex+20);\n return identifier.substring(fromIndex + 20, toIndex);\n }\n\n String extractNetworkIdFromIetfIdentifier(String identifier) {\n return StringUtils.substringBetween(identifier, \"network-id='\", \"'\");\n }\n\n String extractLinkIdFromIetfIdentifier(String identifier) {\n return StringUtils.substringBetween(identifier, \"link-id='\", \"'\");\n }\n\n String extractNodePathFromPrefixPath(String identifier) {\n int fromIndex = 0;\n int toIndex = identifier.indexOf(\"/prefix[\");\n return identifier.substring(fromIndex, toIndex);\n }\n\n String getNetworkIdFromLink(List<String> aInDomains, String aInProtocol) {\n String networkId = null;\n if(aInDomains == null) {\n logger.error(\"L3 - Link event missing admin domain info\");\n return null;\n }\n for(String domain : aInDomains) {\n String[] domainSplit = domain.split(\"'\");\n networkId = domainSplit.length > 1 ? domainSplit[1] : null;\n break;\n }\n if(networkId != null) {\n if(aInProtocol.equals(\"ospf\") || aInProtocol.equals(\"isis\")) {\n networkId = networkId + \"-\" + aInProtocol;\n return networkId;\n }\n }\n return null;\n }\n\n String getNetworkIdFromMeta(IYangDB aInYangDb, Map<String, Object> aInSrcObject) {\n String networkId = null;\n Map<String, Object> meta = (Map) aInSrcObject.get(\"@\");\n String identifier = (String) meta.get(\"nsp-model:identifier\");\n String adminDomain = extractAdminDomain(identifier);\n if(\"UnknownDomain\".equals(adminDomain) || adminDomain == null) {\n return null;\n }\n String protocol = null;\n if(aInSrcObject.get(NODE_TYPE).equals(SUBNET)) {\n protocol = (String) aInSrcObject.get(\"protocol\");\n }\n else {\n Collection<String> protocols = (Collection) aInSrcObject.get(\"protocols\");\n for (String p : protocols) {\n if(isValidProtocol(p)) {\n protocol = p;\n break;\n }\n }\n }\n\n if(\"unknown\".equals(protocol) || protocol == null) {\n protocol = getProtocolFromAdminDomain(aInYangDb, adminDomain);\n }\n\n if(isValidProtocol(protocol)) {\n networkId = adminDomain + \"-\" + protocol;\n return networkId;\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - No valid protocol found for {}, {}\", adminDomain, protocol);\n }\n }\n\n return networkId;\n\n }\n\n String getAdminDomainFromMeta(Map<String, Object> aInSrcObject) {\n Map<String, Object> meta = (Map) aInSrcObject.get(\"@\");\n String identifier = (String) meta.get(\"nsp-model:identifier\");\n return extractAdminDomain(identifier);\n }\n\n String getNeIdFromRouterId(IYangDB aInYangDB, String aInNetworkId, String aInRouterId) {\n if(aInRouterId.contains(\"psn\")) return null;\n String[] domainSplit = aInNetworkId.split(\"-\");\n String adminDomain = domainSplit[0] + \"-\" + domainSplit[1];\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain) + String.format(NSP_SERVICE_ROUTING_INS_PATH, aInRouterId);\n QueryParameters qp = getFilteredQueryParameters(\"router/ne\");\n List<IYangObject> nodeObjList = aInYangDB.getMany(nspServiceNodeIden, qp);\n IYangObject nodeObj = (nodeObjList != null && !nodeObjList.isEmpty()) ? nodeObjList.get(0) : null;\n if(nodeObj != null) {\n IYangObject routerDetails = (IYangObject) nodeObj.get(\"router\");\n if(routerDetails != null && routerDetails.get(\"ne\") != null) {\n return extractNeId((String) routerDetails.get(\"ne\"));\n }\n }\n return null;\n }\n\n\n boolean isValidProtocol(String protocol) {\n return protocol != null && (protocol.equals(\"ospf\") || protocol.equals(\"isis\"));\n }\n\n String getNetworkId(IYangDB aInYangDb, IYangObject aInSrcObject) {\n String networkId = (String) aInSrcObject.get(NAME);\n if(networkId != null) {\n String protocol = getProtocolFromAdminDomain(aInYangDb, networkId);\n if (isValidProtocol(protocol)) {\n networkId = networkId + \"-\" + protocol;\n return networkId;\n }\n }\n if(logger.isDebugEnabled()) {\n logger.debug(\"RETURNING NULL FOR {}\", networkId);\n }\n return null;\n }\n\n String getAdminDomainFromNetworkId(String aInNetworkId) {\n String[] networkIds = aInNetworkId.split(\"-\");\n return networkIds[0] + \"-\" + networkIds[1];\n }\n\n String getTeNetworkId(String networkId) {\n return \"TE-\"+networkId;\n }\n\n String getSubnetNodeIdFromDB(YangDBConfig aInDbConfig, String aInSystemId, String aInNetworkId) {\n String adminDomain = getAdminDomainFromNetworkId(aInNetworkId);\n\n String lSql = \"SELECT id FROM service.routinginstance ri JOIN service.admindomain ad ON ad.dbid = ri.adminDomain_dbid\" +\n \" where systemId='\" + aInSystemId + \"' and ad.name = '\" + adminDomain + \"'\";\n try {\n final List<Object> query = aInDbConfig.getDb().selectQuery(lSql, new ArrayList<>(), new ArrayList<>(Arrays.asList(DBType.TEXT)));\n if(query == null || query.isEmpty()) {\n return null;\n }\n else {\n return (String) query.get(0);\n }\n }\n catch (Exception e)\n {\n logger.error(\"Exception when trying to get subnet-node-id for the system id: {} and admin domain: {}\", aInSystemId, adminDomain);\n }\n return null;\n }\n\n private List<Object> getLinkFromDb(String aInName, YangDBConfig aInDbConfig)\n {\n String lSql = \"SELECT linkId, networkId FROM ietf.ietf_241652239nk_ietf_l3_unicast_topology_l3_link_attributes where name = '\" + aInName + \"'\";\n try {\n final List<Object> query = aInDbConfig.getDb().selectQuery(lSql, new ArrayList<>(), new ArrayList<>(Arrays.asList(DBType.TEXT, DBType.TEXT)));\n return query;\n }\n catch (Exception e)\n {\n logger.error(\"Exception when trying to get the link {}\", aInName);\n }\n return null;\n }\n\n private String getPortDetailsFromDb(String aInTpId, IYangDB aInYangDb, String aInNeId)\n {\n List<Object> resourceList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT erb.resource FROM service.endpointaddress ea JOIN service.endpointresourcebinding erb\" +\n \" ON ea.detailsParent_dbId = erb.endpoint_dbId WHERE ea.address = :address and erb.layer = 5\")\n .setParameter(\"address\", aInTpId)\n .getResultList());\n if(resourceList == null || resourceList.isEmpty()) {\n return null;\n }\n List<Long> dbIds = resourceList.stream().map(resource -> ModelFdnUtil.getId(ModelFdn.decode(resource.toString()))).collect(Collectors.toList());\n\n if (dbIds != null && !dbIds.isEmpty()) {\n try {\n List<Object[]> portDetails = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createQuery(\"SELECT eq.neId, eq.name FROM equipment_Equipment eq WHERE eq.dbId IN :dbids\")\n .setParameter(\"dbids\", dbIds)\n .getResultList());\n if (!portDetails.isEmpty()) {\n for(Object[] portDetail : portDetails) {\n if(aInNeId.equals(portDetail[0])) {\n return (String) portDetail[1];\n }\n }\n }\n }\n catch(Exception e) {\n logger.error(\"L3 - Exception when finding the port name for the TP-ID: \" + aInTpId + \" and equipment dbIds: \" + dbIds.toString(), e);\n }\n }\n return null;\n }\n\n private String getProtocolFromAdminDomain(IYangDB aInYangDb, String aInAdminDomain) {\n\n try {\n List<Object> protocols = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT rp.protocols FROM service.routinginstance ri \" +\n \"JOIN service.admindomain ad ON ri.admindomain_dbid = ad.dbid \" +\n \"JOIN service.routinginstance_protocols rp ON ri.dbid = rp.dbid \" +\n \"WHERE ad.name = :name AND ri.operstate = 1\")\n .setParameter(\"name\", aInAdminDomain)\n .getResultList());\n\n if (!protocols.isEmpty()) {\n for(Object protocol : protocols) {\n if((int)protocol == 1 || (int)protocol == 2) {\n return ((int)protocol == 1) ? \"isis\" : \"ospf\";\n }\n }\n return null;\n }\n else {\n logger.warn(\"L3 - getProtocolFromAdminDomain - protocol is empty for {}\", aInAdminDomain);\n }\n }\n catch (Exception e) {\n return null;\n }\n return null;\n }\n\n private List<List<String>> getRouterDetailsFromNeId(IYangDB aInYangDb, String aInNeId)\n {\n List<Long> dbList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createQuery(\"SELECT eq.dbId FROM equipment_NetworkElement eq WHERE eq.neId = :neId\")\n .setParameter(\"neId\", aInNeId)\n .getResultList());\n if(dbList == null || dbList.isEmpty()) {\n return null;\n }\n\n List<String> modelFdns = dbList.stream().map(dbId -> ModelFdn.encode(ModelFdnUtil.modelFdn(\"equipment.NetworkElement\", dbId))).collect(Collectors.toList());\n List<List<String>> routerDetailsList = new ArrayList<>();\n if (modelFdns != null && !modelFdns.isEmpty()) {\n try {\n List<Object[]> routerDetails = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT ri.id, ad.name, rp.protocols FROM service.routinginstance ri \" +\n \"JOIN service.admindomain ad ON ri.admindomain_dbid = ad.dbid \" +\n \"JOIN service.routinginstance_protocols rp ON ri.dbid = rp.dbid \" +\n \"JOIN service.router rr ON ri.router_dbid = rr.dbid \" +\n \"WHERE rr.ne IN :fdns OR rr.ne LIKE :pattern\")\n .setParameter(\"fdns\", modelFdns)\n /* sometimes when a node is re-managed, NRCP takes some time to update the router.ne field with the proper NE fdn.\n Until then it has one of the sources. Meanwhile we get the L2 correlation events and so we end up ignoring it.\n This pattern search will fix it */\n .setParameter(\"pattern\", \"%\" + aInNeId + \"%\")\n .getResultList());\n\n if (routerDetails != null && !routerDetails.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - ROUTER DETAILS for NE-ID: {} are {}\", aInNeId, routerDetails.toString());\n }\n for(Object[] router : routerDetails) {\n int protocol = (int) router[2];\n String protocolName = (protocol == 1) ? \"isis\" : (protocol == 2) ? \"ospf\" : null;\n if(protocolName != null) {\n List<String> routerProps = new ArrayList<>();\n routerProps.add((String) router[0]);\n routerProps.add((String) router[1]);\n routerProps.add(protocolName);\n routerDetailsList.add(routerProps);\n }\n }\n }\n return routerDetailsList;\n }\n catch(Exception e) {\n logger.error(\"L3 - Exception when finding the router ID for the NE-ID: \" + aInNeId, e);\n }\n }\n return routerDetailsList;\n }\n\n public <T> T execute(IDB db, Function<ITransactionContext, T> fn) {\n try {\n if (Transactor.isInTransaction()) {\n return fn.apply(Transactor.getContext());\n } else {\n return Transactor.execute(db, fn, true);\n }\n } catch (DBRuntimeException e) {\n logger.error(\"L3 - DB ACCESS ERROR: \", e);\n return null;\n }\n }\n\n\n private String getSupportingNetworkRef(IYangDB aInYangDb, QueryParameters aInQp) {\n return aInYangDb.exists(L2_NETWORK_PATH, aInQp) ? L2_NETWORK_PATH : null;\n }\n\n private String getSupportingNodeRef(IYangDB aInYangDb, QueryParameters aInQp, String aInNodeId) {\n String supportingNodeRef = L2_NETWORK_PATH + String.format(NODE_PATH, aInNodeId);\n supportingNodeRef = aInYangDb.exists(supportingNodeRef, aInQp) ? supportingNodeRef : null;\n return supportingNodeRef;\n }\n\n private String getSupportingTpRef(IYangDB aInYangDb, QueryParameters aInQp, String aInNodeId, String aInTpId) {\n String supportingTpRef = L2_NETWORK_PATH + String.format(NODE_PATH, aInNodeId)\n + String.format(TP_PATH, aInTpId);\n supportingTpRef = aInYangDb.exists(supportingTpRef, aInQp) ? supportingTpRef : null;\n return supportingTpRef;\n }\n\n private String getSupportingLinkRef(IYangDB aInYangDb, QueryParameters aInQp, String aInLinkId) {\n String supportingLinkRef = L2_NETWORK_PATH + String.format(LINK_PATH, aInLinkId);\n supportingLinkRef = aInYangDb.exists(supportingLinkRef, aInQp) ? supportingLinkRef : null;\n return supportingLinkRef;\n }\n\n String extractNeId(String identifier) {\n if(identifier != null) {\n int fromIndex = identifier.indexOf(\"ne-id='\");\n if(fromIndex != -1) {\n int toIndex = identifier.indexOf(\"'\", fromIndex + 7);\n return identifier.substring(fromIndex + 7, toIndex);\n }\n }\n return null;\n }\n\n public Map<String, String> getSubInterfacePortMap(String aInNodeId, IMdConverterFw aInConverterFw) {\n String subInterfacePath = String.format(SUBINTERFACE_FILTER, aInNodeId);\n Map<String, String> portInterfaceMap = new HashMap<>();\n try {\n IRestConfClient restConfClient = aInConverterFw.getRestConfClient();\n Map<String,Object> lResponse = restConfClient.xpathGetData(subInterfacePath, \"fields=openconfig-if-ip:ipv4;config&depth=5\");\n if (lResponse != null && !lResponse.isEmpty()) {\n List<Map> subInterfaces = (List<Map>) lResponse.get(\"openconfig-interfaces:subinterface\");\n if(subInterfaces != null) {\n for (Map subInterface : subInterfaces) {\n String ip = extractIpFromSubInterface((Map) subInterface.get(\"openconfig-if-ip:ipv4\"));\n if(ip != null) {\n String port = extractPortFromSubInterface((Map) subInterface.get(\"config\"));\n portInterfaceMap.put(ip, getPortNameFromOpenConfigPortName(port));\n }\n }\n }\n }\n }\n catch(Exception e) {\n logger.warn(\"L3 - RestconfApi cannot get subinterfaces.\");\n }\n return portInterfaceMap;\n }\n\n public String getSubInterfaces(String aInNodeId, IMdConverterFw aInConverterFw, String ip) {\n /* Getting errors when tried to query the parent based on the child attributes.\n java.lang.IllegalArgumentException: only simple xpaths are supported - failing with this error message\n So we have to get all the network interfaces on the node and find the matching one. Ideal filter below\n /nsp-network:network/node[node-id='%s']/node-root/\" +\n \"openconfig-interfaces:interfaces/interface/subinterfaces/subinterface\" +\n \"[boolean(openconfig-if-ip:ipv4/addresses/address[ip='%s'])]\"\n */\n String subInterfacePath = String.format(SUBINTERFACE_FILTER, aInNodeId);\n Integer unnumbered = Ints.tryParse(ip);\n String unnumberedInterface = ip.contains(\"%\") ? ip.split(\"%\")[1] : unnumbered == null ? null : unnumbered.toString();\n if(unnumberedInterface != null && !unnumberedInterface.isEmpty()) {\n subInterfacePath += String.format(SUBINTERFACE_UNNUM_FILTER, unnumberedInterface);\n }\n try {\n IRestConfClient restConfClient = aInConverterFw.getRestConfClient();\n Map<String,Object> lResponse = restConfClient.xpathGetData(subInterfacePath, \"fields=openconfig-if-ip:ipv4;config&depth=5\");\n if (lResponse != null && !lResponse.isEmpty()) {\n List<Map> subInterfaces = (List<Map>) lResponse.get(\"openconfig-interfaces:subinterface\");\n if(subInterfaces != null) {\n for (Map subInterface : subInterfaces) {\n if (!unnumberedInterface.isEmpty() || ip.equals(extractIpFromSubInterface((Map) subInterface.get(\"openconfig-if-ip:ipv4\")))){\n String port = extractPortFromSubInterface((Map) subInterface.get(\"config\"));\n return getPortNameFromOpenConfigPortName(port);\n }\n }\n }\n }\n }\n catch(Exception e) {\n logger.warn(\"L3 - RestconfApi cannot get subinterfaces.\");\n }\n return null;\n }\n\n private String extractIpFromSubInterface(Map aInIpMap) {\n if(aInIpMap != null) {\n Map addresses = (Map) aInIpMap.get(\"addresses\");\n if (addresses != null) {\n List<Map> addressList = (List) addresses.get(\"address\");\n if (addressList != null) {\n for (Map ipMap : addressList) {\n return (String) ipMap.getOrDefault(\"ip\", null);\n }\n }\n }\n }\n return null;\n }\n\n private String extractPortFromSubInterface(Map aInConfigMap) {\n if(aInConfigMap != null) {\n return (String) aInConfigMap.getOrDefault(\"nsp-openconfig-interfaces-augments:port\", null);\n }\n return null;\n }\n\n private String getPortNameFromOpenConfigPortName(String portName) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Port Name from openConfig api: {}\",portName);\n }\n if(portName == null) return null;\n\n// if(portName.contains(\"GigabitEthernet\")) {\n// //cisco\n// String[] port = portName.split(\"GigabitEthernet\");\n// return \"GigabitEthernet Port \" + port[1];\n// }\n\n if(portName.contains(\":\")) {\n String[] port = portName.split(\":\");\n return port[0];\n }\n else {\n return portName;\n }\n }\n\n private boolean canDeleteTp(IYangDB aInYangDb, String aInPattern, String aInNetworkId) {\n BigInteger count = (BigInteger) execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT count(*) FROM \" +\n \"ietf.ietf_network_networks_network_ietf_network_topology_link sl WHERE sl.linkId LIKE :pattern \" +\n \"AND sl.networkId = :networkId\")\n .setParameter(\"pattern\", aInPattern)\n .setParameter(\"networkId\", aInNetworkId)\n .getSingleResult());\n return count != null && count.longValue() == 0;\n }\n\n private void createSupportingNetwork(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInSupportingNetworkRef) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId);\n IYangObject supportingNetworkobj = new YangObject();\n supportingNetworkobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingNetworkobj.setProperty(NETWORK_REF, aInSupportingNetworkRef);\n updateInDb(aInYangDB, supportingNetworkobj, \"\", networkPathIdentifier, SUPPORTING_NETWORK, CREATE, null, aInQp);\n }\n\n private void createSupportingNode(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInSupportingNodeRef, String aInNodePathIdentifier) {\n IYangObject supportingNodeobj = new YangObject();\n supportingNodeobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingNodeobj.setProperty(NODE_ID, aInNodeId);\n supportingNodeobj.setProperty(NETWORK_REF, L2_NETWORK_PATH);\n supportingNodeobj.setProperty(NODE_REF, aInSupportingNodeRef);\n updateInDb(aInYangDB, supportingNodeobj, \"\", aInNodePathIdentifier, SUPPORTING_NODE, CREATE, null, aInQp);\n if(supportingNodeMap.containsKey(aInSupportingNodeRef)) {\n supportingNodeMap.get(aInSupportingNodeRef).add(aInNodePathIdentifier);\n }\n else {\n supportingNodeMap.put(aInSupportingNodeRef, new HashSet<>(Arrays.asList(aInNodePathIdentifier)));\n }\n }\n\n private void createSupportingTp(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInTpId, String aInNeId, String aInSupportingTpRef, String aInTpPathIdentifier) {\n IYangObject supportingTpobj = new YangObject();\n supportingTpobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingTpobj.setProperty(NODE_ID, aInNodeId);\n supportingTpobj.setProperty(TP_ID, aInTpId);\n supportingTpobj.setProperty(NETWORK_REF, L2_NETWORK_PATH);\n supportingTpobj.setProperty(NODE_REF, L2_NETWORK_PATH + String.format(NODE_PATH, aInNeId));\n supportingTpobj.setProperty(TP_REF, aInSupportingTpRef);\n updateInDb(aInYangDB, supportingTpobj, \"\", aInTpPathIdentifier, SUPPORTING_TP, CREATE, null, aInQp);\n supportingTpMap.put(aInSupportingTpRef, aInTpPathIdentifier);\n if(l2TpCreateEvents.containsKey(aInNeId)) {\n l2TpCreateEvents.get(aInNeId).portsToAdd.remove(StringUtils.substringBetween(aInSupportingTpRef, \"[tp-id='\", \"']\"));\n }\n }\n\n private void deleteSupportingTp(String aInSupportingTpIden, IYangDB aInYangDB) {\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInYangDB.exists(aInSupportingTpIden, qp)) {\n IYangObject supportingTpObj = aInYangDB.getSingle(aInSupportingTpIden, qp);\n String l2TpRef = (String) supportingTpObj.get(TP_REF);\n logger.debug(\"L3 - RESYNC TP - deleteSupportingTp {} , {}\", aInSupportingTpIden, l2TpRef);\n updateInDb(aInYangDB, null, aInSupportingTpIden, null, null, DELETE, null, qp);\n supportingTpMap.remove(l2TpRef);\n }\n }\n\n private void createSupportingLink(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInLinkId,\n String aInSupportingLinkRef, String aInLinkIdentifier) {\n IYangObject supportingLinkobj = new YangObject();\n supportingLinkobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingLinkobj.setProperty(LINK_ID, aInLinkId);\n supportingLinkobj.setProperty(NETWORK_REF, L2_NETWORK_PATH);\n supportingLinkobj.setProperty(LINK_REF, aInSupportingLinkRef);\n updateInDb(aInYangDB, supportingLinkobj, \"\", aInLinkIdentifier, SUPPORTING_LINK, CREATE, null, aInQp);\n supportingLinkMap.put(aInSupportingLinkRef, aInLinkIdentifier);\n l2LinkCreateEvents.remove(aInSupportingLinkRef);\n }\n\n private void deleteSupportingLink(String aInSupportingLinkIden, IYangDB aInYangDB) {\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInYangDB.exists(aInSupportingLinkIden, qp)) {\n IYangObject supportingLinkObj = aInYangDB.getSingle(aInSupportingLinkIden, qp);\n String l2TpRef = (String) supportingLinkObj.get(LINK_REF);\n logger.debug(\"L3 - RESYNC LINK - deleteSupportingLink {} , {}\", aInSupportingLinkIden, l2TpRef);\n updateInDb(aInYangDB, null, aInSupportingLinkIden, null, null, DELETE, null, qp);\n supportingLinkMap.remove(l2TpRef);\n }\n }\n\n private void createTeNetworkRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInTeNetworkRef) {\n String networkTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) +\n \"/ietf-l3-unicast-topology:l3-topology-attributes\";\n if(!aInYangDB.exists(networkTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-topology-attributes\", aInQp)) {\n IYangObject teNetworkRefObj = new YangObject();\n teNetworkRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teNetworkRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n updateInDb(aInYangDB, teNetworkRefObj, \"\", networkTopoAttrIdentifier,\n \"ietf-l3-te-topology:l3-te-topology-attributes\", CREATE, null, aInQp);\n }\n }\n\n private void createTeNodeRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInTeNetworkRef, String aInTeNodeRef) {\n String nodeTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) +\n String.format(NODE_PATH, aInNodeId) + \"/ietf-l3-unicast-topology:l3-node-attributes\";\n if(!aInYangDB.exists(nodeTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-node-attributes\", aInQp)) {\n IYangObject teNodeRefObj = new YangObject();\n teNodeRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teNodeRefObj.setProperty(NODE_ID, aInNodeId);\n teNodeRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n teNodeRefObj.setProperty(NODE_REF, aInTeNodeRef);\n updateInDb(aInYangDB, teNodeRefObj, \"\", nodeTopoAttrIdentifier,\n \"ietf-l3-te-topology:l3-te-node-attributes\", CREATE, null, aInQp);\n }\n }\n\n private void createTeTpRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInTpId, String aInTeNetworkRef, String aInTeNodeRef, String aInTeTpRef) {\n String tpTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) +\n String.format(NODE_PATH, aInNodeId) + String.format(TP_PATH, aInTpId) +\n \"/ietf-l3-unicast-topology:l3-termination-point-attributes\";\n if(!aInYangDB.exists(tpTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-tp-attributes\", aInQp)) {\n IYangObject teTpRefObj = new YangObject();\n teTpRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teTpRefObj.setProperty(NODE_ID, aInNodeId);\n teTpRefObj.setProperty(TP_ID, aInTpId);\n teTpRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n teTpRefObj.setProperty(NODE_REF, aInTeNodeRef);\n teTpRefObj.setProperty(TP_REF, aInTeTpRef);\n updateInDb(aInYangDB, teTpRefObj, \"\", tpTopoAttrIdentifier, \"ietf-l3-te-topology:l3-te-tp-attributes\",\n CREATE, null, aInQp);\n }\n }\n\n private void createTeLinkRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInLinkId,\n String aInTeNetworkRef, String aInTeLinkRef) {\n String linkTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) + String.format(LINK_PATH, aInLinkId)\n + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n if(!aInYangDB.exists(linkTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-link-attributes\", aInQp)) {\n IYangObject teLinkRefObj = new YangObject();\n teLinkRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teLinkRefObj.setProperty(LINK_ID, aInLinkId);\n teLinkRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n teLinkRefObj.setProperty(LINK_REF, aInTeLinkRef);\n updateInDb(aInYangDB, teLinkRefObj, \"\", linkTopoAttrIdentifier, \"ietf-l3-te-topology:l3-te-link-attributes\",\n CREATE, null, aInQp);\n }\n }\n\n private QueryParameters getFilteredQueryParameters (String fields) {\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n if(fields != null) {\n qp.setFields(Fields.parse(fields));\n }\n return qp;\n }\n\n private void populateSuportingNodeMap(IYangDB aInYangDb) {\n List<Object[]> nodeList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT sn.networkId, sn.nodeId, sn.nodeRef FROM \" +\n \"ietf.ietf_network_networks_network_node_supporting_node sn WHERE sn.networkId LIKE :pattern1 \" +\n \"OR sn.networkId LIKE :pattern2\")\n .setParameter(\"pattern1\", \"%ospf%\")\n .setParameter(\"pattern2\", \"%isis%\")\n .getResultList());\n if (nodeList == null || nodeList.isEmpty()) {\n return;\n }\n\n for(Object[] nodeInfo : nodeList) {\n if(nodeInfo.length == 3) {\n String l3NodeIden = String.format(L3_NETWORK_PATH, nodeInfo[0]) + String.format(NODE_PATH, nodeInfo[1]);\n if (supportingNodeMap.containsKey(nodeInfo[2])) {\n supportingNodeMap.get(nodeInfo[2]).add(l3NodeIden);\n } else {\n supportingNodeMap.put(nodeInfo[2].toString(), new HashSet<>(Arrays.asList(l3NodeIden)));\n }\n }\n }\n\n if (logger.isDebugEnabled()) {\n logger.debug(supportingNodeMap.toString());\n }\n }\n\n private void populateSuportingTpMap(IYangDB aInYangDb) {\n List<Object[]> tpList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT sp.networkId, sp.nodeId, sp.tpId, sp.tpRef FROM \" +\n \"ietf.ietf_90278165_termination_point_supporting_termination_point sp WHERE sp.networkId LIKE :pattern1 \" +\n \"OR sp.networkId LIKE :pattern2\")\n .setParameter(\"pattern1\", \"%ospf%\")\n .setParameter(\"pattern2\", \"%isis%\")\n .getResultList());\n if (tpList == null || tpList.isEmpty()) {\n return;\n }\n\n for(Object[] tpInfo : tpList) {\n if(tpInfo.length == 4) {\n String l3TpIden = String.format(L3_NETWORK_PATH, tpInfo[0]) + String.format(NODE_PATH, tpInfo[1]) +\n String.format(TP_PATH, tpInfo[2]);\n supportingTpMap.put(tpInfo[3].toString(), l3TpIden);\n }\n }\n\n if(logger.isDebugEnabled()) {\n logger.debug(supportingTpMap.toString());\n }\n }\n\n private void populateSuportingLinkMap(IYangDB aInYangDb) {\n List<Object[]> linkListInfo = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT sl.networkId, sl.linkId, sl.linkRef FROM \" +\n \"ietf.ietf_139678392ork_ietf_network_topology_link_supporting_link sl WHERE sl.networkId LIKE :pattern1 \" +\n \"OR sl.networkId LIKE :pattern2\")\n .setParameter(\"pattern1\", \"%ospf%\")\n .setParameter(\"pattern2\", \"%isis%\")\n .getResultList());\n if (linkListInfo == null || linkListInfo.isEmpty()) {\n return;\n }\n\n for(Object[] linkInfo : linkListInfo) {\n if(linkInfo.length == 3) {\n String l3LinkIden = String.format(L3_NETWORK_PATH, linkInfo[0]) + String.format(LINK_PATH, linkInfo[1]);\n supportingLinkMap.put(linkInfo[2].toString(), l3LinkIden);\n }\n }\n\n if (logger.isDebugEnabled()) {\n logger.debug(supportingLinkMap.toString());\n }\n }\n\n private void startCorrelationService() {\n synchronized (this) {\n if (correlationService == null || correlationService.isShutdown()) {\n logger.debug(\"L3 - L2 - Correlation - correlationService has been started that will run periodically until correlation is complete\");\n correlationService = Executors.newScheduledThreadPool(1,\n new ThreadFactoryBuilder().setNameFormat(\"L3-CorrelationHandler-to-L2\").build());\n correlationService.scheduleAtFixedRate(() -> correlateTpsAndLinks(), 2, 2, TimeUnit.MINUTES);\n }\n }\n }\n\n @SuppressFBWarnings(\"WMI_WRONG_MAP_ITERATOR\")\n class L2TpCreateTask implements Runnable {\n String neId;\n Map<String, Integer> portsToAdd = new HashMap<>();\n IYangDB yangDB;\n IMdConverterFw converterFw;\n\n L2TpCreateTask(String neId, String portToAdd, IMdConverterFw converterFw ) {\n this.neId = neId;\n if(portToAdd != null && !portToAdd.isEmpty()) {\n portsToAdd.put(portToAdd, 1);\n }\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(!portsToAdd.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"Trying to add correlation for ports {} on {}\", portsToAdd.entrySet().toString(), neId);\n }\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n if(routers == null || routers.isEmpty()) {\n logger.debug(\"******** L3 - Correlation - no router found for the NE ID {}\", neId);\n return;\n }\n Map<String, String> portInterfaceMap = null;\n for(List<String> router: routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n QueryParameters qp = getFilteredQueryParameters(\"tp-id;\"+SUPPORTING_TP);\n qp.setDepth(2);\n\n /*\n 1. call the openconfig subinterface query and get the map of port and interfaces for the NE ID\n 2. For each router, get all the TPs\n 3. If supporting tp is null\n 3.1 If the map contains the TP, add correlation.\n 3.2 If not, try to get the nfmp way or unnumbered interface way and add correlation\n 3.3 remove the ports from the portsToadd list.\n 4.If there is any port remaining, retry them (3 times).\n */\n\n List<IYangObject> tpList = yangDB.getMany(nodeIdentifer + \"/\" + TP_TYPE, qp);\n if(tpList != null && !tpList.isEmpty()) {\n for(IYangObject tp : tpList) {\n if(tp.get(SUPPORTING_TP) == null) {\n if(portInterfaceMap == null) {\n portInterfaceMap = getSubInterfacePortMap(neId, converterFw);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation mdm port interface map {} for {}\", portInterfaceMap.toString(), neId);\n }\n }\n String tpId = (String) tp.get(\"tp-id\");\n String portName = portInterfaceMap.get(tpId);\n\n if(portName == null) {\n portName = getPortDetailsFromDb(tpId, yangDB, neId);\n if(portName == null && tpId.contains(\"%\")) {\n portName = getSubInterfaces(neId, converterFw, tpId);\n if(logger.isDebugEnabled() && portName == null) {\n logger.debug(\"portName is still null for {} and {}\", tpId, neId);\n }\n }\n }\n\n if(portName != null && portsToAdd.containsKey(portName)) {\n String tpIden = nodeIdentifer + String.format(TP_PATH, tpId);\n String supportingTpIden = tpIden + \"/\" + SUPPORTING_TP;\n if(!yangDB.exists(supportingTpIden)) {\n String instanceId = L2_NETWORK_PATH + String.format(NODE_PATH, neId)\n + String.format(TP_PATH, portName);\n logger.debug(\"L3 - createSupportingTp {}\", instanceId);\n qp = getFilteredQueryParameters(null);\n createSupportingTp(yangDB, qp, networkId, router.get(0), tpId, neId, instanceId, tpIden);\n portsToAdd.remove(portName);\n }\n }\n }\n }\n // the remaining ports in portsToAdd can be re-tried.\n for(String port : portsToAdd.keySet()) {\n portsToAdd.put(port, portsToAdd.get(port) + 1);\n }\n //remove after 3 attempts.\n portsToAdd.entrySet().removeIf(e -> e.getValue() > 3);\n\n }\n else {\n portsToAdd.clear();\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - NO TP for {}\", nodeIdentifer + \"/\" + TP_TYPE);\n }\n }\n }\n }\n\n //for retries\n if(!portsToAdd.isEmpty()) {\n portsToAdd.entrySet().removeIf(e -> supportingTpMap.containsKey(L2_NETWORK_PATH +\n String.format(NODE_PATH, neId) + String.format(TP_PATH, e.getKey())));\n\n if(l2TpCreateEvents.containsKey(neId)) {\n for(Map.Entry<String,Integer> port : portsToAdd.entrySet()) {\n l2TpCreateEvents.get(neId).portsToAdd.put(port.getKey(), port.getValue());\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - retrying for port {} on {}\", port.getKey(), neId);\n }\n }\n }\n else {\n l2TpCreateEvents.put(neId, this);\n }\n startCorrelationService();\n }\n }\n }\n\n @SuppressFBWarnings(\"URF_UNREAD_FIELD\")\n class L2TpDeleteTask implements Runnable {\n String neId;\n List<String> portsToDelete = new ArrayList<>();\n IYangDB yangDB;\n IMdConverterFw converterFw;\n\n L2TpDeleteTask(String neId, String portToDelete, IMdConverterFw converterFw ) {\n this.neId = neId;\n if(portToDelete != null && !portToDelete.isEmpty()) {\n portsToDelete.add(portToDelete);\n }\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(!portsToDelete.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"correlation delete tp task is running\");\n }\n deleteL2SupportingTps(portsToDelete, neId, yangDB);\n portsToDelete.clear();\n }\n }\n }\n\n class L2LinkCreateTask implements Runnable {\n String instanceId;\n String linkId;\n IYangDB yangDB;\n IMdConverterFw converterFw;\n int retryAttempt = 1;\n\n L2LinkCreateTask(String instanceId, IMdConverterFw converterFw) {\n this.instanceId = instanceId;\n this.linkId = StringUtils.substringBetween(instanceId, \"[link-id='\", \"']\");\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(linkId != null) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3- correlation - Trying to correlate link {}\", linkId);\n }\n String[] tps = linkId.split(\"--\");\n if(tps != null && tps.length == 2) {\n List<String> networkDetails = new ArrayList<>();\n List<String> l3SourceTps = getTpDetails(tps[0].split(\":\"), yangDB, converterFw, networkDetails);\n if(!l3SourceTps.isEmpty()) {\n List<String> l3DstTps = getTpDetails(tps[1].split(\":\"), yangDB, converterFw, null);\n if(!l3DstTps.isEmpty()) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkDetails.get(0));\n for(String sourceTp : l3SourceTps) {\n for (String dstTp : l3DstTps ) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation exists for L3 source and destination tps for {}\", linkId);\n }\n String l3LinkId = sourceTp + \"--\" + dstTp;\n String linkIdentifier = networkPathIdentifier + String.format(LINK_PATH, l3LinkId);\n String supportingLinkIden = linkIdentifier + \"/\" + SUPPORTING_LINK;\n QueryParameters qp = getFilteredQueryParameters(null);\n if(networkDetails.get(0).contains(\"isis\")) {\n String l3IsisLinkId = l3LinkId + \"--l1\";\n linkIdentifier = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId);\n supportingLinkIden = linkIdentifier + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(linkIdentifier, qp) && !yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - createSupportingLink {}\", instanceId);\n createSupportingLink(yangDB, qp, networkDetails.get(0), l3IsisLinkId, instanceId, linkIdentifier);\n }\n\n l3IsisLinkId = l3LinkId + \"--l2\";\n linkIdentifier = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId);\n supportingLinkIden = linkIdentifier + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(linkIdentifier, qp) && !yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - createSupportingLink {}\", instanceId);\n createSupportingLink(yangDB, qp, networkDetails.get(0), l3IsisLinkId, instanceId, linkIdentifier);\n }\n }\n else if(yangDB.exists(linkIdentifier, qp) && !yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - createSupportingLink {}\", instanceId);\n createSupportingLink(yangDB, qp, networkDetails.get(0), l3LinkId, instanceId, linkIdentifier);\n }\n }\n }\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - link retrying because destination tp is not correlated for {}\", this.linkId);\n }\n if(retryAttempt < 3 && !supportingLinkMap.containsKey(this.instanceId)) {\n this.retryAttempt++;\n l2LinkCreateEvents.put(this.instanceId, this);\n startCorrelationService();\n }\n\n }\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - link retrying because source tp is not correlated for {}\", this.linkId);\n }\n if(retryAttempt < 3 && !supportingLinkMap.containsKey(this.instanceId)) {\n this.retryAttempt++;\n l2LinkCreateEvents.put(this.instanceId, this);\n startCorrelationService();\n }\n }\n }\n }\n\n }\n }\n\n class L2LinkDeleteTask implements Runnable {\n String instanceId;\n String linkId;\n IYangDB yangDB;\n IMdConverterFw converterFw;\n\n L2LinkDeleteTask(String instanceId, IMdConverterFw converterFw) {\n this.instanceId = instanceId;\n this.linkId = StringUtils.substringBetween(instanceId, \"[link-id='\", \"']\");\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(logger.isDebugEnabled()) {\n logger.debug(\"correlation link delete task is running\");\n }\n List<String> linksDeleted = new ArrayList<>();\n if(supportingLinkMap.containsKey(instanceId)) {\n String supportingLinkIden = supportingLinkMap.get(instanceId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supportingLinkIden)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supportingLinkIden);\n updateInDb(yangDB, null, supportingLinkIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n linksDeleted.add(supportingLinkMap.get(instanceId));\n supportingLinkMap.remove(instanceId);\n }\n else if(linkId != null) {\n String[] tps = linkId.split(\"--\");\n if(tps != null && tps.length == 2) {\n List<String> networkDetails = new ArrayList<>();\n List<String> l3SourceTps = getTpDetails(tps[0].split(\":\"), yangDB, converterFw, networkDetails);\n if(!l3SourceTps.isEmpty()) {\n List<String> l3DstTps = getTpDetails(tps[1].split(\":\"), yangDB, converterFw, null);\n if(!l3DstTps.isEmpty()) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkDetails.get(0));\n for(String sourceTp : l3SourceTps) {\n for (String dstTp : l3DstTps ) {\n String l3LinkId = sourceTp + \"--\" + dstTp;\n QueryParameters qp = getFilteredQueryParameters(null);\n if(networkDetails.get(0).contains(\"isis\")) {\n String l3IsisLinkId = l3LinkId + \"--l1\";\n String supportingLinkIden = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supportingLinkIden);\n updateInDb(yangDB, null, supportingLinkIden, null, null, DELETE, null, qp);\n linksDeleted.add(networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId));\n }\n\n l3IsisLinkId = l3LinkId + \"--l2\";\n supportingLinkIden = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supportingLinkIden);\n updateInDb(yangDB, null, supportingLinkIden, null, null, DELETE, null, qp);\n linksDeleted.add(networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId));\n }\n }\n else {\n String supporingLinkIden = networkPathIdentifier + String.format(LINK_PATH, l3LinkId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supporingLinkIden, qp)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supporingLinkIden);\n updateInDb(yangDB, null, supporingLinkIden, null, null, DELETE, null, qp);\n linksDeleted.add(networkPathIdentifier + String.format(LINK_PATH, l3LinkId));\n }\n }\n }\n }\n }\n }\n\n }\n }\n\n //Delete the related correlated TPs for the deleted links.\n if(!linksDeleted.isEmpty()) {\n for(String l3Link : linksDeleted) {\n String l3LinkId = extractLinkIdFromIetfIdentifier(l3Link);\n String l3NetworkId = extractNetworkIdFromIetfIdentifier(l3Link);\n\n // build tp identifier and check for supporting identifier and delete it.\n String l3NetworkPathIdentifier = String.format(L3_NETWORK_PATH, l3NetworkId);\n String[] l3Tp = l3LinkId.split(\"--\");\n for(int i = 0; i < l3Tp.length; i++) {\n String[] tpDetails = l3Tp[i].split(\":\");\n if (tpDetails.length == 2) {\n String supportingTpIden = l3NetworkPathIdentifier + String.format(NODE_PATH, tpDetails[0])\n + String.format(TP_PATH, tpDetails[1]) + \"/\" + SUPPORTING_TP;\n if(yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTp {}\", supportingTpIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n\n // build the port identifier and delete it from cache.\n\n String[] l2Tp = instanceId.split(\"--\");\n for(int i = 0; i < l2Tp.length - 1; i++) {\n String[] l2TpDetails = l2Tp[i].split(\":\");\n String l2TpIden = L2_NETWORK_PATH + String.format(NODE_PATH, l2TpDetails[0])\n + String.format(TP_PATH, l2TpDetails[1]);\n supportingTpMap.remove(l2TpIden);\n }\n }\n }\n }\n }\n}\n"
27
+ }
28
+ ]
29
+ },
30
+ {
31
+ "@": {
32
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler",
33
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler']",
34
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
35
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
36
+ },
37
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
38
+ "version": "1.0.1",
39
+ "java-code": [
40
+ {
41
+ "@": {
42
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler/java-code",
43
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/tracking-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler']/java-code[page-number='1']",
44
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
45
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
46
+ },
47
+ "page-number": 1,
48
+ "page": "package com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.nokia.nsp.md.common.notif.ObjectCreation;\nimport com.nokia.nsp.md.common.notif.ObjectDeletion;\nimport com.nokia.nsp.md.common.notif.ObjectModification;\nimport com.nokia.nsp.md.common.notif.ObjectReplacement;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.ICustomHandler;\nimport com.nokia.nsp.md.converter.yang.plugin.common.IHandleDeleteTracking;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\n\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.ifg.yang.api.Fields;\nimport com.nokia.nspos.persistence.impl.db.transaction.DBRuntimeException;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\n\nimport com.nokia.nspos.persistence.impl.db.transaction.ITransactionContext;\nimport com.nokia.nspos.persistence.impl.db.transaction.Transactor;\nimport com.nokia.nspos.persistence.api.IDB;\n\nimport com.nokia.nspos.model.domain.service.types.Layer;\nimport com.nokia.nspos.model.domain.service.types.ServiceType;\nimport com.nokia.nspos.model.domain.service.types.EndpointType;\nimport com.nokia.nspos.model.domain.service.types.Direction;\n\nimport org.apache.commons.lang.StringUtils;\n\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.function.Function;\nimport java.util.regex.Pattern;\n\npublic class L2TopologyHandler implements ICustomHandler, IHandleDeleteTracking\n{\n private static final org.slf4j.Logger handleResyncLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleResync\");\n private static final org.slf4j.Logger handlePostResyncDeleteLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".postResyncDelete\");\n private static final org.slf4j.Logger handleCreateEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleCreateEvent\");\n private static final org.slf4j.Logger handleUpdateEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleUpdateEvent\");\n private static final org.slf4j.Logger handleReplaceEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleReplaceEvent\");\n private static final org.slf4j.Logger handleDeleteEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleDeleteEvent\");\n private static final org.slf4j.Logger handleNodeLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleNode\");\n private static final org.slf4j.Logger handleTpLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleTp\");\n private static final org.slf4j.Logger handlePortLagLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handlePortLag\");\n private static final org.slf4j.Logger handleLinkLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleLink\");\n private static final org.slf4j.Logger dataBaseAccessLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".dataBaseAccess\");\n private static final org.slf4j.Logger handleTrackedDeleteLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleTrackedDelete\");\n\n private static final String IETF_L2_NETWORK_ID = \"L2Topology\";\n private static final String IETF_L2_NETWORK_PATH = String.format(\"/ietf-network:networks/network[network-id='%s']\", IETF_L2_NETWORK_ID);\n private static final String IETF_L2_NODE_PATH = IETF_L2_NETWORK_PATH + \"/node[node-id='%s']\";\n private static final String IETF_L2_TP_PATH = IETF_L2_NODE_PATH + \"/ietf-network-topology:termination-point[tp-id='%s']\";\n private static final String IETF_L2_LINK_PATH = IETF_L2_NETWORK_PATH + \"/ietf-network-topology:link[link-id='%s']\";\n private static final String IETF_NODE_TYPE = \"node\";\n private static final String IETF_TP_TYPE = \"ietf-network-topology:termination-point\";\n private static final String IETF_LINK_TYPE = \"ietf-network-topology:link\";\n\n private static final String IETF_NETWORK_CLASS = \"ietf-network:/networks/network\";\n private static final String IETF_NODE_CLASS = IETF_NETWORK_CLASS + \"/\" + IETF_NODE_TYPE;\n private static final String IETF_TP_CLASS = IETF_NODE_CLASS + \"/\" + IETF_TP_TYPE;\n private static final String IETF_LINK_CLASS = IETF_NETWORK_CLASS + \"/\" + IETF_LINK_TYPE;\n\n private static final String NSP_SERVICE_CABLE_CLASS = \"nsp-service:/services/physical-layer/cable\";\n private static final String NSP_ENDPOINT_CABLE_CLASS = \"nsp-service:/services/physical-layer/cable/link-endpoint\";\n private static final String NSP_SERVICE_RADIO_CLASS = \"nsp-service:/services/physical-layer/radio-link\";\n private static final String NSP_ENDPOINT_RADIO_CLASS = \"nsp-service:/services/physical-layer/radio-link/link-endpoint\";\n private static final String NSP_EQUIPMENT_PORT_CLASS = \"nsp-equipment:/network/network-element/hardware-component/port\";\n private static final String NSP_EQUIPMENT_PORT_DETAILS_CLASS = \"nsp-equipment:/network/network-element/hardware-component/port/port-details\";\n private static final String NSP_EQUIPMENT_LAG_CLASS = \"nsp-equipment:/network/network-element/lag\";\n\n private static final String NSP_SERVICE_PATH = \"/nsp-service:services/physical-layer/%s[id='%s']\";\n private static final String NSP_ENDPOINT_PATH = \"/nsp-service:services/physical-layer/%s[id='%s']/link-endpoint[site-id='%s'][endpoint-id='%s']\";\n private static final String nokia_nsp_network_management_ELEMENT_PATH = \"/nsp-equipment:network/network-element[ne-id='%s']\";\n\n private static final String NSP_ENDPOINT_TABLE = \"service_Endpoint\";\n private static final String NSP_SERVICE_TABLE = \"service_Service\";\n private static final Layer NSP_L2_LAYER = Layer.physical;\n private static final Set<ServiceType> NSP_L2_SERVICE_TYPES = ImmutableSet.of(ServiceType.cable, ServiceType.radioLink);\n\n private static final String IETF_MEMBER_LINK_TP_TABLE = \"ietf.ietf_204762653l2_termination_point_attributes_member_link_tp\";\n private static final String IETF_LINK_NSP_ATTR_TABLE = \"ietf.ietf_19924911ibutes_nsp_ietf_network_topology_nsp_attributes\";\n private static final String IETF_TP_NSP_ATTR_TABLE = \"ietf.ietf_48789230ibutes_nsp_ietf_network_topology_nsp_attributes\";\n\n public static final Fields nokia_nsp_network_management_ELEMENT_READ_FIELDS = Fields.parse(\"ne-name;mac-address;ip-address\");\n public static final Fields NSP_ENDPOINT_READ_FIELDS = Fields.parse(\"endpoint-id;site-id;type;port-bindings/resource\");\n public static final Fields NSP_SERVICE_READ_FIELDS = Fields.parse(\"link-endpoint(endpoint-id;site-id;type;port-bindings/resource);id;name;latency;direction\");\n public static final Fields NSP_SERVICE_READ_FIELDS_REDUCED = Fields.parse(\"name;latency\");\n public static final Fields NSP_PORT_READ_FIELDS_FOR_TP = Fields.parse(\"name;ne-id;hw-mac-address;port-details(encap-type;port-index)\");\n public static final Fields NSP_PORT_READ_FIELDS_FOR_LAG_MEMBER = Fields.parse(\"name\");\n public static final Fields NSP_PORT_DETAILS_READ_FIELDS_FOR_TP = Fields.parse(\"encap-type;port-index\");\n public static final Fields NSP_PORT_DETAILS_READ_FIELDS_FOR_LINK = Fields.parse(\"actual-rate;actual-rate-units;operational-duplex;auto-negotiate\");\n public static final Fields NSP_LAG_READ_FIELDS = Fields.parse(\"name;configured-address;encap-type;lag-index;members\");\n public static final Fields NSP_LAG_READ_FIELDS_MEMBERS = Fields.parse(\"members\");\n public static final Fields IETF_LINK_ATTR_READ_FIELDS = Fields.parse(\"name;nsp-ietf-network-topology:nsp-attributes\");\n public static final Fields IETF_TP_ATTR_READ_FIELDS = Fields.parse(\"nsp-ietf-network-topology:nsp-attributes\");\n public static final Fields IETF_TP_READ_FIELDS = Fields.parse(\"ietf-l2-topology:l2-termination-point-attributes/nsp-ietf-network-topology:nsp-attributes\");\n public static final Fields IETF_TP_MEMBERS_READ_FIELDS = Fields.parse(\"ietf-l2-topology:l2-termination-point-attributes/member-link-tp\");\n\n private enum IetfL2EncapType\n {\n ETHERNET(\"ietf-l2-topology:ethernet\"),\n VLAN(\"ietf-l2-topology:vlan\"),\n QINQ(\"ietf-l2-topology:qinq\"),\n PBB(\"ietf-l2-topology:pbb\"),\n TRILL(\"ietf-l2-topology:trill\"),\n VPLS(\"ietf-l2-topology:vpls\"),\n VXLAN(\"ietf-l2-topology:vxlan\");\n\n public final String value;\n private IetfL2EncapType(String value)\n {\n this.value = value;\n }\n }\n\n private enum IetfDuplexMode\n {\n FULL(\"full-duplex\"),\n HALF(\"half-duplex\");\n\n public final String value;\n private IetfDuplexMode(String value)\n {\n this.value = value;\n }\n }\n\n private static final Pattern MAC_ADDRESS_PATTERN = Pattern.compile(\"[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}\");\n private static final Pattern RAW_MAC_ADDRESS_PATTERN = Pattern.compile(\"[0-9a-fA-F]{12}\");\n\n\n @Override\n public void handlePostResyncDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handlePostResyncDeleteLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId);\n }\n\n @Override\n public int readSrcObjectDepth(String aInSrcClassPath)\n {\n if(aInSrcClassPath.equals(NSP_ENDPOINT_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_ENDPOINT_RADIO_CLASS))\n {\n return 3;\n }\n else if(aInSrcClassPath.equals(NSP_SERVICE_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_SERVICE_RADIO_CLASS))\n {\n return 4;\n }\n return 2;\n }\n\n @Override\n public Fields srcFilterFieldsToInclude(String aInSrcClassPath)\n {\n if(aInSrcClassPath.equals(NSP_ENDPOINT_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_ENDPOINT_RADIO_CLASS))\n {\n return NSP_ENDPOINT_READ_FIELDS;\n }\n else if(aInSrcClassPath.equals(NSP_SERVICE_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_SERVICE_RADIO_CLASS))\n {\n return NSP_SERVICE_READ_FIELDS;\n }\n return null;\n }\n\n @Override\n public void handleTrackedDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, String aInIdentifier, Map<String, Object> aInData, YangPluginMdConverterProvider aInYangPlugin) {\n if (handleTrackedDeleteLogger.isDebugEnabled()) {\n handleTrackedDeleteLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInIdentifier:{}, aInData:{}\", aInSrcClass, aInSyncClass, aInIdentifier, aInData);\n }\n\n if(aInSrcClass.getSrcClassPath().equals(NSP_SERVICE_CABLE_CLASS)\n || aInSrcClass.getSrcClassPath().equals(NSP_SERVICE_RADIO_CLASS)) {\n\n IYangDB yangDB = aInYangPlugin.getiMdConverterFw().getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n String linkId = StringUtils.substringBetween(aInIdentifier, \"[id='\", \"'\");\n IYangObject yangObj = new YangObject();\n yangObj.setProperty(\"name\", aInData.get(\"name\"));\n yangObj.setProperty(\"id\", linkId);\n handleTrackedDeleteLogger.debug(\" L2 tracked deletion for link {}\", linkId);\n deleteLink(yangObj, yangDB, qp);\n }\n }\n\n @Override\n public void handleResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInExistingObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleResyncLogger.debug(\"aInSrcIdentifier:{}, aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcObject.getIdentifier(), aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId);\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n //don't sync ports and lags, only care for their updates\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n break;\n }\n handleResyncLogger.debug(\"TP SYNC\");\n if(isValidEndpoint(aInSrcObject, yangDB)) {\n handleTP(aInSrcObject, yangDB, qp, null);\n }\n break;\n }\n case IETF_LINK_CLASS: {\n handleResyncLogger.debug(\"LINK SYNC\");\n handleLink(aInSrcObject, false, false, yangDB, qp);\n break;\n }\n }\n }\n\n @Override\n public void handleCreateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectCreation aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleCreateEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId:{}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n IYangObject lSrcObject = aInEvent.getEntity();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n // need to listen for create port/lag as link can be created first in the managing scenario\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS)){\n //wait for port-details\n break;\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS)){\n handleCreateEventLogger.debug(\"PORT DETAILS CREATE\");\n String portPath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/port-details\"));\n lSrcObject = yangDB.getSingle(portPath, getFilteredQueryParameters(NSP_PORT_READ_FIELDS_FOR_TP) );\n handlePortLag(lSrcObject, EndpointType.physicalPort, yangDB, qp);\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n handleCreateEventLogger.debug(\"LAG CREATE\");\n handlePortLag(lSrcObject, EndpointType.lag, yangDB, qp);\n }\n else {\n handleCreateEventLogger.debug(\"TP CREATE\");\n if(isValidEndpoint(lSrcObject, yangDB)) {\n handleTP(lSrcObject, yangDB, qp, null);\n\n //create link on TP event - on target endpoint event only\n if (lSrcObject.get(\"type\").toString().equals(\"physical-port\")) {\n List<?> nspEpSources = (List<?>) ((YangObject) lSrcObject).getExtraDatas().get(\"sources\");\n for (Object epSource : nspEpSources) {\n if (epSource.toString().contains(\"@endpointB\")) {\n String servicePath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/link-endpoint[\"));\n IYangObject lLinkSourceObj = getSingleFromYangDb(\n yangDB, servicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if (lLinkSourceObj != null) {\n handleLink(lLinkSourceObj, false, false, yangDB, qp);\n }\n }\n break;\n }\n }\n }\n }\n break;\n }\n case IETF_LINK_CLASS: {\n handleCreateEventLogger.debug(\"LINK CREATE\");\n //link is created on tp event\n break;\n }\n }\n }\n\n @Override\n public void handleUpdateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectModification aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleUpdateEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId:{}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n IYangObject lSrcObject = aInEvent.getEntity();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS)){\n handleUpdateEventLogger.debug(\"PORT UPDATE\");\n boolean shouldUpdate = false;\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"hw-mac-address\")) {\n shouldUpdate = true;\n break;\n }\n }\n if(shouldUpdate){\n handlePortLag(lSrcObject, EndpointType.physicalPort, yangDB, qp);\n }\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS)){\n handleUpdateEventLogger.debug(\"PORT DETAILS UPDATE\");\n boolean shouldUpdate = false;\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"encap-type\") || change.getName().equals(\"actual-rate\") ||\n change.getName().equals(\"operational-duplex\") || change.getName().equals(\"auto-negotiate\")) {\n shouldUpdate = true;\n break;\n }\n }\n if(shouldUpdate){\n String portPath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/port-details\"));\n lSrcObject = yangDB.getSingle(portPath, getFilteredQueryParameters(NSP_PORT_READ_FIELDS_FOR_TP));\n handlePortLag(lSrcObject, EndpointType.physicalPort, yangDB, qp);\n }\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n handleUpdateEventLogger.debug(\"LAG UPDATE\");\n boolean shouldUpdate = false;\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"encap-type\") || change.getName().equals(\"configured-address\")) {\n shouldUpdate = true;\n break;\n }\n }\n if(shouldUpdate){\n handlePortLag(lSrcObject, EndpointType.lag, yangDB, qp);\n }\n }\n else {\n handleUpdateEventLogger.debug(\"TP UPDATE\");\n boolean isManageTypeChange = false;\n boolean isLagEndpointObjectDetailsChange = false;\n int changesSize = aInEvent.getChanges().size();\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"type\")){\n if(change.getNewValue().toString().equals(EndpointType.physicalPort.getAltName())) {\n isManageTypeChange = true;\n }\n break;\n }\n // looking for objectDetails update - starting 23.4, aInEvent.getChanges() will have \"last-modified-time\" change\n else if(change.getName().equals(\"last-modified-time\")\n && lSrcObject.get(\"type\").toString().equals(\"lag\")\n && changesSize == 1) {\n isLagEndpointObjectDetailsChange = true;\n break;\n }\n }\n if(isManageTypeChange || isLagEndpointObjectDetailsChange) {\n //on managing ne - link is created on link update event\n //but the opposite(already managed) endpoint doesn't get any events - need to handle it to create tp/node\n String servicePath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/link-endpoint[\"));\n IYangObject lLinkSourceObj = getSingleFromYangDb(\n yangDB, servicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if(lLinkSourceObj != null) {\n List<?> endpoints = (List<?>)lLinkSourceObj.get(\"link-endpoint\");\n if (endpoints != null && !endpoints.isEmpty()) {\n if (isManageTypeChange && isValidLinkEndpoints(endpoints)) {\n handleUpdateEventLogger.debug(\"TP MANAGE CHANGE\");\n endpoints.forEach(endpoint -> handleTP((IYangObject) endpoint, yangDB, qp, null));\n }\n else if (isLagEndpointObjectDetailsChange && isValidLagEndpoints(endpoints)\n && isValidLinkType(lLinkSourceObj.get(\"id\").toString(), yangDB)) {\n //handle update for lag tps - needed for add/remove member scenario\n handleUpdateEventLogger.debug(\"TP LAG ENDPOINT CHANGE\");\n endpoints.forEach(endpoint -> handleTP((IYangObject) endpoint, yangDB, qp, null));\n }\n }\n }\n }\n }\n break;\n }\n case IETF_LINK_CLASS: {\n handleUpdateEventLogger.debug(\"LINK UPDATE\");\n boolean isUnManageChange = false;\n boolean ignoreUpdate = false;\n boolean isNameUpdate = false;\n int changesSize = aInEvent.getChanges().size();\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"name\")){\n if(change.getNewValue().toString().contains(\"Unmanaged-Ne\")) {\n handleUpdateEventLogger.debug(\"LINK UN-MANAGE CHANGE\");\n isUnManageChange = true;\n }\n else {\n //update on any other link name change - needed for nfmp managing scenario\n isNameUpdate = true;\n ignoreUpdate = false;\n break;\n }\n }\n else if(change.getName().equals(\"oper-state\") ||\n (change.getName().equals(\"last-modified-time\") && changesSize == 1)){ //todo: other link changes to ignore?\n ignoreUpdate = true;\n }\n }\n if(isUnManageChange) {\n deleteLink(lSrcObject, yangDB, qp);\n }\n else if (!ignoreUpdate) {\n handleLink(lSrcObject, isNameUpdate, false, yangDB, qp);\n }\n break;\n }\n }\n }\n\n @Override\n public void handleReplaceEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectReplacement aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleReplaceEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n }\n\n @Override\n public void handleDeleteEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectDeletion aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleDeleteEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n IYangObject lSrcObject = aInEvent.getEntity();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n //don't delete ports and lags, only care for their updates\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n break;\n }\n handleDeleteEventLogger.debug(\"TP DELETE\");\n //endpoint delete event is not sent for nfmp and lldp links\n //both node/tp are deleted on the link delete event\n break;\n }\n case IETF_LINK_CLASS: {\n handleDeleteEventLogger.debug(\"LINK DELETE\");\n deleteLink(lSrcObject, yangDB, qp);\n break;\n }\n }\n }\n\n private boolean canDeleteNode (String nodeId, IYangDB yangDB) {\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + \"WHERE e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\",\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort.getValue())\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n private boolean canDeleteTp (String nodeId, String tpId, boolean isLagTp, boolean isLagMember, IYangDB yangDB) {\n int endpointType = isLagTp ? EndpointType.lag.getValue() : EndpointType.physicalPort.getValue();\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + (isLagTp ? \"JOIN service.Service_objectDetails sod ON (sod.dbId = svc.dbId AND sod.objectDetails_key = 'linkType') \" : \"\") //linkType is not set on manual lag links\n + (isLagMember ? \"JOIN service.Service_objectDetails sod ON (sod.dbId = svc.dbId AND sod.objectDetails_key = 'isLagMember') \" : \"\")\n + \"WHERE e.id=:endpointId AND e.siteId=:siteId AND e.type=:endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\"\n + (isLagMember ? \" AND sod.objectDetails = 'true'\" : \"\"),\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"endpointId\", tpId)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", endpointType)\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n private boolean canDeleteLink (Object sourceTpPath, Object destTpPath, IYangDB yangDB) {\n if (sourceTpPath != null && destTpPath != null) {\n String sourceTpId = getTpIdFromTpPath(sourceTpPath.toString());\n String sourceNodeId = getNodeIdFromTpPath(sourceTpPath.toString());\n String destTpId = getTpIdFromTpPath(destTpPath.toString());\n String destNodeId = getNodeIdFromTpPath(destTpPath.toString());\n boolean canDelete = runCanDeleteLink(sourceTpId, sourceNodeId, destTpId, destNodeId, false, yangDB);\n if(canDelete) {\n canDelete = runCanDeleteLink(destTpId, destNodeId, sourceTpId, sourceNodeId,true, yangDB);\n }\n return canDelete;\n }\n return true;\n }\n\n private boolean runCanDeleteLink (String sourceTpId, String sourceNodeId, String destTpId, String destNodeId,\n boolean shouldIncludeDirection, IYangDB yangDB) {\n String subquery = String.format(\"SELECT svc FROM %s e JOIN e.service svc \"\n + \"JOIN e.objectDetails eod ON (KEY(eod) = :objectDetailsSource) \"\n + \"WHERE e.id=:endpointIdSource AND e.siteId=:siteIdSource \"\n + \"AND e.type=:endpointType AND svc.layer=:layer \"\n + (shouldIncludeDirection ? \"AND svc.direction=:direction \" : \"\")\n + \"AND svc.type IN :serviceTypes\", NSP_ENDPOINT_TABLE);\n String query = String.format(\"SELECT count(e.dbId) FROM %s e \"\n + \"JOIN e.objectDetails eod ON (KEY(eod) = :objectDetailsTarget) \"\n + \"WHERE e.id=:endpointIdTarget AND e.siteId=:siteIdTarget \"\n + \"AND e.type = :endpointType AND e.service IN (%s)\",\n NSP_ENDPOINT_TABLE, subquery);\n Long count = execute(yangDB.getDb(), tx -> {\n javax.persistence.Query lQuery = tx.getEntityManager().createQuery(query)\n .setParameter(\"objectDetailsSource\", \"isSource\")\n .setParameter(\"endpointIdSource\", sourceTpId)\n .setParameter(\"siteIdSource\", sourceNodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort)\n .setParameter(\"layer\", NSP_L2_LAYER)\n .setParameter(\"serviceTypes\", NSP_L2_SERVICE_TYPES)\n .setParameter(\"objectDetailsTarget\", \"isTarget\")\n .setParameter(\"endpointIdTarget\", destTpId)\n .setParameter(\"siteIdTarget\", destNodeId);\n if(shouldIncludeDirection) {\n lQuery.setParameter(\"direction\", Direction.biDirectional);\n }\n return (Long)lQuery.getSingleResult();\n });\n return count != null && count.intValue() == 0;\n }\n\n private void deleteLink (IYangObject aInSrcObject, IYangDB yangDB, QueryParameters qp) {\n\n String nspServiceId = aInSrcObject.get(\"id\").toString();\n\n // note: objectDetails.linkType won't help with manual link as linkType is not set\n\n List<?> linkList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(String.format(\n \"SELECT linkid FROM %s WHERE nspietfnetworktopologynspattributes = :nspServiceId\",\n IETF_LINK_NSP_ATTR_TABLE))\n .setParameter(\"nspServiceId\", nspServiceId)\n .getResultList());\n if (linkList != null && !linkList.isEmpty()) {\n for(Object link : linkList) {\n String linkId = (String) link;\n String ietfLinkPath = String.format(IETF_L2_LINK_PATH, linkId);\n IYangObject ietfLink = yangDB.getSingle(ietfLinkPath, qp);\n if (ietfLink != null) {\n String lSourceTpPath = null, lDestTpPath = null;\n IYangObject lSourceYangObj = (YangObject) ietfLink.get(\"source\");\n if (lSourceYangObj.get(\"source-tp\") != null) {\n lSourceTpPath = lSourceYangObj.get(\"source-tp\").toString();\n String lSourceNodeId = getNodeIdFromTpPath(lSourceTpPath);\n String lSourceTpId = getTpIdFromTpPath(lSourceTpPath);\n if (canDeleteNode(lSourceNodeId, yangDB) && lSourceYangObj.get(\"source-node\") != null) {\n String lSourceNodePath = lSourceYangObj.get(\"source-node\").toString();\n handleDeleteEventLogger.debug(\"DELETING NODE \" + lSourceNodePath);\n yangDB.delete(lSourceNodePath, qp);\n }\n else if (canDeleteTp(lSourceNodeId, lSourceTpId, false, false, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING TP \" + lSourceTpPath);\n yangDB.delete(lSourceTpPath, qp);\n updateLagTpOnMemberDeleteEvent(lSourceTpPath, yangDB, qp);\n }\n }\n IYangObject lDestYangObj = (YangObject) ietfLink.get(\"destination\");\n if (lDestYangObj.get(\"dest-tp\") != null) {\n lDestTpPath = lDestYangObj.get(\"dest-tp\").toString();\n String lDestNodeId = getNodeIdFromTpPath(lDestTpPath);\n String lDestTpId = getTpIdFromTpPath(lDestTpPath);\n if (canDeleteNode(lDestNodeId, yangDB) && lDestYangObj.get(\"dest-node\") != null) {\n String lDestNodePath = lDestYangObj.get(\"dest-node\").toString();\n handleDeleteEventLogger.debug(\"DELETING NODE \" + lDestNodePath);\n yangDB.delete(lDestNodePath, qp);\n }\n else if (canDeleteTp(lDestNodeId, lDestTpId, false, false, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING TP \" + lDestTpPath);\n yangDB.delete(lDestTpPath, qp);\n updateLagTpOnMemberDeleteEvent(lDestTpPath, yangDB, qp);\n }\n }\n\n if (lSourceTpPath == null || lDestTpPath == null || canDeleteLink(lSourceTpPath, lDestTpPath, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING LINK \" + ietfLinkPath);\n yangDB.delete(ietfLinkPath, qp);\n }\n else {\n //remove nspServiceId from the nsp-attributes list\n IYangObject linkAttributes = (YangObject) ietfLink.get(\"ietf-l2-topology:l2-link-attributes\");\n List<?> linkNspAttrs = (List<?>) linkAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n List<String> lNewNspServiceIdList = new ArrayList<>();\n linkNspAttrs.stream()\n .filter(attr -> !attr.equals(nspServiceId))\n .forEach(attr -> lNewNspServiceIdList.add(attr.toString()));\n linkAttributes.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", lNewNspServiceIdList);\n\n // if the current ietf link name is the same as the deleted link name, then update it\n // the lNewNspServiceIdList should never be empty, if so, canDelete*** logic is wrong...\n if(linkAttributes.get(\"name\").equals(aInSrcObject.get(\"name\")) && !lNewNspServiceIdList.isEmpty()){\n //fetch name/delay of the first remaining nspServiceId in the list\n String lRemainingNspServiceId = lNewNspServiceIdList.get(0);\n String lLinkType = ((List<?>) linkAttributes.get(\"flags\")).get(0).toString().split(\":\")[1];\n String lServicePath = String.format(NSP_SERVICE_PATH, lLinkType, lRemainingNspServiceId);\n IYangObject lService = getSingleFromYangDb(yangDB, lServicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS_REDUCED));\n if(lService != null){\n linkAttributes.setProperty(\"name\", lService.get(\"name\"));\n linkAttributes.setProperty(\"delay\", lService.get(\"latency\"));\n }\n }\n handleDeleteEventLogger.debug(\"UPDATING LINK ATTRIBUTES\" + ietfLinkPath);\n yangDB.update(linkAttributes.getIdentifier(), linkAttributes, qp);\n }\n }\n }\n return; //ietf link is found, return from the method\n }\n\n\n //this could be lag link being deleted - check if lag tp should be deleted/updated\n\n List<?> lagTpList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(String.format(\n \"SELECT nodeid, tpid FROM %s WHERE nspietfnetworktopologynspattributes = :nspServiceId\",\n IETF_TP_NSP_ATTR_TABLE))\n .setParameter(\"nspServiceId\", nspServiceId)\n .getResultList());\n if (lagTpList != null && !lagTpList.isEmpty()) {\n for(Object lagTp : lagTpList){\n Object[] tuple = (Object[]) lagTp;\n String nodeId = tuple[0] != null ? tuple[0].toString() : StringUtils.EMPTY;\n String tpId = tuple[1] != null ? tuple[1].toString() : StringUtils.EMPTY;\n String tpPath = String.format(IETF_L2_TP_PATH, nodeId, tpId);\n if(canDeleteNode(nodeId, yangDB)) {\n String nodePath = String.format(IETF_L2_NODE_PATH, nodeId);\n handleDeleteEventLogger.debug(\"DELETING NODE \" + nodePath);\n yangDB.delete(nodePath, qp);\n }\n else if(canDeleteTp(nodeId, tpId, true, false, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING TP \" + tpPath);\n yangDB.delete(tpPath, qp);\n }\n else {\n //remove nspServiceId from the nsp-attributes list - is this executed ever?\n IYangObject tp = yangDB.getSingle(tpPath, getFilteredQueryParameters(IETF_TP_READ_FIELDS));\n if(tp != null) {\n IYangObject tpAttributes = (IYangObject)tp.get(\"ietf-l2-topology:l2-termination-point-attributes\");\n List<?> tpNspAttrs = (List<?>)tpAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n List<String> nspServiceIdList = new ArrayList<>();\n tpNspAttrs.stream()\n .filter(attr -> !attr.equals(nspServiceId))\n .forEach(attr -> nspServiceIdList.add(attr.toString()));\n tpAttributes.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n handleDeleteEventLogger.debug(\"UPDATING TP ATTRIBUTES \" + tpPath);\n yangDB.update(tpAttributes.getIdentifier(), tpAttributes, qp);\n }\n }\n }\n }\n }\n\n private void updateLagTpOnMemberDeleteEvent (String deletedMemberTpPath, IYangDB yangDB, QueryParameters qp){\n List<?> lagTpList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(String.format(\n \"SELECT nodeid, tpid, count(*) FROM %s WHERE fkparent = (SELECT fkparent FROM %s WHERE memberlinktp = :memberlinktp) GROUP BY nodeid, tpid\",\n IETF_MEMBER_LINK_TP_TABLE, IETF_MEMBER_LINK_TP_TABLE))\n .setParameter(\"memberlinktp\", deletedMemberTpPath)\n .getResultList());\n if (lagTpList != null && !lagTpList.isEmpty()) {\n Object[] tuple = (Object[]) lagTpList.get(0);\n String nodeId = tuple[0] != null ? tuple[0].toString() : StringUtils.EMPTY;\n String tpId = tuple[1] != null ? tuple[1].toString() : StringUtils.EMPTY;\n long count = tuple[2] != null ? ((BigInteger)tuple[2]).longValue() : 0;\n String lagTpPath = String.format(IETF_L2_TP_PATH, nodeId, tpId);\n if(count <= 1 && canDeleteTp(nodeId, tpId, true, false, yangDB))\n {\n //delete this lag tp as last member is deleted\n handleDeleteEventLogger.debug(\"DELETING TP \" + lagTpPath);\n yangDB.delete(lagTpPath, qp);\n }\n else {\n //update this lag tp member-link-tp list\n if(yangDB.exists(lagTpPath, qp)){\n String lagTpAttributesPath = lagTpPath + \"/ietf-l2-topology:l2-termination-point-attributes\";\n IYangObject lagTpAttributesObj = yangDB.getSingle(lagTpAttributesPath, getFilteredQueryParameters(IETF_TP_MEMBERS_READ_FIELDS));\n if(lagTpAttributesObj != null) {\n List<String> newMemberList = new ArrayList<>();\n List<?> lagTpMembers = (List<?>)lagTpAttributesObj.get(\"member-link-tp\");\n lagTpMembers.stream()\n .filter(memberTp -> !memberTp.equals(deletedMemberTpPath))\n .forEach(memberTp -> newMemberList.add(memberTp.toString()));\n lagTpAttributesObj.setProperty(\"member-link-tp\", newMemberList);\n handleDeleteEventLogger.debug(\"UPDATING TP \" + lagTpPath);\n yangDB.update(lagTpAttributesPath, lagTpAttributesObj, qp);\n }\n }\n }\n }\n }\n\n private IYangObject buildNodeConfig(String siteId, IYangDB yangDB) {\n IYangObject lNodeObj = new YangObject();\n lNodeObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lNodeObj.setProperty(\"node-id\", siteId);\n\n //l2-node-attributes\n IYangObject lNodeAttrObj = new YangObject();\n lNodeAttrObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lNodeAttrObj.setProperty(\"node-id\", siteId);\n\n String lNePath = String.format(nokia_nsp_network_management_ELEMENT_PATH, siteId);\n IYangObject lNe = yangDB.getSingle(lNePath, getFilteredQueryParameters(nokia_nsp_network_management_ELEMENT_READ_FIELDS));\n if(lNe != null) {\n if(lNe.get(\"ne-name\") != null){\n lNodeAttrObj.setProperty(\"name\", lNe.get(\"ne-name\"));\n }\n if(lNe.get(\"mac-address\") != null){\n String macAddress = convertMacAddress(lNe.get(\"mac-address\").toString());\n if (macAddress != null) {\n lNodeAttrObj.setProperty(\"management-mac\", macAddress);\n }\n }\n if(lNe.get(\"ip-address\") != null){\n lNodeAttrObj.setProperty(\"management-address\", Collections.singletonList(lNe.get(\"ip-address\")));\n }\n }\n lNodeObj.setProperty(\"ietf-l2-topology:l2-node-attributes\", lNodeAttrObj);\n return lNodeObj;\n }\n\n private void handlePortLag(IYangObject aInSrcObject, EndpointType type, IYangDB yangDB, QueryParameters qp) {\n //rely on equipment.name == endpoint.id, lag.name == endpoint.id\n String lName = aInSrcObject.get(\"name\").toString();\n String lNeId = aInSrcObject.get(\"ne-id\").toString();\n List<?> resultList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createQuery(String.format(\"SELECT svc.id, svc.type FROM %s e JOIN e.service svc \"\n + (type.equals(EndpointType.lag) ? \"JOIN svc.objectDetails sod ON (KEY(sod) = 'linkType') \" : \"\") //linkType is not set on manual lag links\n + \"WHERE e.id=:endpointId AND e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type in :serviceTypes\", NSP_ENDPOINT_TABLE))\n .setParameter(\"endpointId\", lName)\n .setParameter(\"siteId\", lNeId)\n .setParameter(\"endpointType\", type)\n .setParameter(\"layer\", NSP_L2_LAYER)\n .setParameter(\"serviceTypes\", NSP_L2_SERVICE_TYPES)\n .getResultList());\n if (resultList != null && !resultList.isEmpty()) {\n Object[] tuple = (Object[]) resultList.get(0); //get first result, don't care for duplicates\n String lLinkId = tuple[0] != null ? tuple[0].toString() : StringUtils.EMPTY;\n ServiceType lSvcType = tuple[1] instanceof ServiceType ? ((ServiceType) tuple[1]) : ServiceType.unknown;\n String lLinkType = lSvcType.equals(ServiceType.cable) ? \"cable\" : (lSvcType.equals(ServiceType.radioLink) ? \"radio-link\" : StringUtils.EMPTY);\n String lEndpointPath = String.format(NSP_ENDPOINT_PATH, lLinkType, lLinkId, lNeId, lName);\n IYangObject endpoint = getSingleFromYangDb(yangDB, lEndpointPath, getFilteredQueryParameters(NSP_ENDPOINT_READ_FIELDS));\n if(endpoint != null && isValidEndpoint(endpoint, yangDB)) {\n handlePortLagLogger.debug(\"HANDLE PORT/LAG ENDPOINT FOUND: {}\", lEndpointPath);\n handleTP(endpoint, yangDB, qp, aInSrcObject);\n if(endpoint.get(\"type\").toString().equals(\"physical-port\")) {\n String servicePath = endpoint.getIdentifier().substring(0, endpoint.getIdentifier().indexOf(\"/link-endpoint[\"));\n IYangObject lLinkSourceObj = getSingleFromYangDb(\n yangDB, servicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if (lLinkSourceObj != null) {\n handlePortLagLogger.debug(\"HANDLE PORT SERVICE FOUND: {}\", servicePath);\n handleLink(lLinkSourceObj, false, true, yangDB, qp);\n }\n }\n }\n }\n }\n\n private boolean isValidEndpoint(IYangObject aInEndpoint, IYangDB yangDB) {\n String endpointId = aInEndpoint.get(\"endpoint-id\").toString();\n String siteId = getSiteIdForEndpoint(aInEndpoint);\n boolean isLag = aInEndpoint.get(\"type\").toString().equals(\"lag\");\n if(isLag) {\n String nspServiceId = getServiceIdFromEndpointPath(aInEndpoint.getIdentifier());\n return isValidLagEndpoint(aInEndpoint) && isValidLinkType(nspServiceId, yangDB)\n && !canDeleteTp(siteId, endpointId, isLag, false, yangDB);\n }\n return isValidPortEndpoint(aInEndpoint) && !canDeleteTp(siteId, endpointId, isLag, false, yangDB);\n }\n\n private void handleTP(IYangObject aInEndpoint, IYangDB yangDB, QueryParameters qp, IYangObject aInResource) {\n String endpointId = aInEndpoint.get(\"endpoint-id\").toString();\n String siteId = getSiteIdForEndpoint(aInEndpoint);\n String lTpPath = String.format(IETF_L2_TP_PATH, siteId, endpointId);\n boolean isLag = aInEndpoint.get(\"type\").toString().equals(\"lag\");\n String lNodePath = String.format(IETF_L2_NODE_PATH, siteId);\n IYangObject lTpObj = buildTpConfig(aInEndpoint, siteId, endpointId, isLag, yangDB, aInResource);\n if(lTpObj != null) {\n if (!yangDB.exists(lNodePath, qp)) {\n handleNodeLogger.debug(\"CREATING NODE \" + lNodePath);\n IYangObject lNodeObj = buildNodeConfig(siteId, yangDB);\n yangDB.createChild(IETF_L2_NETWORK_PATH, IETF_NODE_TYPE, lNodeObj, qp);\n }\n if (!yangDB.exists(lTpPath, qp)) {\n handleTpLogger.debug(\"CREATING TP \" + lTpPath);\n yangDB.createChild(lNodePath, IETF_TP_TYPE, lTpObj, qp);\n } else {\n handleTpLogger.debug(\"UPDATING TP \" + lTpPath);\n yangDB.update(lTpPath, lTpObj, qp);\n }\n }\n }\n\n private IYangObject buildTpConfig(IYangObject aInEndpoint, String siteId, String endpointId, boolean isLag, IYangDB yangDB, IYangObject resource) {\n IYangObject lTpObj = new YangObject();\n lTpObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lTpObj.setProperty(\"node-id\", siteId);\n lTpObj.setProperty(\"tp-id\", endpointId);\n\n //l2-termination-point-attributes\n IYangObject lTPAttrObj = new YangObject();\n lTPAttrObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lTPAttrObj.setProperty(\"node-id\", siteId);\n lTPAttrObj.setProperty(\"tp-id\", endpointId);\n lTPAttrObj.setProperty(\"lag\", isLag);\n\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n if (resource == null) {\n Object resourcePath = null;\n if(aInEndpoint.get(\"port-bindings\") != null && !((List<?>) aInEndpoint.get(\"port-bindings\")).isEmpty()) {\n resourcePath = ((YangObject) ((List<?>) aInEndpoint.get(\"port-bindings\")).get(0)).get(\"resource\");\n }\n else {\n IYangObject lEndpointObj = getSingleFromYangDb(yangDB, aInEndpoint.getIdentifier(), setFilterOnQueryParameters(qp, NSP_ENDPOINT_READ_FIELDS));\n if(lEndpointObj != null) {\n if(lEndpointObj.get(\"port-bindings\") != null && !((List<?>) lEndpointObj.get(\"port-bindings\")).isEmpty()) {\n resourcePath = ((YangObject) ((List<?>) lEndpointObj.get(\"port-bindings\")).get(0)).get(\"resource\");\n }\n }\n }\n if (resourcePath != null && isValidYangPath(resourcePath.toString())) {\n if(isLag) {\n resource = yangDB.getSingle(resourcePath.toString(), setFilterOnQueryParameters(qp, NSP_LAG_READ_FIELDS));\n }\n else {\n resource = yangDB.getSingle(resourcePath.toString(), setFilterOnQueryParameters(qp, NSP_PORT_READ_FIELDS_FOR_TP));\n }\n }\n }\n if (resource != null) {\n lTPAttrObj.setProperty(\"interface-name\", resource.get(\"name\").toString());\n if (isLag) {\n if(resource.get(\"configured-address\") != null) {\n String macAddress = convertMacAddress(resource.get(\"configured-address\").toString());\n if (macAddress != null) {\n lTPAttrObj.setProperty(\"mac-address\", macAddress);\n }\n }\n if (resource.get(\"encap-type\") != null) {\n String encapType = convertEncapType(resource.get(\"encap-type\").toString());\n if (encapType != null) {\n lTPAttrObj.setProperty(\"encapsulation-type\", encapType);\n }\n }\n if (resource.get(\"lag-index\") != null) {\n lTPAttrObj.setProperty(\"unnumbered-id\", Collections.singletonList(resource.get(\"lag-index\")));\n }\n List<Object> members = new ArrayList<>();\n List<?> resourceMembers = Collections.EMPTY_LIST;\n if(resource.get(\"members\") != null) {\n resourceMembers = (List<?>)resource.get(\"members\");\n }\n else {\n resource = yangDB.getSingle(resource.getIdentifier(), setFilterOnQueryParameters(qp, NSP_LAG_READ_FIELDS_MEMBERS));\n if(resource != null && resource.get(\"members\") != null) {\n resourceMembers = (List<?>) resource.get(\"members\");\n }\n }\n resourceMembers.forEach(member -> {\n String memberPath = ((String) member).substring(0, ((String) member).indexOf(\"/lag-member-details\"));\n IYangObject lMemberObj = yangDB.getSingle(memberPath, setFilterOnQueryParameters(qp, NSP_PORT_READ_FIELDS_FOR_LAG_MEMBER));\n if (lMemberObj != null) {\n //memberPath is the identifier of the port, not link endpoint\n //need to find endpoint because there could be no link on the lag member port, or unmanaged link\n //also look for the link with objectDetails.isLagMember=true\n String memberName = lMemberObj.get(\"name\").toString();\n if(!canDeleteTp(siteId, memberName, false, true, yangDB)) {\n members.add(String.format(IETF_L2_TP_PATH, siteId, memberName));\n }\n }\n });\n if (!members.isEmpty()) {\n lTPAttrObj.setProperty(\"member-link-tp\", members);\n }\n else {\n return null; //don't sync this lag endpoint to ietf\n }\n //set nsp-ietf-network-topology:nsp-attributes\n String nspServiceId = getServiceIdFromEndpointPath(aInEndpoint.getIdentifier());\n List<String> nspServiceIdList = new ArrayList<>();\n String lTpPath = String.format(IETF_L2_TP_PATH, siteId, endpointId);\n if(yangDB.exists(lTpPath)) {\n String tpAttrPath = lTpPath + \"/ietf-l2-topology:l2-termination-point-attributes\";\n IYangObject tpAttributes = yangDB.getSingle(tpAttrPath, setFilterOnQueryParameters(qp, IETF_TP_ATTR_READ_FIELDS));\n if(tpAttributes != null) {\n List<?> existingNspAttr = (List<?>)tpAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n if(!existingNspAttr.contains(nspServiceId)){\n existingNspAttr.forEach(attr -> nspServiceIdList.add(attr.toString()));\n nspServiceIdList.add(nspServiceId);\n lTPAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n }\n }\n }\n else {\n nspServiceIdList.add(nspServiceId);\n lTPAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n }\n } else {\n if(resource.get(\"hw-mac-address\") != null) {\n String macAddress = convertMacAddress(resource.get(\"hw-mac-address\").toString());\n if (macAddress != null) {\n lTPAttrObj.setProperty(\"mac-address\", macAddress);\n }\n }\n IYangObject lPortDetails = null;\n if (resource.get(\"port-details\") != null && !((List<?>) resource.get(\"port-details\")).isEmpty()) {\n lPortDetails = (IYangObject) ((List<?>) resource.get(\"port-details\")).get(0);\n }\n else {\n String portDetailsPath = resource.getIdentifier() + \"/port-details\";\n lPortDetails = yangDB.getSingle(portDetailsPath, setFilterOnQueryParameters(qp, NSP_PORT_DETAILS_READ_FIELDS_FOR_TP));\n }\n if (lPortDetails != null) {\n if (lPortDetails.get(\"encap-type\") != null) {\n String encapType = convertEncapType(lPortDetails.get(\"encap-type\").toString());\n if (encapType != null) {\n lTPAttrObj.setProperty(\"encapsulation-type\", encapType);\n }\n }\n if (lPortDetails.get(\"port-index\") != null) {\n lTPAttrObj.setProperty(\"unnumbered-id\", Collections.singletonList(lPortDetails.get(\"port-index\")));\n }\n }\n }\n }\n else {\n handleTpLogger.debug(\"RESOURCE MISSING FOR TP \" + String.format(IETF_L2_TP_PATH, siteId, endpointId));\n return null; //don't create/update tp, wait for another event\n }\n lTpObj.setProperty(\"ietf-l2-topology:l2-termination-point-attributes\", lTPAttrObj);\n return lTpObj;\n }\n\n private void handleLink(IYangObject aInSrcObject, boolean isNameUpdate, boolean isPortUpdate, IYangDB yangDB, QueryParameters qp) {\n\n String nspServiceId = aInSrcObject.get(\"id\").toString();\n\n List<?> endpoints = (List<?>)aInSrcObject.get(\"link-endpoint\");\n if (endpoints == null || endpoints.isEmpty()) {\n IYangObject lSourceObj = getSingleFromYangDb(\n yangDB, aInSrcObject.getIdentifier(), getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if (lSourceObj != null) {\n endpoints = (List<?>)lSourceObj.get(\"link-endpoint\");\n }\n }\n\n if(endpoints == null || endpoints.size() != 2 || !isValidLinkEndpoints(endpoints)) {\n deleteLink(aInSrcObject, yangDB, qp); //delete if the link is already in ietf\n return; //do not sync this link to ietf\n }\n\n final Map<String,String> linkExtraProps = new HashMap<>(); //will hold source, destination, port-details props\n getLinkExtraFromEndpoints(endpoints, linkExtraProps, yangDB);\n if (linkExtraProps.get(\"srcNodeId\") == null || linkExtraProps.get(\"srcTpId\") == null ||\n linkExtraProps.get(\"destNodeId\") == null || linkExtraProps.get(\"destTpId\") == null) {\n\n handleLinkLogger.warn(\"ENDPOINTS MISCONFIGURED - CANNOT PROCESS LINK ID: \" + nspServiceId);\n return; //cannot proceed without valid endpoints info\n }\n String ietfLinkId = getIetfLinkId(linkExtraProps.get(\"srcNodeId\"), linkExtraProps.get(\"srcTpId\"),\n linkExtraProps.get(\"destNodeId\"), linkExtraProps.get(\"destTpId\"));\n doHandleLink(aInSrcObject, linkExtraProps, nspServiceId, isNameUpdate, isPortUpdate, ietfLinkId,\n linkExtraProps.get(\"srcNode\"), linkExtraProps.get(\"srcTp\"),\n linkExtraProps.get(\"destNode\"), linkExtraProps.get(\"destTp\"), yangDB, qp);\n\n if(aInSrcObject.get(\"direction\").toString().equals(\"bi-directional\"))\n {\n ietfLinkId = getIetfLinkId(linkExtraProps.get(\"destNodeId\"), linkExtraProps.get(\"destTpId\"),\n linkExtraProps.get(\"srcNodeId\"), linkExtraProps.get(\"srcTpId\"));\n doHandleLink(aInSrcObject, linkExtraProps, nspServiceId, isNameUpdate, isPortUpdate, ietfLinkId,\n linkExtraProps.get(\"destNode\"), linkExtraProps.get(\"destTp\"),\n linkExtraProps.get(\"srcNode\"), linkExtraProps.get(\"srcTp\"), yangDB, qp);\n }\n }\n\n private void doHandleLink(IYangObject aInSrcObject, Map<String,String> linkExtraProps, String nspServiceId, boolean isNameUpdate, boolean isPortUpdate,\n String ietfLinkId, String srcNode, String srcTp, String destNode, String destTp, IYangDB yangDB, QueryParameters qp)\n {\n\n IYangObject lLinkObject = new YangObject();\n lLinkObject.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lLinkObject.setProperty(\"link-id\", ietfLinkId);\n\n //source\n IYangObject lSrcObject = new YangObject();\n lSrcObject.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lSrcObject.setProperty(\"link-id\", ietfLinkId);\n lSrcObject.setProperty(\"source-node\", srcNode);\n lSrcObject.setProperty(\"source-tp\", srcTp);\n lLinkObject.setProperty(\"source\", lSrcObject);\n\n //destination\n IYangObject lDestObject = new YangObject();\n lDestObject.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lDestObject.setProperty(\"link-id\", ietfLinkId);\n lDestObject.setProperty(\"dest-node\", destNode);\n lDestObject.setProperty(\"dest-tp\", destTp);\n lLinkObject.setProperty(\"destination\", lDestObject);\n\n //link-attributes\n IYangObject lLinkAttrObj = new YangObject();\n lLinkAttrObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lLinkAttrObj.setProperty(\"link-id\", ietfLinkId);\n if(linkExtraProps.get(\"rate\") != null) {\n lLinkAttrObj.setProperty(\"rate\", Math.round(Float.parseFloat(linkExtraProps.get(\"rate\"))));\n }\n if(linkExtraProps.get(\"duplex\") != null) {\n lLinkAttrObj.setProperty(\"duplex\", linkExtraProps.get(\"duplex\"));\n }\n if(linkExtraProps.get(\"auto-nego\") != null) {\n lLinkAttrObj.setProperty(\"auto-nego\", linkExtraProps.get(\"auto-nego\").equals(\"enabled\"));\n }\n\n String lLinkPath = String.format(IETF_L2_LINK_PATH, ietfLinkId);\n List<String> nspServiceIdList = new ArrayList<>();\n boolean isLinkExists = false;\n if(yangDB.exists(lLinkPath, qp)) {\n isLinkExists = true;\n String linkAttrPath = lLinkPath + \"/ietf-l2-topology:l2-link-attributes\";\n IYangObject linkAttributes = yangDB.getSingle(linkAttrPath, getFilteredQueryParameters(IETF_LINK_ATTR_READ_FIELDS));\n if(linkAttributes != null) {\n List<?> existingNspAttr = (List<?>)linkAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n if(!existingNspAttr.contains(nspServiceId)){\n existingNspAttr.forEach(attr -> nspServiceIdList.add(attr.toString()));\n nspServiceIdList.add(nspServiceId);\n lLinkAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n }\n\n //below logic is needed for nfmp managing scenario when link name is updated multiple times\n //how to decide if ietf link name should be updated??\n //try comparing nspServiceId with the first in the existing list\n if(isNameUpdate && nspServiceId.equals(existingNspAttr.get(0).toString())) {\n lLinkAttrObj.setProperty(\"name\", aInSrcObject.get(\"name\"));\n }\n\n //if name is the same, then update delay\n if(linkAttributes.get(\"name\").equals(aInSrcObject.get(\"name\"))) {\n lLinkAttrObj.setProperty(\"delay\", aInSrcObject.get(\"latency\"));\n }\n }\n }\n else {\n //set name only on create and don't overwrite by duplicates\n lLinkAttrObj.setProperty(\"name\", aInSrcObject.get(\"name\"));\n lLinkAttrObj.setProperty(\"delay\", aInSrcObject.get(\"latency\"));\n nspServiceIdList.add(nspServiceId);\n lLinkAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n lLinkAttrObj.setProperty(\"flags\", Collections.singletonList(\"nsp-ietf-network-topology:\" + getServiceTypeFromPath(aInSrcObject.getIdentifier())));\n }\n lLinkObject.setProperty(\"ietf-l2-topology:l2-link-attributes\", lLinkAttrObj);\n\n if (!isLinkExists) {\n if(!isPortUpdate){\n handleLinkLogger.debug(\"CREATING LINK \" + lLinkPath);\n yangDB.createChild(IETF_L2_NETWORK_PATH, IETF_LINK_TYPE, lLinkObject, qp);\n }\n } else {\n handleLinkLogger.debug(\"UPDATING LINK \" + lLinkPath);\n yangDB.update(lLinkPath, lLinkObject, qp);\n }\n }\n\n private void getLinkExtraFromEndpoints (List<?> endpoints, Map<String,String> linkExtraProps, IYangDB yangDB) {\n endpoints.forEach(endpoint -> {\n String endpointId = ((IYangObject) endpoint).get(\"endpoint-id\").toString();\n String siteId = getSiteIdForEndpoint((IYangObject) endpoint);\n String lNodePath = String.format(IETF_L2_NODE_PATH, siteId);\n String lTpPath = String.format(IETF_L2_TP_PATH, siteId, endpointId);\n List<?> nspSources = (List<?>)((YangObject) endpoint).getExtraDatas().get(\"sources\");\n nspSources.forEach(source -> {\n if (source.toString().contains(\"@endpointA\")) {\n linkExtraProps.put(\"srcNode\", lNodePath);\n linkExtraProps.put(\"srcTp\", lTpPath);\n linkExtraProps.put(\"srcNodeId\", siteId);\n linkExtraProps.put(\"srcTpId\", endpointId);\n }\n else if (source.toString().contains(\"@endpointB\")) {\n linkExtraProps.put(\"destNode\", lNodePath);\n linkExtraProps.put(\"destTp\", lTpPath);\n linkExtraProps.put(\"destNodeId\", siteId);\n linkExtraProps.put(\"destTpId\", endpointId);\n }\n });\n if (((YangObject) endpoint).get(\"port-bindings\") != null && !((List<?>) ((YangObject) endpoint).get(\"port-bindings\")).isEmpty()) {\n Object resource = ((YangObject) ((List<?>) ((YangObject) endpoint).get(\"port-bindings\")).get(0)).get(\"resource\");\n if (resource != null && isValidYangPath(resource.toString())) {\n String portDetailsPath = resource + \"/port-details\";\n IYangObject lPortDetails = yangDB.getSingle(\n portDetailsPath,\n getFilteredQueryParameters(NSP_PORT_DETAILS_READ_FIELDS_FOR_LINK));\n if (lPortDetails != null) {\n if (lPortDetails.get(\"actual-rate\") != null && lPortDetails.get(\"actual-rate-units\") != null) {\n double rate = Double.parseDouble(lPortDetails.get(\"actual-rate\").toString());\n String units = lPortDetails.get(\"actual-rate-units\").toString();\n if(units.equals(\"mbps\")) {\n rate *= 1000;\n }\n else if(!units.equals(\"kbps\")) {\n rate = 0;\n }\n linkExtraProps.put(\"rate\", String.valueOf(rate));\n }\n if (lPortDetails.get(\"operational-duplex\") != null) {\n String duplex = convertDuplex(lPortDetails.get(\"operational-duplex\").toString());\n if (duplex != null) {\n linkExtraProps.put(\"duplex\", lPortDetails.get(\"operational-duplex\").toString());\n }\n }\n if (lPortDetails.get(\"auto-negotiate\") != null) {\n linkExtraProps.put(\"auto-nego\", lPortDetails.get(\"auto-negotiate\").toString());\n }\n }\n }\n }\n else {\n handleLinkLogger.debug(\"LINK PORT-BINDINGS MISSING {}, {}\", endpointId, siteId);\n }\n });\n }\n\n private String getServiceIdFromEndpointPath(String endpointPath) {\n String idKey = \"[id='\";\n return endpointPath.substring(endpointPath.indexOf(idKey) + idKey.length(), endpointPath.indexOf(\"']/link-endpoint\"));\n }\n\n private String getServiceTypeFromPath(String servicePath) {\n return servicePath.substring(\"/nsp-service:services/physical-layer/\".length(), servicePath.indexOf(\"[id=\"));\n }\n\n private String getNodeIdFromTpPath(String tpPath) {\n String nodeIdKey = \"[node-id='\";\n return tpPath.substring(tpPath.indexOf(nodeIdKey) + nodeIdKey.length(), tpPath.indexOf(\"']/ietf\"));\n }\n\n private String getTpIdFromTpPath(String tpPath) {\n String tpIdKey = \"[tp-id='\";\n return tpPath.substring(tpPath.indexOf(tpIdKey) + tpIdKey.length(), tpPath.lastIndexOf(\"']\"));\n }\n\n private String getIetfLinkId (String srcNodeId, String srcTpId, String destNodeId, String destTpId) {\n return srcNodeId + \":\" + srcTpId + \"--\" + destNodeId + \":\" + destTpId;\n }\n\n //this is a way to filter out manual lag links\n //check if objectDetails.linkType is set - manually created links don't have linkType entry\n private boolean isValidLinkType (String nspServiceId, IYangDB yangDB) {\n String query = String.format(\"SELECT count(s.dbId) FROM %s s JOIN s.objectDetails sod ON (KEY(sod) = :sodKey) \"\n + \"WHERE s.id = :nspServiceId\", NSP_SERVICE_TABLE);\n Long count = execute(yangDB.getDb(), tx -> (Long)tx.getEntityManager()\n .createQuery(query)\n .setParameter(\"sodKey\", \"linkType\")\n .setParameter(\"nspServiceId\", nspServiceId)\n .getSingleResult());\n return !(count != null && count.intValue() == 0);\n }\n\n //Filtering out links terminating on NE, Lag, Bundle, GNI, unmanaged\n private boolean isValidLinkEndpoints (List<?> endpoints) {\n boolean isValidEndpoint = true;\n for(Object endpoint : endpoints) {\n isValidEndpoint &= isValidPortEndpoint((IYangObject)endpoint);\n }\n return isValidEndpoint;\n }\n\n private boolean isValidLagEndpoints (List<?> endpoints) {\n boolean isValidEndpoint = true;\n for(Object endpoint : endpoints) {\n isValidEndpoint &= isValidLagEndpoint((IYangObject)endpoint);\n }\n return isValidEndpoint;\n }\n\n private boolean isValidPortEndpoint (IYangObject aInEndpointObject) {\n return isValidId(aInEndpointObject.get(\"endpoint-id\").toString())\n && isValidSiteId(getSiteIdForEndpoint(aInEndpointObject))\n && (aInEndpointObject.get(\"type\").toString().equals(\"physical-port\"));\n }\n\n private boolean isValidLagEndpoint (IYangObject aInEndpointObject) {\n return isValidId(aInEndpointObject.get(\"endpoint-id\").toString())\n && isValidSiteId(getSiteIdForEndpoint(aInEndpointObject))\n && aInEndpointObject.get(\"type\").toString().equals(\"lag\");\n }\n\n private String getSiteIdForEndpoint (IYangObject aInEndpointObject) {\n return aInEndpointObject.get(\"site-id\") != null\n ? aInEndpointObject.get(\"site-id\").toString() : \"0.0.0.0\";\n }\n\n private boolean isValidSiteId (String siteId) {\n return isValidId(siteId) && !(\"0.0.0.0\").equals(siteId);\n }\n\n private boolean isValidId (String id) {\n return (null != id) && (0 != id.length());\n }\n\n private boolean isValidYangPath (String path) {\n return path.startsWith(\"/nsp-equipment:\")\n || path.startsWith(\"/nsp-service:\")\n || path.startsWith(\"/ietf-network:\");\n }\n\n //todo: map encap-type?? ietf-l2-topology encap-types: ethernet, vlan, qinq, pbb, trill, vpls, vxlan\n private String convertEncapType (String encapType) {\n switch (encapType) {\n case \"qinq\":\n return IetfL2EncapType.QINQ.value;\n case \"dot1q\":\n return IetfL2EncapType.VLAN.value;//?\n case \"null-encap\":\n return IetfL2EncapType.ETHERNET.value;//?\n default:\n return null;\n }\n }\n\n private String convertDuplex (String duplex) {\n switch (duplex) {\n case \"full-duplex\":\n return IetfDuplexMode.FULL.value;\n case \"half-duplex\":\n return IetfDuplexMode.HALF.value;\n default:\n return null;\n }\n }\n\n private String convertMacAddress (String aInMacAddress) {\n String macAddress = aInMacAddress.replace(\"-\", \":\").replace(\".\", \"\");\n if (MAC_ADDRESS_PATTERN.matcher(macAddress).matches()) {\n return macAddress;\n }\n if (RAW_MAC_ADDRESS_PATTERN.matcher(macAddress).matches()) {\n StringBuilder macAddressSB = new StringBuilder(macAddress);\n macAddressSB.insert(10, ':')\n .insert(8, ':')\n .insert(6, ':')\n .insert(4, ':')\n .insert(2, ':');\n return macAddressSB.toString();\n }\n return null;\n }\n\n private QueryParameters getFilteredQueryParameters (Fields fields) {\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n return setFilterOnQueryParameters(qp, fields);\n }\n\n private QueryParameters setFilterOnQueryParameters (QueryParameters qp, Fields fields) {\n qp.setFields(fields);\n return qp;\n }\n\n private IYangObject getSingleFromYangDb(IYangDB yangDB, String path, QueryParameters qp) {\n List<IYangObject> list = yangDB.getMany(path, qp);\n if(list != null && !list.isEmpty()){\n return list.get(0);\n }\n return null;\n }\n\n private <T> T execute(IDB db, Function<ITransactionContext, T> fn) {\n try {\n if (Transactor.isInTransaction()) {\n return fn.apply(Transactor.getContext());\n } else {\n return Transactor.execute(db, fn, true);\n }\n } catch (DBRuntimeException e) {\n dataBaseAccessLogger.error(\"DB ACCESS ERROR: \", e);\n return null;\n }\n }\n\n}\n"
49
+ }
50
+ ]
51
+ }
52
+ ],
53
+ "sync-classes": [
54
+ {
55
+ "@": {
56
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes",
57
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network']",
58
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
59
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
60
+ },
61
+ "dest-class-path": "ietf-network:/networks/network",
62
+ "version": "1.0",
63
+ "is-root-class": true,
64
+ "dest-ne-id-field-name": "",
65
+ "dest-ne-id-field-step": "",
66
+ "support-creation": true,
67
+ "support-deletion": true,
68
+ "delete-object-filter-ref": "com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter",
69
+ "support-create-on-modify-event": false,
70
+ "default-instances": [
71
+ "{\"network-id\": \"SAPTopology\",\"network-types\": {\"ietf-sap-ntw:sap-network\": {\"service-type\": [\"ietf-vpn-common:vpws\",\"ietf-vpn-common:vpls\",\"ietf-vpn-common:l3vpn\"]}}}",
72
+ "{\"network-id\": \"L2Topology\",\"network-types\": {\"ietf-l2-topology:l2-topology\": {}},\"ietf-l2-topology:l2-topology-attributes\": {\"name\": \"L2Topology\"}}"
73
+ ],
74
+ "src-classes": [
75
+ {
76
+ "@": {
77
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
78
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain']",
79
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
80
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
81
+ },
82
+ "src-class-path": "nsp-service:/services/igp-layer/admin-domain",
83
+ "is-global": true,
84
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
85
+ "tracking-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
86
+ "is-resync": true,
87
+ "support-deletion": true,
88
+ "tracking-fields": [],
89
+ "full-resync-search-by-fields": [
90
+ {
91
+ "@": {
92
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
93
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain']/full-resync-search-by-fields[step='network']",
94
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
95
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
96
+ },
97
+ "step": "network",
98
+ "expression": "network-id!='L2Topology' and network-id!='SAPTopology'",
99
+ "expression-converter-ref": ""
100
+ }
101
+ ]
102
+ },
103
+ {
104
+ "@": {
105
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
106
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network']/src-classes[src-class-path='ietf-network:/networks/network']",
107
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
108
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
109
+ },
110
+ "src-class-path": "ietf-network:/networks/network",
111
+ "is-global": true,
112
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
113
+ "is-resync": false,
114
+ "support-deletion": false,
115
+ "tracking-fields": []
116
+ }
117
+ ]
118
+ },
119
+ {
120
+ "@": {
121
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes",
122
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']",
123
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
124
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
125
+ },
126
+ "dest-class-path": "ietf-network:/networks/network/node",
127
+ "version": "1.0",
128
+ "is-root-class": true,
129
+ "dest-ne-id-field-name": "node-id",
130
+ "dest-ne-id-field-step": "",
131
+ "depends-on": "ietf-network:/networks/network",
132
+ "support-creation": true,
133
+ "support-deletion": true,
134
+ "delete-object-filter-ref": "com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter",
135
+ "support-create-on-modify-event": false,
136
+ "default-instances": [],
137
+ "src-classes": [
138
+ {
139
+ "@": {
140
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
141
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-equipment:/network/network-element']",
142
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
143
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
144
+ },
145
+ "src-class-path": "nsp-equipment:/network/network-element",
146
+ "is-global": false,
147
+ "ne-id-field-name": "ne-id",
148
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.IetfNodeHandlerForNSPNetworkElement",
149
+ "is-resync": true,
150
+ "support-deletion": true,
151
+ "tracking-fields": [],
152
+ "full-resync-search-by-fields": [
153
+ {
154
+ "@": {
155
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
156
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-equipment:/network/network-element']/full-resync-search-by-fields[step='network']",
157
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
158
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
159
+ },
160
+ "step": "network",
161
+ "expression": "network-id='L2Topology' or network-id='SAPTopology'",
162
+ "expression-converter-ref": ""
163
+ }
164
+ ]
165
+ },
166
+ {
167
+ "@": {
168
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
169
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain/routing-instance']",
170
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
171
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
172
+ },
173
+ "src-class-path": "nsp-service:/services/igp-layer/admin-domain/routing-instance",
174
+ "is-global": true,
175
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
176
+ "is-resync": true,
177
+ "support-deletion": true,
178
+ "tracking-fields": [],
179
+ "full-resync-search-by-fields": [
180
+ {
181
+ "@": {
182
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
183
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain/routing-instance']/full-resync-search-by-fields[step='node']",
184
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
185
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
186
+ },
187
+ "step": "node",
188
+ "expression": "boolean(ietf-l3-unicast-topology:l3-node-attributes[equalsIgnoreCase(flag,'nsp-ietf-network-topology:routing-instance')])",
189
+ "expression-converter-ref": ""
190
+ }
191
+ ]
192
+ },
193
+ {
194
+ "@": {
195
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
196
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain/subnet']",
197
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
198
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
199
+ },
200
+ "src-class-path": "nsp-service:/services/igp-layer/admin-domain/subnet",
201
+ "is-global": true,
202
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
203
+ "tracking-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
204
+ "is-resync": true,
205
+ "support-deletion": true,
206
+ "tracking-fields": [
207
+ "node-type",
208
+ "protocol",
209
+ "id",
210
+ "dr-ip-address"
211
+ ],
212
+ "full-resync-search-by-fields": [
213
+ {
214
+ "@": {
215
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
216
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain/subnet']/full-resync-search-by-fields[step='node']",
217
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
218
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
219
+ },
220
+ "step": "node",
221
+ "expression": "boolean(ietf-l3-unicast-topology:l3-node-attributes[equalsIgnoreCase(flag,'nsp-ietf-network-topology:subnet')])",
222
+ "expression-converter-ref": ""
223
+ }
224
+ ]
225
+ },
226
+ {
227
+ "@": {
228
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
229
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='nsp-service:/services/igp-layer/admin-domain/routing-instance/prefix']",
230
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
231
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
232
+ },
233
+ "src-class-path": "nsp-service:/services/igp-layer/admin-domain/routing-instance/prefix",
234
+ "is-global": true,
235
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
236
+ "tracking-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
237
+ "is-resync": false,
238
+ "support-deletion": true,
239
+ "tracking-fields": []
240
+ },
241
+ {
242
+ "@": {
243
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
244
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node']/src-classes[src-class-path='ietf-network:/networks/network/node']",
245
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
246
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
247
+ },
248
+ "src-class-path": "ietf-network:/networks/network/node",
249
+ "is-global": true,
250
+ "ne-id-field-name": "node-id",
251
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
252
+ "is-resync": false,
253
+ "support-deletion": false,
254
+ "tracking-fields": []
255
+ }
256
+ ]
257
+ },
258
+ {
259
+ "@": {
260
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes",
261
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']",
262
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
263
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
264
+ },
265
+ "dest-class-path": "ietf-network:/networks/network/ietf-network-topology:link",
266
+ "version": "1.0",
267
+ "is-root-class": true,
268
+ "dest-ne-id-field-name": "",
269
+ "dest-ne-id-field-step": "",
270
+ "depends-on": "ietf-network:/networks/network/node",
271
+ "support-creation": true,
272
+ "support-deletion": true,
273
+ "delete-object-filter-ref": "com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter",
274
+ "support-create-on-modify-event": false,
275
+ "default-instances": [],
276
+ "src-classes": [
277
+ {
278
+ "@": {
279
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
280
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='nsp-service:/services/physical-layer/cable']",
281
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
282
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
283
+ },
284
+ "src-class-path": "nsp-service:/services/physical-layer/cable",
285
+ "is-global": true,
286
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
287
+ "tracking-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
288
+ "is-resync": true,
289
+ "support-deletion": true,
290
+ "tracking-fields": [
291
+ "name"
292
+ ],
293
+ "full-resync-search-by-fields": [
294
+ {
295
+ "@": {
296
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
297
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='nsp-service:/services/physical-layer/cable']/full-resync-search-by-fields[step='ietf-network-topology:link']",
298
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
299
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
300
+ },
301
+ "step": "ietf-network-topology:link",
302
+ "expression": "boolean(ietf-l2-topology:l2-link-attributes[equalsIgnoreCase(flags,'nsp-ietf-network-topology:cable')])",
303
+ "expression-converter-ref": ""
304
+ }
305
+ ]
306
+ },
307
+ {
308
+ "@": {
309
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
310
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='nsp-service:/services/physical-layer/radio-link']",
311
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
312
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
313
+ },
314
+ "src-class-path": "nsp-service:/services/physical-layer/radio-link",
315
+ "is-global": true,
316
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
317
+ "tracking-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
318
+ "is-resync": true,
319
+ "support-deletion": true,
320
+ "tracking-fields": [
321
+ "name"
322
+ ],
323
+ "full-resync-search-by-fields": [
324
+ {
325
+ "@": {
326
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
327
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='nsp-service:/services/physical-layer/radio-link']/full-resync-search-by-fields[step='ietf-network-topology:link']",
328
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
329
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
330
+ },
331
+ "step": "ietf-network-topology:link",
332
+ "expression": "boolean(ietf-l2-topology:l2-link-attributes[equalsIgnoreCase(flags,'nsp-ietf-network-topology:radio-link')])",
333
+ "expression-converter-ref": ""
334
+ }
335
+ ]
336
+ },
337
+ {
338
+ "@": {
339
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
340
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='nsp-service:/services/igp-layer/ip-links']",
341
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
342
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
343
+ },
344
+ "src-class-path": "nsp-service:/services/igp-layer/ip-links",
345
+ "is-global": true,
346
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
347
+ "tracking-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
348
+ "is-resync": true,
349
+ "support-deletion": true,
350
+ "tracking-fields": [],
351
+ "full-resync-search-by-fields": [
352
+ {
353
+ "@": {
354
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
355
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='nsp-service:/services/igp-layer/ip-links']/full-resync-search-by-fields[step='ietf-network-topology:link']",
356
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
357
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
358
+ },
359
+ "step": "ietf-network-topology:link",
360
+ "expression": "boolean(ietf-l3-unicast-topology:l3-link-attributes[equalsIgnoreCase(flag,'nsp-ietf-network-topology:igp')])",
361
+ "expression-converter-ref": ""
362
+ }
363
+ ]
364
+ },
365
+ {
366
+ "@": {
367
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
368
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/ietf-network-topology:link']/src-classes[src-class-path='ietf-network:/networks/network/ietf-network-topology:link']",
369
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
370
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
371
+ },
372
+ "src-class-path": "ietf-network:/networks/network/ietf-network-topology:link",
373
+ "is-global": true,
374
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
375
+ "is-resync": false,
376
+ "support-deletion": false,
377
+ "tracking-fields": []
378
+ }
379
+ ]
380
+ },
381
+ {
382
+ "@": {
383
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes",
384
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']",
385
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
386
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
387
+ },
388
+ "dest-class-path": "ietf-network:/networks/network/node/ietf-network-topology:termination-point",
389
+ "version": "1.0",
390
+ "is-root-class": true,
391
+ "dest-ne-id-field-name": "node-id",
392
+ "dest-ne-id-field-step": "ietf-network:node",
393
+ "depends-on": "ietf-network:/networks/network/node",
394
+ "support-creation": true,
395
+ "support-deletion": true,
396
+ "delete-object-filter-ref": "com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter",
397
+ "support-create-on-modify-event": false,
398
+ "default-instances": [],
399
+ "src-classes": [
400
+ {
401
+ "@": {
402
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
403
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']/src-classes[src-class-path='nsp-service:/services/physical-layer/cable/link-endpoint']",
404
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
405
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
406
+ },
407
+ "src-class-path": "nsp-service:/services/physical-layer/cable/link-endpoint",
408
+ "is-global": false,
409
+ "ne-id-field-name": "site-id",
410
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
411
+ "is-resync": true,
412
+ "support-deletion": true,
413
+ "tracking-fields": []
414
+ },
415
+ {
416
+ "@": {
417
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
418
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']/src-classes[src-class-path='nsp-service:/services/physical-layer/radio-link/link-endpoint']",
419
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
420
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
421
+ },
422
+ "src-class-path": "nsp-service:/services/physical-layer/radio-link/link-endpoint",
423
+ "is-global": false,
424
+ "ne-id-field-name": "site-id",
425
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
426
+ "is-resync": true,
427
+ "support-deletion": true,
428
+ "tracking-fields": []
429
+ },
430
+ {
431
+ "@": {
432
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
433
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port']",
434
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
435
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
436
+ },
437
+ "src-class-path": "nsp-equipment:/network/network-element/hardware-component/port",
438
+ "is-global": false,
439
+ "ne-id-field-name": "ne-id",
440
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
441
+ "is-resync": false,
442
+ "support-deletion": true,
443
+ "tracking-fields": []
444
+ },
445
+ {
446
+ "@": {
447
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
448
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port/port-details']",
449
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
450
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
451
+ },
452
+ "src-class-path": "nsp-equipment:/network/network-element/hardware-component/port/port-details",
453
+ "is-global": false,
454
+ "ne-id-from-identifier-parser-ref": "port-details.neId.parser",
455
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
456
+ "is-resync": false,
457
+ "support-deletion": true,
458
+ "tracking-fields": []
459
+ },
460
+ {
461
+ "@": {
462
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
463
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']/src-classes[src-class-path='nsp-equipment:/network/network-element/lag']",
464
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
465
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
466
+ },
467
+ "src-class-path": "nsp-equipment:/network/network-element/lag",
468
+ "is-global": false,
469
+ "ne-id-field-name": "ne-id",
470
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
471
+ "is-resync": false,
472
+ "support-deletion": true,
473
+ "tracking-fields": []
474
+ },
475
+ {
476
+ "@": {
477
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
478
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']/src-classes[src-class-path='ietf-network:/networks/network/node/ietf-network-topology:termination-point']",
479
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
480
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
481
+ },
482
+ "src-class-path": "ietf-network:/networks/network/node/ietf-network-topology:termination-point",
483
+ "is-global": false,
484
+ "ne-id-field-name": "node-id",
485
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
486
+ "is-resync": false,
487
+ "support-deletion": false,
488
+ "tracking-fields": []
489
+ }
490
+ ]
491
+ },
492
+ {
493
+ "@": {
494
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes",
495
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']",
496
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
497
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
498
+ },
499
+ "dest-class-path": "ietf-network:/networks/network/node/ietf-sap-ntw:service/sap",
500
+ "version": "2311.0.3",
501
+ "is-root-class": true,
502
+ "dest-ne-id-field-name": "node-id",
503
+ "dest-ne-id-field-step": "ietf-network:node",
504
+ "depends-on": "ietf-network:/networks/network/node",
505
+ "support-creation": true,
506
+ "support-deletion": true,
507
+ "delete-object-filter-ref": "com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter",
508
+ "support-create-on-modify-event": false,
509
+ "default-instances": [],
510
+ "src-classes": [
511
+ {
512
+ "@": {
513
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
514
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port']",
515
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
516
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
517
+ },
518
+ "src-class-path": "nsp-equipment:/network/network-element/hardware-component/port",
519
+ "is-global": false,
520
+ "ne-id-field-name": "ne-id",
521
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
522
+ "is-resync": true,
523
+ "support-deletion": true,
524
+ "tracking-fields": [],
525
+ "full-resync-search-by-fields": [
526
+ {
527
+ "@": {
528
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
529
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port']/full-resync-search-by-fields[step='ietf-sap-ntw:sap']",
530
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
531
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
532
+ },
533
+ "step": "ietf-sap-ntw:sap",
534
+ "expression": "interface-type='ietf-sap-ntw:phy'",
535
+ "expression-converter-ref": ""
536
+ }
537
+ ]
538
+ },
539
+ {
540
+ "@": {
541
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
542
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port/port-details']",
543
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
544
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
545
+ },
546
+ "src-class-path": "nsp-equipment:/network/network-element/hardware-component/port/port-details",
547
+ "is-global": false,
548
+ "ne-id-field-name": "ne-id",
549
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
550
+ "is-resync": false,
551
+ "support-deletion": false,
552
+ "tracking-fields": []
553
+ },
554
+ {
555
+ "@": {
556
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
557
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port/lag-member-details']",
558
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
559
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
560
+ },
561
+ "src-class-path": "nsp-equipment:/network/network-element/hardware-component/port/lag-member-details",
562
+ "is-global": false,
563
+ "ne-id-field-name": "ne-id",
564
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
565
+ "is-resync": false,
566
+ "support-deletion": false,
567
+ "tracking-fields": [],
568
+ "fields": [
569
+ {
570
+ "@": {
571
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/fields",
572
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/hardware-component/port/lag-member-details']/fields[dest-attribute=''][src-attribute='lag-id']",
573
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
574
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
575
+ },
576
+ "dest-attribute": "",
577
+ "src-attribute": "lag-id",
578
+ "is-key": false,
579
+ "is-src-key": false,
580
+ "converter-ref": ""
581
+ }
582
+ ]
583
+ },
584
+ {
585
+ "@": {
586
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
587
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/lag']",
588
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
589
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
590
+ },
591
+ "src-class-path": "nsp-equipment:/network/network-element/lag",
592
+ "is-global": false,
593
+ "ne-id-field-name": "ne-id",
594
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
595
+ "is-resync": true,
596
+ "support-deletion": true,
597
+ "tracking-fields": [],
598
+ "full-resync-search-by-fields": [
599
+ {
600
+ "@": {
601
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
602
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/lag']/full-resync-search-by-fields[step='ietf-sap-ntw:sap']",
603
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
604
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
605
+ },
606
+ "step": "ietf-sap-ntw:sap",
607
+ "expression": "interface-type='ietf-sap-ntw:lag'",
608
+ "expression-converter-ref": ""
609
+ }
610
+ ],
611
+ "fields": [
612
+ {
613
+ "@": {
614
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/fields",
615
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-equipment:/network/network-element/lag']/fields[dest-attribute=''][src-attribute='members']",
616
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
617
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
618
+ },
619
+ "dest-attribute": "",
620
+ "src-attribute": "members",
621
+ "is-key": false,
622
+ "is-src-key": false,
623
+ "converter-ref": ""
624
+ }
625
+ ]
626
+ },
627
+ {
628
+ "@": {
629
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
630
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/eline/endpoint']",
631
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
632
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
633
+ },
634
+ "src-class-path": "nsp-service:/services/service-layer/eline/endpoint",
635
+ "is-global": false,
636
+ "ne-id-field-name": "site-id",
637
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
638
+ "is-resync": true,
639
+ "support-deletion": true,
640
+ "tracking-fields": [],
641
+ "full-resync-search-by-fields": [
642
+ {
643
+ "@": {
644
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
645
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/eline/endpoint']/full-resync-search-by-fields[step='ietf-sap-ntw:sap']",
646
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
647
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
648
+ },
649
+ "step": "ietf-sap-ntw:sap",
650
+ "expression": "interface-type='ietf-sap-ntw:logical'",
651
+ "expression-converter-ref": ""
652
+ },
653
+ {
654
+ "@": {
655
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
656
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/eline/endpoint']/full-resync-search-by-fields[step='ietf-sap-ntw:service']",
657
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
658
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
659
+ },
660
+ "step": "ietf-sap-ntw:service",
661
+ "expression": "service-type='ietf-vpn-common:vpws'",
662
+ "expression-converter-ref": ""
663
+ }
664
+ ]
665
+ },
666
+ {
667
+ "@": {
668
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
669
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/eline/endpoint/ipservice-endpoint-detail']",
670
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
671
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
672
+ },
673
+ "src-class-path": "nsp-service:/services/service-layer/eline/endpoint/ipservice-endpoint-detail",
674
+ "is-global": false,
675
+ "ne-id-from-identifier-parser-ref": "ibsf.ietf.sap.neId.fromEpFdn.converter",
676
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
677
+ "is-resync": false,
678
+ "support-deletion": false,
679
+ "tracking-fields": []
680
+ },
681
+ {
682
+ "@": {
683
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
684
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/elan/endpoint']",
685
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
686
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
687
+ },
688
+ "src-class-path": "nsp-service:/services/service-layer/elan/endpoint",
689
+ "is-global": false,
690
+ "ne-id-field-name": "site-id",
691
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
692
+ "is-resync": true,
693
+ "support-deletion": true,
694
+ "tracking-fields": [],
695
+ "full-resync-search-by-fields": [
696
+ {
697
+ "@": {
698
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
699
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/elan/endpoint']/full-resync-search-by-fields[step='ietf-sap-ntw:sap']",
700
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
701
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
702
+ },
703
+ "step": "ietf-sap-ntw:sap",
704
+ "expression": "interface-type='ietf-sap-ntw:logical'",
705
+ "expression-converter-ref": ""
706
+ },
707
+ {
708
+ "@": {
709
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
710
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/elan/endpoint']/full-resync-search-by-fields[step='ietf-sap-ntw:service']",
711
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
712
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
713
+ },
714
+ "step": "ietf-sap-ntw:service",
715
+ "expression": "service-type='ietf-vpn-common:vpls'",
716
+ "expression-converter-ref": ""
717
+ }
718
+ ]
719
+ },
720
+ {
721
+ "@": {
722
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
723
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/elan/endpoint/ipservice-endpoint-detail']",
724
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
725
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
726
+ },
727
+ "src-class-path": "nsp-service:/services/service-layer/elan/endpoint/ipservice-endpoint-detail",
728
+ "is-global": false,
729
+ "ne-id-from-identifier-parser-ref": "ibsf.ietf.sap.neId.fromEpFdn.converter",
730
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
731
+ "is-resync": false,
732
+ "support-deletion": false,
733
+ "tracking-fields": []
734
+ },
735
+ {
736
+ "@": {
737
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
738
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/l3vpn/endpoint']",
739
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
740
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
741
+ },
742
+ "src-class-path": "nsp-service:/services/service-layer/l3vpn/endpoint",
743
+ "is-global": false,
744
+ "ne-id-field-name": "site-id",
745
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
746
+ "is-resync": true,
747
+ "support-deletion": true,
748
+ "tracking-fields": [],
749
+ "full-resync-search-by-fields": [
750
+ {
751
+ "@": {
752
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
753
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/l3vpn/endpoint']/full-resync-search-by-fields[step='ietf-sap-ntw:sap']",
754
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
755
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
756
+ },
757
+ "step": "ietf-sap-ntw:sap",
758
+ "expression": "interface-type='ietf-sap-ntw:logical'",
759
+ "expression-converter-ref": ""
760
+ },
761
+ {
762
+ "@": {
763
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes/full-resync-search-by-fields",
764
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/l3vpn/endpoint']/full-resync-search-by-fields[step='ietf-sap-ntw:service']",
765
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
766
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
767
+ },
768
+ "step": "ietf-sap-ntw:service",
769
+ "expression": "service-type='ietf-vpn-common:l3vpn'",
770
+ "expression-converter-ref": ""
771
+ }
772
+ ]
773
+ },
774
+ {
775
+ "@": {
776
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes/src-classes",
777
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/sync-classes[dest-class-path='ietf-network:/networks/network/node/ietf-sap-ntw:service/sap']/src-classes[src-class-path='nsp-service:/services/service-layer/l3vpn/endpoint/ipservice-endpoint-detail']",
778
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
779
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
780
+ },
781
+ "src-class-path": "nsp-service:/services/service-layer/l3vpn/endpoint/ipservice-endpoint-detail",
782
+ "is-global": false,
783
+ "ne-id-from-identifier-parser-ref": "ibsf.ietf.sap.neId.fromEpFdn.converter",
784
+ "custom-handler-ref": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
785
+ "is-resync": false,
786
+ "support-deletion": false,
787
+ "tracking-fields": []
788
+ }
789
+ ]
790
+ }
791
+ ],
792
+ "nsp-module-set": [
793
+ {
794
+ "@": {
795
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/nsp-module-set",
796
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/nsp-module-set[name='service']",
797
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
798
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
799
+ },
800
+ "name": "service"
801
+ },
802
+ {
803
+ "@": {
804
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/nsp-module-set",
805
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/nsp-module-set[name='equipment']",
806
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
807
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
808
+ },
809
+ "name": "equipment"
810
+ }
811
+ ],
812
+ "java-script": [
813
+ {
814
+ "@": {
815
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/java-script",
816
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/java-script[script-id='port-details.neId.parser']",
817
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
818
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
819
+ },
820
+ "script-id": "port-details.neId.parser",
821
+ "body": "function convert(aInSrcObj,prop,id){ var neId=id.replace(/.*ne-id\\=\\'/,'').replace(/'.*/,''); /*print(neId);*/ return(neId); } ",
822
+ "version": "1.0.0",
823
+ "java-interface": "com.nokia.nsp.md.converter.yang.plugin.common.IValueConverter"
824
+ },
825
+ {
826
+ "@": {
827
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/java-script",
828
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/java-script[script-id='ibsf.ietf.sap.neId.fromEpFdn.converter']",
829
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
830
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
831
+ },
832
+ "script-id": "ibsf.ietf.sap.neId.fromEpFdn.converter",
833
+ "body": "function convert(aInSrcObj,prop,id){ var neId=id.replace(/.*endpoint-id\\=\\'/,'').replace(/-.*/,''); /*print(neId);*/ return(neId); } ",
834
+ "version": "2304.0.0",
835
+ "java-interface": "com.nokia.nsp.md.converter.yang.plugin.common.IValueConverter"
836
+ }
837
+ ],
838
+ "delete-object-filter": [
839
+ {
840
+ "@": {
841
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/delete-object-filter",
842
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/delete-object-filter[java-class-path='com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter']",
843
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
844
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
845
+ },
846
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter",
847
+ "version": "1.0.1",
848
+ "java-code": [
849
+ {
850
+ "@": {
851
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/delete-object-filter/java-code",
852
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/delete-object-filter[java-class-path='com.nokia.nsp.md.converter.yang.plugin.IetfTopologyDeleteObjectFilter']/java-code[page-number='1']",
853
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
854
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
855
+ },
856
+ "page-number": 1,
857
+ "page": "package com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.IDeleteObjectFilter;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\nimport org.apache.commons.lang.StringUtils;\nimport com.nokia.nspos.model.domain.service.types.EndpointType;\nimport com.nokia.nspos.model.domain.service.types.Layer;\nimport com.nokia.nspos.model.domain.service.types.ServiceType;\nimport com.nokia.nspos.model.domain.service.types.Direction;\nimport com.nokia.nspos.persistence.api.IDB;\nimport com.nokia.nspos.persistence.impl.db.transaction.DBRuntimeException;\nimport com.nokia.nspos.persistence.impl.db.transaction.ITransactionContext;\nimport com.nokia.nspos.persistence.impl.db.transaction.Transactor;\n\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\n\npublic class IetfTopologyDeleteObjectFilter implements IDeleteObjectFilter\n{\n private static final org.slf4j.Logger canDeleteObjectLogger = org.slf4j.LoggerFactory.getLogger(IetfTopologyDeleteObjectFilter.class.getName() + \".canDeleteObject\");\n\n private static final String NSP_NE_CLASS_PATH = \"nsp-equipment:/network/network-element\";\n private static final String NSP_PORT_CLASS_PATH = \"nsp-equipment:/network/network-element/hardware-component/port\";\n private static final String NSP_PORT_DETAILS_CLASS_PATH = \"nsp-equipment:/network/network-element/hardware-component/port/port-details\";\n private static final String NSP_LAG_CLASS_PATH = \"nsp-equipment:/network/network-element/lag\";\n private static final String NSP_ELINE_ENDPOINT_CLASS_PATH = \"nsp-service:/services/service-layer/eline/endpoint\";\n private static final String NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH = \"nsp-service:/services/service-layer/eline/endpoint/ipservice-endpoint-detail\";\n private static final String NSP_ELAN_ENDPOINT_CLASS_PATH = \"nsp-service:/services/service-layer/elan/endpoint\";\n private static final String NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH = \"nsp-service:/services/service-layer/elan/endpoint/ipservice-endpoint-detail\";\n private static final String NSP_L3VPN_ENDPOINT_CLASS_PATH = \"nsp-service:/services/service-layer/l3vpn/endpoint\";\n private static final String NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH = \"nsp-service:/services/service-layer/l3vpn/endpoint/ipservice-endpoint-detail\";\n\n private static final String IETF_VPN_COMMON_VPWS = \"ietf-vpn-common:vpws\";\n private static final String IETF_VPN_COMMON_VPLS = \"ietf-vpn-common:vpls\";\n private static final String IETF_VPN_COMMON_L3VPN = \"ietf-vpn-common:l3vpn\";\n\n private static final String IETF_NETWORK_CLASS_PATH = \"ietf-network:/networks/network\";\n private static final String IETF_NODE_CLASS_PATH = \"ietf-network:/networks/network/node\";\n private static final String IETF_SAP_CLASS_PATH = \"ietf-network:/networks/network/node/ietf-sap-ntw:service/sap\";\n private static final String IETF_TP_CLASS_PATH = \"ietf-network:/networks/network/node/ietf-network-topology:termination-point\";\n private static final String IETF_LINK_CLASS_PATH = \"ietf-network:/networks/network/ietf-network-topology:link\";\n\n private static final String IETF_NODE_ID_PROP = \"node-id\";\n private static final String IETF_INTERFACE_TYPE_PROP = \"interface-type\";\n private static final String IETF_SAP_ID_PROP = \"sap-id\";\n\n private static final String NSP_NE_YANG_PATH = \"/nsp-equipment:network/network-element[ne-id='%s']\";\n\n private static final String NSP_SERVICE_IGP_LAYER_PATH = \"/nsp-service:services/igp-layer\";\n private static final String NSP_SERVICE_ADMIN_DOMAIN_PATH = NSP_SERVICE_IGP_LAYER_PATH + \"/admin-domain[name='%s']\";\n private static final String NSP_SERVICE_ROUTING_INS_PATH = \"/routing-instance[id='%s']\";\n private static final String NSP_SERVICE_SUBNET_PATH = \"/subnet[id='%s']\";\n private static final String NSP_SERVICE_LINK_PATH = NSP_SERVICE_IGP_LAYER_PATH + \"/ip-links[name='%s']\";\n\n private static final String NETWORK_ID = \"network-id\";\n private static final String NODE_ID = \"node-id\";\n private static final String LINK_ID = \"link-id\";\n private static final String NAME = \"name\";\n\n private static String IETF_NETWORKS_PATH = \"/ietf-network:networks/network[network-id='%s']\";\n private static final String NODE_PATH = \"/node[node-id='%s']\";\n private static final String LINK_PATH = \"/ietf-network-topology:link[link-id='%s']\";\n private static final String TP_PATH = \"/ietf-network-topology:termination-point[tp-id='%s']\";\n public static final boolean TE_TOPOLOGY_ENABLED = true;\n\n private List<String> ietfL3SrcClasses = new ArrayList<>(Arrays.asList(\n \"nsp-service:/services/igp-layer/admin-domain\",\n \"nsp-service:/services/igp-layer/admin-domain/routing-instance\",\n \"nsp-service:/services/igp-layer/admin-domain/subnet\",\n \"nsp-service:/services/igp-layer/ip-links\"\n ));\n\n private enum IetfInterfaceType\n {\n PHY(\"ietf-sap-ntw:phy\"),\n LOOPBACK(\"ietf-sap-ntw:loopback\"),\n LAG(\"ietf-sap-ntw:lag\"),\n IRB(\"ietf-sap-ntw:irb\"),\n LOCAL_BRIDGE(\"ietf-sap-ntw:local-bridge\"),\n LOGICAL(\"ietf-sap-ntw:logical\");\n\n public String value;\n private IetfInterfaceType(String value)\n {\n this.value = value;\n }\n }\n\n @Override\n public boolean canDeleteObjectOnUnmanageNe(IYangObject aInIYangObject, SyncClass aInSyncClass, IMdConverterFw aInMdConverterFw)\n {\n String instanceIdentifier = aInIYangObject.getIdentifier();\n\n if(instanceIdentifier.contains(\"network-id='SAPTopology'\") || instanceIdentifier.contains(\"network-id='L2Topology'\"))\n {\n return true;\n }\n else\n {\n // do L3Topology stuff\n return false;\n }\n\n }\n\n @Override\n public boolean canDeleteObject(IYangObject aInIYangObject, SyncClass aInSyncClass, SrcClass aInSrcClass, IMdConverterFw aInMdConverterFw)\n {\n canDeleteObjectLogger.debug(\"********** canDeleteObject - aInSrcClass:{}, aInSyncClass:{}, aInIYangObject:{}\", aInSrcClass, aInSyncClass, aInIYangObject);\n\n String instanceIdentifier = aInIYangObject.getIdentifier();\n\n if(instanceIdentifier.contains(\"network-id='SAPTopology'\"))\n {\n return canDeleteSAPTopologyObject(aInIYangObject, aInSyncClass, aInSrcClass, aInMdConverterFw);\n }\n else if(instanceIdentifier.contains(\"network-id='L2Topology'\"))\n {\n return canDeleteL2TopologyObject(aInIYangObject, aInSyncClass, aInSrcClass, aInMdConverterFw);\n }\n else\n {\n // do L3 & TE Topology stuff\n return canDeleteL3TopologyObject(aInIYangObject, aInSyncClass, aInSrcClass, aInMdConverterFw);\n }\n\n }\n\n private boolean canDeleteSAPTopologyObject(IYangObject aInIYangObject, SyncClass aInSyncClass, SrcClass aInSrcClass, IMdConverterFw aInMdConverterFw)\n {\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n String lDestClassPath = aInSyncClass.getDestClassPath();\n String lSrcClassPath = aInSrcClass.getSrcClassPath();\n\n if (NSP_PORT_DETAILS_CLASS_PATH.equals(lSrcClassPath) ||\n NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(lSrcClassPath) ||\n NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(lSrcClassPath) ||\n NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(lSrcClassPath))\n {\n // Code should not reach here. FW should not call this.\n canDeleteObjectLogger.debug(\"<><><><><><><><><><> Code should not reach here. canDeleteObject called for srcClassPath: {}\", lSrcClassPath);\n return false;\n }\n\n if(IETF_NETWORK_CLASS_PATH.equals(lDestClassPath))\n {\n return false; // We don't delete the IETF SAP topology network root object ever\n }\n else if(IETF_NODE_CLASS_PATH.equals(lDestClassPath))\n {\n String neId = aInIYangObject.getProperty(IETF_NODE_ID_PROP);\n\n if (!yangDB.exists(String.format(NSP_NE_YANG_PATH, neId)))\n {\n return true; // if NSP no longer has this NE, delete it from IETF SAP topology\n }\n }\n else if(IETF_SAP_CLASS_PATH.equals(lDestClassPath))\n {\n //String neId = StringUtils.substringBetween(aInIYangObject.getIdentifier(), \"[node-id='\", \"']\");\n String serviceType = StringUtils.substringBetween(aInIYangObject.getIdentifier(), \"[service-type='\", \"']\");\n\n String sapInterfaceType = aInIYangObject.getProperty(IETF_INTERFACE_TYPE_PROP);\n String sapId = aInIYangObject.getProperty(IETF_SAP_ID_PROP);\n\n /*\n The following complicated if-else conditions are required to prevent querying the DB using yangDB.exists() unnecessarily\n since this code will be hit for EVERY combination of lDestClassPath (all IETF SAPs) and lSrcClassPath (every port/LAG/SvcEndpoints).\n See IetfSapTopology.json mapping file entry for \"destClassPath\": \"ietf-network:/networks/network/node/ietf-sap-ntw:service/sap\"\n For examples,\n lDestClassPath could be that of a SAP that corresponds to a LAG and lSrcClassPath could be that of a port\n lDestClassPath could be that of a SAP that corresponds to an ELINE endpoint and lSrcClassPath could be that of a L3VPN endpoint\n */\n\n if (IetfInterfaceType.PHY.value.equals(sapInterfaceType) && NSP_PORT_CLASS_PATH.equals(lSrcClassPath))\n {\n //if(!yangDB.exists(String.format(NSP_PORT_YANG_PATH, neId, aInIYangObject.getProperty(IETF_SAP_ID_PROP))))\n if(!yangDB.exists(sapId))\n {\n return true; // delete this SAP if NSP no longer has this port\n }\n }\n else if (IetfInterfaceType.LAG.value.equals(sapInterfaceType) && NSP_LAG_CLASS_PATH.equals(lSrcClassPath))\n {\n //if(!yangDB.exists(String.format(NSP_LAG_YANG_PATH, neId, aInIYangObject.getProperty(IETF_SAP_ID_PROP))))\n if(!yangDB.exists(sapId))\n {\n return true; // delete this SAP if NSP no longer has this LAG\n }\n }\n else if (IetfInterfaceType.LOGICAL.value.equals(sapInterfaceType))\n {\n if(\n (IETF_VPN_COMMON_VPWS.equals(serviceType) && NSP_ELINE_ENDPOINT_CLASS_PATH.equals(lSrcClassPath)) ||\n (IETF_VPN_COMMON_VPLS.equals(serviceType) && NSP_ELAN_ENDPOINT_CLASS_PATH.equals(lSrcClassPath)) ||\n (IETF_VPN_COMMON_L3VPN.equals(serviceType) && NSP_L3VPN_ENDPOINT_CLASS_PATH.equals(lSrcClassPath))\n )\n {\n if(!yangDB.exists(sapId))\n {\n return true; // delete this SAP if NSP no longer has this ELINE/ELAN/L3VPN endpoint\n }\n }\n }\n }\n\n return false;\n }\n\n\n private boolean canDeleteL2TopologyObject (IYangObject aInIYangObject, SyncClass aInSyncClass, SrcClass aInSrcClass, IMdConverterFw aInMdConverterFw) {\n\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n String srcClassPath = aInSrcClass.getSrcClassPath();\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_NETWORK_CLASS_PATH: {\n return false;\n }\n case IETF_NODE_CLASS_PATH: {\n return canDeleteL2Node(aInIYangObject.get(\"node-id\").toString(), yangDB);\n }\n case IETF_TP_CLASS_PATH: {\n if (srcClassPath.equals(NSP_PORT_DETAILS_CLASS_PATH) ||\n srcClassPath.equals(NSP_PORT_CLASS_PATH) ||\n srcClassPath.equals(NSP_LAG_CLASS_PATH)) {\n return false;\n }\n return canDeleteL2Tp(\n aInIYangObject.getIdentifier(),\n (boolean)((YangObject) aInIYangObject.get(\"ietf-l2-topology:l2-termination-point-attributes\")).get(\"lag\"),\n yangDB);\n }\n case IETF_LINK_CLASS_PATH: {\n return canDeleteL2Link(((YangObject) aInIYangObject.get(\"source\")).get(\"source-tp\"),\n ((YangObject) aInIYangObject.get(\"destination\")).get(\"dest-tp\"), yangDB);\n }\n default:\n return false;\n }\n }\n\n /*\n L2 node cannot be deleted if node-id correspond to one of two nsp endpoints of the same service that both are:\n - of layer \"physical\"\n - of service type \"cable\" or \"radio-link\"\n - of endpoint type \"physicalPort\"\n (valid \"lag\" tp cannot exist with empty member-link-tp list, therefore, no need to look for \"lag\" endpoint type)\n */\n private boolean canDeleteL2Node (String nodeId, IYangDB yangDB) {\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + \"WHERE e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\",\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort.getValue())\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n /*\n L2 tp cannot be deleted if tp-id/node-id correspond to one of two nsp endpoints of the same service that both are:\n - of layer \"physical\"\n - of service type \"cable\" or \"radio-link\"\n - of endpoint type \"physicalPort\" or \"lag\"\n */\n private boolean canDeleteL2Tp (String tpPath, boolean isLagTp, IYangDB yangDB) {\n int endpointType = isLagTp ? EndpointType.lag.getValue() : EndpointType.physicalPort.getValue();\n String nodeId = getNodeIdFromTpPath(tpPath);\n String tpId = getTpIdFromTpPath(tpPath);\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + (isLagTp ? \"JOIN service.Service_objectDetails sod ON (sod.dbId = svc.dbId AND sod.objectDetails_key = 'linkType') \" : \"\") //linkType is not set on manual lag links\n + \"WHERE e.id=:endpointId AND e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\",\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"endpointId\", tpId)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", endpointType)\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n /*\n L2 link cannot be deleted if there exist two nsp endpoints of the same service that both are:\n - of layer \"physical\"\n - of service type \"cable\" or \"radio-link\"\n - of endpoint type \"physicalPort\"\n - source tp-id/node-id correspond to \"isSource\" endpoint (or switch source and dest for bi-directional link)\n - destination tp-id/node-id correspond to \"isTarget\" endpoint\n */\n private boolean canDeleteL2Link (Object sourceTpPath, Object destTpPath, IYangDB yangDB) {\n if (sourceTpPath != null && destTpPath != null) {\n String sourceTpId = getTpIdFromTpPath(sourceTpPath.toString());\n String sourceNodeId = getNodeIdFromTpPath(sourceTpPath.toString());\n String destTpId = getTpIdFromTpPath(destTpPath.toString());\n String destNodeId = getNodeIdFromTpPath(destTpPath.toString());\n boolean canDelete = runCanDeleteLink(sourceTpId, sourceNodeId, destTpId, destNodeId, false, yangDB);\n if(canDelete) {\n canDelete = runCanDeleteLink(destTpId, destNodeId, sourceTpId, sourceNodeId,true, yangDB);\n }\n return canDelete;\n }\n return true;\n }\n\n private boolean runCanDeleteLink (String sourceTpId, String sourceNodeId, String destTpId, String destNodeId,\n boolean shouldIncludeDirection, IYangDB yangDB) {\n String endpointTable = \"service_Endpoint\";\n String subquery = String.format(\"SELECT svc FROM %s e JOIN e.service svc \"\n + \"JOIN e.objectDetails eod ON (KEY(eod) = :objectDetailsSource) \"\n + \"WHERE e.id=:endpointIdSource AND e.siteId=:siteIdSource \"\n + \"AND e.type=:endpointType AND svc.layer=:layer \"\n + (shouldIncludeDirection ? \"AND svc.direction=:direction \" : \"\")\n + \"AND svc.type IN :serviceTypes\", endpointTable);\n String query = String.format(\"SELECT count(e.dbId) FROM %s e \"\n + \"JOIN e.objectDetails eod ON (KEY(eod) = :objectDetailsTarget) \"\n + \"WHERE e.id=:endpointIdTarget AND e.siteId=:siteIdTarget \"\n + \"AND e.type = :endpointType AND e.service IN (%s)\",\n endpointTable, subquery);\n Long count = execute(yangDB.getDb(), tx -> {\n javax.persistence.Query lQuery = tx.getEntityManager().createQuery(query)\n .setParameter(\"objectDetailsSource\", \"isSource\")\n .setParameter(\"endpointIdSource\", sourceTpId)\n .setParameter(\"siteIdSource\", sourceNodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort)\n .setParameter(\"layer\", Layer.physical)\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable, ServiceType.radioLink))\n .setParameter(\"objectDetailsTarget\", \"isTarget\")\n .setParameter(\"endpointIdTarget\", destTpId)\n .setParameter(\"siteIdTarget\", destNodeId);\n if(shouldIncludeDirection) {\n lQuery.setParameter(\"direction\", Direction.biDirectional);\n }\n return (Long)lQuery.getSingleResult();\n });\n return count != null && count.intValue() == 0;\n }\n\n private String getNodeIdFromTpPath(String tpPath) {\n String nodeIdKey = \"[node-id='\";\n return tpPath.substring(tpPath.indexOf(nodeIdKey) + nodeIdKey.length(), tpPath.indexOf(\"']/ietf\"));\n }\n\n private String getTpIdFromTpPath(String tpPath) {\n String tpIdKey = \"[tp-id='\";\n return tpPath.substring(tpPath.indexOf(tpIdKey) + tpIdKey.length(), tpPath.lastIndexOf(\"']\"));\n }\n\n private <T> T execute(IDB db, Function<ITransactionContext, T> fn) {\n try {\n if (Transactor.isInTransaction()) {\n return fn.apply(Transactor.getContext());\n } else {\n return Transactor.execute(db, fn, true);\n }\n } catch (DBRuntimeException e) {\n return null;\n }\n }\n\n // we are manually deleting L3 objects because we also need to delete corresponding TE objects.\n private boolean canDeleteL3TopologyObject (IYangObject aInIYangObject, SyncClass aInSyncClass, SrcClass aInSrcClass, IMdConverterFw aInMdConverterFw) {\n if(!ietfL3SrcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return false;\n }\n\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_NETWORK_CLASS_PATH: {\n String networkId = (String) aInIYangObject.get(NETWORK_ID);\n if(networkId.startsWith(\"TE-\")) {\n if(canDeleteObjectLogger.isDebugEnabled()) {\n canDeleteObjectLogger.debug(\"L3 - can delete - ignoring TE network\");\n }\n return false;\n }\n String[] domainSplit = networkId.split(\"-\");\n String adminDomain = null;\n if(domainSplit.length >= 3 && isValidProtocol(domainSplit[2])) { //could be other networks (not a L3 network)\n adminDomain = domainSplit[0] + \"-\" + domainSplit[1];\n if (yangDB.exists(String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain), qp)) {\n return false;\n\n } else {\n String ietfNetworkIdentifier = aInIYangObject.getIdentifier();\n deleteL3Network(yangDB, qp, ietfNetworkIdentifier, networkId);\n }\n }\n return false;\n }\n case IETF_NODE_CLASS_PATH : {\n String ietfNodeIdentifier = aInIYangObject.getIdentifier();\n String networkId = extractNetworkIdFromIetfIdentifier(ietfNodeIdentifier);\n if(networkId.startsWith(\"TE-\")) {\n if(canDeleteObjectLogger.isDebugEnabled()) {\n canDeleteObjectLogger.debug(\"L3 - can delete - ignoring TE node\");\n }\n return false;\n }\n String[] domainSplit = networkId.split(\"-\");\n String adminDomain = domainSplit[0] + \"-\" + domainSplit[1];\n //if the node-id contains psn then its a subnet / otherwise routing instance.\n String nodeId = (String) aInIYangObject.get(NODE_ID);\n String nodeIdentifier = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n\n if(nodeId.contains(\"psn\")) {\n String routerId = getSubnetRouterId(nodeId);\n nodeIdentifier += String.format(NSP_SERVICE_SUBNET_PATH, routerId);\n }\n else {\n nodeIdentifier += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n }\n if(!yangDB.exists(nodeIdentifier, qp)){\n deleteL3Node(yangDB, qp, networkId, ietfNodeIdentifier, nodeId);\n }\n return false;\n }\n case IETF_LINK_CLASS_PATH : {\n String ietfLinkIdentifier = aInIYangObject.getIdentifier();\n String networkId = extractNetworkIdFromIetfIdentifier(ietfLinkIdentifier);\n if(networkId.startsWith(\"TE-\")) {\n if(canDeleteObjectLogger.isDebugEnabled()) {\n canDeleteObjectLogger.debug(\"L3 - can delete - ignoring TE link\");\n }\n return false;\n }\n //need to get the ietf link attributes object first and get the name and query the nsp-service link object.\n String ietfLinkAttrIdentifier = ietfLinkIdentifier + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n IYangObject linkAttrObj = yangDB.getSingle(ietfLinkAttrIdentifier,qp);\n if(linkAttrObj != null) {\n String name = (String) linkAttrObj.get(NAME);\n if(yangDB.exists(String.format(NSP_SERVICE_LINK_PATH, name), qp)) {\n return false;\n }\n else {\n //call deleteLink() instead as we have to clean up TPs as well?\n String linkId = (String) aInIYangObject.get(LINK_ID);\n deleteL3Link(yangDB, qp, networkId, ietfLinkIdentifier, linkId);\n }\n }\n else {\n return false;\n }\n }\n default:\n return true;\n }\n }\n\n private boolean isValidProtocol(String protocol) {\n return protocol != null && (protocol.equals(\"ospf\") || protocol.equals(\"isis\"));\n }\n\n private String extractNetworkIdFromIetfIdentifier(String identifier) {\n int fromIndex = identifier.indexOf(\"network-id='\");\n int toIndex = identifier.indexOf(\"'\", fromIndex+12);\n return identifier.substring(fromIndex + 12, toIndex);\n }\n\n String getSubnetRouterId(String aInNodeId) {\n return aInNodeId.split(\"-psn\")[0];\n }\n\n private void deleteL3Network(IYangDB aInYangDB, QueryParameters aInQp, String aInIetfNetworkIdentifier, String aInNetworkId) {\n canDeleteObjectLogger.debug(\"L3 - Deleting network - can delete : {}\", aInIetfNetworkIdentifier);\n aInYangDB.delete(aInIetfNetworkIdentifier, aInQp);\n if(TE_TOPOLOGY_ENABLED) {\n String teNetworkId = getTeNetworkId(aInNetworkId);\n canDeleteObjectLogger.debug(\"L3 - Deleting network - can delete : {}\", teNetworkId);\n aInYangDB.delete(String.format(IETF_NETWORKS_PATH, teNetworkId), aInQp);\n }\n }\n\n private void deleteL3Node(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodePathIdentifier, String nodeId ) {\n canDeleteObjectLogger.debug(\"L3 - Deleting node - can delete : {}\", aInNodePathIdentifier);\n aInYangDB.delete(aInNodePathIdentifier, aInQp);\n if(TE_TOPOLOGY_ENABLED) {\n String teNodePathIdentfier = String.format(IETF_NETWORKS_PATH, getTeNetworkId(aInNetworkId)) + String.format(NODE_PATH, nodeId);\n if (aInYangDB.exists(teNodePathIdentfier, aInQp)) {\n canDeleteObjectLogger.debug(\"L3 - Deleting node - can delete {}\", teNodePathIdentfier);\n aInYangDB.delete(teNodePathIdentfier, aInQp);\n }\n }\n }\n\n private void deleteL3Link(IYangDB aInYangDB, QueryParameters aInQp,String aInNetworkId, String aInLinkIdentifier, String aInLinkId) {\n\n canDeleteObjectLogger.debug(\"L3 - Deleting link - can delete : {}\", aInLinkIdentifier);\n aInYangDB.delete(aInLinkIdentifier, aInQp);\n\n String teNetworkPathIdentifier = String.format(IETF_NETWORKS_PATH, getTeNetworkId(aInNetworkId));\n //delete TE link\n if(TE_TOPOLOGY_ENABLED) {\n String teLinkPathIdentifier = teNetworkPathIdentifier + String.format(LINK_PATH, aInLinkId);\n canDeleteObjectLogger.debug(\"L3 - Deleting link - can delete : {}\", teLinkPathIdentifier);\n aInYangDB.delete(teLinkPathIdentifier, aInQp);\n }\n //can delete source tp and destination tp?\n String oppLinkId = getOppIetfLinkId(aInLinkId);\n String networkPathIdentifier = String.format(IETF_NETWORKS_PATH, aInNetworkId);\n String oppLinkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, oppLinkId);\n if (!aInYangDB.exists(oppLinkPathIdentifier, aInQp)) {\n // no other link is using the same source and destination. delete the TPs.\n List<String> linkObjIds = getLinkObjIds(aInLinkId);\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(0));\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, linkObjIds.get(1));\n if(canDeleteTp(aInYangDB, \"%\" + linkObjIds.get(0) + \":\" + linkObjIds.get(1) + \"%\", aInNetworkId)) {\n deleteL3TerminationPoint(aInYangDB, aInQp, srcNodeIdentifier, srcNodeTPIdentifier);\n\n // delete TE src termination point\n if (TE_TOPOLOGY_ENABLED) {\n String teSrcNodeIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(0));\n String teSrcNodeTPIdentifier = teSrcNodeIdentifier + String.format(TP_PATH, linkObjIds.get(1));\n deleteL3TerminationPoint(aInYangDB, aInQp, teSrcNodeIdentifier, teSrcNodeTPIdentifier);\n }\n }\n\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(2));\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, linkObjIds.get(3));\n if(canDeleteTp(aInYangDB, \"%\" + linkObjIds.get(2) + \":\" + linkObjIds.get(3) + \"%\", aInNetworkId)) {\n deleteL3TerminationPoint(aInYangDB, aInQp, dstNodeIdentifier, dstNodeTPIdentifier);\n\n // delete TE dst termination point\n if (TE_TOPOLOGY_ENABLED) {\n String teDstNodeIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(2));\n String teDstNodeTPIdentifier = teDstNodeIdentifier + String.format(TP_PATH, linkObjIds.get(3));\n deleteL3TerminationPoint(aInYangDB, aInQp, teDstNodeIdentifier, teDstNodeTPIdentifier);\n }\n }\n }\n }\n\n private void deleteL3TerminationPoint(IYangDB aInYangDB, QueryParameters aInQp, String aInSrcNodeIdentifier, String aInSrcNodeTPIdentifier) {\n if(aInYangDB.exists(aInSrcNodeIdentifier, aInQp)) {\n canDeleteObjectLogger.debug(\"L3 - Deleting TP - can delete : {}\", aInSrcNodeTPIdentifier);\n aInYangDB.delete(aInSrcNodeTPIdentifier, aInQp);\n }\n }\n\n private String getTeNetworkId(String networkId) {\n return \"TE-\"+networkId;\n }\n\n private String getOppIetfLinkId(String aInLinkId) {\n String[] idSplits = aInLinkId.split(\"--\");\n String oppLinkId = idSplits[1] + \"--\" + idSplits[0];\n oppLinkId += (idSplits.length == 3) ? \"--\" + idSplits[2] : \"\";\n return oppLinkId;\n }\n\n private List<String> getLinkObjIds(String aInLinkId) {\n String[] idSplits = aInLinkId.split(\"--\");\n String[] srcNodeSplits = idSplits[0].split(\":\");\n String[] dstNodeSplits = idSplits[1].split(\":\");\n List<String> linkObjIds = new ArrayList<>();\n linkObjIds.add(srcNodeSplits[0]);\n linkObjIds.add(srcNodeSplits[1]);\n linkObjIds.add(dstNodeSplits[0]);\n linkObjIds.add(dstNodeSplits[1]);\n return linkObjIds;\n }\n\n private boolean canDeleteTp(IYangDB aInYangDb, String aInPattern, String aInNetworkId) {\n BigInteger count = (BigInteger) execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT count(*) FROM \" +\n \"ietf.ietf_network_networks_network_ietf_network_topology_link sl WHERE sl.linkId LIKE :pattern \" +\n \"AND sl.networkId = :networkId\")\n .setParameter(\"pattern\", aInPattern)\n .setParameter(\"networkId\", aInNetworkId)\n .getSingleResult());\n return count != null && count.longValue() == 0;\n }\n}\n"
858
+ }
859
+ ]
860
+ }
861
+ ],
862
+ "custom-handler": [
863
+ {
864
+ "@": {
865
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler",
866
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler']",
867
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
868
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
869
+ },
870
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler",
871
+ "version": "1.0.1",
872
+ "java-code": [
873
+ {
874
+ "@": {
875
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler/java-code",
876
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L2TopologyHandler']/java-code[page-number='1']",
877
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
878
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
879
+ },
880
+ "page-number": 1,
881
+ "page": "package com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.nokia.nsp.md.common.notif.ObjectCreation;\nimport com.nokia.nsp.md.common.notif.ObjectDeletion;\nimport com.nokia.nsp.md.common.notif.ObjectModification;\nimport com.nokia.nsp.md.common.notif.ObjectReplacement;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.ICustomHandler;\nimport com.nokia.nsp.md.converter.yang.plugin.common.IHandleDeleteTracking;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\n\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.ifg.yang.api.Fields;\nimport com.nokia.nspos.persistence.impl.db.transaction.DBRuntimeException;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\n\nimport com.nokia.nspos.persistence.impl.db.transaction.ITransactionContext;\nimport com.nokia.nspos.persistence.impl.db.transaction.Transactor;\nimport com.nokia.nspos.persistence.api.IDB;\n\nimport com.nokia.nspos.model.domain.service.types.Layer;\nimport com.nokia.nspos.model.domain.service.types.ServiceType;\nimport com.nokia.nspos.model.domain.service.types.EndpointType;\nimport com.nokia.nspos.model.domain.service.types.Direction;\n\nimport org.apache.commons.lang.StringUtils;\n\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.function.Function;\nimport java.util.regex.Pattern;\n\npublic class L2TopologyHandler implements ICustomHandler, IHandleDeleteTracking\n{\n private static final org.slf4j.Logger handleResyncLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleResync\");\n private static final org.slf4j.Logger handlePostResyncDeleteLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".postResyncDelete\");\n private static final org.slf4j.Logger handleCreateEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleCreateEvent\");\n private static final org.slf4j.Logger handleUpdateEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleUpdateEvent\");\n private static final org.slf4j.Logger handleReplaceEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleReplaceEvent\");\n private static final org.slf4j.Logger handleDeleteEventLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleDeleteEvent\");\n private static final org.slf4j.Logger handleNodeLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleNode\");\n private static final org.slf4j.Logger handleTpLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleTp\");\n private static final org.slf4j.Logger handlePortLagLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handlePortLag\");\n private static final org.slf4j.Logger handleLinkLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleLink\");\n private static final org.slf4j.Logger dataBaseAccessLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".dataBaseAccess\");\n private static final org.slf4j.Logger handleTrackedDeleteLogger = org.slf4j.LoggerFactory.getLogger(L2TopologyHandler.class.getName() + \".handleTrackedDelete\");\n\n private static final String IETF_L2_NETWORK_ID = \"L2Topology\";\n private static final String IETF_L2_NETWORK_PATH = String.format(\"/ietf-network:networks/network[network-id='%s']\", IETF_L2_NETWORK_ID);\n private static final String IETF_L2_NODE_PATH = IETF_L2_NETWORK_PATH + \"/node[node-id='%s']\";\n private static final String IETF_L2_TP_PATH = IETF_L2_NODE_PATH + \"/ietf-network-topology:termination-point[tp-id='%s']\";\n private static final String IETF_L2_LINK_PATH = IETF_L2_NETWORK_PATH + \"/ietf-network-topology:link[link-id='%s']\";\n private static final String IETF_NODE_TYPE = \"node\";\n private static final String IETF_TP_TYPE = \"ietf-network-topology:termination-point\";\n private static final String IETF_LINK_TYPE = \"ietf-network-topology:link\";\n\n private static final String IETF_NETWORK_CLASS = \"ietf-network:/networks/network\";\n private static final String IETF_NODE_CLASS = IETF_NETWORK_CLASS + \"/\" + IETF_NODE_TYPE;\n private static final String IETF_TP_CLASS = IETF_NODE_CLASS + \"/\" + IETF_TP_TYPE;\n private static final String IETF_LINK_CLASS = IETF_NETWORK_CLASS + \"/\" + IETF_LINK_TYPE;\n\n private static final String NSP_SERVICE_CABLE_CLASS = \"nsp-service:/services/physical-layer/cable\";\n private static final String NSP_ENDPOINT_CABLE_CLASS = \"nsp-service:/services/physical-layer/cable/link-endpoint\";\n private static final String NSP_SERVICE_RADIO_CLASS = \"nsp-service:/services/physical-layer/radio-link\";\n private static final String NSP_ENDPOINT_RADIO_CLASS = \"nsp-service:/services/physical-layer/radio-link/link-endpoint\";\n private static final String NSP_EQUIPMENT_PORT_CLASS = \"nsp-equipment:/network/network-element/hardware-component/port\";\n private static final String NSP_EQUIPMENT_PORT_DETAILS_CLASS = \"nsp-equipment:/network/network-element/hardware-component/port/port-details\";\n private static final String NSP_EQUIPMENT_LAG_CLASS = \"nsp-equipment:/network/network-element/lag\";\n\n private static final String NSP_SERVICE_PATH = \"/nsp-service:services/physical-layer/%s[id='%s']\";\n private static final String NSP_ENDPOINT_PATH = \"/nsp-service:services/physical-layer/%s[id='%s']/link-endpoint[site-id='%s'][endpoint-id='%s']\";\n private static final String nokia_nsp_network_management_ELEMENT_PATH = \"/nsp-equipment:network/network-element[ne-id='%s']\";\n\n private static final String NSP_ENDPOINT_TABLE = \"service_Endpoint\";\n private static final String NSP_SERVICE_TABLE = \"service_Service\";\n private static final Layer NSP_L2_LAYER = Layer.physical;\n private static final Set<ServiceType> NSP_L2_SERVICE_TYPES = ImmutableSet.of(ServiceType.cable, ServiceType.radioLink);\n\n private static final String IETF_MEMBER_LINK_TP_TABLE = \"ietf.ietf_204762653l2_termination_point_attributes_member_link_tp\";\n private static final String IETF_LINK_NSP_ATTR_TABLE = \"ietf.ietf_19924911ibutes_nsp_ietf_network_topology_nsp_attributes\";\n private static final String IETF_TP_NSP_ATTR_TABLE = \"ietf.ietf_48789230ibutes_nsp_ietf_network_topology_nsp_attributes\";\n\n public static final Fields nokia_nsp_network_management_ELEMENT_READ_FIELDS = Fields.parse(\"ne-name;mac-address;ip-address\");\n public static final Fields NSP_ENDPOINT_READ_FIELDS = Fields.parse(\"endpoint-id;site-id;type;port-bindings/resource\");\n public static final Fields NSP_SERVICE_READ_FIELDS = Fields.parse(\"link-endpoint(endpoint-id;site-id;type;port-bindings/resource);id;name;latency;direction\");\n public static final Fields NSP_SERVICE_READ_FIELDS_REDUCED = Fields.parse(\"name;latency\");\n public static final Fields NSP_PORT_READ_FIELDS_FOR_TP = Fields.parse(\"name;ne-id;hw-mac-address;port-details(encap-type;port-index)\");\n public static final Fields NSP_PORT_READ_FIELDS_FOR_LAG_MEMBER = Fields.parse(\"name\");\n public static final Fields NSP_PORT_DETAILS_READ_FIELDS_FOR_TP = Fields.parse(\"encap-type;port-index\");\n public static final Fields NSP_PORT_DETAILS_READ_FIELDS_FOR_LINK = Fields.parse(\"actual-rate;actual-rate-units;operational-duplex;auto-negotiate\");\n public static final Fields NSP_LAG_READ_FIELDS = Fields.parse(\"name;configured-address;encap-type;lag-index;members\");\n public static final Fields NSP_LAG_READ_FIELDS_MEMBERS = Fields.parse(\"members\");\n public static final Fields IETF_LINK_ATTR_READ_FIELDS = Fields.parse(\"name;nsp-ietf-network-topology:nsp-attributes\");\n public static final Fields IETF_TP_ATTR_READ_FIELDS = Fields.parse(\"nsp-ietf-network-topology:nsp-attributes\");\n public static final Fields IETF_TP_READ_FIELDS = Fields.parse(\"ietf-l2-topology:l2-termination-point-attributes/nsp-ietf-network-topology:nsp-attributes\");\n public static final Fields IETF_TP_MEMBERS_READ_FIELDS = Fields.parse(\"ietf-l2-topology:l2-termination-point-attributes/member-link-tp\");\n\n private enum IetfL2EncapType\n {\n ETHERNET(\"ietf-l2-topology:ethernet\"),\n VLAN(\"ietf-l2-topology:vlan\"),\n QINQ(\"ietf-l2-topology:qinq\"),\n PBB(\"ietf-l2-topology:pbb\"),\n TRILL(\"ietf-l2-topology:trill\"),\n VPLS(\"ietf-l2-topology:vpls\"),\n VXLAN(\"ietf-l2-topology:vxlan\");\n\n public final String value;\n private IetfL2EncapType(String value)\n {\n this.value = value;\n }\n }\n\n private enum IetfDuplexMode\n {\n FULL(\"full-duplex\"),\n HALF(\"half-duplex\");\n\n public final String value;\n private IetfDuplexMode(String value)\n {\n this.value = value;\n }\n }\n\n private static final Pattern MAC_ADDRESS_PATTERN = Pattern.compile(\"[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}\");\n private static final Pattern RAW_MAC_ADDRESS_PATTERN = Pattern.compile(\"[0-9a-fA-F]{12}\");\n\n\n @Override\n public void handlePostResyncDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handlePostResyncDeleteLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId);\n }\n\n @Override\n public int readSrcObjectDepth(String aInSrcClassPath)\n {\n if(aInSrcClassPath.equals(NSP_ENDPOINT_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_ENDPOINT_RADIO_CLASS))\n {\n return 3;\n }\n else if(aInSrcClassPath.equals(NSP_SERVICE_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_SERVICE_RADIO_CLASS))\n {\n return 4;\n }\n return 2;\n }\n\n @Override\n public Fields srcFilterFieldsToInclude(String aInSrcClassPath)\n {\n if(aInSrcClassPath.equals(NSP_ENDPOINT_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_ENDPOINT_RADIO_CLASS))\n {\n return NSP_ENDPOINT_READ_FIELDS;\n }\n else if(aInSrcClassPath.equals(NSP_SERVICE_CABLE_CLASS)\n || aInSrcClassPath.equals(NSP_SERVICE_RADIO_CLASS))\n {\n return NSP_SERVICE_READ_FIELDS;\n }\n return null;\n }\n\n @Override\n public void handleTrackedDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, String aInIdentifier, Map<String, Object> aInData, YangPluginMdConverterProvider aInYangPlugin) {\n if (handleTrackedDeleteLogger.isDebugEnabled()) {\n handleTrackedDeleteLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInIdentifier:{}, aInData:{}\", aInSrcClass, aInSyncClass, aInIdentifier, aInData);\n }\n\n if(aInSrcClass.getSrcClassPath().equals(NSP_SERVICE_CABLE_CLASS)\n || aInSrcClass.getSrcClassPath().equals(NSP_SERVICE_RADIO_CLASS)) {\n\n IYangDB yangDB = aInYangPlugin.getiMdConverterFw().getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n String linkId = StringUtils.substringBetween(aInIdentifier, \"[id='\", \"'\");\n IYangObject yangObj = new YangObject();\n yangObj.setProperty(\"name\", aInData.get(\"name\"));\n yangObj.setProperty(\"id\", linkId);\n handleTrackedDeleteLogger.debug(\" L2 tracked deletion for link {}\", linkId);\n deleteLink(yangObj, yangDB, qp);\n }\n }\n\n @Override\n public void handleResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInExistingObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleResyncLogger.debug(\"aInSrcIdentifier:{}, aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcObject.getIdentifier(), aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId);\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n //don't sync ports and lags, only care for their updates\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n break;\n }\n handleResyncLogger.debug(\"TP SYNC\");\n if(isValidEndpoint(aInSrcObject, yangDB)) {\n handleTP(aInSrcObject, yangDB, qp, null);\n }\n break;\n }\n case IETF_LINK_CLASS: {\n handleResyncLogger.debug(\"LINK SYNC\");\n handleLink(aInSrcObject, false, false, yangDB, qp);\n break;\n }\n }\n }\n\n @Override\n public void handleCreateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectCreation aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleCreateEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId:{}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n IYangObject lSrcObject = aInEvent.getEntity();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n // need to listen for create port/lag as link can be created first in the managing scenario\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS)){\n //wait for port-details\n break;\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS)){\n handleCreateEventLogger.debug(\"PORT DETAILS CREATE\");\n String portPath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/port-details\"));\n lSrcObject = yangDB.getSingle(portPath, getFilteredQueryParameters(NSP_PORT_READ_FIELDS_FOR_TP) );\n handlePortLag(lSrcObject, EndpointType.physicalPort, yangDB, qp);\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n handleCreateEventLogger.debug(\"LAG CREATE\");\n handlePortLag(lSrcObject, EndpointType.lag, yangDB, qp);\n }\n else {\n handleCreateEventLogger.debug(\"TP CREATE\");\n if(isValidEndpoint(lSrcObject, yangDB)) {\n handleTP(lSrcObject, yangDB, qp, null);\n\n //create link on TP event - on target endpoint event only\n if (lSrcObject.get(\"type\").toString().equals(\"physical-port\")) {\n List<?> nspEpSources = (List<?>) ((YangObject) lSrcObject).getExtraDatas().get(\"sources\");\n for (Object epSource : nspEpSources) {\n if (epSource.toString().contains(\"@endpointB\")) {\n String servicePath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/link-endpoint[\"));\n IYangObject lLinkSourceObj = getSingleFromYangDb(\n yangDB, servicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if (lLinkSourceObj != null) {\n handleLink(lLinkSourceObj, false, false, yangDB, qp);\n }\n }\n break;\n }\n }\n }\n }\n break;\n }\n case IETF_LINK_CLASS: {\n handleCreateEventLogger.debug(\"LINK CREATE\");\n //link is created on tp event\n break;\n }\n }\n }\n\n @Override\n public void handleUpdateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectModification aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleUpdateEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId:{}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n IYangObject lSrcObject = aInEvent.getEntity();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS)){\n handleUpdateEventLogger.debug(\"PORT UPDATE\");\n boolean shouldUpdate = false;\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"hw-mac-address\")) {\n shouldUpdate = true;\n break;\n }\n }\n if(shouldUpdate){\n handlePortLag(lSrcObject, EndpointType.physicalPort, yangDB, qp);\n }\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS)){\n handleUpdateEventLogger.debug(\"PORT DETAILS UPDATE\");\n boolean shouldUpdate = false;\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"encap-type\") || change.getName().equals(\"actual-rate\") ||\n change.getName().equals(\"operational-duplex\") || change.getName().equals(\"auto-negotiate\")) {\n shouldUpdate = true;\n break;\n }\n }\n if(shouldUpdate){\n String portPath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/port-details\"));\n lSrcObject = yangDB.getSingle(portPath, getFilteredQueryParameters(NSP_PORT_READ_FIELDS_FOR_TP));\n handlePortLag(lSrcObject, EndpointType.physicalPort, yangDB, qp);\n }\n }\n else if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n handleUpdateEventLogger.debug(\"LAG UPDATE\");\n boolean shouldUpdate = false;\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"encap-type\") || change.getName().equals(\"configured-address\")) {\n shouldUpdate = true;\n break;\n }\n }\n if(shouldUpdate){\n handlePortLag(lSrcObject, EndpointType.lag, yangDB, qp);\n }\n }\n else {\n handleUpdateEventLogger.debug(\"TP UPDATE\");\n boolean isManageTypeChange = false;\n boolean isLagEndpointObjectDetailsChange = false;\n int changesSize = aInEvent.getChanges().size();\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"type\")){\n if(change.getNewValue().toString().equals(EndpointType.physicalPort.getAltName())) {\n isManageTypeChange = true;\n }\n break;\n }\n // looking for objectDetails update - starting 23.4, aInEvent.getChanges() will have \"last-modified-time\" change\n else if(change.getName().equals(\"last-modified-time\")\n && lSrcObject.get(\"type\").toString().equals(\"lag\")\n && changesSize == 1) {\n isLagEndpointObjectDetailsChange = true;\n break;\n }\n }\n if(isManageTypeChange || isLagEndpointObjectDetailsChange) {\n //on managing ne - link is created on link update event\n //but the opposite(already managed) endpoint doesn't get any events - need to handle it to create tp/node\n String servicePath = lSrcObject.getIdentifier().substring(0, lSrcObject.getIdentifier().indexOf(\"/link-endpoint[\"));\n IYangObject lLinkSourceObj = getSingleFromYangDb(\n yangDB, servicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if(lLinkSourceObj != null) {\n List<?> endpoints = (List<?>)lLinkSourceObj.get(\"link-endpoint\");\n if (endpoints != null && !endpoints.isEmpty()) {\n if (isManageTypeChange && isValidLinkEndpoints(endpoints)) {\n handleUpdateEventLogger.debug(\"TP MANAGE CHANGE\");\n endpoints.forEach(endpoint -> handleTP((IYangObject) endpoint, yangDB, qp, null));\n }\n else if (isLagEndpointObjectDetailsChange && isValidLagEndpoints(endpoints)\n && isValidLinkType(lLinkSourceObj.get(\"id\").toString(), yangDB)) {\n //handle update for lag tps - needed for add/remove member scenario\n handleUpdateEventLogger.debug(\"TP LAG ENDPOINT CHANGE\");\n endpoints.forEach(endpoint -> handleTP((IYangObject) endpoint, yangDB, qp, null));\n }\n }\n }\n }\n }\n break;\n }\n case IETF_LINK_CLASS: {\n handleUpdateEventLogger.debug(\"LINK UPDATE\");\n boolean isUnManageChange = false;\n boolean ignoreUpdate = false;\n boolean isNameUpdate = false;\n int changesSize = aInEvent.getChanges().size();\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"name\")){\n if(change.getNewValue().toString().contains(\"Unmanaged-Ne\")) {\n handleUpdateEventLogger.debug(\"LINK UN-MANAGE CHANGE\");\n isUnManageChange = true;\n }\n else {\n //update on any other link name change - needed for nfmp managing scenario\n isNameUpdate = true;\n ignoreUpdate = false;\n break;\n }\n }\n else if(change.getName().equals(\"oper-state\") ||\n (change.getName().equals(\"last-modified-time\") && changesSize == 1)){ //todo: other link changes to ignore?\n ignoreUpdate = true;\n }\n }\n if(isUnManageChange) {\n deleteLink(lSrcObject, yangDB, qp);\n }\n else if (!ignoreUpdate) {\n handleLink(lSrcObject, isNameUpdate, false, yangDB, qp);\n }\n break;\n }\n }\n }\n\n @Override\n public void handleReplaceEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectReplacement aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleReplaceEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n }\n\n @Override\n public void handleDeleteEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectDeletion aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handleDeleteEventLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, aInEventObject:{}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().getIdentifier());\n\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n IYangObject lSrcObject = aInEvent.getEntity();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n switch (aInSyncClass.getDestClassPath()) {\n case IETF_TP_CLASS: {\n //don't delete ports and lags, only care for their updates\n if(aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_PORT_DETAILS_CLASS) ||\n aInSrcClass.getSrcClassPath().equals(NSP_EQUIPMENT_LAG_CLASS)){\n break;\n }\n handleDeleteEventLogger.debug(\"TP DELETE\");\n //endpoint delete event is not sent for nfmp and lldp links\n //both node/tp are deleted on the link delete event\n break;\n }\n case IETF_LINK_CLASS: {\n handleDeleteEventLogger.debug(\"LINK DELETE\");\n deleteLink(lSrcObject, yangDB, qp);\n break;\n }\n }\n }\n\n private boolean canDeleteNode (String nodeId, IYangDB yangDB) {\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + \"WHERE e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\",\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort.getValue())\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n private boolean canDeleteTp (String nodeId, String tpId, boolean isLagTp, boolean isLagMember, IYangDB yangDB) {\n int endpointType = isLagTp ? EndpointType.lag.getValue() : EndpointType.physicalPort.getValue();\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + (isLagTp ? \"JOIN service.Service_objectDetails sod ON (sod.dbId = svc.dbId AND sod.objectDetails_key = 'linkType') \" : \"\") //linkType is not set on manual lag links\n + (isLagMember ? \"JOIN service.Service_objectDetails sod ON (sod.dbId = svc.dbId AND sod.objectDetails_key = 'isLagMember') \" : \"\")\n + \"WHERE e.id=:endpointId AND e.siteId=:siteId AND e.type=:endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\"\n + (isLagMember ? \" AND sod.objectDetails = 'true'\" : \"\"),\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"endpointId\", tpId)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", endpointType)\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n private boolean canDeleteLink (Object sourceTpPath, Object destTpPath, IYangDB yangDB) {\n if (sourceTpPath != null && destTpPath != null) {\n String sourceTpId = getTpIdFromTpPath(sourceTpPath.toString());\n String sourceNodeId = getNodeIdFromTpPath(sourceTpPath.toString());\n String destTpId = getTpIdFromTpPath(destTpPath.toString());\n String destNodeId = getNodeIdFromTpPath(destTpPath.toString());\n boolean canDelete = runCanDeleteLink(sourceTpId, sourceNodeId, destTpId, destNodeId, false, yangDB);\n if(canDelete) {\n canDelete = runCanDeleteLink(destTpId, destNodeId, sourceTpId, sourceNodeId,true, yangDB);\n }\n return canDelete;\n }\n return true;\n }\n\n private boolean runCanDeleteLink (String sourceTpId, String sourceNodeId, String destTpId, String destNodeId,\n boolean shouldIncludeDirection, IYangDB yangDB) {\n String subquery = String.format(\"SELECT svc FROM %s e JOIN e.service svc \"\n + \"JOIN e.objectDetails eod ON (KEY(eod) = :objectDetailsSource) \"\n + \"WHERE e.id=:endpointIdSource AND e.siteId=:siteIdSource \"\n + \"AND e.type=:endpointType AND svc.layer=:layer \"\n + (shouldIncludeDirection ? \"AND svc.direction=:direction \" : \"\")\n + \"AND svc.type IN :serviceTypes\", NSP_ENDPOINT_TABLE);\n String query = String.format(\"SELECT count(e.dbId) FROM %s e \"\n + \"JOIN e.objectDetails eod ON (KEY(eod) = :objectDetailsTarget) \"\n + \"WHERE e.id=:endpointIdTarget AND e.siteId=:siteIdTarget \"\n + \"AND e.type = :endpointType AND e.service IN (%s)\",\n NSP_ENDPOINT_TABLE, subquery);\n Long count = execute(yangDB.getDb(), tx -> {\n javax.persistence.Query lQuery = tx.getEntityManager().createQuery(query)\n .setParameter(\"objectDetailsSource\", \"isSource\")\n .setParameter(\"endpointIdSource\", sourceTpId)\n .setParameter(\"siteIdSource\", sourceNodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort)\n .setParameter(\"layer\", NSP_L2_LAYER)\n .setParameter(\"serviceTypes\", NSP_L2_SERVICE_TYPES)\n .setParameter(\"objectDetailsTarget\", \"isTarget\")\n .setParameter(\"endpointIdTarget\", destTpId)\n .setParameter(\"siteIdTarget\", destNodeId);\n if(shouldIncludeDirection) {\n lQuery.setParameter(\"direction\", Direction.biDirectional);\n }\n return (Long)lQuery.getSingleResult();\n });\n return count != null && count.intValue() == 0;\n }\n\n private void deleteLink (IYangObject aInSrcObject, IYangDB yangDB, QueryParameters qp) {\n\n String nspServiceId = aInSrcObject.get(\"id\").toString();\n\n // note: objectDetails.linkType won't help with manual link as linkType is not set\n\n List<?> linkList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(String.format(\n \"SELECT linkid FROM %s WHERE nspietfnetworktopologynspattributes = :nspServiceId\",\n IETF_LINK_NSP_ATTR_TABLE))\n .setParameter(\"nspServiceId\", nspServiceId)\n .getResultList());\n if (linkList != null && !linkList.isEmpty()) {\n for(Object link : linkList) {\n String linkId = (String) link;\n String ietfLinkPath = String.format(IETF_L2_LINK_PATH, linkId);\n IYangObject ietfLink = yangDB.getSingle(ietfLinkPath, qp);\n if (ietfLink != null) {\n String lSourceTpPath = null, lDestTpPath = null;\n IYangObject lSourceYangObj = (YangObject) ietfLink.get(\"source\");\n if (lSourceYangObj.get(\"source-tp\") != null) {\n lSourceTpPath = lSourceYangObj.get(\"source-tp\").toString();\n String lSourceNodeId = getNodeIdFromTpPath(lSourceTpPath);\n String lSourceTpId = getTpIdFromTpPath(lSourceTpPath);\n if (canDeleteNode(lSourceNodeId, yangDB) && lSourceYangObj.get(\"source-node\") != null) {\n String lSourceNodePath = lSourceYangObj.get(\"source-node\").toString();\n handleDeleteEventLogger.debug(\"DELETING NODE \" + lSourceNodePath);\n yangDB.delete(lSourceNodePath, qp);\n }\n else if (canDeleteTp(lSourceNodeId, lSourceTpId, false, false, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING TP \" + lSourceTpPath);\n yangDB.delete(lSourceTpPath, qp);\n updateLagTpOnMemberDeleteEvent(lSourceTpPath, yangDB, qp);\n }\n }\n IYangObject lDestYangObj = (YangObject) ietfLink.get(\"destination\");\n if (lDestYangObj.get(\"dest-tp\") != null) {\n lDestTpPath = lDestYangObj.get(\"dest-tp\").toString();\n String lDestNodeId = getNodeIdFromTpPath(lDestTpPath);\n String lDestTpId = getTpIdFromTpPath(lDestTpPath);\n if (canDeleteNode(lDestNodeId, yangDB) && lDestYangObj.get(\"dest-node\") != null) {\n String lDestNodePath = lDestYangObj.get(\"dest-node\").toString();\n handleDeleteEventLogger.debug(\"DELETING NODE \" + lDestNodePath);\n yangDB.delete(lDestNodePath, qp);\n }\n else if (canDeleteTp(lDestNodeId, lDestTpId, false, false, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING TP \" + lDestTpPath);\n yangDB.delete(lDestTpPath, qp);\n updateLagTpOnMemberDeleteEvent(lDestTpPath, yangDB, qp);\n }\n }\n\n if (lSourceTpPath == null || lDestTpPath == null || canDeleteLink(lSourceTpPath, lDestTpPath, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING LINK \" + ietfLinkPath);\n yangDB.delete(ietfLinkPath, qp);\n }\n else {\n //remove nspServiceId from the nsp-attributes list\n IYangObject linkAttributes = (YangObject) ietfLink.get(\"ietf-l2-topology:l2-link-attributes\");\n List<?> linkNspAttrs = (List<?>) linkAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n List<String> lNewNspServiceIdList = new ArrayList<>();\n linkNspAttrs.stream()\n .filter(attr -> !attr.equals(nspServiceId))\n .forEach(attr -> lNewNspServiceIdList.add(attr.toString()));\n linkAttributes.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", lNewNspServiceIdList);\n\n // if the current ietf link name is the same as the deleted link name, then update it\n // the lNewNspServiceIdList should never be empty, if so, canDelete*** logic is wrong...\n if(linkAttributes.get(\"name\").equals(aInSrcObject.get(\"name\")) && !lNewNspServiceIdList.isEmpty()){\n //fetch name/delay of the first remaining nspServiceId in the list\n String lRemainingNspServiceId = lNewNspServiceIdList.get(0);\n String lLinkType = ((List<?>) linkAttributes.get(\"flags\")).get(0).toString().split(\":\")[1];\n String lServicePath = String.format(NSP_SERVICE_PATH, lLinkType, lRemainingNspServiceId);\n IYangObject lService = getSingleFromYangDb(yangDB, lServicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS_REDUCED));\n if(lService != null){\n linkAttributes.setProperty(\"name\", lService.get(\"name\"));\n linkAttributes.setProperty(\"delay\", lService.get(\"latency\"));\n }\n }\n handleDeleteEventLogger.debug(\"UPDATING LINK ATTRIBUTES\" + ietfLinkPath);\n yangDB.update(linkAttributes.getIdentifier(), linkAttributes, qp);\n }\n }\n }\n return; //ietf link is found, return from the method\n }\n\n\n //this could be lag link being deleted - check if lag tp should be deleted/updated\n\n List<?> lagTpList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(String.format(\n \"SELECT nodeid, tpid FROM %s WHERE nspietfnetworktopologynspattributes = :nspServiceId\",\n IETF_TP_NSP_ATTR_TABLE))\n .setParameter(\"nspServiceId\", nspServiceId)\n .getResultList());\n if (lagTpList != null && !lagTpList.isEmpty()) {\n for(Object lagTp : lagTpList){\n Object[] tuple = (Object[]) lagTp;\n String nodeId = tuple[0] != null ? tuple[0].toString() : StringUtils.EMPTY;\n String tpId = tuple[1] != null ? tuple[1].toString() : StringUtils.EMPTY;\n String tpPath = String.format(IETF_L2_TP_PATH, nodeId, tpId);\n if(canDeleteNode(nodeId, yangDB)) {\n String nodePath = String.format(IETF_L2_NODE_PATH, nodeId);\n handleDeleteEventLogger.debug(\"DELETING NODE \" + nodePath);\n yangDB.delete(nodePath, qp);\n }\n else if(canDeleteTp(nodeId, tpId, true, false, yangDB)) {\n handleDeleteEventLogger.debug(\"DELETING TP \" + tpPath);\n yangDB.delete(tpPath, qp);\n }\n else {\n //remove nspServiceId from the nsp-attributes list - is this executed ever?\n IYangObject tp = yangDB.getSingle(tpPath, getFilteredQueryParameters(IETF_TP_READ_FIELDS));\n if(tp != null) {\n IYangObject tpAttributes = (IYangObject)tp.get(\"ietf-l2-topology:l2-termination-point-attributes\");\n List<?> tpNspAttrs = (List<?>)tpAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n List<String> nspServiceIdList = new ArrayList<>();\n tpNspAttrs.stream()\n .filter(attr -> !attr.equals(nspServiceId))\n .forEach(attr -> nspServiceIdList.add(attr.toString()));\n tpAttributes.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n handleDeleteEventLogger.debug(\"UPDATING TP ATTRIBUTES \" + tpPath);\n yangDB.update(tpAttributes.getIdentifier(), tpAttributes, qp);\n }\n }\n }\n }\n }\n\n private void updateLagTpOnMemberDeleteEvent (String deletedMemberTpPath, IYangDB yangDB, QueryParameters qp){\n List<?> lagTpList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(String.format(\n \"SELECT nodeid, tpid, count(*) FROM %s WHERE fkparent = (SELECT fkparent FROM %s WHERE memberlinktp = :memberlinktp) GROUP BY nodeid, tpid\",\n IETF_MEMBER_LINK_TP_TABLE, IETF_MEMBER_LINK_TP_TABLE))\n .setParameter(\"memberlinktp\", deletedMemberTpPath)\n .getResultList());\n if (lagTpList != null && !lagTpList.isEmpty()) {\n Object[] tuple = (Object[]) lagTpList.get(0);\n String nodeId = tuple[0] != null ? tuple[0].toString() : StringUtils.EMPTY;\n String tpId = tuple[1] != null ? tuple[1].toString() : StringUtils.EMPTY;\n long count = tuple[2] != null ? ((BigInteger)tuple[2]).longValue() : 0;\n String lagTpPath = String.format(IETF_L2_TP_PATH, nodeId, tpId);\n if(count <= 1 && canDeleteTp(nodeId, tpId, true, false, yangDB))\n {\n //delete this lag tp as last member is deleted\n handleDeleteEventLogger.debug(\"DELETING TP \" + lagTpPath);\n yangDB.delete(lagTpPath, qp);\n }\n else {\n //update this lag tp member-link-tp list\n if(yangDB.exists(lagTpPath, qp)){\n String lagTpAttributesPath = lagTpPath + \"/ietf-l2-topology:l2-termination-point-attributes\";\n IYangObject lagTpAttributesObj = yangDB.getSingle(lagTpAttributesPath, getFilteredQueryParameters(IETF_TP_MEMBERS_READ_FIELDS));\n if(lagTpAttributesObj != null) {\n List<String> newMemberList = new ArrayList<>();\n List<?> lagTpMembers = (List<?>)lagTpAttributesObj.get(\"member-link-tp\");\n lagTpMembers.stream()\n .filter(memberTp -> !memberTp.equals(deletedMemberTpPath))\n .forEach(memberTp -> newMemberList.add(memberTp.toString()));\n lagTpAttributesObj.setProperty(\"member-link-tp\", newMemberList);\n handleDeleteEventLogger.debug(\"UPDATING TP \" + lagTpPath);\n yangDB.update(lagTpAttributesPath, lagTpAttributesObj, qp);\n }\n }\n }\n }\n }\n\n private IYangObject buildNodeConfig(String siteId, IYangDB yangDB) {\n IYangObject lNodeObj = new YangObject();\n lNodeObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lNodeObj.setProperty(\"node-id\", siteId);\n\n //l2-node-attributes\n IYangObject lNodeAttrObj = new YangObject();\n lNodeAttrObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lNodeAttrObj.setProperty(\"node-id\", siteId);\n\n String lNePath = String.format(nokia_nsp_network_management_ELEMENT_PATH, siteId);\n IYangObject lNe = yangDB.getSingle(lNePath, getFilteredQueryParameters(nokia_nsp_network_management_ELEMENT_READ_FIELDS));\n if(lNe != null) {\n if(lNe.get(\"ne-name\") != null){\n lNodeAttrObj.setProperty(\"name\", lNe.get(\"ne-name\"));\n }\n if(lNe.get(\"mac-address\") != null){\n String macAddress = convertMacAddress(lNe.get(\"mac-address\").toString());\n if (macAddress != null) {\n lNodeAttrObj.setProperty(\"management-mac\", macAddress);\n }\n }\n if(lNe.get(\"ip-address\") != null){\n lNodeAttrObj.setProperty(\"management-address\", Collections.singletonList(lNe.get(\"ip-address\")));\n }\n }\n lNodeObj.setProperty(\"ietf-l2-topology:l2-node-attributes\", lNodeAttrObj);\n return lNodeObj;\n }\n\n private void handlePortLag(IYangObject aInSrcObject, EndpointType type, IYangDB yangDB, QueryParameters qp) {\n //rely on equipment.name == endpoint.id, lag.name == endpoint.id\n String lName = aInSrcObject.get(\"name\").toString();\n String lNeId = aInSrcObject.get(\"ne-id\").toString();\n List<?> resultList = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createQuery(String.format(\"SELECT svc.id, svc.type FROM %s e JOIN e.service svc \"\n + (type.equals(EndpointType.lag) ? \"JOIN svc.objectDetails sod ON (KEY(sod) = 'linkType') \" : \"\") //linkType is not set on manual lag links\n + \"WHERE e.id=:endpointId AND e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type in :serviceTypes\", NSP_ENDPOINT_TABLE))\n .setParameter(\"endpointId\", lName)\n .setParameter(\"siteId\", lNeId)\n .setParameter(\"endpointType\", type)\n .setParameter(\"layer\", NSP_L2_LAYER)\n .setParameter(\"serviceTypes\", NSP_L2_SERVICE_TYPES)\n .getResultList());\n if (resultList != null && !resultList.isEmpty()) {\n Object[] tuple = (Object[]) resultList.get(0); //get first result, don't care for duplicates\n String lLinkId = tuple[0] != null ? tuple[0].toString() : StringUtils.EMPTY;\n ServiceType lSvcType = tuple[1] instanceof ServiceType ? ((ServiceType) tuple[1]) : ServiceType.unknown;\n String lLinkType = lSvcType.equals(ServiceType.cable) ? \"cable\" : (lSvcType.equals(ServiceType.radioLink) ? \"radio-link\" : StringUtils.EMPTY);\n String lEndpointPath = String.format(NSP_ENDPOINT_PATH, lLinkType, lLinkId, lNeId, lName);\n IYangObject endpoint = getSingleFromYangDb(yangDB, lEndpointPath, getFilteredQueryParameters(NSP_ENDPOINT_READ_FIELDS));\n if(endpoint != null && isValidEndpoint(endpoint, yangDB)) {\n handlePortLagLogger.debug(\"HANDLE PORT/LAG ENDPOINT FOUND: {}\", lEndpointPath);\n handleTP(endpoint, yangDB, qp, aInSrcObject);\n if(endpoint.get(\"type\").toString().equals(\"physical-port\")) {\n String servicePath = endpoint.getIdentifier().substring(0, endpoint.getIdentifier().indexOf(\"/link-endpoint[\"));\n IYangObject lLinkSourceObj = getSingleFromYangDb(\n yangDB, servicePath, getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if (lLinkSourceObj != null) {\n handlePortLagLogger.debug(\"HANDLE PORT SERVICE FOUND: {}\", servicePath);\n handleLink(lLinkSourceObj, false, true, yangDB, qp);\n }\n }\n }\n }\n }\n\n private boolean isValidEndpoint(IYangObject aInEndpoint, IYangDB yangDB) {\n String endpointId = aInEndpoint.get(\"endpoint-id\").toString();\n String siteId = getSiteIdForEndpoint(aInEndpoint);\n boolean isLag = aInEndpoint.get(\"type\").toString().equals(\"lag\");\n if(isLag) {\n String nspServiceId = getServiceIdFromEndpointPath(aInEndpoint.getIdentifier());\n return isValidLagEndpoint(aInEndpoint) && isValidLinkType(nspServiceId, yangDB)\n && !canDeleteTp(siteId, endpointId, isLag, false, yangDB);\n }\n return isValidPortEndpoint(aInEndpoint) && !canDeleteTp(siteId, endpointId, isLag, false, yangDB);\n }\n\n private void handleTP(IYangObject aInEndpoint, IYangDB yangDB, QueryParameters qp, IYangObject aInResource) {\n String endpointId = aInEndpoint.get(\"endpoint-id\").toString();\n String siteId = getSiteIdForEndpoint(aInEndpoint);\n String lTpPath = String.format(IETF_L2_TP_PATH, siteId, endpointId);\n boolean isLag = aInEndpoint.get(\"type\").toString().equals(\"lag\");\n String lNodePath = String.format(IETF_L2_NODE_PATH, siteId);\n IYangObject lTpObj = buildTpConfig(aInEndpoint, siteId, endpointId, isLag, yangDB, aInResource);\n if(lTpObj != null) {\n if (!yangDB.exists(lNodePath, qp)) {\n handleNodeLogger.debug(\"CREATING NODE \" + lNodePath);\n IYangObject lNodeObj = buildNodeConfig(siteId, yangDB);\n yangDB.createChild(IETF_L2_NETWORK_PATH, IETF_NODE_TYPE, lNodeObj, qp);\n }\n if (!yangDB.exists(lTpPath, qp)) {\n handleTpLogger.debug(\"CREATING TP \" + lTpPath);\n yangDB.createChild(lNodePath, IETF_TP_TYPE, lTpObj, qp);\n } else {\n handleTpLogger.debug(\"UPDATING TP \" + lTpPath);\n yangDB.update(lTpPath, lTpObj, qp);\n }\n }\n }\n\n private IYangObject buildTpConfig(IYangObject aInEndpoint, String siteId, String endpointId, boolean isLag, IYangDB yangDB, IYangObject resource) {\n IYangObject lTpObj = new YangObject();\n lTpObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lTpObj.setProperty(\"node-id\", siteId);\n lTpObj.setProperty(\"tp-id\", endpointId);\n\n //l2-termination-point-attributes\n IYangObject lTPAttrObj = new YangObject();\n lTPAttrObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lTPAttrObj.setProperty(\"node-id\", siteId);\n lTPAttrObj.setProperty(\"tp-id\", endpointId);\n lTPAttrObj.setProperty(\"lag\", isLag);\n\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n if (resource == null) {\n Object resourcePath = null;\n if(aInEndpoint.get(\"port-bindings\") != null && !((List<?>) aInEndpoint.get(\"port-bindings\")).isEmpty()) {\n resourcePath = ((YangObject) ((List<?>) aInEndpoint.get(\"port-bindings\")).get(0)).get(\"resource\");\n }\n else {\n IYangObject lEndpointObj = getSingleFromYangDb(yangDB, aInEndpoint.getIdentifier(), setFilterOnQueryParameters(qp, NSP_ENDPOINT_READ_FIELDS));\n if(lEndpointObj != null) {\n if(lEndpointObj.get(\"port-bindings\") != null && !((List<?>) lEndpointObj.get(\"port-bindings\")).isEmpty()) {\n resourcePath = ((YangObject) ((List<?>) lEndpointObj.get(\"port-bindings\")).get(0)).get(\"resource\");\n }\n }\n }\n if (resourcePath != null && isValidYangPath(resourcePath.toString())) {\n if(isLag) {\n resource = yangDB.getSingle(resourcePath.toString(), setFilterOnQueryParameters(qp, NSP_LAG_READ_FIELDS));\n }\n else {\n resource = yangDB.getSingle(resourcePath.toString(), setFilterOnQueryParameters(qp, NSP_PORT_READ_FIELDS_FOR_TP));\n }\n }\n }\n if (resource != null) {\n lTPAttrObj.setProperty(\"interface-name\", resource.get(\"name\").toString());\n if (isLag) {\n if(resource.get(\"configured-address\") != null) {\n String macAddress = convertMacAddress(resource.get(\"configured-address\").toString());\n if (macAddress != null) {\n lTPAttrObj.setProperty(\"mac-address\", macAddress);\n }\n }\n if (resource.get(\"encap-type\") != null) {\n String encapType = convertEncapType(resource.get(\"encap-type\").toString());\n if (encapType != null) {\n lTPAttrObj.setProperty(\"encapsulation-type\", encapType);\n }\n }\n if (resource.get(\"lag-index\") != null) {\n lTPAttrObj.setProperty(\"unnumbered-id\", Collections.singletonList(resource.get(\"lag-index\")));\n }\n List<Object> members = new ArrayList<>();\n List<?> resourceMembers = Collections.EMPTY_LIST;\n if(resource.get(\"members\") != null) {\n resourceMembers = (List<?>)resource.get(\"members\");\n }\n else {\n resource = yangDB.getSingle(resource.getIdentifier(), setFilterOnQueryParameters(qp, NSP_LAG_READ_FIELDS_MEMBERS));\n if(resource != null && resource.get(\"members\") != null) {\n resourceMembers = (List<?>) resource.get(\"members\");\n }\n }\n resourceMembers.forEach(member -> {\n String memberPath = ((String) member).substring(0, ((String) member).indexOf(\"/lag-member-details\"));\n IYangObject lMemberObj = yangDB.getSingle(memberPath, setFilterOnQueryParameters(qp, NSP_PORT_READ_FIELDS_FOR_LAG_MEMBER));\n if (lMemberObj != null) {\n //memberPath is the identifier of the port, not link endpoint\n //need to find endpoint because there could be no link on the lag member port, or unmanaged link\n //also look for the link with objectDetails.isLagMember=true\n String memberName = lMemberObj.get(\"name\").toString();\n if(!canDeleteTp(siteId, memberName, false, true, yangDB)) {\n members.add(String.format(IETF_L2_TP_PATH, siteId, memberName));\n }\n }\n });\n if (!members.isEmpty()) {\n lTPAttrObj.setProperty(\"member-link-tp\", members);\n }\n else {\n return null; //don't sync this lag endpoint to ietf\n }\n //set nsp-ietf-network-topology:nsp-attributes\n String nspServiceId = getServiceIdFromEndpointPath(aInEndpoint.getIdentifier());\n List<String> nspServiceIdList = new ArrayList<>();\n String lTpPath = String.format(IETF_L2_TP_PATH, siteId, endpointId);\n if(yangDB.exists(lTpPath)) {\n String tpAttrPath = lTpPath + \"/ietf-l2-topology:l2-termination-point-attributes\";\n IYangObject tpAttributes = yangDB.getSingle(tpAttrPath, setFilterOnQueryParameters(qp, IETF_TP_ATTR_READ_FIELDS));\n if(tpAttributes != null) {\n List<?> existingNspAttr = (List<?>)tpAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n if(!existingNspAttr.contains(nspServiceId)){\n existingNspAttr.forEach(attr -> nspServiceIdList.add(attr.toString()));\n nspServiceIdList.add(nspServiceId);\n lTPAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n }\n }\n }\n else {\n nspServiceIdList.add(nspServiceId);\n lTPAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n }\n } else {\n if(resource.get(\"hw-mac-address\") != null) {\n String macAddress = convertMacAddress(resource.get(\"hw-mac-address\").toString());\n if (macAddress != null) {\n lTPAttrObj.setProperty(\"mac-address\", macAddress);\n }\n }\n IYangObject lPortDetails = null;\n if (resource.get(\"port-details\") != null && !((List<?>) resource.get(\"port-details\")).isEmpty()) {\n lPortDetails = (IYangObject) ((List<?>) resource.get(\"port-details\")).get(0);\n }\n else {\n String portDetailsPath = resource.getIdentifier() + \"/port-details\";\n lPortDetails = yangDB.getSingle(portDetailsPath, setFilterOnQueryParameters(qp, NSP_PORT_DETAILS_READ_FIELDS_FOR_TP));\n }\n if (lPortDetails != null) {\n if (lPortDetails.get(\"encap-type\") != null) {\n String encapType = convertEncapType(lPortDetails.get(\"encap-type\").toString());\n if (encapType != null) {\n lTPAttrObj.setProperty(\"encapsulation-type\", encapType);\n }\n }\n if (lPortDetails.get(\"port-index\") != null) {\n lTPAttrObj.setProperty(\"unnumbered-id\", Collections.singletonList(lPortDetails.get(\"port-index\")));\n }\n }\n }\n }\n else {\n handleTpLogger.debug(\"RESOURCE MISSING FOR TP \" + String.format(IETF_L2_TP_PATH, siteId, endpointId));\n return null; //don't create/update tp, wait for another event\n }\n lTpObj.setProperty(\"ietf-l2-topology:l2-termination-point-attributes\", lTPAttrObj);\n return lTpObj;\n }\n\n private void handleLink(IYangObject aInSrcObject, boolean isNameUpdate, boolean isPortUpdate, IYangDB yangDB, QueryParameters qp) {\n\n String nspServiceId = aInSrcObject.get(\"id\").toString();\n\n List<?> endpoints = (List<?>)aInSrcObject.get(\"link-endpoint\");\n if (endpoints == null || endpoints.isEmpty()) {\n IYangObject lSourceObj = getSingleFromYangDb(\n yangDB, aInSrcObject.getIdentifier(), getFilteredQueryParameters(NSP_SERVICE_READ_FIELDS));\n if (lSourceObj != null) {\n endpoints = (List<?>)lSourceObj.get(\"link-endpoint\");\n }\n }\n\n if(endpoints == null || endpoints.size() != 2 || !isValidLinkEndpoints(endpoints)) {\n deleteLink(aInSrcObject, yangDB, qp); //delete if the link is already in ietf\n return; //do not sync this link to ietf\n }\n\n final Map<String,String> linkExtraProps = new HashMap<>(); //will hold source, destination, port-details props\n getLinkExtraFromEndpoints(endpoints, linkExtraProps, yangDB);\n if (linkExtraProps.get(\"srcNodeId\") == null || linkExtraProps.get(\"srcTpId\") == null ||\n linkExtraProps.get(\"destNodeId\") == null || linkExtraProps.get(\"destTpId\") == null) {\n\n handleLinkLogger.warn(\"ENDPOINTS MISCONFIGURED - CANNOT PROCESS LINK ID: \" + nspServiceId);\n return; //cannot proceed without valid endpoints info\n }\n String ietfLinkId = getIetfLinkId(linkExtraProps.get(\"srcNodeId\"), linkExtraProps.get(\"srcTpId\"),\n linkExtraProps.get(\"destNodeId\"), linkExtraProps.get(\"destTpId\"));\n doHandleLink(aInSrcObject, linkExtraProps, nspServiceId, isNameUpdate, isPortUpdate, ietfLinkId,\n linkExtraProps.get(\"srcNode\"), linkExtraProps.get(\"srcTp\"),\n linkExtraProps.get(\"destNode\"), linkExtraProps.get(\"destTp\"), yangDB, qp);\n\n if(aInSrcObject.get(\"direction\").toString().equals(\"bi-directional\"))\n {\n ietfLinkId = getIetfLinkId(linkExtraProps.get(\"destNodeId\"), linkExtraProps.get(\"destTpId\"),\n linkExtraProps.get(\"srcNodeId\"), linkExtraProps.get(\"srcTpId\"));\n doHandleLink(aInSrcObject, linkExtraProps, nspServiceId, isNameUpdate, isPortUpdate, ietfLinkId,\n linkExtraProps.get(\"destNode\"), linkExtraProps.get(\"destTp\"),\n linkExtraProps.get(\"srcNode\"), linkExtraProps.get(\"srcTp\"), yangDB, qp);\n }\n }\n\n private void doHandleLink(IYangObject aInSrcObject, Map<String,String> linkExtraProps, String nspServiceId, boolean isNameUpdate, boolean isPortUpdate,\n String ietfLinkId, String srcNode, String srcTp, String destNode, String destTp, IYangDB yangDB, QueryParameters qp)\n {\n\n IYangObject lLinkObject = new YangObject();\n lLinkObject.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lLinkObject.setProperty(\"link-id\", ietfLinkId);\n\n //source\n IYangObject lSrcObject = new YangObject();\n lSrcObject.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lSrcObject.setProperty(\"link-id\", ietfLinkId);\n lSrcObject.setProperty(\"source-node\", srcNode);\n lSrcObject.setProperty(\"source-tp\", srcTp);\n lLinkObject.setProperty(\"source\", lSrcObject);\n\n //destination\n IYangObject lDestObject = new YangObject();\n lDestObject.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lDestObject.setProperty(\"link-id\", ietfLinkId);\n lDestObject.setProperty(\"dest-node\", destNode);\n lDestObject.setProperty(\"dest-tp\", destTp);\n lLinkObject.setProperty(\"destination\", lDestObject);\n\n //link-attributes\n IYangObject lLinkAttrObj = new YangObject();\n lLinkAttrObj.setProperty(\"network-id\", IETF_L2_NETWORK_ID);\n lLinkAttrObj.setProperty(\"link-id\", ietfLinkId);\n if(linkExtraProps.get(\"rate\") != null) {\n lLinkAttrObj.setProperty(\"rate\", Math.round(Float.parseFloat(linkExtraProps.get(\"rate\"))));\n }\n if(linkExtraProps.get(\"duplex\") != null) {\n lLinkAttrObj.setProperty(\"duplex\", linkExtraProps.get(\"duplex\"));\n }\n if(linkExtraProps.get(\"auto-nego\") != null) {\n lLinkAttrObj.setProperty(\"auto-nego\", linkExtraProps.get(\"auto-nego\").equals(\"enabled\"));\n }\n\n String lLinkPath = String.format(IETF_L2_LINK_PATH, ietfLinkId);\n List<String> nspServiceIdList = new ArrayList<>();\n boolean isLinkExists = false;\n if(yangDB.exists(lLinkPath, qp)) {\n isLinkExists = true;\n String linkAttrPath = lLinkPath + \"/ietf-l2-topology:l2-link-attributes\";\n IYangObject linkAttributes = yangDB.getSingle(linkAttrPath, getFilteredQueryParameters(IETF_LINK_ATTR_READ_FIELDS));\n if(linkAttributes != null) {\n List<?> existingNspAttr = (List<?>)linkAttributes.get(\"nsp-ietf-network-topology:nsp-attributes\");\n if(!existingNspAttr.contains(nspServiceId)){\n existingNspAttr.forEach(attr -> nspServiceIdList.add(attr.toString()));\n nspServiceIdList.add(nspServiceId);\n lLinkAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n }\n\n //below logic is needed for nfmp managing scenario when link name is updated multiple times\n //how to decide if ietf link name should be updated??\n //try comparing nspServiceId with the first in the existing list\n if(isNameUpdate && nspServiceId.equals(existingNspAttr.get(0).toString())) {\n lLinkAttrObj.setProperty(\"name\", aInSrcObject.get(\"name\"));\n }\n\n //if name is the same, then update delay\n if(linkAttributes.get(\"name\").equals(aInSrcObject.get(\"name\"))) {\n lLinkAttrObj.setProperty(\"delay\", aInSrcObject.get(\"latency\"));\n }\n }\n }\n else {\n //set name only on create and don't overwrite by duplicates\n lLinkAttrObj.setProperty(\"name\", aInSrcObject.get(\"name\"));\n lLinkAttrObj.setProperty(\"delay\", aInSrcObject.get(\"latency\"));\n nspServiceIdList.add(nspServiceId);\n lLinkAttrObj.setProperty(\"nsp-ietf-network-topology:nsp-attributes\", nspServiceIdList);\n lLinkAttrObj.setProperty(\"flags\", Collections.singletonList(\"nsp-ietf-network-topology:\" + getServiceTypeFromPath(aInSrcObject.getIdentifier())));\n }\n lLinkObject.setProperty(\"ietf-l2-topology:l2-link-attributes\", lLinkAttrObj);\n\n if (!isLinkExists) {\n if(!isPortUpdate){\n handleLinkLogger.debug(\"CREATING LINK \" + lLinkPath);\n yangDB.createChild(IETF_L2_NETWORK_PATH, IETF_LINK_TYPE, lLinkObject, qp);\n }\n } else {\n handleLinkLogger.debug(\"UPDATING LINK \" + lLinkPath);\n yangDB.update(lLinkPath, lLinkObject, qp);\n }\n }\n\n private void getLinkExtraFromEndpoints (List<?> endpoints, Map<String,String> linkExtraProps, IYangDB yangDB) {\n endpoints.forEach(endpoint -> {\n String endpointId = ((IYangObject) endpoint).get(\"endpoint-id\").toString();\n String siteId = getSiteIdForEndpoint((IYangObject) endpoint);\n String lNodePath = String.format(IETF_L2_NODE_PATH, siteId);\n String lTpPath = String.format(IETF_L2_TP_PATH, siteId, endpointId);\n List<?> nspSources = (List<?>)((YangObject) endpoint).getExtraDatas().get(\"sources\");\n nspSources.forEach(source -> {\n if (source.toString().contains(\"@endpointA\")) {\n linkExtraProps.put(\"srcNode\", lNodePath);\n linkExtraProps.put(\"srcTp\", lTpPath);\n linkExtraProps.put(\"srcNodeId\", siteId);\n linkExtraProps.put(\"srcTpId\", endpointId);\n }\n else if (source.toString().contains(\"@endpointB\")) {\n linkExtraProps.put(\"destNode\", lNodePath);\n linkExtraProps.put(\"destTp\", lTpPath);\n linkExtraProps.put(\"destNodeId\", siteId);\n linkExtraProps.put(\"destTpId\", endpointId);\n }\n });\n if (((YangObject) endpoint).get(\"port-bindings\") != null && !((List<?>) ((YangObject) endpoint).get(\"port-bindings\")).isEmpty()) {\n Object resource = ((YangObject) ((List<?>) ((YangObject) endpoint).get(\"port-bindings\")).get(0)).get(\"resource\");\n if (resource != null && isValidYangPath(resource.toString())) {\n String portDetailsPath = resource + \"/port-details\";\n IYangObject lPortDetails = yangDB.getSingle(\n portDetailsPath,\n getFilteredQueryParameters(NSP_PORT_DETAILS_READ_FIELDS_FOR_LINK));\n if (lPortDetails != null) {\n if (lPortDetails.get(\"actual-rate\") != null && lPortDetails.get(\"actual-rate-units\") != null) {\n double rate = Double.parseDouble(lPortDetails.get(\"actual-rate\").toString());\n String units = lPortDetails.get(\"actual-rate-units\").toString();\n if(units.equals(\"mbps\")) {\n rate *= 1000;\n }\n else if(!units.equals(\"kbps\")) {\n rate = 0;\n }\n linkExtraProps.put(\"rate\", String.valueOf(rate));\n }\n if (lPortDetails.get(\"operational-duplex\") != null) {\n String duplex = convertDuplex(lPortDetails.get(\"operational-duplex\").toString());\n if (duplex != null) {\n linkExtraProps.put(\"duplex\", lPortDetails.get(\"operational-duplex\").toString());\n }\n }\n if (lPortDetails.get(\"auto-negotiate\") != null) {\n linkExtraProps.put(\"auto-nego\", lPortDetails.get(\"auto-negotiate\").toString());\n }\n }\n }\n }\n else {\n handleLinkLogger.debug(\"LINK PORT-BINDINGS MISSING {}, {}\", endpointId, siteId);\n }\n });\n }\n\n private String getServiceIdFromEndpointPath(String endpointPath) {\n String idKey = \"[id='\";\n return endpointPath.substring(endpointPath.indexOf(idKey) + idKey.length(), endpointPath.indexOf(\"']/link-endpoint\"));\n }\n\n private String getServiceTypeFromPath(String servicePath) {\n return servicePath.substring(\"/nsp-service:services/physical-layer/\".length(), servicePath.indexOf(\"[id=\"));\n }\n\n private String getNodeIdFromTpPath(String tpPath) {\n String nodeIdKey = \"[node-id='\";\n return tpPath.substring(tpPath.indexOf(nodeIdKey) + nodeIdKey.length(), tpPath.indexOf(\"']/ietf\"));\n }\n\n private String getTpIdFromTpPath(String tpPath) {\n String tpIdKey = \"[tp-id='\";\n return tpPath.substring(tpPath.indexOf(tpIdKey) + tpIdKey.length(), tpPath.lastIndexOf(\"']\"));\n }\n\n private String getIetfLinkId (String srcNodeId, String srcTpId, String destNodeId, String destTpId) {\n return srcNodeId + \":\" + srcTpId + \"--\" + destNodeId + \":\" + destTpId;\n }\n\n //this is a way to filter out manual lag links\n //check if objectDetails.linkType is set - manually created links don't have linkType entry\n private boolean isValidLinkType (String nspServiceId, IYangDB yangDB) {\n String query = String.format(\"SELECT count(s.dbId) FROM %s s JOIN s.objectDetails sod ON (KEY(sod) = :sodKey) \"\n + \"WHERE s.id = :nspServiceId\", NSP_SERVICE_TABLE);\n Long count = execute(yangDB.getDb(), tx -> (Long)tx.getEntityManager()\n .createQuery(query)\n .setParameter(\"sodKey\", \"linkType\")\n .setParameter(\"nspServiceId\", nspServiceId)\n .getSingleResult());\n return !(count != null && count.intValue() == 0);\n }\n\n //Filtering out links terminating on NE, Lag, Bundle, GNI, unmanaged\n private boolean isValidLinkEndpoints (List<?> endpoints) {\n boolean isValidEndpoint = true;\n for(Object endpoint : endpoints) {\n isValidEndpoint &= isValidPortEndpoint((IYangObject)endpoint);\n }\n return isValidEndpoint;\n }\n\n private boolean isValidLagEndpoints (List<?> endpoints) {\n boolean isValidEndpoint = true;\n for(Object endpoint : endpoints) {\n isValidEndpoint &= isValidLagEndpoint((IYangObject)endpoint);\n }\n return isValidEndpoint;\n }\n\n private boolean isValidPortEndpoint (IYangObject aInEndpointObject) {\n return isValidId(aInEndpointObject.get(\"endpoint-id\").toString())\n && isValidSiteId(getSiteIdForEndpoint(aInEndpointObject))\n && (aInEndpointObject.get(\"type\").toString().equals(\"physical-port\"));\n }\n\n private boolean isValidLagEndpoint (IYangObject aInEndpointObject) {\n return isValidId(aInEndpointObject.get(\"endpoint-id\").toString())\n && isValidSiteId(getSiteIdForEndpoint(aInEndpointObject))\n && aInEndpointObject.get(\"type\").toString().equals(\"lag\");\n }\n\n private String getSiteIdForEndpoint (IYangObject aInEndpointObject) {\n return aInEndpointObject.get(\"site-id\") != null\n ? aInEndpointObject.get(\"site-id\").toString() : \"0.0.0.0\";\n }\n\n private boolean isValidSiteId (String siteId) {\n return isValidId(siteId) && !(\"0.0.0.0\").equals(siteId);\n }\n\n private boolean isValidId (String id) {\n return (null != id) && (0 != id.length());\n }\n\n private boolean isValidYangPath (String path) {\n return path.startsWith(\"/nsp-equipment:\")\n || path.startsWith(\"/nsp-service:\")\n || path.startsWith(\"/ietf-network:\");\n }\n\n //todo: map encap-type?? ietf-l2-topology encap-types: ethernet, vlan, qinq, pbb, trill, vpls, vxlan\n private String convertEncapType (String encapType) {\n switch (encapType) {\n case \"qinq\":\n return IetfL2EncapType.QINQ.value;\n case \"dot1q\":\n return IetfL2EncapType.VLAN.value;//?\n case \"null-encap\":\n return IetfL2EncapType.ETHERNET.value;//?\n default:\n return null;\n }\n }\n\n private String convertDuplex (String duplex) {\n switch (duplex) {\n case \"full-duplex\":\n return IetfDuplexMode.FULL.value;\n case \"half-duplex\":\n return IetfDuplexMode.HALF.value;\n default:\n return null;\n }\n }\n\n private String convertMacAddress (String aInMacAddress) {\n String macAddress = aInMacAddress.replace(\"-\", \":\").replace(\".\", \"\");\n if (MAC_ADDRESS_PATTERN.matcher(macAddress).matches()) {\n return macAddress;\n }\n if (RAW_MAC_ADDRESS_PATTERN.matcher(macAddress).matches()) {\n StringBuilder macAddressSB = new StringBuilder(macAddress);\n macAddressSB.insert(10, ':')\n .insert(8, ':')\n .insert(6, ':')\n .insert(4, ':')\n .insert(2, ':');\n return macAddressSB.toString();\n }\n return null;\n }\n\n private QueryParameters getFilteredQueryParameters (Fields fields) {\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n return setFilterOnQueryParameters(qp, fields);\n }\n\n private QueryParameters setFilterOnQueryParameters (QueryParameters qp, Fields fields) {\n qp.setFields(fields);\n return qp;\n }\n\n private IYangObject getSingleFromYangDb(IYangDB yangDB, String path, QueryParameters qp) {\n List<IYangObject> list = yangDB.getMany(path, qp);\n if(list != null && !list.isEmpty()){\n return list.get(0);\n }\n return null;\n }\n\n private <T> T execute(IDB db, Function<ITransactionContext, T> fn) {\n try {\n if (Transactor.isInTransaction()) {\n return fn.apply(Transactor.getContext());\n } else {\n return Transactor.execute(db, fn, true);\n }\n } catch (DBRuntimeException e) {\n dataBaseAccessLogger.error(\"DB ACCESS ERROR: \", e);\n return null;\n }\n }\n\n}\n"
882
+ }
883
+ ]
884
+ },
885
+ {
886
+ "@": {
887
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler",
888
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler']",
889
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
890
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
891
+ },
892
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler",
893
+ "version": "2.0.2",
894
+ "java-code": [
895
+ {
896
+ "@": {
897
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler/java-code",
898
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.L3UnicastTopologyHandler']/java-code[page-number='1']",
899
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
900
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
901
+ },
902
+ "page-number": 1,
903
+ "page": "/**\n * ***************************************************************************\n *\n * $RCSfile$\n *\n * <Your Name Here>\n *\n * ***************************************************************************\n *\n * $Revision$\n *\n * $Id$\n *\n * ***************************************************************************\n *\n * Copyright (c) 2022 NOKIA Inc. All Rights Reserved. Please read the associated COPYRIGHTS file for more details.\n *\n * ***************************************************************************\n */\npackage com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.alu.nms.common.util.model.ModelFdn;\nimport com.google.common.net.InetAddresses;\nimport com.google.common.primitives.Ints;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport com.nokia.nsp.md.common.notif.ObjectCreation;\nimport com.nokia.nsp.md.common.notif.ObjectDeletion;\nimport com.nokia.nsp.md.common.notif.ObjectModification;\nimport com.nokia.nsp.md.common.notif.ObjectReplacement;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.ICustomHandler;\nimport com.nokia.nsp.md.converter.yang.plugin.common.IHandleDeleteTracking;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\n\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nsp.md.db.yang.api.config.YangDBConfig;\nimport com.nokia.nsp.md.db.yang.spi.DBType;\nimport com.nokia.nsp.md.ifg.yang.api.Field;\nimport com.nokia.nsp.md.ifg.yang.api.Fields;\nimport com.nokia.nsp.md.ifg.yang.api.YangException;\nimport com.nokia.nsp.md.restconf.client.api.IRestConfClient;\nimport com.nokia.nspos.persistence.api.IDB;\nimport com.nokia.nspos.persistence.impl.db.transaction.DBRuntimeException;\nimport com.nokia.nspos.persistence.impl.db.transaction.ITransactionContext;\nimport com.nokia.nspos.persistence.impl.db.transaction.Transactor;\nimport com.nokia.nspos.persistence.impl.db.util.ModelFdnUtil;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\nimport edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\n@SuppressFBWarnings({\"BX_UNBOXING_IMMEDIATELY_REBOXED\", \"DM_NUMBER_CTOR\", \"BX_UNBOXING_IMMEDIATELY_REBOXED\", \"NP_ALWAYS_NULL\", \"NP_LOAD_OF_KNOWN_NULL_VALUE\"})\npublic class L3UnicastTopologyHandler implements ICustomHandler, IHandleDeleteTracking\n{\n private static final Logger handleSrcClassLogger = LoggerFactory.getLogger(L3UnicastTopologyHandler.class.getName() + \".handleSrcClass\");\n private static final Logger handleUpdateLogger = LoggerFactory.getLogger(L3UnicastTopologyHandler.class.getName() + \".handleUpdate\");\n private static final Logger logger = LoggerFactory.getLogger(L3UnicastTopologyHandler.class.getName());\n\n private static String NETWORKS_PATH = \"/ietf-network:networks\";\n private static String L3_NETWORK_PATH = NETWORKS_PATH + \"/network[network-id='%s']\";\n private static final String LINK_PATH_PREFIX = \"/ietf-network-topology:link\";\n private static final String LINK_PATH = LINK_PATH_PREFIX + \"[link-id='%s']\";\n private static final String NODE_PATH = \"/node[node-id='%s']\";\n private static final String TP_PATH = \"/ietf-network-topology:termination-point[tp-id='%s']\";\n\n private static final String TP_TYPE = \"ietf-network-topology:termination-point\";\n private static final String LINK_TYPE = \"ietf-network-topology:link\";\n private static final String NETWORK_CLASS_PATH =\"ietf-network:/networks/network\";\n private static final String NODE_CLASS_PATH = NETWORK_CLASS_PATH + \"/node\";\n private static final String LINK_CLASS_PATH = NETWORK_CLASS_PATH + \"/\" + LINK_TYPE;\n private static final String SR_MPLS_TYPE = \"ietf-sr-mpls-topology:sr-mpls\";\n\n private static final String NETWORK_ID = \"network-id\";\n private static final String NODE_ID = \"node-id\";\n private static final String LINK_ID = \"link-id\";\n private static final String TP_ID = \"tp-id\";\n private static final String NAME = \"name\";\n private static final String ROUTER_ID = \"router-id\";\n private static final String IP_ADDRESS = \"ip-address\";\n private static final String ID = \"id\";\n private static final String PREFIX = \"prefix\";\n private static final String MSDS = \"msds\";\n private static final String SIDS = \"sids\";\n private static final String MSD_TYPE = \"msd-type\";\n private static final String MSD_VALUE= \"msd-value\";\n private static final String VALUE_TYPE= \"value-type\";\n private static final String SID= \"sid\";\n private static final String ADDRESS_FAMILY= \"address-family\";\n private static final String IS_ELG_PROT= \"is-eligible-for-protection\";\n private static final String IS_LOCAL= \"is-local\";\n private static final String IS_PART_SET= \"is-part-of-set\";\n private static final String IS_PERS= \"is-persistent\";\n private static final String IS_ON_LAN= \"is-on-lan\";\n private static final String WEIGHT= \"weight\";\n private static final String SUBNET = \"subnet\";\n private static final String NODE_TYPE = \"node-type\";\n\n private static final String IETF_NETWORK_PATH = NETWORKS_PATH + \"/network\";\n\n private static final String NSP_SERVICE_IGP_LAYER_PATH = \"/nsp-service:services/igp-layer\";\n private static final String NSP_SERVICE_ADMIN_DOMAIN_PATH = NSP_SERVICE_IGP_LAYER_PATH + \"/admin-domain[name='%s']\";\n private static final String NSP_SERVICE_ROUTING_INS_PATH = \"/routing-instance[id='%s']\";\n private static final String NSP_SERVICE_SUBNET_PATH = \"/subnet[id='%s']\";\n private static final String NSP_SERVICE_LINK_PATH = NSP_SERVICE_IGP_LAYER_PATH + \"/ip-links[name='%s']\";\n private static final String NSP_SERVICE_GENERIC_PREFIX = NSP_SERVICE_IGP_LAYER_PATH + \"/admin-domain/routing-instance/prefix\";\n\n private static final String CREATE = \"CREATE\";\n private static final String UPDATE = \"UPDATE\";\n private static final String DELETE = \"DELETE\";\n\n private static final String L2_NETWORK_ID = \"L2Topology\";\n private static final String L2_NETWORK_PATH = String.format(L3_NETWORK_PATH, L2_NETWORK_ID);\n private static final String NETWORK_REF = \"network-ref\";\n private static final String NODE_REF = \"node-ref\";\n private static final String TP_REF = \"tp-ref\";\n private static final String LINK_REF = \"link-ref\";\n\n private static final String SUBINTERFACE_FILTER = \"/nsp-network:network/node[node-id='%s']/node-root/\" +\n \"openconfig-interfaces:interfaces/interface/subinterfaces/subinterface\";\n private static final String SUBINTERFACE_UNNUM_FILTER = \"[index='%s']\";\n private static final String SUPPORTING_NETWORK = \"supporting-network\";\n private static final String SUPPORTING_NODE = \"supporting-node\";\n private static final String SUPPORTING_TP = \"supporting-termination-point\";\n private static final String SUPPORTING_LINK = \"supporting-link\";\n\n private static final String ADMIN_DOMAIN_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain\";\n private static final String ADMIN_DOMAIN_FIELDS = \"name\";\n private static final String IP_LINK_SRC_PATH = \"nsp-service:/services/igp-layer/ip-links\";\n private static final String IP_LINK_FIELDS = \"admin-domains;protocol;name;destination-node;source-node;ip-address;\" +\n \"cost;te-metric;latency;opposite-link;isis-level;bw;available-bw;un-resv-bw;one-way-min-delay;one-way-max-delay;\" +\n \"srg-labels;sids\";\n private static final String ROUTING_INSTANCE_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain/routing-instance\";\n private static final String ROUTING_INSTANCE_FIELDS = \"node-type;protocols;id;name;router/ne;router-id;\" +\n \"prefix(ip-address;metric);msds\";\n private static final String SUBNET_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain/subnet\";\n private static final String SUBNET_FIELDS = \"node-type;protocol;id;name;dr-ip-address\";\n private static final String PREFIX_SRC_PATH = \"nsp-service:/services/igp-layer/admin-domain/routing-instance/prefix\";\n\n public static final boolean TE_TOPOLOGY_ENABLED = true;\n private static final String TIME_FIELD_LAST_MODIFIED = \"lastModifiedTime\";\n\n private List<String> srcClasses = new ArrayList<> (Arrays.asList(\n \"nsp-service:/services/igp-layer/admin-domain\",\n \"nsp-service:/services/igp-layer/admin-domain/routing-instance\",\n \"nsp-service:/services/igp-layer/admin-domain/routing-instance/prefix\",\n \"nsp-service:/services/igp-layer/admin-domain/subnet\",\n \"nsp-service:/services/igp-layer/ip-links\"\n ));\n\n private static Map<String, Set<String>> supportingNodeMap = new ConcurrentHashMap();\n private static Map<String, String> supportingTpMap = new ConcurrentHashMap();\n private static Map<String, String> supportingLinkMap = new ConcurrentHashMap();\n private static Map<String, String> oppLinkMap = new ConcurrentHashMap();\n\n private ScheduledExecutorService correlationService;\n private ThreadPoolExecutor correlationWorker;\n private static Map<String, L2TpCreateTask> l2TpCreateEvents = new ConcurrentHashMap();\n private static Map<String, L2TpDeleteTask> l2TpDeleteEvents = new ConcurrentHashMap();\n private static Map<String, L2LinkCreateTask> l2LinkCreateEvents = new ConcurrentHashMap();\n private static Map<String, L2LinkDeleteTask> l2LinkDeleteEvents = new ConcurrentHashMap();\n\n public L3UnicastTopologyHandler() {\n try {\n YangPluginMdConverterProvider mdConverterFw = YangPluginMdConverterProvider.getInstance();\n IMdConverterFw converterFw = mdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n populateSuportingNodeMap(yangDB);\n populateSuportingTpMap(yangDB);\n populateSuportingLinkMap(yangDB);\n correlationWorker = new ThreadPoolExecutor(\n 1, 2, 5L, TimeUnit.MINUTES, new LinkedBlockingQueue<>(),\n new ThreadFactoryBuilder().setNameFormat(\"L3-correlaion-worker-%d\").build());\n correlationWorker.allowCoreThreadTimeOut(true);\n }\n catch (Exception e) {\n logger.warn(\"Could not populate the correlation cache\");\n }\n }\n\n void handleL2CreateEvent(ObjectCreation aInObjectNotification, IMdConverterFw aInMdConverterFw) {\n String instanceId = aInObjectNotification.getInstanceId();\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - handleL2CreateEvent - {}\", instanceId);\n }\n if(instanceId.contains(L2_NETWORK_PATH)) {\n if (instanceId.equals(L2_NETWORK_PATH)) {\n QueryParameters qp = getFilteredQueryParameters(NETWORK_ID);\n qp.setDepth(2);\n List<IYangObject> l3NetworkObjList = yangDB.getMany(IETF_NETWORK_PATH, qp);\n if(l3NetworkObjList != null && !l3NetworkObjList.isEmpty()) {\n for(IYangObject l3NetworkObj : l3NetworkObjList) {\n String networkId = (String) l3NetworkObj.get(NETWORK_ID);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - NETWORK ID : {}\", networkId);\n }\n if(networkId != null && (networkId.contains(\"-ospf\") || networkId.contains(\"-isis\"))) {\n String supportingNetworkIdentifier = String.format(L3_NETWORK_PATH, networkId) + \"/\" + SUPPORTING_NETWORK;\n if(!yangDB.exists(supportingNetworkIdentifier)) {\n logger.debug(\"L3 - createSupportingNetwork {}\", instanceId);\n createSupportingNetwork(yangDB, getFilteredQueryParameters(null), networkId, instanceId);\n }\n }\n }\n }\n } else if (instanceId.contains(TP_TYPE)) {\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n String port = StringUtils.substringBetween(instanceId, \"[tp-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n if (l2TpCreateEvents.containsKey(neId)) {\n L2TpCreateTask l2TpTask = l2TpCreateEvents.get(neId);\n if(l2TpDeleteEvents.containsKey(neId) && l2TpDeleteEvents.get(neId).portsToDelete.contains(port)) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} not added to the queue {} as it was in the list to be removed\", port, neId);\n }\n l2TpDeleteEvents.get(neId).portsToDelete.remove(port);\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} added to the queue {} \", port, neId);\n }\n l2TpTask.portsToAdd.put(port, 1);\n }\n } else {\n L2TpCreateTask tpTask = new L2TpCreateTask(neId, port, aInMdConverterFw);\n l2TpCreateEvents.put(neId, tpTask);\n }\n synchronized (this) {\n if (correlationService == null || correlationService.isShutdown()) {\n logger.debug(\"L3 - L2 - Correlation - correlationService has been started that will run periodically until correlation is complete\");\n correlationService = Executors.newScheduledThreadPool(1,\n new ThreadFactoryBuilder().setNameFormat(\"L3-CorrelationHandler-to-L2\").build());\n correlationService.scheduleAtFixedRate(() -> correlateTpsAndLinks(), 2, 2, TimeUnit.MINUTES);\n }\n }\n }\n } else if (instanceId.contains(\"/node\")) {\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - NE ID - {}\", neId);\n }\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n for(List<String> router: routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n String supportingNodeIden = nodeIdentifer + \"/\" + SUPPORTING_NODE;\n if(!yangDB.exists(supportingNodeIden) && yangDB.exists(nodeIdentifer)) {\n logger.debug(\"L3 - createSupportingNode {}\", instanceId);\n createSupportingNode(yangDB, getFilteredQueryParameters(null), networkId, router.get(0), instanceId, nodeIdentifer);\n }\n }\n }\n } else if(instanceId.contains(LINK_TYPE)) {\n if(!l2LinkCreateEvents.containsKey(instanceId)) {\n L2LinkCreateTask l2LinkCreateTask = new L2LinkCreateTask(instanceId, aInMdConverterFw);\n l2LinkCreateEvents.put(instanceId, l2LinkCreateTask);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - links to correlate: {}\", l2LinkCreateEvents.keySet());\n }\n startCorrelationService();\n }\n }\n }\n }\n\n List<String> getTpDetails(String[] tpDetails, IYangDB yangDB, IMdConverterFw aInMdConverterFw, List<String> aInNetworkDetails) {\n List<String> l3SourceTps = new ArrayList<>();\n if(tpDetails != null && tpDetails.length == 2) {\n String sourceNeId = tpDetails[0];\n String sourcePort = tpDetails[1];\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, sourceNeId);\n if(routers == null) {\n return l3SourceTps;\n }\n for(List<String> router: routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n if(aInNetworkDetails != null) {\n aInNetworkDetails.add(networkId);\n }\n QueryParameters qp = getFilteredQueryParameters(\"tp-id;\" + SUPPORTING_TP);\n qp.setDepth(2);\n List<IYangObject> tpList = yangDB.getMany(nodeIdentifer + \"/\" + TP_TYPE, qp);\n if(tpList != null && !tpList.isEmpty()) {\n for(IYangObject tp : tpList) {\n String tpId = (String) tp.get(\"tp-id\");\n String portName = null;\n if(tp.get(SUPPORTING_TP) == null || ((List<IYangObject>) tp.get(SUPPORTING_TP)).isEmpty()) {\n portName = getPortDetailsFromDb(tpId, yangDB, sourceNeId);\n if (portName == null) {\n //try to get the details via openconfig restconf. It works for mdm managed nodes\n portName = getSubInterfaces(sourceNeId, aInMdConverterFw, tpId);\n }\n }\n else {\n List<IYangObject> supportingTp = (List<IYangObject>) tp.get(SUPPORTING_TP);\n String tpRef = (String) supportingTp.get(0).get(TP_REF);\n portName = StringUtils.substringBetween(tpRef, \"[tp-id='\", \"']\");\n }\n if(portName != null && portName.equals(sourcePort)) {\n l3SourceTps.add(router.get(0) + \":\" + tpId);\n }\n }\n }\n }\n }\n return l3SourceTps;\n }\n\n void handleL2DeleteEvent(ObjectDeletion aInObjectNotification, IMdConverterFw aInMdConverterFw) {\n String instanceId = aInObjectNotification.getInstanceId();\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - handleL2DeleteEvent - {}\", instanceId);\n }\n IYangDB yangDB = aInMdConverterFw.getIYangDB();\n\n if(instanceId.contains(L2_NETWORK_PATH)) {\n if (instanceId.equals(L2_NETWORK_PATH)) {\n QueryParameters qp = getFilteredQueryParameters(NETWORK_ID);\n qp.setDepth(2);\n List<IYangObject> l3NetworkObjList = yangDB.getMany(IETF_NETWORK_PATH, qp);\n if(l3NetworkObjList != null && !l3NetworkObjList.isEmpty()) {\n for(IYangObject l3NetworkObj : l3NetworkObjList) {\n String networkId = (String) l3NetworkObj.get(NETWORK_ID);\n if(networkId != null && (networkId.contains(\"-ospf\") || networkId.contains(\"-isis\"))) {\n String supportingNetworkIdentifier = String.format(L3_NETWORK_PATH, networkId) + \"/\" + SUPPORTING_NETWORK;\n if(yangDB.exists(supportingNetworkIdentifier)) {\n updateInDb(yangDB, null, supportingNetworkIdentifier, null, null, DELETE, null, qp);\n }\n }\n }\n }\n } else if (instanceId.contains(TP_TYPE)) {\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n String port = StringUtils.substringBetween(instanceId, \"[tp-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n if (l2TpDeleteEvents.containsKey(neId)) {\n L2TpDeleteTask l2TpTask = l2TpDeleteEvents.get(neId);\n if(l2TpCreateEvents.containsKey(neId) && l2TpCreateEvents.get(neId).portsToAdd.containsKey(port)) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} not added to the delete queue {} as it was in the list to be added\", port, neId);\n }\n l2TpCreateEvents.get(neId).portsToAdd.remove(port);\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Correlation - Port {} added to the delete queue {} \", port, neId);\n }\n l2TpTask.portsToDelete.add(port);\n }\n } else {\n L2TpDeleteTask tpTask = new L2TpDeleteTask(neId, port, aInMdConverterFw);\n l2TpDeleteEvents.put(neId, tpTask);\n }\n if(logger.isDebugEnabled()) {\n logger.debug(l2TpDeleteEvents.keySet().toString());\n }\n startCorrelationService();\n }\n } else if (instanceId.contains(\"/node\")) {\n if(supportingNodeMap.containsKey(instanceId)) {\n for (String nodeIden : supportingNodeMap.get(instanceId)) {\n String supportingNodeIden = nodeIden + \"/\" + SUPPORTING_NODE;\n if (yangDB.exists(supportingNodeIden)) {\n logger.debug(\"L3 - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(yangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n String supportingTpIden = nodeIden + \"/\" + TP_TYPE + \"/\" + SUPPORTING_TP;\n if(yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTps on node {}\", supportingNodeIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n supportingTpMap.entrySet().removeIf(entry -> entry.getKey().startsWith(instanceId));\n }\n }\n }\n supportingNodeMap.remove(instanceId);\n return;\n }\n String neId = StringUtils.substringBetween(instanceId, \"[node-id='\", \"']\");\n if(neId != null || !neId.isEmpty()) {\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n if(routers != null) {\n for (List<String> router : routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n String supportingNodeIden = nodeIdentifer + \"/\" + SUPPORTING_NODE;\n if (yangDB.exists(supportingNodeIden)) {\n logger.debug(\"L3 - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(yangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n } else if(instanceId.contains(LINK_TYPE)) {\n if(!l2LinkDeleteEvents.containsKey(instanceId)) {\n L2LinkDeleteTask l2LinkDeleteTask = new L2LinkDeleteTask(instanceId, aInMdConverterFw);\n l2LinkDeleteEvents.put(instanceId, l2LinkDeleteTask);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - links to delete correlation: {}\", l2LinkDeleteEvents.keySet());\n }\n startCorrelationService();\n }\n }\n }\n }\n\n private void deleteL2SupportingTps(List<String> portsToDelete, String neId, IYangDB yangDB) {\n List<String> deletedPorts = new ArrayList<>();\n for(String port : portsToDelete) {\n String instanceId = L2_NETWORK_PATH + String.format(NODE_PATH, neId) + String.format(TP_PATH, port);\n if (supportingTpMap.containsKey(instanceId)) {\n String supportingTpIden = supportingTpMap.get(instanceId) + \"/\" + SUPPORTING_TP;\n if (yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTp {}\", supportingTpIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n supportingTpMap.remove(instanceId);\n deletedPorts.add(port);\n }\n }\n\n portsToDelete.removeAll(deletedPorts);\n if(portsToDelete.isEmpty()) {\n return;\n }\n\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n if(routers != null) {\n for (List<String> router : routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n QueryParameters qp = getFilteredQueryParameters(\"tp-id;\" + SUPPORTING_TP);\n qp.setDepth(2);\n List<IYangObject> tpList = yangDB.getMany(nodeIdentifer + \"/\" + TP_TYPE, qp);\n if (tpList != null && !tpList.isEmpty()) {\n for (IYangObject tp : tpList) {\n if (tp.get(SUPPORTING_TP) != null) {\n String supportingTpRef = (String) ((IYangObject) ((List) tp.get(SUPPORTING_TP)).get(0)).get(TP_REF);\n String port = StringUtils.substringBetween(supportingTpRef, \"[tp-id='\", \"']\");\n if (portsToDelete.contains(port)) {\n String tpId = (String) tp.get(TP_ID);\n String tpIden = nodeIdentifer + String.format(TP_PATH, tpId);\n String supportingTpIden = tpIden + \"/\" + SUPPORTING_TP;\n if (yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTp {}\", supportingTpIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n portsToDelete.remove(port);\n }\n }\n }\n }\n }\n }\n }\n\n private void correlateTpsAndLinks() {\n\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Running routine correlation task\");\n }\n Map<String, L2TpCreateTask> l2TpCreateTaskMap =new HashMap<>(l2TpCreateEvents);\n l2TpCreateEvents.clear();\n Map<String, L2TpDeleteTask> l2TpDeleteTaskMap =new HashMap<>(l2TpDeleteEvents);\n l2TpDeleteEvents.clear();\n Map<String, L2LinkCreateTask> l2LinkCreateTaskMap =new HashMap<>(l2LinkCreateEvents);\n l2LinkCreateEvents.clear();\n Map<String, L2LinkDeleteTask> l2LinkDeleteTaskMap =new HashMap<>(l2LinkDeleteEvents);\n l2LinkDeleteEvents.clear();\n\n if(!l2TpCreateTaskMap.isEmpty()) {\n for(L2TpCreateTask l2TpTask : l2TpCreateTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate ports creation on {}\", l2TpTask.neId);\n correlationWorker.execute(l2TpTask);\n }\n }\n\n if(!l2TpDeleteTaskMap.isEmpty()) {\n for(L2TpDeleteTask l2TpTask : l2TpDeleteTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate ports deletion on {}\", l2TpTask.neId);\n correlationWorker.execute(l2TpTask);\n }\n }\n\n if(!l2LinkCreateTaskMap.isEmpty()) {\n for(L2LinkCreateTask l2LinkTask : l2LinkCreateTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate link creation {}\", l2LinkTask.linkId);\n correlationWorker.execute(l2LinkTask);\n }\n }\n\n if(!l2LinkDeleteTaskMap.isEmpty()) {\n for(L2LinkDeleteTask l2LinkTask : l2LinkDeleteTaskMap.values()) {\n logger.debug(\"L3 - Trying to correlate link deletion {}\", l2LinkTask.linkId);\n correlationWorker.execute(l2LinkTask);\n }\n }\n\n if(l2TpCreateEvents.isEmpty() && l2TpDeleteEvents.isEmpty()\n && l2LinkCreateEvents.isEmpty() && l2LinkDeleteEvents.isEmpty()) {\n logger.debug(\"L3 - correlationService is shutdown\");\n correlationService.shutdown();\n }\n\n }\n\n @Override\n public int readSrcObjectDepth(String aInSrcClassPath) {\n if(aInSrcClassPath.equals(ROUTING_INSTANCE_SRC_PATH)) {\n return 3;\n }\n else {\n return 2;\n }\n }\n\n @Override\n public Fields srcFilterFieldsToInclude(String aInSrcClassPath) {\n if(aInSrcClassPath.equals(ADMIN_DOMAIN_SRC_PATH)) {\n return Fields.parse(ADMIN_DOMAIN_FIELDS);\n }\n else if(aInSrcClassPath.equals(IP_LINK_SRC_PATH)) {\n return Fields.parse(IP_LINK_FIELDS);\n }\n else if(aInSrcClassPath.equals(ROUTING_INSTANCE_SRC_PATH)) {\n return Fields.parse(ROUTING_INSTANCE_FIELDS);\n }\n else if(aInSrcClassPath.equals(SUBNET_SRC_PATH)) {\n return Fields.parse(SUBNET_FIELDS);\n }\n else {\n return null;\n }\n }\n\n @Override\n public void handlePostResyncDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n //this method is called after the fwk deletes the object. extra post processing logics like cleaning up routing instances/tp.\n if(logger.isDebugEnabled()) {\n logger.debug(\"POST RE-SYNC DELETE - aInSrcClass:{}, aInSyncClass:{}\", aInSrcClass, aInSyncClass);\n }\n }\n\n @Override\n public void handleTrackedDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, String aInIdentifier, Map<String, Object> aInData, YangPluginMdConverterProvider aInYangPlugin)\n {\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInIdentifier:{}, aInData:{}\", aInSrcClass, aInSyncClass, aInIdentifier, aInData);\n }\n IMdConverterFw converterFw = aInYangPlugin.getiMdConverterFw();\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n IYangDB yangDB = converterFw.getIYangDB();\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInSrcClass.getSrcClassPath().equals(IP_LINK_SRC_PATH)) {\n Map<String, Object> linkObj = new HashMap<>();\n linkObj.put(NAME, StringUtils.substringBetween(aInIdentifier, \"ip-links[name='\", \"'\"));\n logger.debug(\"L3 - handleTrackedDelete - DELETING LINK - {} \", aInIdentifier);\n deleteLink(yangDB, qp, linkObj, dbConfig, null);\n }\n else if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n String ipAddress = StringUtils.substringBetween(aInIdentifier, \"prefix[ip-address='\", \"'\");\n logger.debug(\"L3 - handleTrackedDelete - DELETING PREFIX {}, {} \", aInIdentifier, ipAddress);\n deletePrefix(yangDB, qp, aInIdentifier, ipAddress);\n }\n else if(aInSrcClass.getSrcClassPath().equals(SUBNET_SRC_PATH)) {\n String networkId = extractAdminDomain(aInIdentifier) + \"-\" + aInData.get(\"protocols\");\n logger.debug(\"L3 - handleTrackedDelete - DELETING SUBNET - {}, {} \", aInIdentifier, networkId);\n deleteNode(yangDB, qp, aInData, dbConfig, networkId, null);\n }\n else if(aInSrcClass.getSrcClassPath().equals(ADMIN_DOMAIN_SRC_PATH)) {\n String adminDomain = StringUtils.substringBetween(aInIdentifier, \"admin-domain[name='\", \"'\");\n IYangObject yangObj = new YangObject();\n yangObj.setProperty(NAME, adminDomain);\n logger.debug(\"L3 - handleTrackedDelete - DELETING NETWORK - {} \", aInIdentifier);\n deleteNetwork(yangDB, qp, yangObj);\n }\n }\n\n\n public void handleResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInExistingObject,\n String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n if(handleSrcClassLogger.isDebugEnabled()) {\n handleSrcClassLogger.debug(\"---------------------------------------------------------RE-SYNC----------------------------------------------------------------------\");\n handleSrcClassLogger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n }\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n\n if (aInSyncClass.getDestClassPath().equals(NETWORK_CLASS_PATH)) {\n handleSrcClassLogger.debug(\"L3 - RESYNC NETWORK - {}\", aInSrcObject.get(NAME) );\n createL3Network(aInSrcObject, yangDB, dbConfig, converterFw);\n }\n else if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n Map<String, Object> srcObject = aInSrcObject.asMap();\n handleSrcClassLogger.debug(\"L3 - RESYNC NODE - {}\", srcObject.get(ID));\n String networkId = getNetworkIdFromMeta(yangDB, srcObject);\n if(networkId == null) {\n return;\n }\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n //could be routing instance or subnet.\n if(yangDB.exists(networkPathIdentifier, qp)) {\n if (srcObject.get(NODE_TYPE).equals(SUBNET)) {\n if(handleSrcClassLogger.isDebugEnabled()) {\n handleSrcClassLogger.debug(\"L3 - SUBNET\");\n }\n createSubnet(srcObject, yangDB, dbConfig, networkId, null);\n } else {\n if(handleSrcClassLogger.isDebugEnabled()) {\n handleSrcClassLogger.debug(\"L3 - NODE\");\n }\n createRoutingInstance(srcObject, yangDB, networkId);\n }\n }\n else {\n handleSrcClassLogger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", srcObject.get(ID));\n }\n\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n Map<String, Object> srcObject = aInSrcObject.asMap();\n handleSrcClassLogger.debug(\"L3 - RESYNC LINK - {}\", srcObject.get(NAME));\n String networkId = getNetworkIdFromLink((List<String>) srcObject.get(\"admin-domains\"), (String) srcObject.get(\"protocol\"));\n if(networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n if (yangDB.exists(networkPathIdentifier, qp)) {\n createLink(srcObject, yangDB, converterFw, networkId, false, null);\n }\n else {\n handleSrcClassLogger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", srcObject.get(NAME));\n }\n }\n }\n }\n\n @Override\n public void handleCreateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectCreation aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n\n if(aInEvent.getInstanceId().contains(L2_NETWORK_PATH)) {\n handleL2CreateEvent(aInEvent, converterFw);\n return;\n }\n\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n if(logger.isDebugEnabled()) {\n logger.debug(\"---------------------------------------------------CREATION---------------------------------------------------------------------------\");\n }\n IYangDB yangDB = converterFw.getIYangDB();\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n if (aInSyncClass.getDestClassPath().equals(NETWORK_CLASS_PATH)) {\n logger.debug(\"L3 - CREATE NETWORK\");\n createL3Network(aInEvent.getEntity(), yangDB, dbConfig, converterFw);\n }\n else if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n logger.debug(\"L3 - CREATE PREFIX\");\n createPrefix(yangDB, getFilteredQueryParameters(null), aInEvent);\n }\n else {\n logger.debug(\"L3 - CREATE NODE\");\n Map<String, Object> srcObject = aInEvent.getEntity().asMap();\n String id = (String) srcObject.get(ID);\n String adminDomain = getAdminDomainFromMeta(srcObject);\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += srcObject.get(NODE_TYPE).equals(SUBNET) ? String.format(NSP_SERVICE_SUBNET_PATH, id)\n : String.format(NSP_SERVICE_ROUTING_INS_PATH, id);\n QueryParameters qp = srcObject.get(NODE_TYPE).equals(SUBNET) ?\n getFilteredQueryParameters(\"node-type;protocol;id;name;dr-ip-address\") :\n getFilteredQueryParameters(\"node-type;protocols;id;name;router/ne;router-id;prefix(ip-address;metric)\");\n //IYangObject nodeObj = yangDB.getSingle(nspServiceNodeIden, qp);\n //GetMany for debug\n qp.setLimit(2);\n List<IYangObject> nodeObjs = yangDB.getMany(nspServiceNodeIden, qp);\n IYangObject nodeObj=null;\n if(nodeObjs.size()>0){\n nodeObj=nodeObjs.get(0);\n }\n if(nodeObjs.size()>1){\n logger.error(\"More than one object returned for path: {}\", nspServiceNodeIden);\n }\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(yangDB, nodeMap);\n if(networkId == null) {\n return;\n }\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n qp = getFilteredQueryParameters(null);\n //could be routing instance or subnet.\n if (yangDB.exists(networkPathIdentifier, qp)) {\n if (nodeMap.get(NODE_TYPE).equals(SUBNET)) {\n if (logger.isDebugEnabled()) {\n logger.debug(\"L3 - CREATE SUBNET\");\n }\n createSubnet(nodeMap, yangDB, dbConfig, networkId, null);\n } else {\n if (logger.isDebugEnabled()) {\n logger.debug(\"L3 - CREATE ROUTING-INSTANCE\");\n }\n createRoutingInstance(nodeMap, yangDB, networkId);\n }\n }\n } else {\n logger.warn(\"L3 - Not found: \" + nspServiceNodeIden);\n }\n }\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n logger.debug(\"L3 - CREATE LINK\");\n String name = (String) aInEvent.getEntity().get(NAME);\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n QueryParameters qp = getFilteredQueryParameters(IP_LINK_FIELDS);\n IYangObject linkObj = yangDB.getSingle(nspServiceIpLinkIden, qp);\n\n if(linkObj != null) {\n String networkId = getNetworkIdFromLink((List<String>) linkObj.get(\"admin-domains\"), (String) linkObj.get(\"protocol\"));\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if (yangDB.exists(networkPathIdentifier, qp)) {\n createLink(linkObj.asMap(), yangDB, converterFw, networkId, true, null);\n } else {\n logger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", linkObj.get(NAME));\n }\n }\n }\n }\n }\n\n void createL3Network(IYangObject aInSrcObject, IYangDB aInYangDB, YangDBConfig aInDbConfig, IMdConverterFw aInConverterFw) {\n\n String adminDomain = (String) aInSrcObject.get(NAME);\n if(\"UnknownDomain\".equals(adminDomain)) {\n return;\n }\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInSrcObject != null) {\n String networkId = getNetworkId(aInYangDB, aInSrcObject);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n try {\n if (!aInYangDB.exists(networkPathIdentifier, qp)) {\n logger.debug(\"L3 - creating new network: {}\", networkId);\n qp = getFilteredQueryParameters(null);\n\n IYangObject l3NetworkObj = new YangObject();\n l3NetworkObj.setProperty(NETWORK_ID, networkId);\n IYangObject networkTypesObj = new YangObject();\n IYangObject l3UnicastNwObj = new YangObject();\n l3UnicastNwObj.setProperty(SR_MPLS_TYPE, new YangObject());\n networkTypesObj.setProperty(\"ietf-l3-unicast-topology:l3-unicast-topology\", l3UnicastNwObj);\n l3NetworkObj.setProperty(\"network-types\", networkTypesObj);\n\n YangObject topologyAttrObj = new YangObject();\n topologyAttrObj.setProperty(\"name\", aInSrcObject.get(NAME));\n l3NetworkObj.setProperty(\"ietf-l3-unicast-topology:l3-topology-attributes\", topologyAttrObj);\n\n updateInDb(aInYangDB, l3NetworkObj, \"\", NETWORKS_PATH, \"network\", CREATE, null, qp);\n\n\n //create supporting-network\n String supportingNetworkRef = getSupportingNetworkRef(aInYangDB, qp);\n if(supportingNetworkRef != null) {\n createSupportingNetwork(aInYangDB, qp, networkId, supportingNetworkRef);\n }\n /* resync is based on equipment.networkelement table and so if there are no corresponding NEs\n discovered for the routers, we wouldn't get any nodes. so it is important (at least for now) to\n get the network and build the nodes from that info instead of relying on the node resync events.\n */\n// createRoutingInstances(aInSrcObject.get(\"routing-instance\"), aInYangDB, networkId);\n// createSubnets(aInSrcObject.get(\"subnet\"), aInYangDB, aInDbConfig, networkId);\n } else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - network exists already - {} \", networkId);\n }\n }\n } catch (Exception e) {\n logger.error(\"L3 - Exception when creating IETF L3 network: \" + networkId, e);\n return;\n }\n\n //create TE Network\n String teNetworkRef = createTeNetwork(networkId, aInYangDB);\n if(teNetworkRef != null) {\n createTeNetworkRef(aInYangDB, getFilteredQueryParameters(null), networkId, teNetworkRef);\n }\n }\n }\n }\n\n String createTeNetwork(String networkId, IYangDB aInYangDB) {\n if(!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n String teNetworkId = getTeNetworkId(networkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n try {\n if (!aInYangDB.exists(teNetworkPathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new network: {}\", teNetworkId);\n\n IYangObject networkObj = new YangObject();\n networkObj.setProperty(NETWORK_ID, teNetworkId);\n IYangObject networkTypesObj = new YangObject();\n IYangObject packetTypesObj = new YangObject();\n packetTypesObj.setProperty(\"ietf-te-topology-packet:packet\", new YangObject());\n networkTypesObj.setProperty(\"ietf-te-topology:te-topology\", packetTypesObj);\n networkObj.setProperty(\"network-types\", networkTypesObj);\n\n YangObject topologyProviderIdObj = new YangObject();\n topologyProviderIdObj.setProperty(\"topology-id\", \"\");\n topologyProviderIdObj.setProperty(\"client-id\", 0);\n topologyProviderIdObj.setProperty(\"provider-id\", 0);\n networkObj.setProperty(\"ietf-te-topology:te-topology-identifier\", topologyProviderIdObj);\n\n updateInDb(aInYangDB, networkObj, \"\", NETWORKS_PATH, \"network\", CREATE, null, qp);\n return teNetworkPathIdentifier;\n } else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"TE Topology - network exists already - {} \", teNetworkId);\n }\n }\n } catch (Exception e) {\n logger.error(\"TE Topology - Exception when creating TE network object {}: {}\", teNetworkId, e);\n }\n return null;\n }\n\n void createSubnets(Object aInSubnets, IYangDB aInYangDB, YangDBConfig aInDbConfig, String networkId) {\n\n if (aInSubnets != null && ((List) aInSubnets).size() > 0) {\n List<IYangObject> subnets = (List<IYangObject>) aInSubnets;\n for (IYangObject subnet : subnets) {\n createSubnet(subnet.asMap(), aInYangDB, aInDbConfig, networkId, null);\n }\n }\n }\n\n\n void createSubnet(Map<String,Object> aInSubnet, IYangDB aInYangDB, YangDBConfig aInDbConfig, String networkId, String aInRouterId) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String systemId = getSubnetSystemId((String) aInSubnet.get(NAME));\n String routerId = aInRouterId;\n if(routerId == null) {\n if (systemId.contains(\"dr\")) {\n routerId = (String) aInSubnet.get(\"dr-ip-address\");\n }\n routerId = routerId == null ? InetAddresses.isInetAddress(systemId) ? systemId : getSubnetNodeIdFromDB(aInDbConfig, systemId, networkId) : routerId;\n if (routerId == null) {\n logger.error(\"Couldn't create the subnet node because router-id is null for {}\", systemId);\n return;\n }\n }\n String nodeId = routerId +\"-\"+getSubnetPsnId((String) aInSubnet.get(NAME));\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n\n if (!aInYangDB.exists(nodePathIdentifier, qp)) {\n logger.debug(\"L3 - creating new subnet: {} on {}\", nodeId, networkId);\n IYangObject nodeObj = new YangObject();\n nodeObj.setProperty(NETWORK_ID, networkId);\n nodeObj.setProperty(NODE_ID, nodeId);\n IYangObject nodeAttrObj = new YangObject();\n nodeAttrObj.setProperty(NETWORK_ID, networkId);\n nodeAttrObj.setProperty(NAME, aInSubnet.get(NAME));\n nodeAttrObj.setProperty(ROUTER_ID, Arrays.asList(new String[]{nodeId}));\n nodeAttrObj.setProperty(\"flag\", Collections.singletonList(\"nsp-ietf-network-topology:subnet\"));\n nodeObj.setProperty(\"ietf-l3-unicast-topology:l3-node-attributes\", nodeAttrObj);\n logger.debug(\"L3 - createSubnet - {}\", networkPathIdentifier);\n updateInDb(aInYangDB, nodeObj, \"\", networkPathIdentifier, \"node\", CREATE, null, qp);\n }\n\n //create TE network subnet\n String teNodeRef = createTeNode(networkId, aInYangDB, nodeId, routerId);\n if(teNodeRef != null) {\n String teNetworkRef = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId));\n createTeNodeRef(aInYangDB, getFilteredQueryParameters(null), networkId, nodeId, teNetworkRef, teNodeRef);\n }\n }\n\n String createTeNode(String networkId,IYangDB aInYangDB, String nodeId, String teNodeId) {\n if(!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n String teNetworkId = getTeNetworkId(networkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n\n String teNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, nodeId);\n\n if (!aInYangDB.exists(teNodePathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new node: {} on {}\", nodeId, teNetworkId);\n IYangObject nodeObj = new YangObject();\n nodeObj.setProperty(NETWORK_ID, teNetworkId);\n nodeObj.setProperty(NODE_ID, nodeId);\n nodeObj.setProperty(\"te-node-id\", teNodeId);\n logger.debug(\"L3 - createTeNode - {}\", teNetworkPathIdentifier);\n updateInDb(aInYangDB, nodeObj, \"\", teNetworkPathIdentifier, \"node\", CREATE, null, qp);\n return teNodePathIdentifier;\n }\n return null;\n }\n\n\n void createRoutingInstances(Object aInRoutingInstances, IYangDB aInYangDB, String networkId) {\n\n if (aInRoutingInstances != null && ((List) aInRoutingInstances).size() > 0) {\n List<IYangObject> routingInstances = (List<IYangObject>) aInRoutingInstances;\n for (IYangObject routingInstance : routingInstances) {\n createRoutingInstance(routingInstance.asMap(), aInYangDB, networkId);\n }\n }\n }\n\n void createRoutingInstance(Map<String,Object> aInRoutingInstance, IYangDB aInYangDB, String networkId) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodeId = (String) aInRoutingInstance.get(ID);\n String routerId = (String) aInRoutingInstance.get(ROUTER_ID);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n\n if (!aInYangDB.exists(nodePathIdentifier, qp)) {\n logger.debug(\"L3 - creating new routing instance: {} on {}\", nodeId, networkId);\n IYangObject nodeObj = new YangObject();\n nodeObj.setProperty(NETWORK_ID, networkId);\n nodeObj.setProperty(NODE_ID, nodeId);\n IYangObject nodeAttrObj = new YangObject();\n nodeAttrObj.setProperty(NETWORK_ID, networkId);\n nodeAttrObj.setProperty(NAME, aInRoutingInstance.get(NAME));\n nodeAttrObj.setProperty(ROUTER_ID, Arrays.asList(new String[]{routerId}));\n nodeAttrObj.setProperty(\"flag\", Collections.singletonList(\"nsp-ietf-network-topology:routing-instance\"));\n nodeObj.setProperty(\"ietf-l3-unicast-topology:l3-node-attributes\", nodeAttrObj);\n\n updateInDb(aInYangDB, nodeObj, \"\", networkPathIdentifier, \"node\", CREATE, null, qp);\n\n //create supporting-node\n Map routerDetails = (Map) aInRoutingInstance.get(\"router\");\n if(routerDetails != null && routerDetails.containsKey(\"ne\")) {\n String neId = extractNeId((String) routerDetails.get(\"ne\"));\n if(neId != null) {\n String supportingNodeRef = getSupportingNodeRef(aInYangDB, qp, neId);\n if(supportingNodeRef != null) {\n String supportingNodeIden = nodePathIdentifier + \"/\" + SUPPORTING_NODE;\n if(!aInYangDB.exists(supportingNodeIden, qp)) {\n createSupportingNode(aInYangDB, qp, networkId, nodeId, supportingNodeRef, nodePathIdentifier);\n }\n }\n }\n }\n\n //create prefixes\n List<Map<String,Object>> prefixes = (List) aInRoutingInstance.get(PREFIX);\n if(prefixes != null) {\n Set<String> prefixSet = new HashSet<>();\n for (Map<String, Object> prefix : prefixes) {\n if (!prefixSet.contains(prefix.get(IP_ADDRESS))) {\n prefixSet.add((String) prefix.get(IP_ADDRESS));\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, prefix.get(IP_ADDRESS));\n prefixObj.setProperty(\"metric\", prefix.get(\"metric\"));\n updateInDb(aInYangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, qp);\n }\n }\n }\n\n //create sr mpls MSDs\n List<Map<String,Object>> msds = (List) aInRoutingInstance.get(MSDS);\n if(msds != null) {\n IYangObject srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, networkId);\n srMplsObj.setProperty(NODE_ID, nodeId);\n\n IYangObject msdObj = new YangObject();\n msdObj.setProperty(NETWORK_ID, networkId);\n msdObj.setProperty(NODE_ID, nodeId);\n srMplsObj.setProperty(MSDS, msdObj);\n\n String nodeAttrIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\";\n updateInDb(aInYangDB, srMplsObj, \"\", nodeAttrIden, SR_MPLS_TYPE, CREATE, null, qp);\n\n for(Map<String, Object> msd : msds) {\n IYangObject nodeMsdObj = new YangObject();\n nodeMsdObj.setProperty(NETWORK_ID, networkId);\n nodeMsdObj.setProperty(NODE_ID, nodeId);\n nodeMsdObj.setProperty(MSD_TYPE, msd.get(MSD_TYPE));\n nodeMsdObj.setProperty(MSD_VALUE, msd.get(MSD_VALUE));\n updateInDb(aInYangDB, nodeMsdObj, \"\", nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"node-msd\", CREATE, null, qp);\n }\n }\n }\n else {\n /** there could be updates during resync.\n * prefix (L3) and msd (SR MPLS) could have been updated or created */\n\n List<Map<String,Object>> prefixes = (List) aInRoutingInstance.get(PREFIX);\n if(prefixes != null) {\n Set<String> prefixSet = new HashSet<>();\n for (Map<String, Object> prefix : prefixes) {\n String ipAddress = (String) prefix.get(IP_ADDRESS);\n if(!prefixSet.contains(prefix.get(IP_ADDRESS))) {\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n QueryParameters queryParameters = getFilteredQueryParameters(null);\n if (aInYangDB.exists(prefixPathIden, queryParameters)) {\n //update\n logger.debug(\"L3 - handleResync - prefix - UPDATE {}\", prefixPathIden);\n IYangObject prefixObj = aInYangDB.getSingle(prefixPathIden, queryParameters);\n if (prefixObj != null) {\n int metric = (int) prefix.get(\"metric\");\n prefixObj.setProperty(\"metric\", metric);\n updateInDb(aInYangDB, prefixObj, prefixPathIden, null, null, UPDATE, null, queryParameters);\n }\n } else {\n logger.debug(\"L3 - handleResync - prefix - CREATE {}\", prefixPathIden);\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, prefix.get(IP_ADDRESS));\n prefixObj.setProperty(\"metric\", prefix.get(\"metric\"));\n updateInDb(aInYangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, qp);\n }\n prefixSet.add((String) prefix.get(IP_ADDRESS));\n }\n }\n }\n\n List<Map<String,Object>> msds = (List) aInRoutingInstance.get(MSDS);\n if(msds != null) {\n //copy code from updateMsds\n updateMsd(aInYangDB, nodeId, aInRoutingInstance, networkId);\n }\n\n //create supporting-node\n Map routerDetails = (Map) aInRoutingInstance.get(\"router\");\n if(routerDetails != null && routerDetails.containsKey(\"ne\")) { //check this for unmanaged NE\n String neId = extractNeId((String) routerDetails.get(\"ne\"));\n if(logger.isDebugEnabled()) {\n logger.debug(\"*********** - NE {} {}\", neId, routerDetails.get(\"ne\"));\n }\n if(neId != null) {\n String supportingNodeRef = getSupportingNodeRef(aInYangDB, qp, neId);\n if(supportingNodeRef != null) {\n String supportingNodeIden = nodePathIdentifier + \"/\" + SUPPORTING_NODE;\n if(!aInYangDB.exists(supportingNodeIden, qp)) {\n logger.debug(\"L3 - Resync Node - createSupportingNode {}\", supportingNodeIden);\n createSupportingNode(aInYangDB, qp, networkId, nodeId, supportingNodeRef, nodePathIdentifier);\n }\n }\n }\n else {\n //NE could have been unmanaged\n if(logger.isDebugEnabled()) {\n logger.debug(\"*********** - Trying to delete supporting node {}\", nodePathIdentifier);\n }\n String supportingNodeIden = nodePathIdentifier + \"/\" + SUPPORTING_NODE;\n if (aInYangDB.exists(supportingNodeIden)) {\n IYangObject supportingNodeObj = aInYangDB.getSingle(supportingNodeIden, getFilteredQueryParameters(null));\n String l2NodeRef = (String) supportingNodeObj.get(\"node-ref\");\n if(supportingNodeMap.containsKey(l2NodeRef)) {\n for (String nodeIden : supportingNodeMap.get(l2NodeRef)) {\n if(nodeIden.equals(nodePathIdentifier)) {\n logger.debug(\"L3 - Resync Node - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(aInYangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n else {\n supportingNodeIden = nodeIden + \"/\" + SUPPORTING_NODE;\n if (aInYangDB.exists(supportingNodeIden)) {\n logger.debug(\"L3 - Resync Node - deleteSupportingNode {}\", supportingNodeIden);\n updateInDb(aInYangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n supportingNodeMap.remove(l2NodeRef);\n }\n else {\n logger.debug(\"L3 - handleResync - delete supporting node {}\", supportingNodeIden);\n updateInDb(aInYangDB, null, supportingNodeIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n\n }\n\n //create te node\n\n String teNodeRef = createTeNode(networkId, aInYangDB, nodeId, nodeId);\n if(teNodeRef != null) {\n String teNetworkRef = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId));\n createTeNodeRef(aInYangDB, getFilteredQueryParameters(null), networkId, nodeId, teNetworkRef, teNodeRef);\n }\n }\n\n boolean createTerminationPoint(IYangDB aInYangDB, String aInNodeIdentifier, IMdConverterFw aInConverterFw, String aInTpIdentifier,\n String aInNetworkId, String aInNodeId, String aInTpId, List<String> aInTpDetails) {\n QueryParameters qp = getFilteredQueryParameters(null);\n\n if(aInYangDB.exists(aInNodeIdentifier, qp)) {\n String neId = getNeIdFromRouterId(aInYangDB, aInNetworkId, aInNodeId);\n String portName = null;\n if(neId != null) {\n portName = getPortDetailsFromDb(aInTpId, aInYangDB, neId);\n if (portName == null) {\n //try to get the details via openconfig restconf. It works for mdm managed nodes\n portName = getSubInterfaces(neId, aInConverterFw, aInTpId);\n if(portName == null) {\n logger.warn(\"Couldn't find L2 port on the NE-ID:{} for the L3 TP-ID: {}. \" +\n \"So correlation is not established.\", neId, aInTpId);\n }\n }\n }\n if(!aInYangDB.exists(aInTpIdentifier, qp)) {\n IYangObject tpObj = new YangObject();\n tpObj.setProperty(NETWORK_ID, aInNetworkId);\n tpObj.setProperty(NODE_ID, aInNodeId);\n tpObj.setProperty(TP_ID, aInTpId);\n IYangObject tpAttrObj = new YangObject();\n tpAttrObj.setProperty(NETWORK_ID, aInNetworkId);\n tpAttrObj.setProperty(NODE_ID, aInNodeId);\n tpAttrObj.setProperty(TP_ID, aInTpId);\n if(aInTpId.contains(\"%\")) {\n int unnumbered = Integer.parseInt(aInTpId.split(\"%\")[1]);\n tpAttrObj.setProperty(\"unnumbered-id\", unnumbered);\n } else{\n try{\n int unnumbered = Integer.parseInt(aInTpId);\n tpAttrObj.setProperty(\"unnumbered-id\", unnumbered);\n }\n catch(NumberFormatException e) {\n tpAttrObj.setProperty(IP_ADDRESS, Arrays.asList(new String[]{aInTpId}));\n }\n }\n tpObj.setProperty(\"ietf-l3-unicast-topology:l3-termination-point-attributes\", tpAttrObj);\n\n updateInDb(aInYangDB, tpObj, \"\", aInNodeIdentifier, TP_TYPE, CREATE, null, qp);\n\n if(neId != null && portName != null) {\n String supportingTpRef = getSupportingTpRef(aInYangDB, qp, neId, portName);\n if (supportingTpRef != null) {\n String supportingTpIden = aInTpIdentifier + \"/\" + SUPPORTING_TP;\n if(!aInYangDB.exists(supportingTpIden, qp)) {\n createSupportingTp(aInYangDB, qp, aInNetworkId, aInNodeId, aInTpId, neId, supportingTpRef, aInTpIdentifier);\n }\n }\n }\n }\n else {\n // supporting port could have been created/deleted.\n // node could have been managed/unmanaged.\n String supportingTpIden = aInTpIdentifier + \"/\" + SUPPORTING_TP;\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - SUPPORTING TP UPDATE {} {} \", neId, portName);\n }\n if(neId != null) {\n if(portName != null) {\n // ne could have been managed or port could have been created\n String supportingTpRef = getSupportingTpRef(aInYangDB, qp, neId, portName);\n if (supportingTpRef != null) {\n if(!aInYangDB.exists(supportingTpIden, qp)) {\n logger.debug(\"L3 - RESYNC TP - createSupportingTp {} , {}\", supportingTpIden, supportingTpRef);\n createSupportingTp(aInYangDB, qp, aInNetworkId, aInNodeId, aInTpId, neId, supportingTpRef, aInTpIdentifier);\n }\n }\n }\n else {\n // port could have been deleted\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - PORT IS NULL - TRYING TO DELETE SUPPORTING TP {} \", supportingTpIden);\n }\n deleteSupportingTp(supportingTpIden, aInYangDB);\n }\n }\n else { //ne id will be null if the ne is unmanaged.\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - NE IS NULL - TRYING TO DELETE SUPPORTING TP {} \", supportingTpIden);\n }\n deleteSupportingTp(supportingTpIden, aInYangDB);\n }\n }\n if(neId != null && portName != null) {\n aInTpDetails.add(neId);\n aInTpDetails.add(portName);\n }\n return true;\n } else {\n logger.warn(\"L3 - Couldn't create termination point \" + aInTpIdentifier + \" because node doesn't exist - \" + aInNodeIdentifier);\n return false;\n }\n }\n\n String createTeTerminationPoint(String aInNetworkId, IYangDB aInYangDB, String aInNodeId, String aInTpId) {\n if(!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n String teNetworkId = getTeNetworkId(aInNetworkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n\n String teNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, aInNodeId);\n String teTPPathIdentifier = teNodePathIdentifier + String.format(TP_PATH, aInTpId);\n\n if (aInYangDB.exists(teNodePathIdentifier,qp) && !aInYangDB.exists(teTPPathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new TP: {} on {}\", aInTpId, aInNodeId);\n IYangObject tpObj = new YangObject();\n tpObj.setProperty(NETWORK_ID, teNetworkId);\n tpObj.setProperty(NODE_ID, aInNodeId);\n tpObj.setProperty(TP_ID, aInTpId);\n if(aInTpId.contains(\"%\")) {\n tpObj.setProperty(\"te-tp-id\", aInTpId.split(\"%\")[1]);\n }\n else {\n tpObj.setProperty(\"te-tp-id\", aInTpId);\n }\n\n updateInDb(aInYangDB, tpObj, \"\", teNodePathIdentifier, TP_TYPE, CREATE, null, qp);\n\n //update the L3 to TE ref.\n createTeTpRef(aInYangDB, getFilteredQueryParameters(null), aInNetworkId, aInNodeId, aInTpId, teNetworkPathIdentifier, teNodePathIdentifier, teTPPathIdentifier);\n return teTPPathIdentifier;\n }\n return null;\n }\n\n void createLink(Map<String,Object> aInLink, IYangDB aInYangDB, IMdConverterFw aInConverterFw, String networkId, boolean aInCheckOppLink, String aInDstTpId) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n logger.debug(\"Creating Link {}, \", aInLink.get(NAME));\n Map<String, String> srcNode = getLinkNodeDetails((String) aInLink.get(\"source-node\"));\n Map<String, String> dstNode = getLinkNodeDetails((String) aInLink.get(\"destination-node\"));\n if(srcNode.isEmpty() || dstNode.isEmpty()) {\n logger.warn(\"L3 - parsing error to get src node / dst node on the link {}\", aInLink.entrySet().toString());\n return;\n }\n String srcNodeId = srcNode.get(ID);\n String dstNodeId = dstNode.get(ID);\n String srcTpId = (String) aInLink.get(IP_ADDRESS);\n String dstTpId = null;\n\n if(aInDstTpId != null) {\n dstTpId = aInDstTpId;\n }\n else {\n if (srcNode.get(NODE_TYPE).equals(SUBNET)) {\n IYangObject nodeObj = aInYangDB.getSingle((String) aInLink.get(\"source-node\"),\n getFilteredQueryParameters(\"name;dr-ip-address\"));\n\n if (nodeObj != null) {\n String subnetNodeId = (String) nodeObj.get(\"dr-ip-address\");\n if(subnetNodeId == null || subnetNodeId.isEmpty()) {\n srcNodeId = (String) nodeObj.get(NAME);\n String systemId = getSubnetSystemId(srcNodeId);\n subnetNodeId = InetAddresses.isInetAddress(systemId) ? systemId :\n getSubnetNodeIdFromDB(aInConverterFw.getYangDBConfig(), systemId, networkId);\n }\n srcNodeId = subnetNodeId == null ? srcNodeId : subnetNodeId + \"-\" + getSubnetPsnId(srcNodeId);\n dstTpId = srcTpId;\n }\n else {\n logger.warn(\"L3 - CreateLink - SUBNET IS NOT IN DB\" + aInLink.get(\"source-node\"));\n }\n\n } else if (dstNode.get(NODE_TYPE).equals(SUBNET)) {\n IYangObject nodeObj = aInYangDB.getSingle((String) aInLink.get(\"destination-node\"),\n getFilteredQueryParameters(\"name;dr-ip-address\"));\n\n if (nodeObj != null) {\n String subnetNodeId = (String) nodeObj.get(\"dr-ip-address\");\n if(subnetNodeId == null || subnetNodeId.isEmpty()) {\n dstNodeId = (String) nodeObj.get(NAME);\n String systemId = getSubnetSystemId(dstNodeId);\n subnetNodeId = InetAddresses.isInetAddress(systemId) ? systemId :\n getSubnetNodeIdFromDB(aInConverterFw.getYangDBConfig(), systemId, networkId);\n }\n dstNodeId = subnetNodeId == null ? dstNodeId : subnetNodeId + \"-\" + getSubnetPsnId(dstNodeId);\n dstTpId = srcTpId;\n }\n else {\n logger.warn(\"L3 - CreateLink - SUBNET IS NOT IN DB\" + aInLink.get(\"destination-node\"));\n }\n }\n\n dstTpId = dstTpId == null ? getTerminationPointId((String) aInLink.get(\"opposite-link\"), aInYangDB, networkId) : dstTpId;\n }\n if(dstTpId == null) {\n logger.warn(\"L3 - couldn't find opposite L3 link and destination TP for {} on {}\", aInLink.get(NAME), networkId);\n oppLinkMap.put(srcNodeId + \":\" + srcTpId + \"--\" + dstNodeId, aInLink.get(NAME).toString());\n return;\n }\n String isisLevel = aInLink.get(\"protocol\").equals(\"isis\") ? (String) aInLink.get(\"isis-level\") : null;\n String linkId = getLinkId(srcNodeId, dstNodeId, srcTpId, dstTpId, isisLevel);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n\n if (!aInYangDB.exists(linkPathIdentifier, qp)) {\n logger.debug(\"creating new L3 link: {} on {}\", linkId, networkId);\n IYangObject linkObj = new YangObject();\n linkObj.setProperty(NETWORK_ID, networkId);\n linkObj.setProperty(LINK_ID, linkId);\n IYangObject linkAttrObj = new YangObject();\n linkAttrObj.setProperty(NETWORK_ID, networkId);\n linkAttrObj.setProperty(NAME, aInLink.get(NAME));\n linkAttrObj.setProperty(\"metric1\", aInLink.get(\"cost\"));\n linkAttrObj.setProperty(\"metric2\", aInLink.get(\"te-metric\"));\n linkAttrObj.setProperty(\"flag\", Collections.singletonList(\"nsp-ietf-network-topology:igp\"));\n linkObj.setProperty(\"ietf-l3-unicast-topology:l3-link-attributes\", linkAttrObj);\n\n //source-node\n\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, srcNodeId);\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, srcTpId);\n List<String> srcTpDetails = new ArrayList<>();\n if(!createTerminationPoint(aInYangDB, srcNodeIdentifier, aInConverterFw, srcNodeTPIdentifier, networkId, srcNodeId, srcTpId, srcTpDetails))\n {\n logger.warn(\"L3 - Termination point creation failed {}, {}\", srcNodeIdentifier, srcNodeTPIdentifier);\n return;\n }\n YangObject srcObj = new YangObject();\n srcObj.setProperty(NETWORK_ID, networkId);\n srcObj.setProperty(LINK_ID, linkId);\n srcObj.setProperty(\"source-node\", srcNodeIdentifier);\n srcObj.setProperty(\"source-tp\", srcNodeTPIdentifier);\n linkObj.setProperty(\"source\", srcObj);\n\n //destination-node\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, dstNodeId);\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, dstTpId);\n List<String> dstTpDetails = new ArrayList<>();\n if(!createTerminationPoint(aInYangDB, dstNodeIdentifier, aInConverterFw, dstNodeTPIdentifier, networkId, dstNodeId, dstTpId, dstTpDetails))\n {\n logger.warn(\"L3 - Termination point creation failed {}, {}\", dstNodeIdentifier, dstNodeTPIdentifier);\n return;\n }\n YangObject dstObj = new YangObject();\n dstObj.setProperty(NETWORK_ID, networkId);\n dstObj.setProperty(LINK_ID, linkId);\n dstObj.setProperty(\"dest-node\", dstNodeIdentifier);\n dstObj.setProperty(\"dest-tp\", dstNodeTPIdentifier);\n linkObj.setProperty(\"destination\", dstObj);\n\n updateInDb(aInYangDB, linkObj, \"\", networkPathIdentifier, LINK_TYPE, CREATE, null, qp);\n\n //create sr mpls MSDs and SIDs\n List<Map<String,Object>> msds = (List) aInLink.get(MSDS);\n List<Map<String,Object>> sids = (List) aInLink.get(SIDS);\n\n if(msds != null || sids != null) {\n IYangObject srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, networkId);\n srMplsObj.setProperty(LINK_ID, linkId);\n if(msds != null) {\n IYangObject msdObj = new YangObject();\n msdObj.setProperty(NETWORK_ID, networkId);\n msdObj.setProperty(LINK_ID, linkId);\n srMplsObj.setProperty(MSDS, msdObj);\n }\n\n if(sids != null) {\n IYangObject sidObject = new YangObject();\n sidObject.setProperty(NETWORK_ID, networkId);\n sidObject.setProperty(LINK_ID, linkId);\n srMplsObj.setProperty(SIDS, sidObject);\n }\n\n String linkAttrIden = linkPathIdentifier + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n updateInDb(aInYangDB, srMplsObj, \"\", linkAttrIden, SR_MPLS_TYPE, CREATE, null, qp);\n\n if(msds != null) {\n for (Map<String, Object> msd : msds) {\n IYangObject nodeMsdObj = new YangObject();\n nodeMsdObj.setProperty(NETWORK_ID, networkId);\n nodeMsdObj.setProperty(LINK_ID, linkId);\n nodeMsdObj.setProperty(MSD_TYPE, msd.get(MSD_TYPE));\n nodeMsdObj.setProperty(MSD_VALUE, msd.get(MSD_VALUE));\n updateInDb(aInYangDB, nodeMsdObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"link-msd\", CREATE, null, qp);\n }\n }\n\n if(sids != null) {\n Set<String> existingSids = new HashSet<>();\n for (Map<String, Object> sid : sids) {\n IYangObject nodeSidObj = new YangObject();\n nodeSidObj.setProperty(NETWORK_ID, networkId);\n nodeSidObj.setProperty(LINK_ID, linkId);\n nodeSidObj.setProperty(VALUE_TYPE, sid.get(VALUE_TYPE));\n nodeSidObj.setProperty(SID, sid.get(SID));\n nodeSidObj.setProperty(ADDRESS_FAMILY, sid.get(ADDRESS_FAMILY));\n nodeSidObj.setProperty(IS_ELG_PROT, sid.get(IS_ELG_PROT));\n nodeSidObj.setProperty(IS_LOCAL, sid.get(IS_LOCAL));\n nodeSidObj.setProperty(IS_PART_SET, sid.get(IS_PART_SET));\n nodeSidObj.setProperty(IS_PERS, sid.get(IS_PERS));\n nodeSidObj.setProperty(IS_ON_LAN, sid.get(IS_ON_LAN));\n nodeSidObj.setProperty(WEIGHT, sid.get(WEIGHT));\n\n String sidKey = sid.get(VALUE_TYPE).toString() +\"-\"+ sid.get(SID);\n if(!existingSids.contains(sidKey)) {\n updateInDb(aInYangDB, nodeSidObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids\", \"sid\", CREATE, null, qp);\n existingSids.add(sidKey);\n }\n }\n }\n }\n\n //supporting link\n\n if(!srcTpDetails.isEmpty() && srcTpDetails.size() >= 2 && !dstTpDetails.isEmpty() && dstTpDetails.size() >=2) {\n String supportingLinkRef = getSupportingLinkRef(aInYangDB, qp,\n getLinkId(srcTpDetails.get(0), dstTpDetails.get(0), srcTpDetails.get(1), dstTpDetails.get(1), null));\n if (supportingLinkRef != null) {\n String supportingLinkIden = linkPathIdentifier + \"/\" + SUPPORTING_LINK;\n if(!aInYangDB.exists(supportingLinkIden, qp)) {\n createSupportingLink(aInYangDB, qp, networkId, linkId, supportingLinkRef, linkPathIdentifier);\n }\n }\n }\n }\n else {\n // link properties could have got updated.resync the updatable properties\n\n IYangObject ietfLinkObj = aInYangDB.getSingle(linkPathIdentifier, qp);\n if (ietfLinkObj != null) {\n logger.debug(\"L3 - RESYNC LINK - updating link: {} on {}\", linkId, networkId);\n IYangObject linkAttrObj = (YangObject) ietfLinkObj.get(\"ietf-l3-unicast-topology:l3-link-attributes\");\n linkAttrObj.setProperty(\"metric1\", aInLink.get(\"cost\"));\n linkAttrObj.setProperty(\"metric2\", aInLink.get(\"te-metric\"));\n ietfLinkObj.setProperty(\"ietf-l3-unicast-topology:l3-link-attributes\", linkAttrObj);\n ietfLinkObj.removeProperty(SUPPORTING_LINK);\n updateInDb(aInYangDB, ietfLinkObj, linkPathIdentifier, null, null, UPDATE, null, getFilteredQueryParameters(null));\n }\n\n if(aInLink.get(SIDS) != null) {\n updateSid(aInYangDB, qp, aInLink, linkPathIdentifier, networkId, linkId);\n }\n\n // update supporting link.\n\n //source-node\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, srcNodeId);\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, srcTpId);\n List<String> srcTpDetails = new ArrayList<>();\n createTerminationPoint(aInYangDB, srcNodeIdentifier, aInConverterFw, srcNodeTPIdentifier, networkId, srcNodeId, srcTpId, srcTpDetails);\n\n //destination-node\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, dstNodeId);\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, dstTpId);\n List<String> dstTpDetails = new ArrayList<>();\n createTerminationPoint(aInYangDB, dstNodeIdentifier, aInConverterFw, dstNodeTPIdentifier, networkId, dstNodeId, dstTpId, dstTpDetails);\n\n String supportingLinkIden = linkPathIdentifier + \"/\" + SUPPORTING_LINK;\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 - SUPPORTING TP UPDATE {} {} \", supportingLinkIden, !srcTpDetails.isEmpty() && srcTpDetails.size() >= 2 && !dstTpDetails.isEmpty() && dstTpDetails.size() >= 2);\n }\n if(!srcTpDetails.isEmpty() && srcTpDetails.size() >= 2 && !dstTpDetails.isEmpty() && dstTpDetails.size() >=2) {\n String supportingLinkRef = getSupportingLinkRef(aInYangDB, qp,\n getLinkId(srcTpDetails.get(0), dstTpDetails.get(0), srcTpDetails.get(1), dstTpDetails.get(1), null));\n if (supportingLinkRef != null) {\n if(!aInYangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - RESYNC LINK - CREATING SUPPORTING LINK {} \", supportingLinkIden);\n createSupportingLink(aInYangDB, qp, networkId, linkId, supportingLinkRef, linkPathIdentifier);\n }\n else if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - SUPPORTING LINK EXISTS {} \", supportingLinkIden);\n }\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"******------ - L3 TRYING TO DELETE SUPPORTING LINK {} \", supportingLinkIden);\n }\n deleteSupportingLink(supportingLinkIden, aInYangDB);\n }\n\n }\n else if(aInYangDB.exists(supportingLinkIden, qp)) {\n //delete supporting link ref\n logger.debug(\"*********** - L3 TRYING TO DELETE SUPPORTING LINK {} \", supportingLinkIden);\n deleteSupportingLink(supportingLinkIden, aInYangDB);\n }\n }\n\n createTeLink(networkId, aInYangDB, aInLink, linkId, srcNodeId, srcTpId, dstNodeId, dstTpId);\n\n // Sometimes during eventing, it happens that both the link is not in dmodel and so we failed to create the opp link earlier.\n // so this is our second chance\n if(aInCheckOppLink) {\n String[] idSplits = linkId.split(\"--\");\n String[] dstSplit = idSplits[0].split(\":\");\n if(oppLinkMap.containsKey(idSplits[1] + \"--\" + dstSplit[0])) {\n String name = oppLinkMap.remove(idSplits[1] + \"--\" + dstSplit[0]);\n String oppLinkId = getOppIetfLinkId(linkId);\n String oppLinkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, oppLinkId);\n if (!aInYangDB.exists(oppLinkPathIdentifier, getFilteredQueryParameters(null))) {\n //create the opposite link\n logger.debug(\"L3 - CREATING OPP LINK with name: {} \", name);\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n IYangObject linkObj = aInYangDB.getSingle(nspServiceIpLinkIden, getFilteredQueryParameters(IP_LINK_FIELDS));\n\n if (linkObj != null) {\n createLink(linkObj.asMap(), aInYangDB, aInConverterFw, networkId, false, dstSplit[1]);\n }\n }\n }\n }\n }\n\n String createTeLink(String aInNetworkId, IYangDB aInYangDB, Map<String,Object> aInLink, String aInLinkId,\n String aInSrcNodeId, String aInSrcTpId, String aInDstNodeId, String aInDstTpId) {\n if (!TE_TOPOLOGY_ENABLED) {\n return null;\n }\n\n createTeTerminationPoint(aInNetworkId, aInYangDB, aInSrcNodeId, aInSrcTpId);\n createTeTerminationPoint(aInNetworkId, aInYangDB, aInDstNodeId, aInDstTpId);\n\n String teNetworkId = getTeNetworkId(aInNetworkId);\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n\n String teSrcNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, aInSrcNodeId);\n String teSrcTPPathIdentifier = teSrcNodePathIdentifier + String.format(TP_PATH, aInSrcTpId);\n\n String teDstNodePathIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, aInDstNodeId);\n String teDstTPPathIdentifier = teDstNodePathIdentifier + String.format(TP_PATH, aInDstTpId);\n\n String teLinkPathIdentifier = teNetworkPathIdentifier + String.format(LINK_PATH, aInLinkId);\n\n if (!aInYangDB.exists(teLinkPathIdentifier, qp)) {\n logger.debug(\"TE Topology - creating new Link: {} on {}\", aInLinkId, teNetworkId);\n IYangObject linkObj = new YangObject();\n linkObj.setProperty(NETWORK_ID, teNetworkId);\n linkObj.setProperty(LINK_ID, aInLinkId);\n YangObject srcObj = new YangObject();\n srcObj.setProperty(NETWORK_ID, teNetworkId);\n srcObj.setProperty(LINK_ID, aInLinkId);\n srcObj.setProperty(\"source-node\", teSrcNodePathIdentifier);\n srcObj.setProperty(\"source-tp\", teSrcTPPathIdentifier);\n linkObj.setProperty(\"source\", srcObj);\n\n YangObject dstObj = new YangObject();\n dstObj.setProperty(NETWORK_ID, teNetworkId);\n dstObj.setProperty(LINK_ID, aInLinkId);\n dstObj.setProperty(\"dest-node\", teDstNodePathIdentifier);\n dstObj.setProperty(\"dest-tp\", teDstTPPathIdentifier);\n linkObj.setProperty(\"destination\", dstObj);\n\n IYangObject teObj = new YangObject();\n IYangObject linkAttrObj = new YangObject();\n linkAttrObj.setProperty(NETWORK_ID, teNetworkId);\n linkAttrObj.setProperty(LINK_ID, aInLinkId);\n linkAttrObj.setProperty(\"te-default-metric\", aInLink.get(\"te-metric\"));\n linkAttrObj.setProperty(\"te-delay-metric\", aInLink.get(\"latency\"));\n linkAttrObj.setProperty(\"te-igp-metric\", aInLink.get(\"cost\"));\n\n if(aInLink.get(\"bw\") != null) {\n\n IYangObject maxLinkBandwidth = new YangObject();\n maxLinkBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxLinkBandwidth.setProperty(LINK_ID, aInLinkId);\n IYangObject maxLinkTeBandwidth = new YangObject();\n maxLinkTeBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxLinkTeBandwidth.setProperty(LINK_ID, aInLinkId);\n // convert kilo bits to bytes and then to IEEE 754 format.\n maxLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes((Long) aInLink.get(\"bw\")))));\n maxLinkBandwidth.setProperty(\"te-bandwidth\", maxLinkTeBandwidth);\n\n IYangObject maxResvLinkBandwidth = new YangObject();\n maxResvLinkBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxResvLinkBandwidth.setProperty(LINK_ID, aInLinkId);\n IYangObject maxResvLinkTeBandwidth = new YangObject();\n maxResvLinkTeBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxResvLinkTeBandwidth.setProperty(LINK_ID, aInLinkId);\n maxResvLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes((Long) aInLink.get(\"bw\")))));\n maxResvLinkBandwidth.setProperty(\"te-bandwidth\", maxResvLinkTeBandwidth);\n\n linkAttrObj.setProperty(\"max-link-bandwidth\", maxLinkBandwidth);\n linkAttrObj.setProperty(\"max-resv-link-bandwidth\", maxResvLinkBandwidth);\n }\n\n IYangObject tesrlgs = new YangObject();\n tesrlgs.setProperty(\"value\", aInLink.get(\"srg-labels\"));\n linkAttrObj.setProperty(\"te-srlgs\", tesrlgs);\n\n IYangObject performanceMetricsOneWay = new YangObject();\n performanceMetricsOneWay.setProperty(NETWORK_ID, teNetworkId);\n performanceMetricsOneWay.setProperty(LINK_ID, aInLinkId);\n performanceMetricsOneWay.setProperty(\"one-way-delay\", aInLink.get(\"latency\"));\n performanceMetricsOneWay.setProperty(\"one-way-min-delay\", aInLink.get(\"one-way-min-delay\"));\n performanceMetricsOneWay.setProperty(\"one-way-max-delay\", aInLink.get(\"one-way-max-delay\"));\n if(aInLink.get(\"available-bw\") != null) {\n performanceMetricsOneWay.setProperty(\"one-way-utilized-bandwidth\", String.format(\"%a\",\n Float.valueOf(convertKiloBitstoBytes((Long) aInLink.get(\"available-bw\")))));\n }\n linkAttrObj.setProperty(\"ietf-te-topology-packet:performance-metrics-one-way\", performanceMetricsOneWay);\n linkAttrObj.setProperty(NAME, aInLink.get(NAME));\n\n teObj.setProperty(\"te-link-attributes\", linkAttrObj);\n teObj.setProperty(NETWORK_ID, teNetworkId);\n teObj.setProperty(LINK_ID, aInLinkId);\n linkObj.setProperty(\"ietf-te-topology:te\", teObj);\n\n updateInDb(aInYangDB, linkObj, \"\", teNetworkPathIdentifier, LINK_TYPE, CREATE, null, qp);\n createTeLinkRef(aInYangDB, getFilteredQueryParameters(null), aInNetworkId, aInLinkId, teNetworkPathIdentifier, teLinkPathIdentifier);\n\n for(int i = 0 ; i <= 7 ; i++) {\n IYangObject maxUnResvBandwidth = new YangObject();\n maxUnResvBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxUnResvBandwidth.setProperty(LINK_ID, aInLinkId);\n maxUnResvBandwidth.setProperty(\"priority\", i);\n IYangObject maxUnResvTeBandwidth = new YangObject();\n maxUnResvTeBandwidth.setProperty(NETWORK_ID, teNetworkId);\n maxUnResvTeBandwidth.setProperty(LINK_ID, aInLinkId);\n maxUnResvTeBandwidth.setProperty(\"priority\", i);\n Long unResvBw = (Long) aInLink.get(\"un-resv-bw\");\n unResvBw = unResvBw == null ? 0 : unResvBw;\n maxUnResvTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes(unResvBw))));\n maxUnResvBandwidth.setProperty(\"te-bandwidth\", maxUnResvTeBandwidth);\n updateInDb(aInYangDB, maxUnResvBandwidth, \"\", teLinkPathIdentifier + \"/ietf-te-topology:te/te-link-attributes\" , \"unreserved-bandwidth\", CREATE, null, qp);\n }\n return teLinkPathIdentifier;\n }\n else {\n //TE link could have got updated. resync the properties.\n if(updateTeLink(aInYangDB, qp, aInLink, teLinkPathIdentifier, teNetworkId, aInLinkId, true)) {\n updateTeLinkPriority(aInYangDB, aInLink, teLinkPathIdentifier);\n }\n }\n return null;\n }\n\n long convertKiloBitstoBytes(long aInBW) {\n return aInBW * 125;\n }\n\n private void createPrefix(IYangDB aInYangDB, QueryParameters aInQp, ObjectCreation aInEvent) {\n\n String instanceId = aInEvent.getInstanceId();\n String adminDomain = extractAdminDomain(instanceId);\n String nodeId = StringUtils.substringBetween(instanceId, \"routing-instance[id='\", \"'\");\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String ipAddress = (String) aInEvent.getEntity().get(IP_ADDRESS);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n if (aInYangDB.exists(nodePathIdentifier) && !aInYangDB.exists(prefixPathIden, aInQp)) {\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, ipAddress);\n prefixObj.setProperty(\"metric\", aInEvent.getEntity().get(\"metric\"));\n updateInDb(aInYangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, aInQp);\n }\n }\n }\n }\n\n public void handleUpdateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectModification aInEvent,\n String aInNeId, YangPluginMdConverterProvider aInMdResyncFw)\n {\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------UPDATE---------------------------------------------------------------------------\");\n }\n\n IMdConverterFw converterFw = aInMdResyncFw.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n logger.debug(\"L3 - handleUpdateEvent - UPDATE PREFIX\");\n updatePrefix(yangDB, getFilteredQueryParameters(null), aInEvent);\n }\n else {\n boolean isValidSrMplsUpdate = false;\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n if(MSDS.equals(change.getName())) {\n logger.debug(\"L3 - handleUpdateEvent - node MSD update\");\n Map<String, Object> node = aInEvent.getEntity().asMap();\n updateMsd(yangDB, StringUtils.substringBetween(aInEvent.getInstanceId(),\n \"routing-instance[id='\", \"'\"), node, getNetworkIdFromMeta(yangDB, node));\n }\n else if(ID.equals(change.getName())) {\n logger.debug(\"L3 - handleUpdateEvent - node ID update\");\n updateNodeAndLinks(yangDB, change.getOldValue().toString(), change.getNewValue().toString(),\n aInEvent.getInstanceId(), converterFw);\n }\n }\n }\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n logger.debug(\"L3 - handleUpdateEvent - UPDATE LINK\");\n updateLink(yangDB, aInEvent, converterFw);\n }\n }\n\n private void updateNodeAndLinks(IYangDB aInYangDB, String aInOldRouterId, String aInNewRouterId, String aInInstanceId,\n IMdConverterFw aInConverterFw) {\n /*Router-id has changed due to correlation.\n 1. delete the old node/tps/links and subnet node if any.\n 2. create new node and the links, tps, etc.\n */\n YangDBConfig dbConfig = aInConverterFw.getYangDBConfig();\n String adminDomain = extractAdminDomain(aInInstanceId);\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, aInNewRouterId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols;id;name;router/ne;router-id;prefix(ip-address;metric)\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n //There can be more than one nodes in IETF as there can be subnets on that node\n List<Object> nodeIds = getNodeIds(aInYangDB, aInOldRouterId, networkId);\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> nodes: {}\", nodeIds.toString());\n }\n List<String> linkNames = new ArrayList<>();\n Map<String,String> subnetNames = new HashMap<>();\n if(CollectionUtils.isNotEmpty(nodeIds)) {\n nodeIds.forEach(node -> {\n String nodeId = node.toString();\n //get the links that originate or end on this nodeId\n List<Map<String,Object>> linkList = getLinkDetails(aInYangDB, nodeId, networkId);\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> links : {}\", linkList.toString());\n }\n if(CollectionUtils.isNotEmpty(linkList)) {\n linkList.forEach(linkMap -> {\n Object[] linkObj = new Object[2];\n linkObj[0] = linkMap.get(LINK_ID);\n linkObj[1] = networkId;\n List<Object> linkObjList = new ArrayList<>();\n linkObjList.add(linkObj);\n deleteLink(aInYangDB, getFilteredQueryParameters(null), linkMap, dbConfig, linkObjList);\n linkNames.add(linkMap.get(NAME).toString());\n });\n }\n if(nodeId.contains(\"psn\")) {\n List<Object> subnetName = getSubnetName(aInYangDB, nodeId, networkId);\n if(CollectionUtils.isNotEmpty(subnetName)) {\n subnetNames.put(nodeId, subnetName.get(0).toString());\n }\n }\n deleteNode(aInYangDB, getFilteredQueryParameters(null), null, dbConfig, networkId, nodeId);\n });\n }\n\n //Now create the new node and the links..\n nodeIds.forEach(nodeId -> {\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> creating equivalent node for {}\", nodeId);\n }\n\n if(nodeId.toString().contains(\"psn\")) {\n Map<String, Object> subnetMap = new HashMap<>();\n subnetMap.put(NAME, subnetNames.get(nodeId));\n createSubnet(nodeMap, aInYangDB, dbConfig, networkId, aInNewRouterId);\n }\n else {\n createRoutingInstance(nodeMap, aInYangDB, networkId);\n }\n });\n\n QueryParameters linkQp = getFilteredQueryParameters(IP_LINK_FIELDS);\n //create links and tps.\n linkNames.forEach(name -> {\n if(logger.isDebugEnabled()) {\n logger.debug(\"<><><><><> creating link : {}\", name);\n }\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n IYangObject linkObj = aInYangDB.getSingle(nspServiceIpLinkIden, linkQp);\n\n if(linkObj != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if (aInYangDB.exists(networkPathIdentifier, qp)) {\n createLink(linkObj.asMap(), aInYangDB, aInConverterFw, networkId, true, null);\n return;\n } else {\n logger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", name);\n }\n }\n });\n }\n }\n }\n\n private List<Object> getNodeIds(IYangDB aInYangDb, String aInNodeId, String aInNetworkId)\n {\n return execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT n.nodeId FROM ietf.ietf_network_networks_network_node n WHERE n.networkId = \" +\n \":networkId AND n.nodeId LIKE :pattern\")\n .setParameter(\"networkId\", aInNetworkId)\n .setParameter(\"pattern\", aInNodeId + \"%\")\n .getResultList());\n\n }\n\n private List<Map<String,Object>> getLinkDetails(IYangDB aInYangDb, String aInNodeId, String aInNetworkId)\n {\n List<Object[]> linkDetails = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT la.linkId, la.name FROM ietf.ietf_241652239nk_ietf_l3_unicast_topology_l3_link_attributes la\" +\n \" WHERE la.networkId = :networkId AND la.linkId LIKE :linkId\")\n .setParameter(\"networkId\", aInNetworkId)\n .setParameter(\"linkId\", \"%\" + aInNodeId + \":%\")\n .getResultList());\n\n List<Map<String,Object>> linkList = new ArrayList<>();\n if(CollectionUtils.isNotEmpty(linkDetails)) {\n linkDetails.forEach(obj -> {\n Map<String,Object> linkMap = new HashMap<>();\n linkMap.put(LINK_ID, obj[0]);\n linkMap.put(NAME, obj[1]);\n linkList.add(linkMap);\n });\n }\n\n return linkList;\n\n }\n\n private List<Object> getSubnetName(IYangDB aInYangDb, String aInNodeId, String aInNetworkId)\n {\n return execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT n.name FROM ietf.ietf_220877889de_ietf_l3_unicast_topology_l3_node_attributes n WHERE n.networkId = \" +\n \":networkId AND n.nodeId = :nodeId\")\n .setParameter(\"networkId\", aInNetworkId)\n .setParameter(\"nodeId\", aInNodeId)\n .getResultList());\n\n }\n\n private void updatePrefix(IYangDB aInYangDB, QueryParameters aInQp, ObjectModification aInEvent) {\n\n //if the changed property is not one of the properties that could change, ignore the event.\n\n Set<String> updateableAttributes = new HashSet<>(Arrays.asList(\"metric\"));\n Map<String, Object> prefix = aInEvent.getEntity().asMap();\n boolean isValidUpdate = false;\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n if (updateableAttributes.contains(change.getName())) {\n isValidUpdate = true;\n break;\n }\n }\n\n if(isValidUpdate) {\n String instanceId = aInEvent.getInstanceId();\n String adminDomain = extractAdminDomain(instanceId);\n String nodeId = StringUtils.substringBetween(instanceId, \"routing-instance[id='\", \"'\");\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String ipAddress = (String) prefix.get(IP_ADDRESS);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n IYangObject prefixObj = aInYangDB.getSingle(prefixPathIden, aInQp);\n if (prefixObj != null) {\n int metric = (int) prefix.get(\"metric\");\n prefixObj.setProperty(\"metric\", metric);\n updateInDb(aInYangDB, prefixObj, prefixPathIden, null, null, UPDATE, null, aInQp);\n }\n }\n }\n\n }\n }\n\n private void updateMsd(IYangDB aInYangDB, String aInNodeId, Map<String,Object> aInNode, String aInNetworkId) {\n\n if (aInNode != null && aInNetworkId != null) {\n QueryParameters qp = getFilteredQueryParameters(null);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, aInNodeId);\n String nodeAttrIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\";\n IYangObject srMplsObj = aInYangDB.getSingle(nodeAttrIden + \"/\" + SR_MPLS_TYPE);\n Map<String, IYangObject> existingMsds = new HashMap<>();\n if(srMplsObj != null) {\n Collection<IYangObject> msdsList = ((IYangObject)srMplsObj.getProperty(MSDS)).getProperty(\"node-msd\");\n\n if(msdsList != null && !msdsList.isEmpty()) {\n for(IYangObject msd : msdsList) {\n String[] msdIden = msd.get(MSD_TYPE).toString().split(\":\");\n existingMsds.put(msdIden.length == 2 ? msdIden[1]:msdIden[0], msd);\n }\n }\n }\n\n List<Map> currentMsds = ((List)aInNode.get(MSDS));\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - EXISTING IETF MSDs - {}\", existingMsds.keySet().toString());\n logger.debug(\"L3 - CURRENT NSP MSDs - {}\", currentMsds.toString());\n }\n if(currentMsds == null || currentMsds.isEmpty()) {\n if(srMplsObj != null) {\n //delete the sr-mpls type.\n logger.debug(\"L3 - Update Node - delete msd sr mpls {}\", nodeAttrIden);\n updateInDb(aInYangDB, null, nodeAttrIden + \"/\" + SR_MPLS_TYPE, null, null, DELETE, null, qp);\n }\n }\n else {\n\n for(Map msd : currentMsds) {\n String msdKey = msd.get(MSD_TYPE).toString();\n if(!existingMsds.containsKey(msdKey) && srMplsObj != null) {\n //creation\n IYangObject newMsdObj = getMsdYangObject(new YangObject(), msd, aInNetworkId, aInNodeId);\n updateInDb(aInYangDB, newMsdObj, \"\", nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"node-msd\", CREATE, null, qp);\n logger.debug(\"L3 - Update Node - create msd {}, {}\", msdKey, nodeAttrIden);\n }\n else if(!existingMsds.containsKey(msdKey) && srMplsObj == null) {\n srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, aInNetworkId);\n srMplsObj.setProperty(NODE_ID, aInNodeId);\n\n IYangObject msdObj = new YangObject();\n msdObj.setProperty(NETWORK_ID, aInNetworkId);\n msdObj.setProperty(NODE_ID, aInNodeId);\n srMplsObj.setProperty(MSDS, msdObj);\n\n updateInDb(aInYangDB, srMplsObj, \"\", nodeAttrIden, SR_MPLS_TYPE, CREATE, null, qp);\n\n IYangObject newMsdObj = getMsdYangObject(new YangObject(), msd, aInNetworkId, aInNodeId);\n updateInDb(aInYangDB, newMsdObj, \"\", nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds\", \"node-msd\", CREATE, null, qp);\n logger.debug(\"L3 - Update Node - create msd {}, {}\", msdKey, nodeAttrIden);\n }\n else {\n //update\n IYangObject aInTargetMsd = existingMsds.get(msdKey);\n aInTargetMsd.setProperty(MSD_VALUE, msd.get(MSD_VALUE));\n logger.debug(\"L3 - Update Node - update msd {}, {}\", msdKey, nodeAttrIden);\n updateInDb(aInYangDB, srMplsObj, nodeAttrIden + \"/\" + SR_MPLS_TYPE, null, null, UPDATE, null, getFilteredQueryParameters(null));\n existingMsds.remove(msdKey);\n }\n }\n if(!existingMsds.isEmpty()) {\n //deletion\n for(IYangObject deleteMsd : existingMsds.values()) {\n String msdPath = String.format(nodeAttrIden + \"/\" + SR_MPLS_TYPE + \"/msds/node-msd[msd-type='%s']\",\n deleteMsd.get(MSD_TYPE));\n logger.debug(\"L3 - Update Node - delete msd {}\", msdPath);\n updateInDb(aInYangDB, null, msdPath, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n }\n\n private IYangObject getMsdYangObject(IYangObject aInTargetMsd, Map aInSourceMsd, String aInNetworkId, String aInNodeId) {\n aInTargetMsd.setProperty(NETWORK_ID, aInNetworkId);\n aInTargetMsd.setProperty(LINK_ID, aInNodeId);\n aInTargetMsd.setProperty(MSD_TYPE, aInSourceMsd.get(MSD_TYPE));\n aInTargetMsd.setProperty(MSD_VALUE, aInSourceMsd.get(MSD_VALUE));\n return aInTargetMsd;\n }\n\n private void updateLink(IYangDB aInYangDB, ObjectModification aInEvent, IMdConverterFw aInConverterFw) {\n\n //if the changed property is not one of the properties that could change, ignore the event.\n\n Set<String> updateableAttributes = new HashSet<>(Arrays.asList(\"te-metric\", \"cost\"));\n Set<String> updateableTeAttributes = new HashSet<>(Arrays.asList(\"te-metric\", \"cost\", \"latency\", \"isis-level\",\n \"bw\", \"available-bw\", \"one-way-min-delay\", \"one-way-max-delay\", \"srg-labels\"));\n Set<String> updatableSrMplsAttributes = new HashSet<>(Arrays.asList(SIDS));\n Map<String, Object> link = aInEvent.getEntity().asMap();\n boolean isValidLinkUpdate = false;\n boolean isValidTeLinkUpdate = false;\n boolean isValidPriorityUpdate = false;\n boolean isValidIpUpdate = false;\n boolean isValidSrMplsUpdate = false;\n\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n isValidLinkUpdate = updateableAttributes.contains(change.getName());\n isValidSrMplsUpdate = updatableSrMplsAttributes.contains(change.getName());\n }\n if(TE_TOPOLOGY_ENABLED) {\n isValidTeLinkUpdate = aInEvent.getChanges().size() == 1; // srlg changes are coming as empty.\n for (ObjectModification.Change change : aInEvent.getChanges()) {\n if (\"un-resv-bw\".equals(change.getName())) {\n isValidPriorityUpdate = true;\n }\n if (updateableTeAttributes.contains(change.getName())) {\n isValidTeLinkUpdate = true;\n }\n isValidIpUpdate = \"ip-address\".equals(change.getName());\n }\n }\n\n // if ip-address is changed, the link needs to be created.\n if(isValidIpUpdate) {\n logger.debug(\"L3 - CREATE LINK FROM IP-ADDRESS UPDATE\");\n String name = (String) link.get(NAME);\n String nspServiceIpLinkIden = String.format(NSP_SERVICE_LINK_PATH, name);\n QueryParameters qp = getFilteredQueryParameters(IP_LINK_FIELDS);\n IYangObject linkObj = aInYangDB.getSingle(nspServiceIpLinkIden, qp);\n\n if(linkObj != null) {\n String networkId = getNetworkIdFromLink((List<String>) linkObj.get(\"admin-domains\"), (String) linkObj.get(\"protocol\"));\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if (aInYangDB.exists(networkPathIdentifier, qp)) {\n createLink(linkObj.asMap(), aInYangDB, aInConverterFw, networkId, true, null);\n return;\n } else {\n logger.warn(\"L3 - NETWORK IS NOT IN THE DB for {}\", linkObj.get(NAME));\n }\n }\n }\n }\n\n if(isValidLinkUpdate || isValidTeLinkUpdate || isValidPriorityUpdate || isValidSrMplsUpdate) {\n String name = (String) link.get(NAME);\n List<Object> linkDetails = getLinkFromDb(name, aInConverterFw.getYangDBConfig());\n if(linkDetails != null && !linkDetails.isEmpty()) {\n String linkId = ((Object[])linkDetails.get(0))[0].toString();\n String networkId = ((Object[])linkDetails.get(0))[1].toString();\n if(isValidLinkUpdate || isValidSrMplsUpdate) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n if(isValidLinkUpdate) {\n IYangObject ietfLinkObj = aInYangDB.getSingle(linkPathIdentifier, qp);\n if (ietfLinkObj != null) {\n logger.debug(\"L3 - updating link: {} on {}\", linkId, networkId);\n IYangObject linkAttrObj = (YangObject) ietfLinkObj.get(\"ietf-l3-unicast-topology:l3-link-attributes\");\n linkAttrObj.setProperty(\"metric1\", link.get(\"cost\"));\n linkAttrObj.setProperty(\"metric2\", link.get(\"te-metric\"));\n ietfLinkObj.setProperty(\"ietf-l3-unicast-topology:l3-link-attributes\", linkAttrObj);\n ietfLinkObj.removeProperty(SUPPORTING_LINK);\n updateInDb(aInYangDB, ietfLinkObj, linkPathIdentifier, null, null, UPDATE, null, getFilteredQueryParameters(null));\n } else {\n logger.debug(\"L3 - LINK changes ignored - link doesn't exist. {}\", linkPathIdentifier);\n }\n }\n\n if(isValidSrMplsUpdate) {\n updateSid(aInYangDB, qp, link, linkPathIdentifier, networkId, linkId);\n }\n }\n\n //Update TE Properties\n if(TE_TOPOLOGY_ENABLED && (isValidTeLinkUpdate || isValidPriorityUpdate)) {\n String teNetworkId = getTeNetworkId(networkId);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, teNetworkId);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n QueryParameters qp = getFilteredQueryParameters(null);\n if(updateTeLink(aInYangDB, qp, link, linkPathIdentifier, teNetworkId, linkId, isValidPriorityUpdate)) {\n if (isValidPriorityUpdate) {\n updateTeLinkPriority(aInYangDB, link, linkPathIdentifier);\n }\n }\n }\n }\n }\n else {\n handleUpdateLogger.debug(\"L3 - LINK changes ignored - {} on {} \", aInEvent.getChanges(), link.toString());\n }\n }\n\n private boolean updateTeLink(IYangDB aInYangDB, QueryParameters aInQp, Map<String, Object> aInLink, String aInLinkPathIdentifier,\n String aInTeNetworkId, String aInLinkId, boolean isValidPriorityUpdate) {\n IYangObject ietfTeLinkObj = aInYangDB.getSingle(aInLinkPathIdentifier, aInQp);\n if (ietfTeLinkObj != null) {\n logger.debug(\"L3 - updating TE link: {} on {}\", aInLinkId, aInTeNetworkId);\n IYangObject teObj = (YangObject) ietfTeLinkObj.get(\"ietf-te-topology:te\");\n IYangObject linkAttrObj = (YangObject) teObj.get(\"te-link-attributes\");\n linkAttrObj.setProperty(\"te-default-metric\", aInLink.get(\"te-metric\"));\n linkAttrObj.setProperty(\"te-delay-metric\", aInLink.get(\"latency\"));\n linkAttrObj.setProperty(\"te-igp-metric\", aInLink.get(\"cost\"));\n if(aInLink.get(\"bw\") != null) {\n IYangObject maxLinkBandwidth = (YangObject) linkAttrObj.get(\"max-link-bandwidth\");\n IYangObject maxLinkTeBandwidth = (YangObject) maxLinkBandwidth.get(\"te-bandwidth\");\n // convert kilo bits to bytes and then to IEEE 754 format.\n maxLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(\n convertKiloBitstoBytes(aInLink.get(\"bw\") instanceof Integer ? (Integer) aInLink.get(\"bw\") :\n (Long) aInLink.get(\"bw\")))));\n maxLinkBandwidth.setProperty(\"te-bandwidth\", maxLinkTeBandwidth);\n\n IYangObject maxResvLinkBandwidth = (YangObject) linkAttrObj.get(\"max-link-bandwidth\");\n IYangObject maxResvLinkTeBandwidth = (YangObject) maxResvLinkBandwidth.get(\"te-bandwidth\");\n maxResvLinkTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(\n convertKiloBitstoBytes(aInLink.get(\"bw\") instanceof Integer ? (Integer) aInLink.get(\"bw\") :\n (Long) aInLink.get(\"bw\")))));\n maxResvLinkBandwidth.setProperty(\"te-bandwidth\", maxResvLinkTeBandwidth);\n linkAttrObj.setProperty(\"max-link-bandwidth\", maxLinkBandwidth);\n linkAttrObj.setProperty(\"max-resv-link-bandwidth\", maxResvLinkBandwidth);\n }\n IYangObject tesrlgs = (YangObject) linkAttrObj.get(\"te-srlgs\");\n tesrlgs.setProperty(\"value\", aInLink.get(\"srg-labels\"));\n\n linkAttrObj.setProperty(\"te-srlgs\", tesrlgs);\n\n\n\n IYangObject performanceMetricsOneWay = (YangObject) linkAttrObj.get(\"ietf-te-topology-packet:performance-metrics-one-way\");\n performanceMetricsOneWay.setProperty(\"one-way-delay\", aInLink.get(\"latency\"));\n performanceMetricsOneWay.setProperty(\"one-way-min-delay\", aInLink.get(\"one-way-min-delay\"));\n performanceMetricsOneWay.setProperty(\"one-way-max-delay\", aInLink.get(\"one-way-max-delay\"));\n if(aInLink.get(\"available-bw\") != null) {\n performanceMetricsOneWay.setProperty(\"one-way-utilized-bandwidth\", String.format(\"%a\",\n Float.valueOf(convertKiloBitstoBytes(\n aInLink.get(\"available-bw\") instanceof Integer ?\n (Integer) aInLink.get(\"available-bw\") : (Long) aInLink.get(\"available-bw\")))));\n }\n linkAttrObj.setProperty(\"ietf-te-topology-packet:performance-metrics-one-way\", performanceMetricsOneWay);\n linkAttrObj.setProperty(NAME, aInLink.get(NAME));\n if (!isValidPriorityUpdate) {\n linkAttrObj.removeProperty(\"unreserved-bandwidth\");\n }\n teObj.setProperty(\"te-link-attributes\", linkAttrObj);\n ietfTeLinkObj.setProperty(\"ietf-te-topology:te\", teObj);\n updateInDb(aInYangDB, ietfTeLinkObj, aInLinkPathIdentifier, null, null, UPDATE, null, getFilteredQueryParameters(null));\n return true;\n }\n else {\n if (logger.isDebugEnabled()) {\n logger.debug(\"L3 - TE LINK changes ignored - link doesn't exist. {}\", aInLinkPathIdentifier);\n }\n }\n return false;\n }\n\n private void updateTeLinkPriority(IYangDB aInYangDB, Map<String, Object> aInLink, String aInLinkPathIdentifier) {\n String teUnResvBwPathIdentifier = aInLinkPathIdentifier + \"/ietf-te-topology:te/te-link-attributes/unreserved-bandwidth\";\n List<IYangObject> teUnResvBwObjList = aInYangDB.getMany(teUnResvBwPathIdentifier, getFilteredQueryParameters(null));\n if (teUnResvBwObjList != null && !teUnResvBwObjList.isEmpty()) {\n for (IYangObject teUnResvBwObj : teUnResvBwObjList) {\n IYangObject maxUnResvTeBandwidth = (YangObject) teUnResvBwObj.get(\"te-bandwidth\");\n Long unResvBw = aInLink.get(\"un-resv-bw\") instanceof Integer ?\n new Long((Integer)aInLink.get(\"un-resv-bw\")) : (Long) aInLink.get(\"un-resv-bw\") ;\n unResvBw = unResvBw == null ? 0 : unResvBw;\n maxUnResvTeBandwidth.setProperty(\"generic\", String.format(\"%a\", Float.valueOf(convertKiloBitstoBytes(unResvBw))));\n teUnResvBwObj.setProperty(\"te-bandwidth\", maxUnResvTeBandwidth);\n updateInDb(aInYangDB, teUnResvBwObj, teUnResvBwPathIdentifier + String.format(\"[priority='%s']\",\n teUnResvBwObj.get(\"priority\")), null, null, UPDATE, null, getFilteredQueryParameters(null));\n }\n }\n }\n\n private void updateSid(IYangDB aInYangDB, QueryParameters aInQp, Map<String, Object> aInLink, String aInLinkPathIdentifier,\n String aInNetworkId, String aInLinkId) {\n String linkAttrIden = aInLinkPathIdentifier + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n IYangObject srMplsObj = aInYangDB.getSingle(linkAttrIden + \"/\" + SR_MPLS_TYPE);\n Map<String, IYangObject> existingSids = new HashMap<>();\n if(srMplsObj != null) {\n Collection<IYangObject> sidsList = ((IYangObject)srMplsObj.getProperty(SIDS)).getProperty(SID);\n\n if(sidsList != null && !sidsList.isEmpty()) {\n for(IYangObject sid : sidsList) {\n String sidKey = sid.get(VALUE_TYPE).toString() +\"-\"+ sid.get(SID);\n existingSids.put(sidKey, sid);\n }\n }\n }\n\n List<Map> currentSids = ((List)aInLink.get(SIDS));\n if(logger.isDebugEnabled()) {\n logger.debug(\"EXISTING IETF SIDS - {}\", existingSids.keySet().toString());\n logger.debug(\"CURRENT NSP SIDS - {}\", currentSids.toString());\n }\n if(currentSids == null || currentSids.isEmpty()) {\n if(srMplsObj != null) {\n //delete the sr-mpls type.\n logger.debug(\"L3 - Update Link - delete sid sr mpls {}\", linkAttrIden);\n updateInDb(aInYangDB, null, linkAttrIden + \"/\" + SR_MPLS_TYPE, null, null, DELETE, null, aInQp);\n }\n }\n else {\n\n for(Map sid : currentSids) {\n String sidKey = sid.get(VALUE_TYPE).toString() +\"-\"+ sid.get(SID);\n if(!existingSids.containsKey(sidKey) && srMplsObj != null) {\n //creation\n IYangObject newSidObj = getSidYangObject(new YangObject(), sid, aInNetworkId, aInLinkId);\n updateInDb(aInYangDB, newSidObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids\", \"sid\", CREATE, null, aInQp);\n logger.debug(\"L3 - Update Link - sid added to existing sids {}, {}\", sidKey, linkAttrIden);\n }\n else if(!existingSids.containsKey(sidKey) && srMplsObj == null) {\n srMplsObj = new YangObject();\n srMplsObj.setProperty(NETWORK_ID, aInNetworkId);\n srMplsObj.setProperty(LINK_ID, aInLinkId);\n\n IYangObject sidObj = new YangObject();\n sidObj.setProperty(NETWORK_ID, aInNetworkId);\n sidObj.setProperty(LINK_ID, aInLinkId);\n srMplsObj.setProperty(SIDS, sidObj);\n\n updateInDb(aInYangDB, srMplsObj, \"\", linkAttrIden, SR_MPLS_TYPE, CREATE, null, aInQp);\n\n IYangObject newSidObj = getSidYangObject(new YangObject(), sid, aInNetworkId, aInLinkId);\n updateInDb(aInYangDB, newSidObj, \"\", linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids\", \"sid\", CREATE, null, aInQp);\n logger.debug(\"L3 - Update Link - create sid {}, {}\", sidKey, linkAttrIden);\n }\n else {\n //update\n IYangObject aInTargetSid = existingSids.get(sidKey);\n aInTargetSid.setProperty(ADDRESS_FAMILY, sid.get(ADDRESS_FAMILY));\n aInTargetSid.setProperty(IS_ELG_PROT, sid.get(IS_ELG_PROT));\n aInTargetSid.setProperty(IS_LOCAL, sid.get(IS_LOCAL));\n aInTargetSid.setProperty(IS_PART_SET, sid.get(IS_PART_SET));\n aInTargetSid.setProperty(IS_PERS, sid.get(IS_PERS));\n aInTargetSid.setProperty(IS_ON_LAN, sid.get(IS_ON_LAN));\n aInTargetSid.setProperty(WEIGHT, sid.get(WEIGHT));\n logger.debug(\"L3 - Update Link - update sid {}, {}\", sidKey, linkAttrIden);\n updateInDb(aInYangDB, srMplsObj, linkAttrIden + \"/\" + SR_MPLS_TYPE, null, null, UPDATE, null, getFilteredQueryParameters(null));\n existingSids.remove(sidKey);\n }\n }\n if(!existingSids.isEmpty()) {\n //deletion\n for(IYangObject deleteSid : existingSids.values()) {\n String sidPath = String.format(linkAttrIden + \"/\" + SR_MPLS_TYPE + \"/sids/sid[value-type='%s'][sid='%s']\",\n deleteSid.get(VALUE_TYPE), deleteSid.get(SID));\n logger.debug(\"L3 - Update Link - delete sid {}\", sidPath);\n updateInDb(aInYangDB, null, sidPath, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n }\n\n private IYangObject getSidYangObject(IYangObject aInTargetSid, Map aInSourceSid, String aInNetworkId, String aInLinkId) {\n aInTargetSid.setProperty(NETWORK_ID, aInNetworkId);\n aInTargetSid.setProperty(LINK_ID, aInLinkId);\n aInTargetSid.setProperty(VALUE_TYPE, aInSourceSid.get(VALUE_TYPE));\n aInTargetSid.setProperty(SID, aInSourceSid.get(SID));\n aInTargetSid.setProperty(ADDRESS_FAMILY, aInSourceSid.get(ADDRESS_FAMILY));\n aInTargetSid.setProperty(IS_ELG_PROT, aInSourceSid.get(IS_ELG_PROT));\n aInTargetSid.setProperty(IS_LOCAL, aInSourceSid.get(IS_LOCAL));\n aInTargetSid.setProperty(IS_PART_SET, aInSourceSid.get(IS_PART_SET));\n aInTargetSid.setProperty(IS_PERS, aInSourceSid.get(IS_PERS));\n aInTargetSid.setProperty(IS_ON_LAN, aInSourceSid.get(IS_ON_LAN));\n aInTargetSid.setProperty(WEIGHT, aInSourceSid.get(WEIGHT));\n return aInTargetSid;\n }\n\n public void handleDeleteEvent(SrcClass aInSrcClass,SyncClass aInSyncClass, ObjectDeletion aInEvent,\n String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n IMdConverterFw converterFw = aInMdConverterFw.getiMdConverterFw();\n\n if(aInEvent.getInstanceId().contains(L2_NETWORK_PATH)) {\n handleL2DeleteEvent(aInEvent, converterFw);\n return;\n }\n\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------DELETE---------------------------------------------------------------------------\");\n }\n\n YangDBConfig dbConfig = converterFw.getYangDBConfig();\n IYangDB yangDB = converterFw.getIYangDB();\n\n QueryParameters qp = getFilteredQueryParameters(null);\n Map<String, Object> srcObject = aInEvent.getEntity().asMap();\n Map<String, Object> meta = (Map) srcObject.get(\"@\");\n if(meta == null) {\n logger.warn(\"L3 - meta details are missing on the event\");\n }\n else if(((String) meta.get(\"nsp-model:identifier\")).contains(NETWORKS_PATH) &&\n !((String) meta.get(\"nsp-model:identifier\")).contains(L2_NETWORK_PATH))\n {\n if (logger.isDebugEnabled())\n {\n logger.debug(\"L3 - DELETE IGNORED {}\", meta.get(\"nsp-model:identifier\"));\n }\n return; //sometimes the srcobject has ietf object details\n }\n\n if (aInSyncClass.getDestClassPath().equals(NETWORK_CLASS_PATH)) {\n\n logger.debug(\"L3 - DELETE NETWORK\");\n deleteNetwork(yangDB, qp, aInEvent.getEntity());\n }\n else if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n if(aInSrcClass.getSrcClassPath().equals(PREFIX_SRC_PATH)) {\n logger.debug(\"L3 - DELETE PREFIX\");\n String instanceId = aInEvent.getInstanceId();\n String ipAddress = (String) aInEvent.getEntity().get(IP_ADDRESS);\n deletePrefix(yangDB, getFilteredQueryParameters(null), instanceId, ipAddress);\n }\n else {\n logger.debug(\"L3 - DELETE NODE\");\n deleteNode(yangDB, qp, srcObject, dbConfig, null, null);\n }\n }\n else if (aInSyncClass.getDestClassPath().equals(LINK_CLASS_PATH)) {\n\n logger.debug(\"L3 - DELETE LINK\");\n deleteLink(yangDB, qp, srcObject, dbConfig, null);\n }\n }\n\n private void deleteNetwork(IYangDB aInYangDB, QueryParameters aInQp, IYangObject aInSrcObject) {\n String networkId = getNetworkId(aInYangDB, aInSrcObject);\n if(networkId == null) {\n //it could be one of isis or ospf.\n String adminDomain = (String) aInSrcObject.get(NAME);\n String ospfNetworkId = adminDomain + \"-ospf\";\n String ospfNetworkPathIdentifier = String.format(L3_NETWORK_PATH, ospfNetworkId);\n if(aInYangDB.exists(ospfNetworkPathIdentifier, aInQp))\n {\n networkId = ospfNetworkId;\n }\n\n String isisNetworkId = adminDomain + \"-isis\";\n String isisNetworkPathIdentifier = String.format(L3_NETWORK_PATH, isisNetworkId);\n if(aInYangDB.exists(isisNetworkPathIdentifier, aInQp)) {\n // exit if both ospf and isis exists for the same admin domain\n networkId = networkId == null ? isisNetworkId : null;\n }\n }\n\n if(networkId != null) {\n logger.debug(\"L3 - DELETING NETWORK {}\", networkId);\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n updateInDb(aInYangDB, null, networkPathIdentifier, networkId, null, DELETE, null, aInQp);\n if(TE_TOPOLOGY_ENABLED) {\n String teNetworkId = getTeNetworkId(networkId);\n logger.debug(\"L3 - DELETING NETWORK {}\", teNetworkId);\n updateInDb(aInYangDB, null, String.format(L3_NETWORK_PATH, teNetworkId), teNetworkId, null, DELETE, null, aInQp);\n }\n }\n else {\n logger.warn(\"L3 - DELETING NETWORK - for admin domain {} failed. Couldn't find the right IETF network.\", aInSrcObject.get(NAME));\n }\n }\n\n private void deleteNode(IYangDB aInYangDB, QueryParameters aInQp, Map<String,Object> aInSrcObject,\n YangDBConfig dbConfig, String aInNetworkId, String aInNodeId) {\n String networkId = aInNetworkId == null ? getNetworkIdFromMeta(aInYangDB, aInSrcObject) : aInNetworkId;\n if(networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n if(aInYangDB.exists(networkPathIdentifier, aInQp)) {\n String nodeId = aInNodeId;\n if(nodeId == null && SUBNET.equals(aInSrcObject.get(NODE_TYPE))) {\n String routerId = null;\n String systemId = getSubnetSystemId((String) aInSrcObject.get(NAME));\n if(systemId != null && systemId.contains(\"dr\")) {\n routerId = (String) aInSrcObject.get(\"dr-ip-address\");\n }\n routerId = routerId == null ? InetAddresses.isInetAddress(systemId) ? systemId : getSubnetNodeIdFromDB(dbConfig, systemId, networkId) : routerId;\n if(routerId == null) {\n logger.error(\"L3 - deleteNode - Couldn't delete the subnet node because router-id is null for {}\", systemId);\n return;\n }\n nodeId = routerId +\"-\"+getSubnetPsnId((String) aInSrcObject.get(NAME));\n }\n else if(nodeId == null) {\n nodeId = (String) aInSrcObject.get(ID);\n }\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n logger.debug(\"Deleting L3 node: {}\", nodePathIdentifier);\n updateInDb(aInYangDB, null, nodePathIdentifier, null, null, DELETE, null, aInQp);\n if(TE_TOPOLOGY_ENABLED) {\n String teNodePathIdentfier = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId)) + String.format(NODE_PATH, nodeId);\n if (aInYangDB.exists(teNodePathIdentfier, aInQp)) {\n logger.debug(\"Deleting TE node: {}\", teNodePathIdentfier);\n updateInDb(aInYangDB, null, teNodePathIdentfier, null, null, DELETE, null, aInQp);\n }\n }\n }\n }\n }\n\n private void deletePrefix(IYangDB aInYangDB, QueryParameters aInQp, String aInInstanceId, String aInIpAddress) {\n\n String adminDomain = extractAdminDomain(aInInstanceId);\n String nodeId = StringUtils.substringBetween(aInInstanceId, \"routing-instance[id='\", \"'\");\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain);\n nspServiceNodeIden += String.format(NSP_SERVICE_ROUTING_INS_PATH, nodeId);\n QueryParameters qp = getFilteredQueryParameters(\"node-type;protocols\");\n IYangObject nodeObj = aInYangDB.getSingle(nspServiceNodeIden, qp);\n\n if (nodeObj != null) {\n Map<String, Object> nodeMap = nodeObj.asMap();\n String networkId = getNetworkIdFromMeta(aInYangDB, nodeMap);\n if (networkId != null) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + aInIpAddress + \"']\";\n if (aInYangDB.exists(prefixPathIden, aInQp)) {\n updateInDb(aInYangDB, null, prefixPathIden, null, null, DELETE, null, aInQp);\n }\n }\n }\n }\n\n private void deleteLink(IYangDB aInYangDB, QueryParameters aInQp, Map<String,Object> aInLink, YangDBConfig aInDbConfig,\n List<Object> aInLinkDetails) {\n String name = (String) aInLink.get(NAME);\n List<Object> linkDetails = CollectionUtils.isEmpty(aInLinkDetails) ? getLinkFromDb(name, aInDbConfig) : aInLinkDetails;\n if(linkDetails != null && !linkDetails.isEmpty()) {\n String linkId = ((Object[])linkDetails.get(0))[0].toString();\n String networkId = ((Object[])linkDetails.get(0))[1].toString();\n\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String linkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, linkId);\n logger.debug(\"L3 - deleteLink {}\", linkPathIdentifier);\n updateInDb(aInYangDB, null, linkPathIdentifier, null, null, DELETE, null, aInQp);\n\n String teNetworkPathIdentifier = String.format(L3_NETWORK_PATH, getTeNetworkId(networkId));\n //delete TE link\n if(TE_TOPOLOGY_ENABLED) {\n String teLinkPathIdentifier = teNetworkPathIdentifier + String.format(LINK_PATH, linkId);\n logger.debug(\"L3 - deleteLink {}\", teLinkPathIdentifier);\n updateInDb(aInYangDB, null, teLinkPathIdentifier, null, null, DELETE, null, aInQp);\n }\n //can delete source tp and destination tp?\n String oppLinkId = getOppIetfLinkId(linkId);\n String oppLinkPathIdentifier = networkPathIdentifier + String.format(LINK_PATH, oppLinkId);\n if (!aInYangDB.exists(oppLinkPathIdentifier, aInQp)) {\n // no other link is using the same source and destination. delete the TPs.\n List<String> linkObjIds = getLinkObjIds(linkId);\n String srcNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(0));\n String srcNodeTPIdentifier = srcNodeIdentifier + String.format(TP_PATH, linkObjIds.get(1));\n if(canDeleteTp(aInYangDB, \"%\" + linkObjIds.get(0) + \":\" + linkObjIds.get(1) + \"%\", networkId)) {\n deleteTerminationPoint(aInYangDB, aInQp, srcNodeIdentifier, srcNodeTPIdentifier);\n\n // delete TE src termination point\n if (TE_TOPOLOGY_ENABLED) {\n String teSrcNodeIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(0));\n String teSrcNodeTPIdentifier = teSrcNodeIdentifier + String.format(TP_PATH, linkObjIds.get(1));\n deleteTerminationPoint(aInYangDB, aInQp, teSrcNodeIdentifier, teSrcNodeTPIdentifier);\n }\n }\n\n String dstNodeIdentifier = networkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(2));\n String dstNodeTPIdentifier = dstNodeIdentifier + String.format(TP_PATH, linkObjIds.get(3));\n if(canDeleteTp(aInYangDB, \"%\" + linkObjIds.get(2) + \":\" + linkObjIds.get(3) + \"%\", networkId)) {\n deleteTerminationPoint(aInYangDB, aInQp, dstNodeIdentifier, dstNodeTPIdentifier);\n\n // delete TE dst termination point\n if (TE_TOPOLOGY_ENABLED) {\n String teDstNodeIdentifier = teNetworkPathIdentifier + String.format(NODE_PATH, linkObjIds.get(2));\n String teDstNodeTPIdentifier = teDstNodeIdentifier + String.format(TP_PATH, linkObjIds.get(3));\n deleteTerminationPoint(aInYangDB, aInQp, teDstNodeIdentifier, teDstNodeTPIdentifier);\n }\n }\n //check whether the nodes has any more tps. if not delete the nodes as well.\n// validateNode(aInYangDB, aInQp, srcNodeIdentifier, networkId);\n// validateNode(aInYangDB, aInQp, dstNodeIdentifier, networkId);\n }\n }\n }\n\n @Override\n public void handleReplaceEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectReplacement aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n if(!srcClasses.contains(aInSrcClass.getSrcClassPath())) {\n return;\n }\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------REPLACE------------------------------------------------------------------\");\n }\n\n// void validateNode(IYangDB aInYangDB, QueryParameters aInQp, String aInNodeIdentifier, String networkId) {\n// handleDeleteLogger.debug(\"VALIDATING NODE\");\n// IYangObject nodeObj = aInYangDB.getSingle(aInNodeIdentifier, aInQp);\n// if(nodeObj != null) {\n// List tp = (List) nodeObj.get(\"ietf-network-topology:termination-point\");\n// if(tp.isEmpty()) {\n// handleDeleteLogger.debug(\"VALIDATING NODE - NO MORE TP. SO DELETING IT\");\n// updateInDb(aInYangDB, null, aInNodeIdentifier, null, null, DELETE, null, aInQp);\n// }\n// }\n// }\n\n private void deleteTerminationPoint(IYangDB aInYangDB, QueryParameters aInQp, String aInSrcNodeIdentifier, String aInSrcNodeTPIdentifier) {\n if(aInYangDB.exists(aInSrcNodeIdentifier, aInQp)) {\n logger.debug(\"deleteTerminationPoint {}\", aInSrcNodeTPIdentifier);\n updateInDb(aInYangDB, null, aInSrcNodeTPIdentifier, null, null, DELETE, null, aInQp);\n }\n }\n\n public void handlePartialResync(SrcClass aInSrcClass, SyncClass aInSyncClass, long aInFromTime, String aInNeId, YangPluginMdConverterProvider aInYangPlugin) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass, aInSyncClass, aInNeId);\n logger.debug(\"---------------------------------------------------handlePartialResync-----------------------------------------------------------\");\n }\n\n IMdConverterFw converterFw = aInYangPlugin.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n if (aInSyncClass.getDestClassPath().equals(NODE_CLASS_PATH)) {\n logger.debug(\"L3 - handlePartialResync - UPDATE PREFIX after {}\", aInFromTime);\n partialResyncPrefix(yangDB, aInFromTime);\n }\n }\n\n void partialResyncPrefix(IYangDB yangDB, long aInFromTime) {\n //get the prefixes that have changed after the timestamp.\n QueryParameters qp = getFilteredQueryParameters(null);\n qp.setTimeField(TIME_FIELD_LAST_MODIFIED);\n qp.setTimeFrom(aInFromTime);\n List<IYangObject> prefixList = yangDB.getMany(NSP_SERVICE_GENERIC_PREFIX, qp);\n if (prefixList != null && !prefixList.isEmpty()) {\n prefixList.stream().forEach(prefix -> {\n Map<String, Object> meta = (Map) prefix.asMap().get(\"@\"); //need to convert it to map to get the identifier\n String identifier = (String) meta.get(\"nsp-model:identifier\");\n String adminDomain = extractAdminDomain(identifier);\n if(\"UnknownDomain\".equals(adminDomain) || adminDomain == null) {\n return;\n }\n String nodeId = StringUtils.substringBetween(identifier, \"routing-instance[id='\", \"'\");\n String nodePath = extractNodePathFromPrefixPath(identifier);\n IYangObject node = yangDB.getSingle(nodePath, getFilteredQueryParameters(\"protocols\"));\n if(node != null) {\n String protocol = null;\n Collection<String> protocols = (Collection) node.get(\"protocols\");\n for (String p : protocols) {\n if(isValidProtocol(p)) {\n protocol = p;\n break;\n }\n }\n if(protocol == null) {\n return;\n }\n String networkId = adminDomain + \"-\" + protocol;\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkId);\n String nodePathIdentifier = networkPathIdentifier + String.format(NODE_PATH, nodeId);\n String ipAddress = (String) prefix.get(IP_ADDRESS);\n String prefixPathIden = nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes/prefix[prefix='\" + ipAddress + \"']\";\n QueryParameters queryParameters = getFilteredQueryParameters(null);\n if(yangDB.exists(prefixPathIden, queryParameters)) {\n //update\n logger.debug(\"L3 - handlePartialResync - prefix - UPDATE {}\", prefixPathIden);\n IYangObject prefixObj = yangDB.getSingle(prefixPathIden, queryParameters);\n if (prefixObj != null) {\n int metric = (int) prefix.get(\"metric\");\n prefixObj.setProperty(\"metric\", metric);\n updateInDb(yangDB, prefixObj, prefixPathIden, null, null, UPDATE, null, queryParameters);\n }\n }\n else if (yangDB.exists(nodePathIdentifier)){\n //create\n logger.debug(\"L3 - handlePartialResync - prefix - CREATE {}\", prefixPathIden);\n IYangObject prefixObj = new YangObject();\n prefixObj.setProperty(NETWORK_ID, networkId);\n prefixObj.setProperty(NODE_ID, nodeId);\n prefixObj.setProperty(PREFIX, ipAddress);\n prefixObj.setProperty(\"metric\", prefix.get(\"metric\"));\n updateInDb(yangDB, prefixObj, \"\", nodePathIdentifier + \"/ietf-l3-unicast-topology:l3-node-attributes\", \"prefix\", CREATE, null, queryParameters);\n\n }\n }\n });\n }\n\n }\n\n private void updateInDb(IYangDB yangDB, IYangObject aInYangObject, String aInXPath, String aInParentPath,\n String aInChildType, String aInAction, ExecutionContext aInExecCtx, QueryParameters aInQp) {\n\n if (null != aInExecCtx) {\n aInQp.setIExecutionContext(aInExecCtx);\n }\n\n if (null != aInAction) {\n if (CREATE.equals(aInAction)) {\n yangDB.createChild(aInParentPath, aInChildType, aInYangObject, aInQp);\n } else if (\"UPDATE\".equals(aInAction)) {\n yangDB.update(aInXPath, aInYangObject, aInQp);\n } else {\n yangDB.delete(aInXPath, aInQp);\n }\n }\n }\n\n List<String> getLinkObjIds(String aInLinkId) {\n String[] idSplits = aInLinkId.split(\"--\");\n String[] srcNodeSplits = idSplits[0].split(\":\");\n String[] dstNodeSplits = idSplits[1].split(\":\");\n List<String> linkObjIds = new ArrayList<>();\n linkObjIds.add(srcNodeSplits[0]);\n linkObjIds.add(srcNodeSplits[1]);\n linkObjIds.add(dstNodeSplits[0]);\n linkObjIds.add(dstNodeSplits[1]);\n return linkObjIds;\n }\n\n String getOppIetfLinkId(String aInLinkId) {\n String[] idSplits = aInLinkId.split(\"--\");\n String oppLinkId = idSplits[1] + \"--\" + idSplits[0];\n oppLinkId += (idSplits.length == 3) ? \"--\" + idSplits[2] : \"\";\n return oppLinkId;\n }\n\n// String getSubnetRouterId(String aInNodeId) {\n// return aInNodeId.split(\"-psn\")[0];\n// }\n\n String getSubnetPsnId(String aInSubnetId) {\n int fromIndex = aInSubnetId.indexOf(\"psn\");\n if(fromIndex != -1 ) {\n return(aInSubnetId.substring(fromIndex));\n }\n return aInSubnetId;\n }\n\n String getSubnetSystemId(String aInSubnetId) {\n int toIndex = aInSubnetId.indexOf(\"-psn\");\n if(toIndex != -1 ) {\n return(aInSubnetId.substring(0, toIndex));\n }\n\n return aInSubnetId;\n }\n\n String getLinkId(String aInSrcNodeId, String aInDstNodeId, String aInSrcTpId, String aInDstTpId, String aInIsisLevel) {\n String linkId = aInSrcNodeId + \":\" + aInSrcTpId + \"--\" + aInDstNodeId + \":\" + aInDstTpId;\n if(aInIsisLevel != null) {\n linkId = linkId + \"--\" + aInIsisLevel;\n }\n return linkId;\n }\n\n String getTerminationPointId( String aInOppLinkIdentifier, IYangDB aInYangDB, String aInNetworkId) {\n logger.debug(\"Getting opposite link {}\", aInOppLinkIdentifier);\n String dstTpId = null;\n if(aInOppLinkIdentifier != null) {\n QueryParameters qp = getFilteredQueryParameters(IP_ADDRESS);\n List<IYangObject> oppLinkObjList = aInYangDB.getMany(aInOppLinkIdentifier, qp);\n if(oppLinkObjList != null && !oppLinkObjList.isEmpty()) {\n IYangObject oppLinkObj = oppLinkObjList.get(0);\n dstTpId = (String) oppLinkObj.get(IP_ADDRESS);\n }\n }\n return dstTpId;\n }\n\n Map<String,String> getLinkNodeDetails(String node) {\n Map<String, String> nodeDetails = new HashMap<>();\n if(node != null) {\n String[] pathSplit = node.split(\"/\");\n if (pathSplit.length > 0) {\n String[] nodeSplit = pathSplit[pathSplit.length - 1].split(\"id=\");\n if (nodeSplit.length > 1) {\n nodeDetails.put(NODE_TYPE, nodeSplit[0].substring(0, nodeSplit[0].length() - 1));\n nodeDetails.put(ID, nodeSplit[1].split(\"'\")[1]);\n }\n }\n }\n return nodeDetails;\n }\n\n String extractAdminDomain(String identifier) {\n int fromIndex = identifier.indexOf(\"/admin-domain[name='\");\n int toIndex = identifier.indexOf(\"'\", fromIndex+20);\n return identifier.substring(fromIndex + 20, toIndex);\n }\n\n String extractNetworkIdFromIetfIdentifier(String identifier) {\n return StringUtils.substringBetween(identifier, \"network-id='\", \"'\");\n }\n\n String extractLinkIdFromIetfIdentifier(String identifier) {\n return StringUtils.substringBetween(identifier, \"link-id='\", \"'\");\n }\n\n String extractNodePathFromPrefixPath(String identifier) {\n int fromIndex = 0;\n int toIndex = identifier.indexOf(\"/prefix[\");\n return identifier.substring(fromIndex, toIndex);\n }\n\n String getNetworkIdFromLink(List<String> aInDomains, String aInProtocol) {\n String networkId = null;\n if(aInDomains == null) {\n logger.error(\"L3 - Link event missing admin domain info\");\n return null;\n }\n for(String domain : aInDomains) {\n String[] domainSplit = domain.split(\"'\");\n networkId = domainSplit.length > 1 ? domainSplit[1] : null;\n break;\n }\n if(networkId != null) {\n if(aInProtocol.equals(\"ospf\") || aInProtocol.equals(\"isis\")) {\n networkId = networkId + \"-\" + aInProtocol;\n return networkId;\n }\n }\n return null;\n }\n\n String getNetworkIdFromMeta(IYangDB aInYangDb, Map<String, Object> aInSrcObject) {\n String networkId = null;\n Map<String, Object> meta = (Map) aInSrcObject.get(\"@\");\n String identifier = (String) meta.get(\"nsp-model:identifier\");\n String adminDomain = extractAdminDomain(identifier);\n if(\"UnknownDomain\".equals(adminDomain) || adminDomain == null) {\n return null;\n }\n String protocol = null;\n if(aInSrcObject.get(NODE_TYPE).equals(SUBNET)) {\n protocol = (String) aInSrcObject.get(\"protocol\");\n }\n else {\n Collection<String> protocols = (Collection) aInSrcObject.get(\"protocols\");\n for (String p : protocols) {\n if(isValidProtocol(p)) {\n protocol = p;\n break;\n }\n }\n }\n\n if(\"unknown\".equals(protocol) || protocol == null) {\n protocol = getProtocolFromAdminDomain(aInYangDb, adminDomain);\n }\n\n if(isValidProtocol(protocol)) {\n networkId = adminDomain + \"-\" + protocol;\n return networkId;\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - No valid protocol found for {}, {}\", adminDomain, protocol);\n }\n }\n\n return networkId;\n\n }\n\n String getAdminDomainFromMeta(Map<String, Object> aInSrcObject) {\n Map<String, Object> meta = (Map) aInSrcObject.get(\"@\");\n String identifier = (String) meta.get(\"nsp-model:identifier\");\n return extractAdminDomain(identifier);\n }\n\n String getNeIdFromRouterId(IYangDB aInYangDB, String aInNetworkId, String aInRouterId) {\n if(aInRouterId.contains(\"psn\")) return null;\n String[] domainSplit = aInNetworkId.split(\"-\");\n String adminDomain = domainSplit[0] + \"-\" + domainSplit[1];\n String nspServiceNodeIden = String.format(NSP_SERVICE_ADMIN_DOMAIN_PATH, adminDomain) + String.format(NSP_SERVICE_ROUTING_INS_PATH, aInRouterId);\n QueryParameters qp = getFilteredQueryParameters(\"router/ne\");\n List<IYangObject> nodeObjList = aInYangDB.getMany(nspServiceNodeIden, qp);\n IYangObject nodeObj = (nodeObjList != null && !nodeObjList.isEmpty()) ? nodeObjList.get(0) : null;\n if(nodeObj != null) {\n IYangObject routerDetails = (IYangObject) nodeObj.get(\"router\");\n if(routerDetails != null && routerDetails.get(\"ne\") != null) {\n return extractNeId((String) routerDetails.get(\"ne\"));\n }\n }\n return null;\n }\n\n\n boolean isValidProtocol(String protocol) {\n return protocol != null && (protocol.equals(\"ospf\") || protocol.equals(\"isis\"));\n }\n\n String getNetworkId(IYangDB aInYangDb, IYangObject aInSrcObject) {\n String networkId = (String) aInSrcObject.get(NAME);\n if(networkId != null) {\n String protocol = getProtocolFromAdminDomain(aInYangDb, networkId);\n if (isValidProtocol(protocol)) {\n networkId = networkId + \"-\" + protocol;\n return networkId;\n }\n }\n if(logger.isDebugEnabled()) {\n logger.debug(\"RETURNING NULL FOR {}\", networkId);\n }\n return null;\n }\n\n String getAdminDomainFromNetworkId(String aInNetworkId) {\n String[] networkIds = aInNetworkId.split(\"-\");\n return networkIds[0] + \"-\" + networkIds[1];\n }\n\n String getTeNetworkId(String networkId) {\n return \"TE-\"+networkId;\n }\n\n String getSubnetNodeIdFromDB(YangDBConfig aInDbConfig, String aInSystemId, String aInNetworkId) {\n String adminDomain = getAdminDomainFromNetworkId(aInNetworkId);\n\n String lSql = \"SELECT id FROM service.routinginstance ri JOIN service.admindomain ad ON ad.dbid = ri.adminDomain_dbid\" +\n \" where systemId='\" + aInSystemId + \"' and ad.name = '\" + adminDomain + \"'\";\n try {\n final List<Object> query = aInDbConfig.getDb().selectQuery(lSql, new ArrayList<>(), new ArrayList<>(Arrays.asList(DBType.TEXT)));\n if(query == null || query.isEmpty()) {\n return null;\n }\n else {\n return (String) query.get(0);\n }\n }\n catch (Exception e)\n {\n logger.error(\"Exception when trying to get subnet-node-id for the system id: {} and admin domain: {}\", aInSystemId, adminDomain);\n }\n return null;\n }\n\n private List<Object> getLinkFromDb(String aInName, YangDBConfig aInDbConfig)\n {\n String lSql = \"SELECT linkId, networkId FROM ietf.ietf_241652239nk_ietf_l3_unicast_topology_l3_link_attributes where name = '\" + aInName + \"'\";\n try {\n final List<Object> query = aInDbConfig.getDb().selectQuery(lSql, new ArrayList<>(), new ArrayList<>(Arrays.asList(DBType.TEXT, DBType.TEXT)));\n return query;\n }\n catch (Exception e)\n {\n logger.error(\"Exception when trying to get the link {}\", aInName);\n }\n return null;\n }\n\n private String getPortDetailsFromDb(String aInTpId, IYangDB aInYangDb, String aInNeId)\n {\n List<Object> resourceList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT erb.resource FROM service.endpointaddress ea JOIN service.endpointresourcebinding erb\" +\n \" ON ea.detailsParent_dbId = erb.endpoint_dbId WHERE ea.address = :address and erb.layer = 5\")\n .setParameter(\"address\", aInTpId)\n .getResultList());\n if(resourceList == null || resourceList.isEmpty()) {\n return null;\n }\n List<Long> dbIds = resourceList.stream().map(resource -> ModelFdnUtil.getId(ModelFdn.decode(resource.toString()))).collect(Collectors.toList());\n\n if (dbIds != null && !dbIds.isEmpty()) {\n try {\n List<Object[]> portDetails = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createQuery(\"SELECT eq.neId, eq.name FROM equipment_Equipment eq WHERE eq.dbId IN :dbids\")\n .setParameter(\"dbids\", dbIds)\n .getResultList());\n if (!portDetails.isEmpty()) {\n for(Object[] portDetail : portDetails) {\n if(aInNeId.equals(portDetail[0])) {\n return (String) portDetail[1];\n }\n }\n }\n }\n catch(Exception e) {\n logger.error(\"L3 - Exception when finding the port name for the TP-ID: \" + aInTpId + \" and equipment dbIds: \" + dbIds.toString(), e);\n }\n }\n return null;\n }\n\n private String getProtocolFromAdminDomain(IYangDB aInYangDb, String aInAdminDomain) {\n\n try {\n List<Object> protocols = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT rp.protocols FROM service.routinginstance ri \" +\n \"JOIN service.admindomain ad ON ri.admindomain_dbid = ad.dbid \" +\n \"JOIN service.routinginstance_protocols rp ON ri.dbid = rp.dbid \" +\n \"WHERE ad.name = :name AND ri.operstate = 1\")\n .setParameter(\"name\", aInAdminDomain)\n .getResultList());\n\n if (!protocols.isEmpty()) {\n for(Object protocol : protocols) {\n if((int)protocol == 1 || (int)protocol == 2) {\n return ((int)protocol == 1) ? \"isis\" : \"ospf\";\n }\n }\n return null;\n }\n else {\n logger.warn(\"L3 - getProtocolFromAdminDomain - protocol is empty for {}\", aInAdminDomain);\n }\n }\n catch (Exception e) {\n return null;\n }\n return null;\n }\n\n private List<List<String>> getRouterDetailsFromNeId(IYangDB aInYangDb, String aInNeId)\n {\n List<Long> dbList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createQuery(\"SELECT eq.dbId FROM equipment_NetworkElement eq WHERE eq.neId = :neId\")\n .setParameter(\"neId\", aInNeId)\n .getResultList());\n if(dbList == null || dbList.isEmpty()) {\n return null;\n }\n\n List<String> modelFdns = dbList.stream().map(dbId -> ModelFdn.encode(ModelFdnUtil.modelFdn(\"equipment.NetworkElement\", dbId))).collect(Collectors.toList());\n List<List<String>> routerDetailsList = new ArrayList<>();\n if (modelFdns != null && !modelFdns.isEmpty()) {\n try {\n List<Object[]> routerDetails = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT ri.id, ad.name, rp.protocols FROM service.routinginstance ri \" +\n \"JOIN service.admindomain ad ON ri.admindomain_dbid = ad.dbid \" +\n \"JOIN service.routinginstance_protocols rp ON ri.dbid = rp.dbid \" +\n \"JOIN service.router rr ON ri.router_dbid = rr.dbid \" +\n \"WHERE rr.ne IN :fdns OR rr.ne LIKE :pattern\")\n .setParameter(\"fdns\", modelFdns)\n /* sometimes when a node is re-managed, NRCP takes some time to update the router.ne field with the proper NE fdn.\n Until then it has one of the sources. Meanwhile we get the L2 correlation events and so we end up ignoring it.\n This pattern search will fix it */\n .setParameter(\"pattern\", \"%\" + aInNeId + \"%\")\n .getResultList());\n\n if (routerDetails != null && !routerDetails.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - ROUTER DETAILS for NE-ID: {} are {}\", aInNeId, routerDetails.toString());\n }\n for(Object[] router : routerDetails) {\n int protocol = (int) router[2];\n String protocolName = (protocol == 1) ? \"isis\" : (protocol == 2) ? \"ospf\" : null;\n if(protocolName != null) {\n List<String> routerProps = new ArrayList<>();\n routerProps.add((String) router[0]);\n routerProps.add((String) router[1]);\n routerProps.add(protocolName);\n routerDetailsList.add(routerProps);\n }\n }\n }\n return routerDetailsList;\n }\n catch(Exception e) {\n logger.error(\"L3 - Exception when finding the router ID for the NE-ID: \" + aInNeId, e);\n }\n }\n return routerDetailsList;\n }\n\n public <T> T execute(IDB db, Function<ITransactionContext, T> fn) {\n try {\n if (Transactor.isInTransaction()) {\n return fn.apply(Transactor.getContext());\n } else {\n return Transactor.execute(db, fn, true);\n }\n } catch (DBRuntimeException e) {\n logger.error(\"L3 - DB ACCESS ERROR: \", e);\n return null;\n }\n }\n\n\n private String getSupportingNetworkRef(IYangDB aInYangDb, QueryParameters aInQp) {\n return aInYangDb.exists(L2_NETWORK_PATH, aInQp) ? L2_NETWORK_PATH : null;\n }\n\n private String getSupportingNodeRef(IYangDB aInYangDb, QueryParameters aInQp, String aInNodeId) {\n String supportingNodeRef = L2_NETWORK_PATH + String.format(NODE_PATH, aInNodeId);\n supportingNodeRef = aInYangDb.exists(supportingNodeRef, aInQp) ? supportingNodeRef : null;\n return supportingNodeRef;\n }\n\n private String getSupportingTpRef(IYangDB aInYangDb, QueryParameters aInQp, String aInNodeId, String aInTpId) {\n String supportingTpRef = L2_NETWORK_PATH + String.format(NODE_PATH, aInNodeId)\n + String.format(TP_PATH, aInTpId);\n supportingTpRef = aInYangDb.exists(supportingTpRef, aInQp) ? supportingTpRef : null;\n return supportingTpRef;\n }\n\n private String getSupportingLinkRef(IYangDB aInYangDb, QueryParameters aInQp, String aInLinkId) {\n String supportingLinkRef = L2_NETWORK_PATH + String.format(LINK_PATH, aInLinkId);\n supportingLinkRef = aInYangDb.exists(supportingLinkRef, aInQp) ? supportingLinkRef : null;\n return supportingLinkRef;\n }\n\n String extractNeId(String identifier) {\n if(identifier != null) {\n int fromIndex = identifier.indexOf(\"ne-id='\");\n if(fromIndex != -1) {\n int toIndex = identifier.indexOf(\"'\", fromIndex + 7);\n return identifier.substring(fromIndex + 7, toIndex);\n }\n }\n return null;\n }\n\n public Map<String, String> getSubInterfacePortMap(String aInNodeId, IMdConverterFw aInConverterFw) {\n String subInterfacePath = String.format(SUBINTERFACE_FILTER, aInNodeId);\n Map<String, String> portInterfaceMap = new HashMap<>();\n try {\n IRestConfClient restConfClient = aInConverterFw.getRestConfClient();\n Map<String,Object> lResponse = restConfClient.xpathGetData(subInterfacePath, \"fields=openconfig-if-ip:ipv4;config&depth=5\");\n if (lResponse != null && !lResponse.isEmpty()) {\n List<Map> subInterfaces = (List<Map>) lResponse.get(\"openconfig-interfaces:subinterface\");\n if(subInterfaces != null) {\n for (Map subInterface : subInterfaces) {\n String ip = extractIpFromSubInterface((Map) subInterface.get(\"openconfig-if-ip:ipv4\"));\n if(ip != null) {\n String port = extractPortFromSubInterface((Map) subInterface.get(\"config\"));\n portInterfaceMap.put(ip, getPortNameFromOpenConfigPortName(port));\n }\n }\n }\n }\n }\n catch(Exception e) {\n logger.warn(\"L3 - RestconfApi cannot get subinterfaces.\");\n }\n return portInterfaceMap;\n }\n\n public String getSubInterfaces(String aInNodeId, IMdConverterFw aInConverterFw, String ip) {\n /* Getting errors when tried to query the parent based on the child attributes.\n java.lang.IllegalArgumentException: only simple xpaths are supported - failing with this error message\n So we have to get all the network interfaces on the node and find the matching one. Ideal filter below\n /nsp-network:network/node[node-id='%s']/node-root/\" +\n \"openconfig-interfaces:interfaces/interface/subinterfaces/subinterface\" +\n \"[boolean(openconfig-if-ip:ipv4/addresses/address[ip='%s'])]\"\n */\n String subInterfacePath = String.format(SUBINTERFACE_FILTER, aInNodeId);\n Integer unnumbered = Ints.tryParse(ip);\n String unnumberedInterface = ip.contains(\"%\") ? ip.split(\"%\")[1] : unnumbered == null ? null : unnumbered.toString();\n if(unnumberedInterface != null && !unnumberedInterface.isEmpty()) {\n subInterfacePath += String.format(SUBINTERFACE_UNNUM_FILTER, unnumberedInterface);\n }\n try {\n IRestConfClient restConfClient = aInConverterFw.getRestConfClient();\n Map<String,Object> lResponse = restConfClient.xpathGetData(subInterfacePath, \"fields=openconfig-if-ip:ipv4;config&depth=5\");\n if (lResponse != null && !lResponse.isEmpty()) {\n List<Map> subInterfaces = (List<Map>) lResponse.get(\"openconfig-interfaces:subinterface\");\n if(subInterfaces != null) {\n for (Map subInterface : subInterfaces) {\n if (!unnumberedInterface.isEmpty() || ip.equals(extractIpFromSubInterface((Map) subInterface.get(\"openconfig-if-ip:ipv4\")))){\n String port = extractPortFromSubInterface((Map) subInterface.get(\"config\"));\n return getPortNameFromOpenConfigPortName(port);\n }\n }\n }\n }\n }\n catch(Exception e) {\n logger.warn(\"L3 - RestconfApi cannot get subinterfaces.\");\n }\n return null;\n }\n\n private String extractIpFromSubInterface(Map aInIpMap) {\n if(aInIpMap != null) {\n Map addresses = (Map) aInIpMap.get(\"addresses\");\n if (addresses != null) {\n List<Map> addressList = (List) addresses.get(\"address\");\n if (addressList != null) {\n for (Map ipMap : addressList) {\n return (String) ipMap.getOrDefault(\"ip\", null);\n }\n }\n }\n }\n return null;\n }\n\n private String extractPortFromSubInterface(Map aInConfigMap) {\n if(aInConfigMap != null) {\n return (String) aInConfigMap.getOrDefault(\"nsp-openconfig-interfaces-augments:port\", null);\n }\n return null;\n }\n\n private String getPortNameFromOpenConfigPortName(String portName) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - Port Name from openConfig api: {}\",portName);\n }\n if(portName == null) return null;\n\n// if(portName.contains(\"GigabitEthernet\")) {\n// //cisco\n// String[] port = portName.split(\"GigabitEthernet\");\n// return \"GigabitEthernet Port \" + port[1];\n// }\n\n if(portName.contains(\":\")) {\n String[] port = portName.split(\":\");\n return port[0];\n }\n else {\n return portName;\n }\n }\n\n private boolean canDeleteTp(IYangDB aInYangDb, String aInPattern, String aInNetworkId) {\n BigInteger count = (BigInteger) execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT count(*) FROM \" +\n \"ietf.ietf_network_networks_network_ietf_network_topology_link sl WHERE sl.linkId LIKE :pattern \" +\n \"AND sl.networkId = :networkId\")\n .setParameter(\"pattern\", aInPattern)\n .setParameter(\"networkId\", aInNetworkId)\n .getSingleResult());\n return count != null && count.longValue() == 0;\n }\n\n private void createSupportingNetwork(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInSupportingNetworkRef) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId);\n IYangObject supportingNetworkobj = new YangObject();\n supportingNetworkobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingNetworkobj.setProperty(NETWORK_REF, aInSupportingNetworkRef);\n updateInDb(aInYangDB, supportingNetworkobj, \"\", networkPathIdentifier, SUPPORTING_NETWORK, CREATE, null, aInQp);\n }\n\n private void createSupportingNode(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInSupportingNodeRef, String aInNodePathIdentifier) {\n IYangObject supportingNodeobj = new YangObject();\n supportingNodeobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingNodeobj.setProperty(NODE_ID, aInNodeId);\n supportingNodeobj.setProperty(NETWORK_REF, L2_NETWORK_PATH);\n supportingNodeobj.setProperty(NODE_REF, aInSupportingNodeRef);\n updateInDb(aInYangDB, supportingNodeobj, \"\", aInNodePathIdentifier, SUPPORTING_NODE, CREATE, null, aInQp);\n if(supportingNodeMap.containsKey(aInSupportingNodeRef)) {\n supportingNodeMap.get(aInSupportingNodeRef).add(aInNodePathIdentifier);\n }\n else {\n supportingNodeMap.put(aInSupportingNodeRef, new HashSet<>(Arrays.asList(aInNodePathIdentifier)));\n }\n }\n\n private void createSupportingTp(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInTpId, String aInNeId, String aInSupportingTpRef, String aInTpPathIdentifier) {\n IYangObject supportingTpobj = new YangObject();\n supportingTpobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingTpobj.setProperty(NODE_ID, aInNodeId);\n supportingTpobj.setProperty(TP_ID, aInTpId);\n supportingTpobj.setProperty(NETWORK_REF, L2_NETWORK_PATH);\n supportingTpobj.setProperty(NODE_REF, L2_NETWORK_PATH + String.format(NODE_PATH, aInNeId));\n supportingTpobj.setProperty(TP_REF, aInSupportingTpRef);\n updateInDb(aInYangDB, supportingTpobj, \"\", aInTpPathIdentifier, SUPPORTING_TP, CREATE, null, aInQp);\n supportingTpMap.put(aInSupportingTpRef, aInTpPathIdentifier);\n if(l2TpCreateEvents.containsKey(aInNeId)) {\n l2TpCreateEvents.get(aInNeId).portsToAdd.remove(StringUtils.substringBetween(aInSupportingTpRef, \"[tp-id='\", \"']\"));\n }\n }\n\n private void deleteSupportingTp(String aInSupportingTpIden, IYangDB aInYangDB) {\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInYangDB.exists(aInSupportingTpIden, qp)) {\n IYangObject supportingTpObj = aInYangDB.getSingle(aInSupportingTpIden, qp);\n String l2TpRef = (String) supportingTpObj.get(TP_REF);\n logger.debug(\"L3 - RESYNC TP - deleteSupportingTp {} , {}\", aInSupportingTpIden, l2TpRef);\n updateInDb(aInYangDB, null, aInSupportingTpIden, null, null, DELETE, null, qp);\n supportingTpMap.remove(l2TpRef);\n }\n }\n\n private void createSupportingLink(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInLinkId,\n String aInSupportingLinkRef, String aInLinkIdentifier) {\n IYangObject supportingLinkobj = new YangObject();\n supportingLinkobj.setProperty(NETWORK_ID, aInNetworkId);\n supportingLinkobj.setProperty(LINK_ID, aInLinkId);\n supportingLinkobj.setProperty(NETWORK_REF, L2_NETWORK_PATH);\n supportingLinkobj.setProperty(LINK_REF, aInSupportingLinkRef);\n updateInDb(aInYangDB, supportingLinkobj, \"\", aInLinkIdentifier, SUPPORTING_LINK, CREATE, null, aInQp);\n supportingLinkMap.put(aInSupportingLinkRef, aInLinkIdentifier);\n l2LinkCreateEvents.remove(aInSupportingLinkRef);\n }\n\n private void deleteSupportingLink(String aInSupportingLinkIden, IYangDB aInYangDB) {\n QueryParameters qp = getFilteredQueryParameters(null);\n if(aInYangDB.exists(aInSupportingLinkIden, qp)) {\n IYangObject supportingLinkObj = aInYangDB.getSingle(aInSupportingLinkIden, qp);\n String l2TpRef = (String) supportingLinkObj.get(LINK_REF);\n logger.debug(\"L3 - RESYNC LINK - deleteSupportingLink {} , {}\", aInSupportingLinkIden, l2TpRef);\n updateInDb(aInYangDB, null, aInSupportingLinkIden, null, null, DELETE, null, qp);\n supportingLinkMap.remove(l2TpRef);\n }\n }\n\n private void createTeNetworkRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInTeNetworkRef) {\n String networkTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) +\n \"/ietf-l3-unicast-topology:l3-topology-attributes\";\n if(!aInYangDB.exists(networkTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-topology-attributes\", aInQp)) {\n IYangObject teNetworkRefObj = new YangObject();\n teNetworkRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teNetworkRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n updateInDb(aInYangDB, teNetworkRefObj, \"\", networkTopoAttrIdentifier,\n \"ietf-l3-te-topology:l3-te-topology-attributes\", CREATE, null, aInQp);\n }\n }\n\n private void createTeNodeRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInTeNetworkRef, String aInTeNodeRef) {\n String nodeTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) +\n String.format(NODE_PATH, aInNodeId) + \"/ietf-l3-unicast-topology:l3-node-attributes\";\n if(!aInYangDB.exists(nodeTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-node-attributes\", aInQp)) {\n IYangObject teNodeRefObj = new YangObject();\n teNodeRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teNodeRefObj.setProperty(NODE_ID, aInNodeId);\n teNodeRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n teNodeRefObj.setProperty(NODE_REF, aInTeNodeRef);\n updateInDb(aInYangDB, teNodeRefObj, \"\", nodeTopoAttrIdentifier,\n \"ietf-l3-te-topology:l3-te-node-attributes\", CREATE, null, aInQp);\n }\n }\n\n private void createTeTpRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInNodeId,\n String aInTpId, String aInTeNetworkRef, String aInTeNodeRef, String aInTeTpRef) {\n String tpTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) +\n String.format(NODE_PATH, aInNodeId) + String.format(TP_PATH, aInTpId) +\n \"/ietf-l3-unicast-topology:l3-termination-point-attributes\";\n if(!aInYangDB.exists(tpTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-tp-attributes\", aInQp)) {\n IYangObject teTpRefObj = new YangObject();\n teTpRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teTpRefObj.setProperty(NODE_ID, aInNodeId);\n teTpRefObj.setProperty(TP_ID, aInTpId);\n teTpRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n teTpRefObj.setProperty(NODE_REF, aInTeNodeRef);\n teTpRefObj.setProperty(TP_REF, aInTeTpRef);\n updateInDb(aInYangDB, teTpRefObj, \"\", tpTopoAttrIdentifier, \"ietf-l3-te-topology:l3-te-tp-attributes\",\n CREATE, null, aInQp);\n }\n }\n\n private void createTeLinkRef(IYangDB aInYangDB, QueryParameters aInQp, String aInNetworkId, String aInLinkId,\n String aInTeNetworkRef, String aInTeLinkRef) {\n String linkTopoAttrIdentifier = String.format(L3_NETWORK_PATH, aInNetworkId) + String.format(LINK_PATH, aInLinkId)\n + \"/ietf-l3-unicast-topology:l3-link-attributes\";\n if(!aInYangDB.exists(linkTopoAttrIdentifier + \"/ietf-l3-te-topology:l3-te-link-attributes\", aInQp)) {\n IYangObject teLinkRefObj = new YangObject();\n teLinkRefObj.setProperty(NETWORK_ID, aInNetworkId);\n teLinkRefObj.setProperty(LINK_ID, aInLinkId);\n teLinkRefObj.setProperty(NETWORK_REF, aInTeNetworkRef);\n teLinkRefObj.setProperty(LINK_REF, aInTeLinkRef);\n updateInDb(aInYangDB, teLinkRefObj, \"\", linkTopoAttrIdentifier, \"ietf-l3-te-topology:l3-te-link-attributes\",\n CREATE, null, aInQp);\n }\n }\n\n private QueryParameters getFilteredQueryParameters (String fields) {\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n if(fields != null) {\n qp.setFields(Fields.parse(fields));\n }\n return qp;\n }\n\n private void populateSuportingNodeMap(IYangDB aInYangDb) {\n List<Object[]> nodeList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT sn.networkId, sn.nodeId, sn.nodeRef FROM \" +\n \"ietf.ietf_network_networks_network_node_supporting_node sn WHERE sn.networkId LIKE :pattern1 \" +\n \"OR sn.networkId LIKE :pattern2\")\n .setParameter(\"pattern1\", \"%ospf%\")\n .setParameter(\"pattern2\", \"%isis%\")\n .getResultList());\n if (nodeList == null || nodeList.isEmpty()) {\n return;\n }\n\n for(Object[] nodeInfo : nodeList) {\n if(nodeInfo.length == 3) {\n String l3NodeIden = String.format(L3_NETWORK_PATH, nodeInfo[0]) + String.format(NODE_PATH, nodeInfo[1]);\n if (supportingNodeMap.containsKey(nodeInfo[2])) {\n supportingNodeMap.get(nodeInfo[2]).add(l3NodeIden);\n } else {\n supportingNodeMap.put(nodeInfo[2].toString(), new HashSet<>(Arrays.asList(l3NodeIden)));\n }\n }\n }\n\n if (logger.isDebugEnabled()) {\n logger.debug(supportingNodeMap.toString());\n }\n }\n\n private void populateSuportingTpMap(IYangDB aInYangDb) {\n List<Object[]> tpList = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT sp.networkId, sp.nodeId, sp.tpId, sp.tpRef FROM \" +\n \"ietf.ietf_90278165_termination_point_supporting_termination_point sp WHERE sp.networkId LIKE :pattern1 \" +\n \"OR sp.networkId LIKE :pattern2\")\n .setParameter(\"pattern1\", \"%ospf%\")\n .setParameter(\"pattern2\", \"%isis%\")\n .getResultList());\n if (tpList == null || tpList.isEmpty()) {\n return;\n }\n\n for(Object[] tpInfo : tpList) {\n if(tpInfo.length == 4) {\n String l3TpIden = String.format(L3_NETWORK_PATH, tpInfo[0]) + String.format(NODE_PATH, tpInfo[1]) +\n String.format(TP_PATH, tpInfo[2]);\n supportingTpMap.put(tpInfo[3].toString(), l3TpIden);\n }\n }\n\n if(logger.isDebugEnabled()) {\n logger.debug(supportingTpMap.toString());\n }\n }\n\n private void populateSuportingLinkMap(IYangDB aInYangDb) {\n List<Object[]> linkListInfo = execute(aInYangDb.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(\"SELECT sl.networkId, sl.linkId, sl.linkRef FROM \" +\n \"ietf.ietf_139678392ork_ietf_network_topology_link_supporting_link sl WHERE sl.networkId LIKE :pattern1 \" +\n \"OR sl.networkId LIKE :pattern2\")\n .setParameter(\"pattern1\", \"%ospf%\")\n .setParameter(\"pattern2\", \"%isis%\")\n .getResultList());\n if (linkListInfo == null || linkListInfo.isEmpty()) {\n return;\n }\n\n for(Object[] linkInfo : linkListInfo) {\n if(linkInfo.length == 3) {\n String l3LinkIden = String.format(L3_NETWORK_PATH, linkInfo[0]) + String.format(LINK_PATH, linkInfo[1]);\n supportingLinkMap.put(linkInfo[2].toString(), l3LinkIden);\n }\n }\n\n if (logger.isDebugEnabled()) {\n logger.debug(supportingLinkMap.toString());\n }\n }\n\n private void startCorrelationService() {\n synchronized (this) {\n if (correlationService == null || correlationService.isShutdown()) {\n logger.debug(\"L3 - L2 - Correlation - correlationService has been started that will run periodically until correlation is complete\");\n correlationService = Executors.newScheduledThreadPool(1,\n new ThreadFactoryBuilder().setNameFormat(\"L3-CorrelationHandler-to-L2\").build());\n correlationService.scheduleAtFixedRate(() -> correlateTpsAndLinks(), 2, 2, TimeUnit.MINUTES);\n }\n }\n }\n\n @SuppressFBWarnings(\"WMI_WRONG_MAP_ITERATOR\")\n class L2TpCreateTask implements Runnable {\n String neId;\n Map<String, Integer> portsToAdd = new HashMap<>();\n IYangDB yangDB;\n IMdConverterFw converterFw;\n\n L2TpCreateTask(String neId, String portToAdd, IMdConverterFw converterFw ) {\n this.neId = neId;\n if(portToAdd != null && !portToAdd.isEmpty()) {\n portsToAdd.put(portToAdd, 1);\n }\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(!portsToAdd.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"Trying to add correlation for ports {} on {}\", portsToAdd.entrySet().toString(), neId);\n }\n List<List<String>> routers = getRouterDetailsFromNeId(yangDB, neId);\n if(routers == null || routers.isEmpty()) {\n logger.debug(\"******** L3 - Correlation - no router found for the NE ID {}\", neId);\n return;\n }\n Map<String, String> portInterfaceMap = null;\n for(List<String> router: routers) {\n String networkId = router.get(1) + \"-\" + router.get(2);\n String nodeIdentifer = String.format(L3_NETWORK_PATH, networkId) + String.format(NODE_PATH, router.get(0));\n QueryParameters qp = getFilteredQueryParameters(\"tp-id;\"+SUPPORTING_TP);\n qp.setDepth(2);\n\n /*\n 1. call the openconfig subinterface query and get the map of port and interfaces for the NE ID\n 2. For each router, get all the TPs\n 3. If supporting tp is null\n 3.1 If the map contains the TP, add correlation.\n 3.2 If not, try to get the nfmp way or unnumbered interface way and add correlation\n 3.3 remove the ports from the portsToadd list.\n 4.If there is any port remaining, retry them (3 times).\n */\n\n List<IYangObject> tpList = yangDB.getMany(nodeIdentifer + \"/\" + TP_TYPE, qp);\n if(tpList != null && !tpList.isEmpty()) {\n for(IYangObject tp : tpList) {\n if(tp.get(SUPPORTING_TP) == null) {\n if(portInterfaceMap == null) {\n portInterfaceMap = getSubInterfacePortMap(neId, converterFw);\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation mdm port interface map {} for {}\", portInterfaceMap.toString(), neId);\n }\n }\n String tpId = (String) tp.get(\"tp-id\");\n String portName = portInterfaceMap.get(tpId);\n\n if(portName == null) {\n portName = getPortDetailsFromDb(tpId, yangDB, neId);\n if(portName == null && tpId.contains(\"%\")) {\n portName = getSubInterfaces(neId, converterFw, tpId);\n if(logger.isDebugEnabled() && portName == null) {\n logger.debug(\"portName is still null for {} and {}\", tpId, neId);\n }\n }\n }\n\n if(portName != null && portsToAdd.containsKey(portName)) {\n String tpIden = nodeIdentifer + String.format(TP_PATH, tpId);\n String supportingTpIden = tpIden + \"/\" + SUPPORTING_TP;\n if(!yangDB.exists(supportingTpIden)) {\n String instanceId = L2_NETWORK_PATH + String.format(NODE_PATH, neId)\n + String.format(TP_PATH, portName);\n logger.debug(\"L3 - createSupportingTp {}\", instanceId);\n qp = getFilteredQueryParameters(null);\n createSupportingTp(yangDB, qp, networkId, router.get(0), tpId, neId, instanceId, tpIden);\n portsToAdd.remove(portName);\n }\n }\n }\n }\n // the remaining ports in portsToAdd can be re-tried.\n for(String port : portsToAdd.keySet()) {\n portsToAdd.put(port, portsToAdd.get(port) + 1);\n }\n //remove after 3 attempts.\n portsToAdd.entrySet().removeIf(e -> e.getValue() > 3);\n\n }\n else {\n portsToAdd.clear();\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - NO TP for {}\", nodeIdentifer + \"/\" + TP_TYPE);\n }\n }\n }\n }\n\n //for retries\n if(!portsToAdd.isEmpty()) {\n portsToAdd.entrySet().removeIf(e -> supportingTpMap.containsKey(L2_NETWORK_PATH +\n String.format(NODE_PATH, neId) + String.format(TP_PATH, e.getKey())));\n\n if(l2TpCreateEvents.containsKey(neId)) {\n for(Map.Entry<String,Integer> port : portsToAdd.entrySet()) {\n l2TpCreateEvents.get(neId).portsToAdd.put(port.getKey(), port.getValue());\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - retrying for port {} on {}\", port.getKey(), neId);\n }\n }\n }\n else {\n l2TpCreateEvents.put(neId, this);\n }\n startCorrelationService();\n }\n }\n }\n\n @SuppressFBWarnings(\"URF_UNREAD_FIELD\")\n class L2TpDeleteTask implements Runnable {\n String neId;\n List<String> portsToDelete = new ArrayList<>();\n IYangDB yangDB;\n IMdConverterFw converterFw;\n\n L2TpDeleteTask(String neId, String portToDelete, IMdConverterFw converterFw ) {\n this.neId = neId;\n if(portToDelete != null && !portToDelete.isEmpty()) {\n portsToDelete.add(portToDelete);\n }\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(!portsToDelete.isEmpty()) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"correlation delete tp task is running\");\n }\n deleteL2SupportingTps(portsToDelete, neId, yangDB);\n portsToDelete.clear();\n }\n }\n }\n\n class L2LinkCreateTask implements Runnable {\n String instanceId;\n String linkId;\n IYangDB yangDB;\n IMdConverterFw converterFw;\n int retryAttempt = 1;\n\n L2LinkCreateTask(String instanceId, IMdConverterFw converterFw) {\n this.instanceId = instanceId;\n this.linkId = StringUtils.substringBetween(instanceId, \"[link-id='\", \"']\");\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(linkId != null) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3- correlation - Trying to correlate link {}\", linkId);\n }\n String[] tps = linkId.split(\"--\");\n if(tps != null && tps.length == 2) {\n List<String> networkDetails = new ArrayList<>();\n List<String> l3SourceTps = getTpDetails(tps[0].split(\":\"), yangDB, converterFw, networkDetails);\n if(!l3SourceTps.isEmpty()) {\n List<String> l3DstTps = getTpDetails(tps[1].split(\":\"), yangDB, converterFw, null);\n if(!l3DstTps.isEmpty()) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkDetails.get(0));\n for(String sourceTp : l3SourceTps) {\n for (String dstTp : l3DstTps ) {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation exists for L3 source and destination tps for {}\", linkId);\n }\n String l3LinkId = sourceTp + \"--\" + dstTp;\n String linkIdentifier = networkPathIdentifier + String.format(LINK_PATH, l3LinkId);\n String supportingLinkIden = linkIdentifier + \"/\" + SUPPORTING_LINK;\n QueryParameters qp = getFilteredQueryParameters(null);\n if(networkDetails.get(0).contains(\"isis\")) {\n String l3IsisLinkId = l3LinkId + \"--l1\";\n linkIdentifier = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId);\n supportingLinkIden = linkIdentifier + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(linkIdentifier, qp) && !yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - createSupportingLink {}\", instanceId);\n createSupportingLink(yangDB, qp, networkDetails.get(0), l3IsisLinkId, instanceId, linkIdentifier);\n }\n\n l3IsisLinkId = l3LinkId + \"--l2\";\n linkIdentifier = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId);\n supportingLinkIden = linkIdentifier + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(linkIdentifier, qp) && !yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - createSupportingLink {}\", instanceId);\n createSupportingLink(yangDB, qp, networkDetails.get(0), l3IsisLinkId, instanceId, linkIdentifier);\n }\n }\n else if(yangDB.exists(linkIdentifier, qp) && !yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - createSupportingLink {}\", instanceId);\n createSupportingLink(yangDB, qp, networkDetails.get(0), l3LinkId, instanceId, linkIdentifier);\n }\n }\n }\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - link retrying because destination tp is not correlated for {}\", this.linkId);\n }\n if(retryAttempt < 3 && !supportingLinkMap.containsKey(this.instanceId)) {\n this.retryAttempt++;\n l2LinkCreateEvents.put(this.instanceId, this);\n startCorrelationService();\n }\n\n }\n }\n else {\n if(logger.isDebugEnabled()) {\n logger.debug(\"L3 - correlation - link retrying because source tp is not correlated for {}\", this.linkId);\n }\n if(retryAttempt < 3 && !supportingLinkMap.containsKey(this.instanceId)) {\n this.retryAttempt++;\n l2LinkCreateEvents.put(this.instanceId, this);\n startCorrelationService();\n }\n }\n }\n }\n\n }\n }\n\n class L2LinkDeleteTask implements Runnable {\n String instanceId;\n String linkId;\n IYangDB yangDB;\n IMdConverterFw converterFw;\n\n L2LinkDeleteTask(String instanceId, IMdConverterFw converterFw) {\n this.instanceId = instanceId;\n this.linkId = StringUtils.substringBetween(instanceId, \"[link-id='\", \"']\");\n this.converterFw = converterFw;\n this.yangDB = converterFw.getIYangDB();\n }\n\n @Override\n public void run() {\n if(logger.isDebugEnabled()) {\n logger.debug(\"correlation link delete task is running\");\n }\n List<String> linksDeleted = new ArrayList<>();\n if(supportingLinkMap.containsKey(instanceId)) {\n String supportingLinkIden = supportingLinkMap.get(instanceId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supportingLinkIden)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supportingLinkIden);\n updateInDb(yangDB, null, supportingLinkIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n linksDeleted.add(supportingLinkMap.get(instanceId));\n supportingLinkMap.remove(instanceId);\n }\n else if(linkId != null) {\n String[] tps = linkId.split(\"--\");\n if(tps != null && tps.length == 2) {\n List<String> networkDetails = new ArrayList<>();\n List<String> l3SourceTps = getTpDetails(tps[0].split(\":\"), yangDB, converterFw, networkDetails);\n if(!l3SourceTps.isEmpty()) {\n List<String> l3DstTps = getTpDetails(tps[1].split(\":\"), yangDB, converterFw, null);\n if(!l3DstTps.isEmpty()) {\n String networkPathIdentifier = String.format(L3_NETWORK_PATH, networkDetails.get(0));\n for(String sourceTp : l3SourceTps) {\n for (String dstTp : l3DstTps ) {\n String l3LinkId = sourceTp + \"--\" + dstTp;\n QueryParameters qp = getFilteredQueryParameters(null);\n if(networkDetails.get(0).contains(\"isis\")) {\n String l3IsisLinkId = l3LinkId + \"--l1\";\n String supportingLinkIden = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supportingLinkIden);\n updateInDb(yangDB, null, supportingLinkIden, null, null, DELETE, null, qp);\n linksDeleted.add(networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId));\n }\n\n l3IsisLinkId = l3LinkId + \"--l2\";\n supportingLinkIden = networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supportingLinkIden, qp)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supportingLinkIden);\n updateInDb(yangDB, null, supportingLinkIden, null, null, DELETE, null, qp);\n linksDeleted.add(networkPathIdentifier + String.format(LINK_PATH, l3IsisLinkId));\n }\n }\n else {\n String supporingLinkIden = networkPathIdentifier + String.format(LINK_PATH, l3LinkId) + \"/\" + SUPPORTING_LINK;\n if(yangDB.exists(supporingLinkIden, qp)) {\n logger.debug(\"L3 - deleteSupportingLink {}\", supporingLinkIden);\n updateInDb(yangDB, null, supporingLinkIden, null, null, DELETE, null, qp);\n linksDeleted.add(networkPathIdentifier + String.format(LINK_PATH, l3LinkId));\n }\n }\n }\n }\n }\n }\n\n }\n }\n\n //Delete the related correlated TPs for the deleted links.\n if(!linksDeleted.isEmpty()) {\n for(String l3Link : linksDeleted) {\n String l3LinkId = extractLinkIdFromIetfIdentifier(l3Link);\n String l3NetworkId = extractNetworkIdFromIetfIdentifier(l3Link);\n\n // build tp identifier and check for supporting identifier and delete it.\n String l3NetworkPathIdentifier = String.format(L3_NETWORK_PATH, l3NetworkId);\n String[] l3Tp = l3LinkId.split(\"--\");\n for(int i = 0; i < l3Tp.length; i++) {\n String[] tpDetails = l3Tp[i].split(\":\");\n if (tpDetails.length == 2) {\n String supportingTpIden = l3NetworkPathIdentifier + String.format(NODE_PATH, tpDetails[0])\n + String.format(TP_PATH, tpDetails[1]) + \"/\" + SUPPORTING_TP;\n if(yangDB.exists(supportingTpIden)) {\n logger.debug(\"L3 - deleteSupportingTp {}\", supportingTpIden);\n updateInDb(yangDB, null, supportingTpIden, null, null, DELETE, null, getFilteredQueryParameters(null));\n }\n }\n }\n\n // build the port identifier and delete it from cache.\n\n String[] l2Tp = instanceId.split(\"--\");\n for(int i = 0; i < l2Tp.length - 1; i++) {\n String[] l2TpDetails = l2Tp[i].split(\":\");\n String l2TpIden = L2_NETWORK_PATH + String.format(NODE_PATH, l2TpDetails[0])\n + String.format(TP_PATH, l2TpDetails[1]);\n supportingTpMap.remove(l2TpIden);\n }\n }\n }\n }\n }\n}\n"
904
+ }
905
+ ]
906
+ },
907
+ {
908
+ "@": {
909
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler",
910
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler']",
911
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
912
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
913
+ },
914
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler",
915
+ "version": "2311.0.9",
916
+ "java-code": [
917
+ {
918
+ "@": {
919
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler/java-code",
920
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.SAPTopologyHandler']/java-code[page-number='1']",
921
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
922
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
923
+ },
924
+ "page-number": 1,
925
+ "page": "package com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.common.notif.ObjectCreation;\nimport com.nokia.nsp.md.common.notif.ObjectDeletion;\nimport com.nokia.nsp.md.common.notif.ObjectEntityNotification;\nimport com.nokia.nsp.md.common.notif.ObjectModification;\nimport com.nokia.nsp.md.common.notif.ObjectReplacement;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.ICustomHandler;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nsp.md.ifg.yang.api.Fields;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\n\nimport org.slf4j.Logger;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\npublic class SAPTopologyHandler implements ICustomHandler//, IDeleteObjectFilter, IYangKafkaMessageConsumer\n{\n private static final Logger classLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName());\n private static final Logger handleResyncLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".handleResync\");\n private static final Logger handlePostResyncDeleteLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".handlePostResyncDelete\");\n private static final Logger handleCreateEventLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".handleCreateEvent\");\n private static final Logger handleUpdateEventLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".handleUpdateEvent\");\n private static final Logger handleReplaceEventLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".handleReplaceEvent\");\n private static final Logger handleDeleteEventLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".handleDeleteEvent\");\n private static final Logger canDeleteObjectLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".canDeleteObject\");\n private static final Logger createOrUpdateIetfSapsForPortLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".createOrUpdateIetfSapsForPort\");\n private static final Logger createorUpdateIetfSapsForLagLogger = org.slf4j.LoggerFactory.getLogger(SAPTopologyHandler.class.getName() + \".createorUpdateIetfSapsForLag\");\n\n private static final String IETF_SAP_NETWORK_ID = \"SAPTopology\";\n\n private static final String IETF_NETWORK_ID_PROP = \"network-id\";\n private static final String IETF_NETWORK_PROP = \"network\";\n private static final String IETF_NETWORK_TYPES_PROP = \"network-types\";\n private static final String IETF_NODE_PROP = \"node\";\n private static final String IETF_NODE_ID_PROP = \"node-id\";\n private static final String IETF_SERVICE_TYPE_PROP = \"service-type\";\n private static final String IETF_SAP_PROP = \"sap\";\n private static final String IETF_SAP_ID_PROP = \"sap-id\";\n private static final String IETF_PARENT_TERMINATION_POINT_PROP = \"parent-termination-point\";\n private static final String IETF_ATTACHMENT_INTERFACE_PROP = \"attachment-interface\";\n private static final String IETF_INTERFACE_TYPE_PROP = \"interface-type\";\n private static final String IETF_ENCAPSULATION_TYPE_PROP = \"encapsulation-type\";\n private static final String IETF_SAP_STATUS_PROP = \"sap-status\";\n private static final String IETF_SERVICE_STATUS_PROP = \"service-status\";\n private static final String IETF_STATUS_PROP = \"status\";\n private static final String IETF_ROLE_PROP = \"role\";\n private static final String IETF_SAP_NTW_SAP_NETWORK_PROP = \"ietf-sap-ntw:sap-network\";\n private static final String IETF_SAP_NTW_SERVICE_PROP = \"ietf-sap-ntw:service\";\n\n private static final String IETF_VPN_COMMON_VPWS = \"ietf-vpn-common:vpws\";\n private static final String IETF_VPN_COMMON_VPLS = \"ietf-vpn-common:vpls\";\n private static final String IETF_VPN_COMMON_L3VPN = \"ietf-vpn-common:l3vpn\";\n\n private static final String IETF_NETWORK_CLASS_PATH = \"ietf-network:/networks/network\";\n private static final String IETF_NODE_CLASS_PATH = \"ietf-network:/networks/network/node\";\n private static final String IETF_SAP_CLASS_PATH = \"ietf-network:/networks/network/node/ietf-sap-ntw:service/sap\";\n\n private static final String IETF_NETWORKS_YANG_PATH = \"/ietf-network:networks\";\n private static final String IETF_SAP_NETWORK_YANG_PATH = String.format(\"/ietf-network:networks/network[network-id='%s']\", IETF_SAP_NETWORK_ID);\n private static final String IETF_SAP_NETWORK_NODE_YANG_PATH = IETF_SAP_NETWORK_YANG_PATH + \"/node[node-id='%s']\";\n private static final String IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH = IETF_SAP_NETWORK_NODE_YANG_PATH + \"/ietf-sap-ntw:service[service-type='%s']\";\n private static final String IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH = IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH + \"/sap[sap-id='%s']\";\n\n private static final String NSP_NE_CLASS_PATH = \"nsp-equipment:/network/network-element\";\n private static final String NSP_PORT_CLASS_PATH = \"nsp-equipment:/network/network-element/hardware-component/port\";\n private static final String NSP_PORT_DETAILS_CLASS_PATH = \"nsp-equipment:/network/network-element/hardware-component/port/port-details\";\n private static final String NSP_LAG_CLASS_PATH = \"nsp-equipment:/network/network-element/lag\";\n private static final String NSP_ELINE_ENDPOINT_CLASS_PATH = \"nsp-service:/services/service-layer/eline/endpoint\";\n private static final String NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH = \"nsp-service:/services/service-layer/eline/endpoint/ipservice-endpoint-detail\";\n private static final String NSP_ELAN_ENDPOINT_CLASS_PATH = \"nsp-service:/services/service-layer/elan/endpoint\";\n private static final String NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH = \"nsp-service:/services/service-layer/elan/endpoint/ipservice-endpoint-detail\";\n private static final String NSP_L3VPN_ENDPOINT_CLASS_PATH = \"nsp-service:/services/service-layer/l3vpn/endpoint\";\n private static final String NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH = \"nsp-service:/services/service-layer/l3vpn/endpoint/ipservice-endpoint-detail\";\n\n private static final String NSP_NE_CLASS_ID = \"/nsp-equipment:network/network-element\";\n private static final String NSP_PORT_CLASS_ID = \"/nsp-equipment:network/network-element/hardware-component/port\";\n private static final String NSP_LAG_MEMEBER_DETAILS_CLASS_ID = \"/nsp-equipment:network/network-element/hardware-component/port/lag-member-details\";\n private static final String NSP_LAG_CLASS_ID = \"/nsp-equipment:network/network-element/lag\";\n private static final String NSP_LAG_MEMBERS_CLASS_ID = \"/nsp-equipment:network/network-element/lag/members\";\n private static final String NSP_ELINE_ENDPOINT_CLASS_ID = \"/nsp-service:services/service-layer/eline/endpoint\";\n private static final String NSP_ELAN_ENDPOINT_CLASS_ID = \"/nsp-service:services/service-layer/elan/endpoint\";\n private static final String NSP_L3VPN_ENDPOINT_CLASS_ID = \"/nsp-service:services/service-layer/l3vpn/endpoint\";\n\n private static final String NSP_PORT_DETAILS_CLASS_ID = \"/nsp-equipment:network/network-element/hardware-component/port/port-details\";\n private static final String NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID = \"/nsp-service:services/service-layer/eline/endpoint/ipservice-endpoint-detail\";\n private static final String NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID = \"/nsp-service:services/service-layer/elan/endpoint/ipservice-endpoint-detail\";\n private static final String NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID = \"/nsp-service:services/service-layer/l3vpn/endpoint/ipservice-endpoint-detail\";\n private static final List<String> classIdsForIYangTopicConsumer = Arrays.asList(NSP_PORT_DETAILS_CLASS_ID,\n NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID,\n NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID,\n NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID);\n\n private static final String NSP_NE_YANG_PATH = \"/nsp-equipment:network/network-element[ne-id='%s']\";\n private static final String NSP_PORT_YANG_PATH = \"/nsp-equipment:network/network-element[ne-id='%s']/hardware-component/port[component-id='%s']\";\n private static final String NSP_LAG_YANG_PATH = \"/nsp-equipment:network/network-element[ne-id='%s']/lag[lag-id='%s']\";\n private static final String NSP_ELINE_ENDPOINT_YANG_PATH = \"/nsp-service:services/service-layer/eline[service-id='%s']/endpoint[endpoint-id='%s']\";\n private static final String NSP_ELAN_ENDPOINT_YANG_PATH = \"/nsp-service:services/service-layer/elan[service-id='%s']/endpoint[endpoint-id='%s']\";\n private static final String NSP_L3VPN_ENDPOINT_YANG_PATH = \"/nsp-service:services/service-layer/l3vpn[service-id='%s']/endpoint[endpoint-id='%s']\";\n\n private static final String NSP_SERVICE_PROP = \"service\";\n private static final String NSP_NAME_PROP = \"name\";\n private static final String NSP_LAG_MEMEBER_DETAILS_PROP = \"lag-member-details\";\n private static final String NSP_PORT_DETAILS_PROP = \"port-details\";\n private static final String NSP_PORT_MODE_PROP = \"port-mode\";\n private static final String NSP_COMPONENT_ID_PROP = \"component-id\";\n private static final String NSP_ENCAP_TYPE_PROP = \"encap-type\";\n private static final String NSP_OPER_STATE_PROP = \"oper-state\";\n private static final String NSP_MEMBERS_PROP = \"members\";\n private static final String NSP_LAG_MODE_PROP = \"lag-mode\";\n private static final String NSP_LAG_ID_PROP = \"lag-id\";\n private static final String NSP_MODEL_IDENTIFIER_PROP = \"nsp-model:identifier\";\n private static final String NSP_PORT_BINDINGS_PROP = \"port-bindings\";\n private static final String NSP_RESOURCE_PROP = \"resource\";\n private static final String NSP_SITE_ID_PROP = \"site-id\";\n private static final String NSP_IP_SERVICE_ENDPOINT_DETAIL_PROP = \"ipservice-endpoint-detail\";\n\n private static final String ACCESS = \"access\";\n private static final String HYBRID = \"hybrid\";\n\n private static final String CLASS_ID = \"class-id\";\n\n private static final String SAPTOPOLOGY_HANDLER_INSTANCE = \"SAPTopologyHandler.instance\";\n\n private static final int QUERY_PARAMETERS_DEPTH_SRC = 3;\n private static final int QUERY_PARAMETERS_DEPTH_DEST = 2;\n\n public static final Fields NSP_PORT_READ_FIELDS = Fields.parse(\"name;oper-state;port-details(port-mode;encap-type);lag-member-details/lag-id\");\n public static final Fields NSP_LAG_READ_FIELDS = Fields.parse(\"name;oper-state;lag-mode;members\");\n public static final Fields NSP_SERVICE_ENDPOINT_READ_FIELDS = Fields.parse(\"name;oper-state;service;port-bindings/resource;ipservice-endpoint-detail/encap-type\");\n\n public static final Fields IETF_SAP_READ_FIELDS = Fields.parse(\"sap-id;interface-type\");\n\n private static final AtomicBoolean iYangTopicConsumerInitialized = new AtomicBoolean(false);\n private static final AtomicBoolean ietfSapNetworkPresent = new AtomicBoolean(false);\n\n private static final Object mutex = new Object();\n\n private enum IetfInterfaceRole\n {\n UNI(\"ietf-sap-ntw:uni\"),\n NNI(\"ietf-sap-ntw:nni\");\n\n public String value;\n private IetfInterfaceRole(String value)\n {\n this.value = value;\n }\n }\n\n private enum IetfInterfaceType\n {\n PHY(\"ietf-sap-ntw:phy\"),\n LOOPBACK(\"ietf-sap-ntw:loopback\"),\n LAG(\"ietf-sap-ntw:lag\"),\n IRB(\"ietf-sap-ntw:irb\"),\n LOCAL_BRIDGE(\"ietf-sap-ntw:local-bridge\"),\n LOGICAL(\"ietf-sap-ntw:logical\");\n\n public String value;\n private IetfInterfaceType(String value)\n {\n this.value = value;\n }\n }\n\n private enum IetfEncapType\n {\n PRIORITY_TAGGED(\"ietf-vpn-common:priority-tagged\"),\n DOT1Q(\"ietf-vpn-common:dot1q\"),\n QINQ(\"ietf-vpn-common:qinq\"),\n QINANY(\"ietf-vpn-common:qinany\"),\n VXLAN(\"ietf-vpn-common:vxlan\"),\n ETHERNET_TYPE(\"ietf-vpn-common:ethernet-type\"),\n VLAN_TYPE(\"ietf-vpn-common:vlan-type\"),\n UNTAGGED_INT(\"ietf-vpn-common:untagged-int\"),\n TAGGED_INT(\"ietf-vpn-common:tagged-int\"),\n LAG_INT(\"ietf-vpn-common:lag-int\");\n\n public String value;\n private IetfEncapType(String value)\n {\n this.value = value;\n }\n }\n\n private enum IetfOperState\n {\n OP_UP(\"ietf-vpn-common:op-up\"),\n OP_DOWN(\"ietf-vpn-common:op-down\"),\n OP_UNKNOWN(\"ietf-vpn-common:op-unknown\");\n\n public String value;\n private IetfOperState(String value)\n {\n this.value = value;\n }\n }\n\n private static Set<String> SUPPORTED_IETF_VPN_TYPES = new HashSet<>();\n static {\n SUPPORTED_IETF_VPN_TYPES.add(IETF_VPN_COMMON_VPWS);\n SUPPORTED_IETF_VPN_TYPES.add(IETF_VPN_COMMON_VPLS);\n SUPPORTED_IETF_VPN_TYPES.add(IETF_VPN_COMMON_L3VPN);\n }\n\n// @Override\n public void init(YangPluginMdConverterProvider aInMdConverterFwProv)\n {\n //aInMdConverterFwProv.getiMdConverterFw().getIYangTopicConsumer().addConsumer(new SAPTopologyIYangMesageConsumer(aInMdConverterFwProv));\n// aInMdConverterFwProv.getiMdConverterFw().getIYangTopicConsumer().addConsumer(this); // because this implements IYangKafkaMessageConsumer\n// System.getProperties().put(SAPTOPOLOGY_HANDLER_INSTANCE, this);\n }\n\n// @Override\n public void destroy(YangPluginMdConverterProvider aInMdConverterFwProv)\n {\n// IYangKafkaMessageConsumer oldHandlerInstance = (IYangKafkaMessageConsumer) System.getProperties().remove(SAPTOPOLOGY_HANDLER_INSTANCE);\n// if(oldHandlerInstance != null)\n// aInMdConverterFwProv.getiMdConverterFw().getIYangTopicConsumer().removeConsumer(oldHandlerInstance);\n }\n\n private static void deleteIfExists(String aInXpath, QueryParameters qp, IYangDB yangDB) {\n if (yangDB.exists(aInXpath)) {\n yangDB.delete(aInXpath, qp);\n }\n }\n\n private static void deleteSap(String aInNeId, String aInInstanceId, String aInIetfVpnType, QueryParameters qp, IYangDB yangDB) {\n if (!SUPPORTED_IETF_VPN_TYPES.contains(aInIetfVpnType)) {\n throw new RuntimeException(\"Invalid ietf type \" + aInIetfVpnType);\n }\n String sapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, aInIetfVpnType, aInInstanceId);\n deleteIfExists(sapPath, qp, yangDB);\n }\n\n private static void deleteAllSaps(String aInNeId, String aInInstanceId, QueryParameters qp, IYangDB yangDB) {\n for (String ietfType : SUPPORTED_IETF_VPN_TYPES) {\n deleteSap(aInNeId, aInInstanceId, ietfType, qp, yangDB);\n }\n }\n\n @Override\n public void handleResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInExistingObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFwProv)\n {\n if(handleResyncLogger.isDebugEnabled()) {\n handleResyncLogger.debug(\"********** handleResync - aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}\", aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId);\n handleResyncLogger.debug(\"********** aInSrcObject: {}\", aInSrcObject.asMap());\n }\n IMdConverterFw converterFw = aInMdConverterFwProv.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n //IDB db = aInMdConverterProv.getiMdConverterFw().getIdb();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n// createIetfSAPNetworkIfNotExists(yangDB, qp);\n createIetfSAPNodeIfNotExists(yangDB, aInNeId, qp);\n\n// if(!iYangTopicConsumerInitialized.get())\n// {\n// init(aInMdConverterFwProv);\n// iYangTopicConsumerInitialized.set(true);\n// }\n\n// String lDestClassPath = aInSyncClass.getDestClassPath();\n\n// createIetfNetworkIfNotExists(yangDB, qp);\n//\n// if(IETF_NODE_CLASS_PATH.equals(lDestClassPath))\n// {\n// createIetfNodeIfNotExists(yangDB, aInNeId, qp);\n// }\n// else if(IETF_SAP_CLASS_PATH.equals(lDestClassPath))\n {\n handleSapResync(aInSrcClass, aInSyncClass, aInSrcObject, aInNeId, yangDB);\n }\n }\n\n private void createIetfSAPNetworkIfNotExists(IYangDB yangDB, QueryParameters qp)\n {\n if(ietfSapNetworkPresent.get()) // IETF SAP Network object is already present, return\n return;\n\n synchronized (mutex)\n {\n if (yangDB.exists(IETF_SAP_NETWORK_YANG_PATH, qp))\n {\n // Converter app just started up OR new SAPTopologyHandler file was uploaded,\n // variable is false, but IETF network object present in DB\n // set to true and return\n ietfSapNetworkPresent.set(true);\n return;\n }\n\n IYangObject lSapNetworkObject = new YangObject();\n lSapNetworkObject.setProperty(IETF_SERVICE_TYPE_PROP, Arrays.asList(IETF_VPN_COMMON_VPWS, IETF_VPN_COMMON_VPLS, IETF_VPN_COMMON_L3VPN));\n\n IYangObject lNetworkTypesObj = new YangObject();\n lNetworkTypesObj.setProperty(IETF_SAP_NTW_SAP_NETWORK_PROP, lSapNetworkObject);\n\n IYangObject lNetworkObj = new YangObject();\n lNetworkObj.setProperty(IETF_NETWORK_ID_PROP, IETF_SAP_NETWORK_ID);\n lNetworkObj.setProperty(IETF_NETWORK_TYPES_PROP, lNetworkTypesObj);\n\n yangDB.createChild(IETF_NETWORKS_YANG_PATH, IETF_NETWORK_PROP, lNetworkObj, qp);\n\n // IETF network object was not present in DB and was just created. Set to true and return\n ietfSapNetworkPresent.set(true);\n }\n }\n\n private void createIetfSAPNodeIfNotExists(IYangDB yangDB, String aInNeId, QueryParameters qp)\n {\n String nodePath = String.format(IETF_SAP_NETWORK_NODE_YANG_PATH, aInNeId);\n if(yangDB.exists(nodePath, qp))\n return;\n\n IYangObject ietfVpwsServiceType = new YangObject();\n ietfVpwsServiceType.setProperty(IETF_SERVICE_TYPE_PROP, IETF_VPN_COMMON_VPWS);\n\n IYangObject ietfVplsServiceType = new YangObject();\n ietfVplsServiceType.setProperty(IETF_SERVICE_TYPE_PROP, IETF_VPN_COMMON_VPLS);\n\n IYangObject ietfl3vpnServiceType = new YangObject();\n ietfl3vpnServiceType.setProperty(IETF_SERVICE_TYPE_PROP, IETF_VPN_COMMON_L3VPN);\n\n IYangObject ietfSapNode = new YangObject();\n ietfSapNode.setProperty(IETF_NODE_ID_PROP, aInNeId);\n ietfSapNode.setProperty(IETF_SAP_NTW_SERVICE_PROP, Arrays.asList(ietfVpwsServiceType, ietfVplsServiceType, ietfl3vpnServiceType));\n\n yangDB.createChild(IETF_SAP_NETWORK_YANG_PATH, IETF_NODE_PROP, ietfSapNode, qp);\n }\n\n\n @Override\n public void handleCreateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectCreation aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw) {\n if (handleCreateEventLogger.isInfoEnabled()){\n handleCreateEventLogger.debug(\"********** handleCreateEvent - aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, ObjectCreation: {}\",\n aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().asMap());\n }\n\n //String eventClassId = aInEvent.getClassId();\n //String instanceId = aInEvent.getEntity().getIdentifier();\n\n IYangDB yangDB = aInMdConverterFw.getiMdConverterFw().getIYangDB();\n\n// if(NSP_NE_CLASS_ID.equals(eventClassId))\n// {\n// createIetfSAPNodeIfNotExists(yangDB, aInNeId, qp);\n// }\n// else\n {\n createOrUpdateSaps(aInEvent, aInNeId, yangDB);\n }\n }\n\n @Override\n public void handleUpdateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectModification aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n\n if(handleUpdateEventLogger.isDebugEnabled()){\n handleUpdateEventLogger.debug(\"********** handleUpdateEvent - aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, ObjectModification: {}\",\n aInSrcClass.getSrcClassPath(), aInSyncClass.getDestClassPath(), aInNeId, aInEvent.getEntity().asMap());\n handleUpdateEventLogger.debug(\"********** aInEvent.changes: {}\", aInEvent.getChanges());\n }\n\n IYangDB yangDB = aInMdConverterFw.getiMdConverterFw().getIYangDB();\n\n createOrUpdateSaps(aInEvent, aInNeId, yangDB);\n }\n\n private void createOrUpdateSaps(ObjectEntityNotification aInEvent, String aInNeId, IYangDB yangDB)\n {\n // This method called for both create event and update event\n\n // createIetfNetworkIfNotExists(yangDB, qp);\n\n String eventClassId = aInEvent.getClassId();\n String instanceId = aInEvent.getEntity().getIdentifier();\n\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n // Since we don't control the order in which events are published,\n // We MAY get an event for a child object before the parent\n createIetfSAPNodeIfNotExists(yangDB, aInNeId, qp);\n\n Logger logger = aInEvent instanceof ObjectCreation ? handleCreateEventLogger : handleUpdateEventLogger;\n\n if(NSP_PORT_CLASS_ID.equals(eventClassId))\n {\n qp.setFields(NSP_PORT_READ_FIELDS);\n IYangObject yangObject = yangDB.getSingle(instanceId, qp); // have to re-read to get the full object, event will not have it\n if(yangObject == null)\n {\n logger.error(\"Got an event for an object that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createOrUpdateIetfSapsForPort(yangObject, aInNeId, yangDB);\n }\n else if (NSP_LAG_CLASS_ID.equals(eventClassId))\n {\n qp.setFields(NSP_LAG_READ_FIELDS);\n IYangObject yangObject = yangDB.getSingle(instanceId, qp); // have to re-read to get the full object, event will not have it\n if(yangObject == null)\n {\n logger.error(\"Got an event for an object that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createorUpdateIetfSapsForLag(yangObject, aInNeId, yangDB);\n }\n else if(NSP_ELINE_ENDPOINT_CLASS_ID.equals(eventClassId))\n {\n qp.setFields(NSP_SERVICE_ENDPOINT_READ_FIELDS);\n IYangObject yangObject = yangDB.getSingle(instanceId, qp); // have to re-read to get the full object, event will not have it\n if(yangObject == null)\n {\n logger.error(\"Got an event for an object that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createOrUpdateIetfSapsForServiceEndpoints(yangObject, aInNeId, IETF_VPN_COMMON_VPWS, yangDB);\n }\n else if(NSP_ELAN_ENDPOINT_CLASS_ID.equals(eventClassId))\n {\n qp.setFields(NSP_SERVICE_ENDPOINT_READ_FIELDS);\n IYangObject yangObject = yangDB.getSingle(instanceId, qp); // have to re-read to get the full object, event will not have it\n if(yangObject == null)\n {\n logger.error(\"Got an event for an object that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createOrUpdateIetfSapsForServiceEndpoints(yangObject, aInNeId, IETF_VPN_COMMON_VPLS, yangDB);\n }\n else if (NSP_L3VPN_ENDPOINT_CLASS_ID.equals(eventClassId))\n {\n qp.setFields(NSP_SERVICE_ENDPOINT_READ_FIELDS);\n IYangObject yangObject = yangDB.getSingle(instanceId, qp); // have to re-read to get the full object, event will not have it\n if(yangObject == null)\n {\n logger.error(\"Got an event for an object that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createOrUpdateIetfSapsForServiceEndpoints(yangObject, aInNeId, IETF_VPN_COMMON_L3VPN, yangDB);\n }\n else\n {\n if(aInEvent instanceof ObjectModification || aInEvent instanceof ObjectCreation)\n {\n if (NSP_PORT_DETAILS_CLASS_ID.equals(eventClassId))\n {\n String portInstanceId = instanceId.split(\"/port-details\")[0];\n\n qp.setFields(NSP_PORT_READ_FIELDS);\n IYangObject nspPortObject = yangDB.getSingle(portInstanceId, qp);\n if(nspPortObject == null)\n {\n logger.error(\"Got an event for port-details of a port that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createOrUpdateIetfSapsForPort(nspPortObject, aInNeId, yangDB);\n }\n else if (NSP_LAG_MEMEBER_DETAILS_CLASS_ID.equals(eventClassId))\n {\n //On lag member details event update saps to remove ports that are lags but also call create lag\n String portInstanceId = instanceId.split(\"/\"+NSP_LAG_MEMEBER_DETAILS_PROP)[0];\n //Create fake portObject with id and lag to delete ports\n IYangObject nspPortObject = new YangObject();\n nspPortObject.setIdentifier(portInstanceId);\n List<IYangObject> lagMemberDetails = new ArrayList<>();\n lagMemberDetails.add(aInEvent.getEntity());\n nspPortObject.setProperty(NSP_LAG_MEMEBER_DETAILS_PROP, lagMemberDetails);\n\n createOrUpdateIetfSapsForPort(nspPortObject, aInNeId, yangDB);\n\n if(aInEvent.getEntity().hasProperty(NSP_LAG_ID_PROP) && aInEvent.getEntity().getProperty(NSP_LAG_ID_PROP)!=null){\n String lagInstanceId= String.format(NSP_LAG_YANG_PATH, aInNeId, aInEvent.getEntity().getProperty(NSP_LAG_ID_PROP));\n qp.setFields(NSP_LAG_READ_FIELDS);\n IYangObject yangObject = yangDB.getSingle(lagInstanceId, qp);\n if(yangObject == null)\n {\n logger.error(\"Got an event for an \"+NSP_LAG_MEMEBER_DETAILS_PROP+\": {} lag: {} does not exist\", instanceId, lagInstanceId);\n return;\n }\n createorUpdateIetfSapsForLag(yangObject, aInNeId, yangDB);\n }\n else {\n logger.error(\"Got an event for an \"+NSP_LAG_MEMEBER_DETAILS_PROP+\": {} but lag-id is not set\", instanceId);\n }\n }\n else if (NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId) ||\n NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId) ||\n NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId))\n {\n String endpointInstanceId = instanceId.split(\"/ipservice-endpoint-detail\")[0];\n\n qp.setFields(NSP_SERVICE_ENDPOINT_READ_FIELDS);\n IYangObject endpoint = yangDB.getSingle(endpointInstanceId, qp);\n if(endpoint == null)\n {\n logger.error(\"Got an event for ipservice-endpoint-detail of an endpoint that does not exist!! instanceId: {}\", instanceId);\n return;\n }\n createOrUpdateIetfSapsForServiceEndpoints(endpoint, aInNeId, mapClassIdToIetfServiceType(eventClassId), yangDB);\n }\n }\n else\n {\n // aInEvent is ObjectCreation. WTF does it mean to create port-details without port or\n // ipservice-endpoint-details without the endpoint\n }\n }\n }\n\n @Override\n public void handleReplaceEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectReplacement aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n if(handleReplaceEventLogger.isDebugEnabled()) {\n handleReplaceEventLogger.debug(\"********** handleReplaceEvent - aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, ObjectReplacement: {}\", aInSrcClass, aInSyncClass, aInNeId, aInEvent.getEntity().asMap());\n }\n }\n\n @Override\n public void handleDeleteEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectDeletion aInEvent, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n if(handleDeleteEventLogger.isDebugEnabled()) {\n handleDeleteEventLogger.debug(\"********** handleDeleteEvent - aInSrcClass:{}, aInSyncClass:{}, aInNeId: {}, ObjectDeletion: {}\", aInSrcClass, aInSyncClass, aInNeId, aInEvent.getEntity().asMap());\n }\n\n IYangDB yangDB = aInMdConverterFw.getiMdConverterFw().getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n String eventClassId = aInEvent.getClassId();\n String instanceId = aInEvent.getInstanceId();\n\n// if(NSP_NE_CLASS_ID.equals(eventClassId))\n// {\n// // Delete this node; will delete all SAPs on this node as child objects\n// String ietfNodePath = String.format(IETF_SAP_NETWORK_NODE_YANG_PATH, aInNeId);\n// yangDB.delete(ietfNodePath, qp);\n// }\n// else\n if(NSP_PORT_CLASS_ID.equals(eventClassId) || NSP_LAG_CLASS_ID.equals(eventClassId))\n {\n deleteAllSaps(aInNeId,instanceId,qp,yangDB);\n }\n else if(NSP_ELINE_ENDPOINT_CLASS_ID.equals(eventClassId))\n {\n deleteSap(aInNeId,instanceId,IETF_VPN_COMMON_VPWS,qp,yangDB);\n }\n else if(NSP_ELAN_ENDPOINT_CLASS_ID.equals(eventClassId))\n {\n deleteSap(aInNeId,instanceId,IETF_VPN_COMMON_VPLS,qp,yangDB);\n }\n else if(NSP_L3VPN_ENDPOINT_CLASS_ID.equals(eventClassId))\n {\n deleteSap(aInNeId,instanceId,IETF_VPN_COMMON_L3VPN,qp,yangDB);\n }\n else if (NSP_PORT_DETAILS_CLASS_ID.equals(eventClassId) ||\n NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId) ||\n NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId) ||\n NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId))\n {\n // WTF does it mean when only port-details get deleted from a port or\n // ipservice-endpoint-detail gets deleted from a service endpoint?\n return;\n }\n }\n\n @Override\n public void handlePostResyncDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, YangPluginMdConverterProvider aInMdConverterFw)\n {\n handlePostResyncDeleteLogger.debug(\"********** handlePostResyncDelete called\");\n }\n\n// @Override\n// public boolean canDeleteObject(IYangObject aInIYangObject, SyncClass aInSyncClass, SrcClass aInSrcClass, IMdConverterFw aInMdConverterFw)\n// {\n// canDeleteObjectLogger.debug(\"********** canDeleteObject - aInSrcClass:{}, aInSyncClass:{}, aInIYangObject:{}\", aInSrcClass, aInSyncClass, aInIYangObject);\n//\n// IYangDB yangDB = aInMdConverterFw.getIYangDB();\n//\n// final QueryParameters qp = new QueryParameters();\n// qp.setSuperUser(true);\n// qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n//\n// String lDestClassPath = aInSyncClass.getDestClassPath();\n// String lSrcClassPath = aInSrcClass.getSrcClassPath();\n//\n// if (NSP_PORT_DETAILS_CLASS_PATH.equals(lSrcClassPath) ||\n// NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(lSrcClassPath) ||\n// NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(lSrcClassPath) ||\n// NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(lSrcClassPath))\n// {\n// // Code should not reach here. FW should not call this.\n// canDeleteObjectLogger.debug(\"<><><><><><><><><><> Code should not reach here. canDeleteObject called for srcClassPath: {}\", lSrcClassPath);\n// return false;\n// }\n//\n// if(IETF_NETWORK_CLASS_PATH.equals(lDestClassPath))\n// {\n// return false; // We don't delete the IETF SAP topology network root object ever\n// }\n// else if(IETF_NODE_CLASS_PATH.equals(lDestClassPath))\n// {\n// String neId = aInIYangObject.getProperty(IETF_NODE_ID_PROP);\n//\n// if (!yangDB.exists(String.format(NSP_NE_YANG_PATH, neId)))\n// {\n// return true; // if NSP no longer has this NE, delete it from IETF SAP topology\n// }\n// }\n// else if(IETF_SAP_CLASS_PATH.equals(lDestClassPath))\n// {\n// String serviceType = StringUtils.substringBetween(aInIYangObject.getIdentifier(), \"[service-type='\", \"']\");\n//\n// String sapInterfaceType = aInIYangObject.getProperty(IETF_INTERFACE_TYPE_PROP);\n// String sapId = aInIYangObject.getProperty(IETF_SAP_ID_PROP);\n//\n// /*\n// The following complicated if-else conditions are required to prevent querying the DB using yangDB.exists() unnecessarily\n// since this code will be hit for EVERY combination of lDestClassPath (all IETF SAPs) and lSrcClassPath (every port/LAG/SvcEndpoints).\n// See IetfSapTopology.json mapping file entry for \"destClassPath\": \"ietf-network:/networks/network/node/ietf-sap-ntw:service/sap\"\n// For examples,\n// lDestClassPath could be that of a SAP that corresponds to a LAG and lSrcClassPath could be that of a port\n// lDestClassPath could be that of a SAP that corresponds to an ELINE endpoint and lSrcClassPath could be that of a L3VPN endpoint\n// */\n//\n// if (IetfInterfaceType.PHY.value.equals(sapInterfaceType) && NSP_PORT_CLASS_PATH.equals(lSrcClassPath))\n// {\n// //if(!yangDB.exists(String.format(NSP_PORT_YANG_PATH, neId, aInIYangObject.getProperty(IETF_SAP_ID_PROP))))\n// if(!yangDB.exists(sapId))\n// {\n// return true; // delete this SAP if NSP no longer has this port\n// }\n// }\n// else if (IetfInterfaceType.LAG.value.equals(sapInterfaceType) && NSP_LAG_CLASS_PATH.equals(lSrcClassPath))\n// {\n// //if(!yangDB.exists(String.format(NSP_LAG_YANG_PATH, neId, aInIYangObject.getProperty(IETF_SAP_ID_PROP))))\n// if(!yangDB.exists(sapId))\n// {\n// return true; // delete this SAP if NSP no longer has this LAG\n// }\n// }\n// else if (IetfInterfaceType.LOGICAL.value.equals(sapInterfaceType))\n// {\n// if(\n// (IETF_VPN_COMMON_VPWS.equals(serviceType) && NSP_ELINE_ENDPOINT_CLASS_PATH.equals(lSrcClassPath)) ||\n// (IETF_VPN_COMMON_VPLS.equals(serviceType) && NSP_ELAN_ENDPOINT_CLASS_PATH.equals(lSrcClassPath)) ||\n// (IETF_VPN_COMMON_L3VPN.equals(serviceType) && NSP_L3VPN_ENDPOINT_CLASS_PATH.equals(lSrcClassPath))\n// )\n// {\n// if(!yangDB.exists(sapId))\n// {\n// return true; // delete this SAP if NSP no longer has this ELINE/ELAN/L3VPN endpoint\n// }\n// }\n// }\n// }\n//\n// return false;\n// }\n\n private void handleSapResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, IYangDB yangDB)\n {\n// createIetfNodeIfNotExists(yangDB, aInNeId, qp);\n\n String srcClassPath = aInSrcClass.getSrcClassPath();\n\n if (NSP_PORT_CLASS_PATH.equals(srcClassPath))\n {\n createOrUpdateIetfSapsForPort(aInSrcObject, aInNeId, yangDB);\n }\n else if (NSP_LAG_CLASS_PATH.equals(srcClassPath))\n {\n createorUpdateIetfSapsForLag(aInSrcObject, aInNeId, yangDB);\n }\n else if (NSP_ELINE_ENDPOINT_CLASS_PATH.equals(srcClassPath))\n {\n createOrUpdateIetfSapsForServiceEndpoints(aInSrcObject, aInNeId, IETF_VPN_COMMON_VPWS, yangDB);\n }\n else if (NSP_ELAN_ENDPOINT_CLASS_PATH.equals(srcClassPath))\n {\n createOrUpdateIetfSapsForServiceEndpoints(aInSrcObject, aInNeId, IETF_VPN_COMMON_VPLS, yangDB);\n }\n else if (NSP_L3VPN_ENDPOINT_CLASS_PATH.equals(srcClassPath))\n {\n createOrUpdateIetfSapsForServiceEndpoints(aInSrcObject, aInNeId, IETF_VPN_COMMON_L3VPN, yangDB);\n }\n else if (NSP_PORT_DETAILS_CLASS_PATH.equals(srcClassPath) ||\n NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(srcClassPath) ||\n NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(srcClassPath) ||\n NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_PATH.equals(srcClassPath))\n {\n // Code should not reach here. FW should not call this.\n handleResyncLogger.debug(\"<><><><><><><><><><> Code should not reach here. handleResync called for srcClassPath: {}\", srcClassPath);\n }\n }\n\n private void createOrUpdateIetfSapsForPort(IYangObject aInSrcObject, String aInNeId, IYangDB yangDB)\n {\n createOrUpdateIetfSapsForPortLogger.debug(\"********** createOrUpdateIetfSapsForPort - aInSrcObject {}\",aInSrcObject.asMap());\n //String portComponentId = (String) aInSrcObject.get(NSP_COMPONENT_ID_PROP);\n //String nspModelIdentifier = (String)((Map) aInSrcObject.get(\"@\")).get(NSP_MODEL_IDENTIFIER_PROP);\n String nspModelIdentifier = aInSrcObject.getIdentifier();\n String vpwsSapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPWS, nspModelIdentifier);\n String vplsSapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPLS, nspModelIdentifier);\n String l3vpnSapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, IETF_VPN_COMMON_L3VPN, nspModelIdentifier);\n createOrUpdateIetfSapsForPortLogger.debug(\"********** SapPaths - vpwsSapPath: {}, vplsSapPath: {}, l3vpnSapPath: {}\", vpwsSapPath, vplsSapPath, l3vpnSapPath);\n\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n List<IYangObject> lagMemberDetailsList = aInSrcObject.getProperty(NSP_LAG_MEMEBER_DETAILS_PROP);\n if (lagMemberDetailsList != null && !lagMemberDetailsList.isEmpty())\n {\n if(createOrUpdateIetfSapsForPortLogger.isDebugEnabled()) {\n createOrUpdateIetfSapsForPortLogger.debug(\"********** deletePortIsLag - vpwsSapPath: {}\", vpwsSapPath);\n }\n // For first-resync/create event, no SAP will be created if this port is in a LAG\n // For subsequent-resync/update event, if this port was just added to a LAG, existing SAPs, if present, will be deleted\n deleteAllSaps(aInNeId,nspModelIdentifier,qp,yangDB);\n return;\n }\n else{\n if(createOrUpdateIetfSapsForPortLogger.isDebugEnabled()) {\n createOrUpdateIetfSapsForPortLogger.debug(\"Keeping port without lag {}\", nspModelIdentifier);\n }\n }\n\n IYangObject sap = new YangObject();\n sap.setProperty(IETF_SAP_ID_PROP, nspModelIdentifier);\n sap.setProperty(IETF_ATTACHMENT_INTERFACE_PROP, aInSrcObject.getProperty(NSP_NAME_PROP));\n sap.setProperty(IETF_INTERFACE_TYPE_PROP, IetfInterfaceType.PHY.value);\n\n List<IYangObject> portDetailsList = aInSrcObject.getProperty(NSP_PORT_DETAILS_PROP);\n if(portDetailsList != null && !portDetailsList.isEmpty())\n {\n IYangObject portDetails = portDetailsList.get(0);\n String portMode = portDetails.getProperty(NSP_PORT_MODE_PROP);\n\n if (!ACCESS.equals(portMode) && !HYBRID.equals(portMode))\n {\n createOrUpdateIetfSapsForPortLogger.debug(\"********** deletePortIsNotAccess - vpwsSapPath: {}\", vpwsSapPath);\n // For first-resync/create event, no SAP will be created if port is not access or hybrid\n // For subsequent-resync/update event, if the port-mode was changed, existing SAPs, if present, will be deleted\n deleteAllSaps(aInNeId,nspModelIdentifier,qp,yangDB);\n return;\n }\n else\n {\n sap.setProperty(IETF_ROLE_PROP, IetfInterfaceRole.UNI.value); // If portDetailsList is empty, role will be null. Can't tell if its UNI/NNI.\n }\n\n String mappedEncapType = mapNspEquipmentModelEncapType(portDetails.getProperty(NSP_ENCAP_TYPE_PROP));\n if (null != mappedEncapType)\n sap.setProperty(IETF_ENCAPSULATION_TYPE_PROP, mappedEncapType);\n }\n else\n {\n if(createOrUpdateIetfSapsForPortLogger.isDebugEnabled()) {\n createOrUpdateIetfSapsForPortLogger.debug(\"Keeping port without mode {}\", nspModelIdentifier);\n }\n // TODO do we still keep this SAP even if we don't know port-mode, role and encaptype? Is that useful?\n sap.setProperty(IETF_ROLE_PROP, null);\n sap.setProperty(IETF_ENCAPSULATION_TYPE_PROP, null);\n }\n\n IYangObject sapStatus = new YangObject();\n sapStatus.setProperty(IETF_STATUS_PROP, mapOperState(aInSrcObject.getProperty(NSP_OPER_STATE_PROP)));\n\n sap.setProperty(IETF_SAP_STATUS_PROP, sapStatus);\n\n // For a port, one SAP will be created for each service-type: ietf-vpn-common:vpws, ietf-vpn-common:vpls, ietf-vpn-common:l3vpn\n\n if (!yangDB.exists(vpwsSapPath, qp))\n {\n String vpwsServicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPWS);\n if (!yangDB.exists(vpwsServicePath))\n {\n createOrUpdateIetfSapsForPortLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", vpwsSapPath, vpwsServicePath);\n }\n else\n {\n yangDB.createChild(vpwsServicePath, IETF_SAP_PROP, sap, qp);\n }\n }\n else\n {\n yangDB.update(vpwsSapPath, sap, qp);\n }\n\n if (!yangDB.exists(vplsSapPath, qp))\n {\n String vplsServicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPLS);\n if (!yangDB.exists(vplsServicePath))\n {\n createOrUpdateIetfSapsForPortLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", vplsSapPath, vplsServicePath);\n }\n else\n {\n yangDB.createChild(vplsServicePath, IETF_SAP_PROP, sap, qp);\n }\n }\n else\n {\n yangDB.update(vplsSapPath, sap, qp);\n }\n\n if (!yangDB.exists(l3vpnSapPath, qp))\n {\n String l3vpnServicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, IETF_VPN_COMMON_L3VPN);\n if (!yangDB.exists(l3vpnServicePath))\n {\n createOrUpdateIetfSapsForPortLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", l3vpnSapPath, l3vpnServicePath);\n }\n else {\n yangDB.createChild(l3vpnServicePath, IETF_SAP_PROP, sap, qp);\n }\n }\n else\n {\n yangDB.update(l3vpnSapPath, sap, qp);\n }\n }\n\n private void createorUpdateIetfSapsForLag(IYangObject aInSrcObject, String aInNeId, IYangDB yangDB)\n {\n //String lagId = (String) aInSrcObject.get(NSP_LAG_ID_PROP);\n //String nspModelIdentifier = (String)((Map) aInSrcObject.get(\"@\")).get(NSP_MODEL_IDENTIFIER_PROP);\n String nspModelIdentifier = aInSrcObject.getIdentifier();\n String vpwsSapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPWS, nspModelIdentifier);\n String vplsSapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPLS, nspModelIdentifier);\n String l3vpnSapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, IETF_VPN_COMMON_L3VPN, nspModelIdentifier);\n\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n if (((List) aInSrcObject.get(NSP_MEMBERS_PROP)).isEmpty())\n {\n // For first-resync/create event, no SAP will be created if LAG does not have any members\n // For subsequent-resync/update event, if the last port was removed from this LAG, existing SAPs, if present, will be deleted\n deleteAllSaps(aInNeId,nspModelIdentifier,qp,yangDB);\n return;\n }\n\n String lagMode = aInSrcObject.getProperty(NSP_LAG_MODE_PROP);\n\n if (!ACCESS.equals(lagMode) && !HYBRID.equals(lagMode))\n {\n // For first-resync/create event, no SAP will be created if LAG is not access or hybrid\n // For subsequent-resync/update event, if the lag-mode was changed, existing SAPs, if present, will be deleted\n deleteAllSaps(aInNeId,nspModelIdentifier,qp,yangDB);\n return; // no SAP will be created if lag is not access or hybrid\n }\n\n IYangObject sap = new YangObject();\n sap.setProperty(IETF_SAP_ID_PROP, nspModelIdentifier);\n sap.setProperty(IETF_ATTACHMENT_INTERFACE_PROP, aInSrcObject.getProperty(NSP_NAME_PROP));\n sap.setProperty(IETF_INTERFACE_TYPE_PROP, IetfInterfaceType.LAG.value);\n sap.setProperty(IETF_ROLE_PROP, IetfInterfaceRole.UNI.value);\n sap.setProperty(IETF_ENCAPSULATION_TYPE_PROP, IetfEncapType.LAG_INT.value);\n\n IYangObject sapStatus = new YangObject();\n sapStatus.setProperty(IETF_STATUS_PROP, mapOperState(aInSrcObject.getProperty(NSP_OPER_STATE_PROP)));\n\n sap.setProperty(IETF_SAP_STATUS_PROP, sapStatus);\n\n // For a LAG, one SAP will be created for each service-type: ietf-vpn-common:vpws, ietf-vpn-common:vpls, ietf-vpn-common:l3vpn\n\n if (!yangDB.exists(vpwsSapPath, qp))\n {\n String vpwsServicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPWS);\n if (!yangDB.exists(vpwsServicePath))\n {\n classLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", vpwsSapPath, vpwsServicePath);\n }\n else {\n yangDB.createChild(vpwsServicePath, IETF_SAP_PROP, sap, qp);\n }\n }\n else\n {\n yangDB.update(vpwsSapPath, sap, qp);\n }\n\n if (!yangDB.exists(vplsSapPath, qp))\n {\n String vplsServicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, IETF_VPN_COMMON_VPLS);\n if (!yangDB.exists(vplsServicePath))\n {\n classLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", vplsSapPath, vplsServicePath);\n }\n else {\n yangDB.createChild(vplsServicePath, IETF_SAP_PROP, sap, qp);\n }\n }\n else\n {\n yangDB.update(vplsSapPath, sap, qp);\n }\n\n if (!yangDB.exists(l3vpnSapPath, qp))\n {\n String l3vpnServicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, IETF_VPN_COMMON_L3VPN);\n if (!yangDB.exists(l3vpnServicePath))\n {\n classLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", l3vpnSapPath, l3vpnServicePath);\n }\n else {\n yangDB.createChild(l3vpnServicePath, IETF_SAP_PROP, sap, qp);\n }\n }\n else\n {\n yangDB.update(l3vpnSapPath, sap, qp);\n }\n }\n\n private void createOrUpdateIetfSapsForServiceEndpoints(IYangObject aInSrcObject, String aInNeId, String aInServiceType, IYangDB yangDB)\n {\n //String nspModelIdentifier = (String)((Map) aInSrcObject.get(\"@\")).get(NSP_MODEL_IDENTIFIER_PROP);\n String nspModelIdentifier = aInSrcObject.getIdentifier();\n\n IYangObject sap = new YangObject();\n sap.setProperty(IETF_SAP_ID_PROP, nspModelIdentifier);\n sap.setProperty(IETF_ATTACHMENT_INTERFACE_PROP, aInSrcObject.getProperty(NSP_NAME_PROP));\n\n String parentTerminationPoint = null;\n List<IYangObject> portBindings = aInSrcObject.getProperty(NSP_PORT_BINDINGS_PROP);\n if(portBindings != null && !portBindings.isEmpty())\n {\n parentTerminationPoint = portBindings.get(0).getProperty(NSP_RESOURCE_PROP);\n }\n sap.setProperty(IETF_PARENT_TERMINATION_POINT_PROP, parentTerminationPoint);\n\n sap.setProperty(IETF_INTERFACE_TYPE_PROP, IetfInterfaceType.LOGICAL.value);\n sap.setProperty(IETF_ROLE_PROP, IetfInterfaceRole.UNI.value);\n\n IYangObject ipServiceEndpointDetail = aInSrcObject.getProperty(NSP_IP_SERVICE_ENDPOINT_DETAIL_PROP);\n\n if(ipServiceEndpointDetail != null)\n {\n String mappedEncapType = mapNspServiceModelEncapType(ipServiceEndpointDetail.getProperty(NSP_ENCAP_TYPE_PROP));\n if (null != mappedEncapType)\n sap.setProperty(IETF_ENCAPSULATION_TYPE_PROP, mappedEncapType);\n }\n else\n {\n sap.setProperty(IETF_ENCAPSULATION_TYPE_PROP, null);\n }\n\n IYangObject sapStatus = new YangObject();\n sapStatus.setProperty(IETF_STATUS_PROP, mapOperState(aInSrcObject.getProperty(NSP_OPER_STATE_PROP)));\n sap.setProperty(IETF_SAP_STATUS_PROP, sapStatus);\n\n String serviceYangPath = aInSrcObject.getProperty(NSP_SERVICE_PROP);\n if(serviceYangPath != null) // this should NEVER be null. The only way this is null is if the endpoint's \"service\" prop is not populated in NSP. If so, WTF?\n {\n QueryParameters serviceObjectReadQueryParameters = new QueryParameters();\n serviceObjectReadQueryParameters.setSuperUser(true);\n serviceObjectReadQueryParameters.setFields(Fields.parse(NSP_OPER_STATE_PROP));\n serviceObjectReadQueryParameters.setDepth(2);\n serviceObjectReadQueryParameters.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n IYangObject nspServiceYangObject = yangDB.getSingle(serviceYangPath, serviceObjectReadQueryParameters);\n\n if(nspServiceYangObject != null) // this should NEVER be null. The only way this is null is if the endpoint's \"service\" prop is points to a non-existent service. If so, WTF?\n {\n IYangObject serviceStatus = new YangObject();\n serviceStatus.setProperty(IETF_STATUS_PROP, mapOperState(nspServiceYangObject.getProperty(NSP_OPER_STATE_PROP)));\n sap.setProperty(IETF_SERVICE_STATUS_PROP, serviceStatus);\n }\n else\n {\n classLogger.warn(\"Service {} does not exist, it seems 'service' property of endpoint {} points to non-existent service.\", serviceYangPath, nspModelIdentifier);\n }\n }\n else\n {\n classLogger.warn(\"Got an endpoint with 'service' property not populated. instanceId: {}. Cannot determine service status for SAP.\", nspModelIdentifier);\n }\n\n String servicePath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_YANG_PATH, aInNeId, aInServiceType);\n String sapPath = String.format(IETF_SAP_NETWORK_NODE_SERVICE_SAP_YANG_PATH, aInNeId, aInServiceType, nspModelIdentifier);\n\n QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n if (!yangDB.exists(sapPath, qp))\n {\n if (!yangDB.exists(servicePath))\n {\n classLogger.warn(\"SQUIBB: Trying to attach sap {} to a non-existent service {}. Dropping to let service conversion handle it.\", sapPath, servicePath);\n return;\n }\n yangDB.createChild(servicePath, IETF_SAP_PROP, sap, qp);\n }\n else\n {\n yangDB.update(sapPath, sap, qp);\n }\n }\n\n// private void handleUpdateEventForSpecialChildObjects(ObjectModification aInEvent, YangPluginMdConverterProvider aInMdConverterFw)\n// {\n// IYangDB yangDB = aInMdConverterFw.getiMdConverterFw().getIYangDB();\n//\n// String eventClassId = aInEvent.getClassId();\n// String instanceId = aInEvent.getInstanceId();\n//\n// handleUpdateEventLogger.debug(\"########## got updateEvent for \" + instanceId);\n// handleUpdateEventLogger.debug(\"########## aInEvent.changes: {}\", aInEvent.getChanges());\n// handleUpdateEventLogger.debug(\"########## aInEvent.entity: {}\", aInEvent.getEntity().asMap());\n//\n// final QueryParameters qp = new QueryParameters();\n// qp.setSuperUser(true);\n// qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n// qp.setDepth(QUERY_PARAMETERS_DEPTH);\n//\n// if(NSP_PORT_DETAILS_CLASS_ID.equals(eventClassId))\n// {\n// String neId = StringUtils.substringBetween(instanceId, \"[ne-id='\", \"']\");\n// String portInstanceId = instanceId.split(\"/port-details\")[0];\n//\n// IYangObject nspPortObject = yangDB.getSingle(portInstanceId, qp);\n// createOrUpdateIetfSapsForPort(nspPortObject, neId, yangDB, qp);\n// }\n// else if (NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId) ||\n// NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId) ||\n// NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(eventClassId))\n// {\n// String endpointInstanceId = instanceId.split(\"/ipservice-endpoint-detail\")[0];\n//\n// IYangObject endpoint = yangDB.getSingle(endpointInstanceId, qp);\n// String neId = endpoint.getProperty(NSP_SITE_ID_PROP);\n// createOrUpdateIetfSapsForServiceEndpoints(endpoint, neId, mapClassIdToIetfServiceType(eventClassId), yangDB, qp);\n// }\n// }\n\n private String mapNspEquipmentModelEncapType(String encapType)\n {\n if(encapType == null)\n return null;\n\n switch (encapType)\n {\n case \"qinq\":\n return IetfEncapType.QINQ.value;\n case \"dot1q\":\n return IetfEncapType.DOT1Q.value;\n case \"null-encap\":\n return IetfEncapType.UNTAGGED_INT.value;\n default:\n return null;\n }\n }\n\n private String mapNspServiceModelEncapType(String encapType)\n {\n if(encapType == null)\n return null;\n\n switch (encapType)\n {\n case \"qinq-encap\":\n return IetfEncapType.QINQ.value;\n case \"q-encap\":\n return IetfEncapType.QINANY.value;\n case \"null-encap\":\n return IetfEncapType.UNTAGGED_INT.value;\n case \"unspecified\":\n case \"cem\":\n default:\n return null;\n }\n }\n\n private String mapOperState(String operState)\n {\n if(operState == null)\n return IetfOperState.OP_UNKNOWN.value; // TODO should return UP??\n\n switch (operState)\n {\n case \"enabled\":\n return IetfOperState.OP_UP.value;\n case \"disabled\":\n return IetfOperState.OP_DOWN.value;\n case \"unknown\":\n return IetfOperState.OP_UNKNOWN.value;\n default:\n /*\n nsp-common.yang states:\n If a piece of equipment does not have an operational state,\n then that component's operational state can be mapped to:\n present = operationally up,\n absent = operationally down.\n Refer to X.731 standard for more information (https://www.itu.int/rec/T-REC-X.731-199201-I/en)\n */\n return IetfOperState.OP_UP.value; // TODO have to check this, should return unknown?\n }\n }\n\n private String mapClassIdToIetfServiceType(String classId)\n {\n if (NSP_ELINE_ENDPOINT_CLASS_ID.equals(classId) || NSP_ELINE_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(classId))\n return IETF_VPN_COMMON_VPWS;\n else if (NSP_ELAN_ENDPOINT_CLASS_ID.equals(classId) || NSP_ELAN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(classId))\n return IETF_VPN_COMMON_VPLS;\n else if (NSP_L3VPN_ENDPOINT_CLASS_ID.equals(classId) || NSP_L3VPN_IP_SERVICE_ENDPOINT_DETAIL_CLASS_ID.equals(classId))\n return IETF_VPN_COMMON_L3VPN;\n else\n return null;\n }\n\n @Override\n public int readSrcObjectDepth(String aInSrcClassPath)\n {\n return QUERY_PARAMETERS_DEPTH_SRC;\n }\n\n @Override\n public int readDestObjectDepth(String aInDestClassPath)\n {\n return QUERY_PARAMETERS_DEPTH_DEST;\n }\n\n public Fields srcFilterFieldsToInclude(String aInSrcClassPath)\n {\n if(NSP_PORT_CLASS_PATH.equals(aInSrcClassPath))\n {\n return NSP_PORT_READ_FIELDS;\n }\n else if (NSP_LAG_CLASS_PATH.equals(aInSrcClassPath))\n {\n return NSP_LAG_READ_FIELDS;\n }\n else if(NSP_ELINE_ENDPOINT_CLASS_PATH.equals(aInSrcClassPath) ||\n NSP_ELAN_ENDPOINT_CLASS_PATH.equals(aInSrcClassPath) ||\n NSP_L3VPN_ENDPOINT_CLASS_PATH.equals(aInSrcClassPath))\n {\n return NSP_SERVICE_ENDPOINT_READ_FIELDS;\n }\n return null;\n }\n public Fields destFilterFieldsToInclude(String aInDestClassPath)\n {\n return IETF_SAP_READ_FIELDS;\n }\n\n\n// @Override\n// public boolean accept(Headers aInHeaders)\n// {\n// if (null != aInHeaders)\n// {\n// handleUpdateEventLogger.debug(\"########## Got Kafka message with headers:\");\n// aInHeaders.iterator().forEachRemaining(header -> handleUpdateEventLogger.debug(\"########## key: \" + header.key() + \", value: \" + new String(header.value())));\n//\n// for (Header lHeader : aInHeaders)\n// {\n// if (lHeader.key().equals(CLASS_ID))\n// {\n// String lValue = new String(lHeader.value());\n// return classIdsForIYangTopicConsumer.contains(lValue);\n// }\n// }\n// }\n// return false;\n// }\n//\n// @Override\n// public void consume(ObjectNotification aInObjectNotification)\n// {\n// if (aInObjectNotification instanceof ObjectModification)\n// {\n// ObjectModification aInEvent = (ObjectModification) aInObjectNotification;\n// handleUpdateEventForSpecialChildObjects(aInEvent, YangPluginMdConverterProvider.getInstance());\n// }\n// }\n}\n"
926
+ }
927
+ ]
928
+ },
929
+ {
930
+ "@": {
931
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler",
932
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.IetfNodeHandlerForNSPNetworkElement']",
933
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
934
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
935
+ },
936
+ "java-class-path": "com.nokia.nsp.md.converter.yang.plugin.IetfNodeHandlerForNSPNetworkElement",
937
+ "version": "1.0.1",
938
+ "java-code": [
939
+ {
940
+ "@": {
941
+ "nsp-model:schema-nodeid": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler/java-code",
942
+ "nsp-model:identifier": "/nsp-yang-mapping-converter:nsp-yang-mapping-converter/custom-handler[java-class-path='com.nokia.nsp.md.converter.yang.plugin.IetfNodeHandlerForNSPNetworkElement']/java-code[page-number='1']",
943
+ "nsp-model:creation-time": "2023-11-28T19:44:30.357Z",
944
+ "nsp-model:last-modified-time": "2023-11-28T19:44:30.357Z"
945
+ },
946
+ "page-number": 1,
947
+ "page": "package com.nokia.nsp.md.converter.yang.plugin;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.nokia.nsp.md.common.IYangObject;\nimport com.nokia.nsp.md.common.YangObject;\nimport com.nokia.nsp.md.common.notif.ObjectCreation;\nimport com.nokia.nsp.md.common.notif.ObjectDeletion;\nimport com.nokia.nsp.md.common.notif.ObjectModification;\nimport com.nokia.nsp.md.common.notif.ObjectReplacement;\nimport com.nokia.nsp.md.converter.api.IMdConverterFw;\nimport com.nokia.nsp.md.converter.yang.plugin.common.ICustomHandler;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SrcClass;\nimport com.nokia.nsp.md.converter.yang.plugin.metadata.SyncClass;\nimport com.nokia.nsp.md.db.yang.api.ExecutionContext;\nimport com.nokia.nsp.md.db.yang.api.QueryParameters;\nimport com.nokia.nsp.md.ifg.yang.api.Fields;\nimport com.nokia.nspos.model.domain.service.types.EndpointType;\nimport com.nokia.nspos.model.domain.service.types.Layer;\nimport com.nokia.nspos.model.domain.service.types.ServiceType;\nimport com.nokia.nspos.persistence.api.IDB;\nimport com.nokia.nspos.persistence.impl.db.transaction.DBRuntimeException;\nimport com.nokia.nspos.persistence.impl.db.transaction.ITransactionContext;\nimport com.nokia.nspos.persistence.impl.db.transaction.Transactor;\nimport com.nokia.nspos.persistence.yang.api.IYangDB;\n\nimport java.math.BigInteger;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.function.Function;\nimport java.util.regex.Pattern;\n\npublic class IetfNodeHandlerForNSPNetworkElement implements ICustomHandler\n{\n private static final org.slf4j.Logger handleResyncLogger = org.slf4j.LoggerFactory.getLogger(IetfNodeHandlerForNSPNetworkElement.class.getName() + \".handleResync\");\n private static final org.slf4j.Logger handlePostResyncDeleteLogger = org.slf4j.LoggerFactory.getLogger(IetfNodeHandlerForNSPNetworkElement.class.getName() + \".handlePostResyncDelete\");\n private static final org.slf4j.Logger handleCreateEventLogger = org.slf4j.LoggerFactory.getLogger(IetfNodeHandlerForNSPNetworkElement.class.getName() + \".handleCreateEvent\");\n private static final org.slf4j.Logger handleUpdateEventLogger = org.slf4j.LoggerFactory.getLogger(IetfNodeHandlerForNSPNetworkElement.class.getName() + \".handleUpdateEvent\");\n private static final org.slf4j.Logger handleReplaceEventLogger = org.slf4j.LoggerFactory.getLogger(IetfNodeHandlerForNSPNetworkElement.class.getName() + \".handleReplaceEvent\");\n private static final org.slf4j.Logger handleDeleteEventLogger = org.slf4j.LoggerFactory.getLogger(IetfNodeHandlerForNSPNetworkElement.class.getName() + \".handleDeleteEvent\");\n\n private static final String IETF_SAP_NETWORK_ID = \"SAPTopology\";\n private static final String IETF_L2_NETWORK_ID = \"L2Topology\";\n\n private static final String IETF_NETWORK_ID_PROP = \"network-id\";\n private static final String IETF_NETWORK_PROP = \"network\";\n private static final String IETF_NETWORK_TYPES_PROP = \"network-types\";\n private static final String IETF_NODE_PROP = \"node\";\n private static final String IETF_NODE_ID_PROP = \"node-id\";\n private static final String IETF_SERVICE_TYPE_PROP = \"service-type\";\n private static final String IETF_SAP_NTW_SAP_NETWORK_PROP = \"ietf-sap-ntw:sap-network\";\n private static final String IETF_SAP_NTW_SERVICE_PROP = \"ietf-sap-ntw:service\";\n\n private static final String IETF_VPN_COMMON_VPWS = \"ietf-vpn-common:vpws\";\n private static final String IETF_VPN_COMMON_VPLS = \"ietf-vpn-common:vpls\";\n private static final String IETF_VPN_COMMON_L3VPN = \"ietf-vpn-common:l3vpn\";\n\n private static final String IETF_NETWORKS_YANG_PATH = \"/ietf-network:networks\";\n private static final String IETF_SAP_NETWORK_YANG_PATH = String.format(\"/ietf-network:networks/network[network-id='%s']\", IETF_SAP_NETWORK_ID);\n private static final String IETF_SAP_NETWORK_NODE_YANG_PATH = IETF_SAP_NETWORK_YANG_PATH + \"/node[node-id='%s']\";\n\n private static final String IETF_L2_NETWORK_PATH = String.format(\"/ietf-network:networks/network[network-id='%s']\", IETF_L2_NETWORK_ID);\n private static final String IETF_L2_NODE_PATH = IETF_L2_NETWORK_PATH + \"/node[node-id='%s']\";\n\n private static final Pattern MAC_ADDRESS_PATTERN = Pattern.compile(\"[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}\");\n private static final Pattern RAW_MAC_ADDRESS_PATTERN = Pattern.compile(\"[0-9a-fA-F]{12}\");\n\n private static final AtomicBoolean ietfSapNetworkPresent = new AtomicBoolean(false);\n private static final Object mutex = new Object();\n\n private static final Fields NSP_NODE_READ_FIELDS = Fields.parse(\"ne-id;name;mac-address;ip-address\");\n private static final Fields IETF_NODE_READ_FIELDS = Fields.parse(\"node-id\");\n\n @Override\n public void handleResync(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInExistingObject, String aInNeId, YangPluginMdConverterProvider aInYangPlugin)\n {\n IMdConverterFw converterFw = aInYangPlugin.getiMdConverterFw();\n IYangDB yangDB = converterFw.getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n //String lSrcClassPath = aInSrcClass.getSrcClassPath(); // should always be nsp-equipment:/network/network-element\n //String lDestClassPath = aInSyncClass.getDestClassPath(); // should always be ietf-network:/networks/network/node\n\n// createIetfSAPNetworkIfNotExists(yangDB, qp);\n createIetfSAPNodeIfNotExists(yangDB, aInNeId, qp);\n\n handleL2Node(aInSrcObject, aInNeId, yangDB, qp);\n }\n\n @Override\n public void handlePostResyncDelete(SrcClass aInSrcClass, SyncClass aInSyncClass, IYangObject aInSrcObject, String aInNeId, YangPluginMdConverterProvider aInYangPlugin)\n {\n\n }\n\n @Override\n public void handleCreateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectCreation aInEvent, String aInNeId, YangPluginMdConverterProvider aInYangPlugin)\n {\n IYangDB yangDB = aInYangPlugin.getiMdConverterFw().getIYangDB();\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n createIetfSAPNodeIfNotExists(yangDB, aInNeId, qp);\n }\n\n @Override\n public void handleUpdateEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectModification aInEvent, String aInNeId, YangPluginMdConverterProvider aInYangPlugin)\n {\n IYangDB yangDB = aInYangPlugin.getiMdConverterFw().getIYangDB();\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n for(ObjectModification.Change change : aInEvent.getChanges()) {\n if(change.getName().equals(\"ne-name\") || change.getName().equals(\"mac-address\") || change.getName().equals(\"ip-address\")){\n handleL2Node(aInEvent.getEntity(), aInNeId, yangDB, qp);\n break;\n }\n }\n }\n\n @Override\n public void handleReplaceEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectReplacement aInEvent, String aInNeId, YangPluginMdConverterProvider aInYangPlugin)\n {\n\n }\n\n @Override\n public void handleDeleteEvent(SrcClass aInSrcClass, SyncClass aInSyncClass, ObjectDeletion aInEvent, String aInNeId, YangPluginMdConverterProvider aInYangPlugin)\n {\n IYangDB yangDB = aInYangPlugin.getiMdConverterFw().getIYangDB();\n\n final QueryParameters qp = new QueryParameters();\n qp.setSuperUser(true);\n qp.setIExecutionContext(new ExecutionContext(null, null, false, false, false));\n\n //String eventClassId = aInEvent.getClassId();\n //String instanceId = aInEvent.getInstanceId();\n\n // Delete this node from SAPTopology; will delete all SAPs on this node as child objects\n String ietfSAPNodePath = String.format(IETF_SAP_NETWORK_NODE_YANG_PATH, aInNeId);\n yangDB.delete(ietfSAPNodePath, qp);\n }\n\n private void createIetfSAPNetworkIfNotExists(IYangDB yangDB, QueryParameters qp)\n {\n if(ietfSapNetworkPresent.get()) // IETF SAP Network object is already present, return\n return;\n\n synchronized (mutex)\n {\n if (yangDB.exists(IETF_SAP_NETWORK_YANG_PATH, qp))\n {\n // Converter app just started up OR new SAPTopologyHandler file was uploaded,\n // variable is false, but IETF network object present in DB\n // set to true and return\n ietfSapNetworkPresent.set(true);\n return;\n }\n\n IYangObject lSapNetworkObject = new YangObject();\n lSapNetworkObject.setProperty(IETF_SERVICE_TYPE_PROP, Arrays.asList(IETF_VPN_COMMON_VPWS, IETF_VPN_COMMON_VPLS, IETF_VPN_COMMON_L3VPN));\n\n IYangObject lNetworkTypesObj = new YangObject();\n lNetworkTypesObj.setProperty(IETF_SAP_NTW_SAP_NETWORK_PROP, lSapNetworkObject);\n\n IYangObject lNetworkObj = new YangObject();\n lNetworkObj.setProperty(IETF_NETWORK_ID_PROP, IETF_SAP_NETWORK_ID);\n lNetworkObj.setProperty(IETF_NETWORK_TYPES_PROP, lNetworkTypesObj);\n\n yangDB.createChild(IETF_NETWORKS_YANG_PATH, IETF_NETWORK_PROP, lNetworkObj, qp);\n\n // IETF network object was not present in DB and was just created. Set to true and return\n ietfSapNetworkPresent.set(true);\n }\n }\n\n private void createIetfSAPNodeIfNotExists(IYangDB yangDB, String aInNeId, QueryParameters qp)\n {\n String nodePath = String.format(IETF_SAP_NETWORK_NODE_YANG_PATH, aInNeId);\n if(yangDB.exists(nodePath, qp))\n return;\n\n IYangObject ietfVpwsServiceType = new YangObject();\n ietfVpwsServiceType.setProperty(IETF_SERVICE_TYPE_PROP, IETF_VPN_COMMON_VPWS);\n\n IYangObject ietfVplsServiceType = new YangObject();\n ietfVplsServiceType.setProperty(IETF_SERVICE_TYPE_PROP, IETF_VPN_COMMON_VPLS);\n\n IYangObject ietfl3vpnServiceType = new YangObject();\n ietfl3vpnServiceType.setProperty(IETF_SERVICE_TYPE_PROP, IETF_VPN_COMMON_L3VPN);\n\n IYangObject ietfSapNode = new YangObject();\n ietfSapNode.setProperty(IETF_NODE_ID_PROP, aInNeId);\n ietfSapNode.setProperty(IETF_SAP_NTW_SERVICE_PROP, Arrays.asList(ietfVpwsServiceType, ietfVplsServiceType, ietfl3vpnServiceType));\n\n yangDB.createChild(IETF_SAP_NETWORK_YANG_PATH, IETF_NODE_PROP, ietfSapNode, qp);\n }\n\n private void handleL2Node (IYangObject neObject, String neId, IYangDB yangDB, QueryParameters qp) {\n String nodePath = String.format(IETF_L2_NODE_PATH, neId);\n if (!canDeleteL2Node(neId, yangDB) // if canDeleteL2Node is true then no need to sync this node\n && yangDB.exists(IETF_L2_NETWORK_PATH, qp)) {\n\n IYangObject lNodeObj = new YangObject();\n lNodeObj.setProperty(IETF_NETWORK_ID_PROP, IETF_L2_NETWORK_ID);\n lNodeObj.setProperty(IETF_NODE_ID_PROP, neId);\n IYangObject lNodeAttrObj = new YangObject();\n lNodeAttrObj.setProperty(IETF_NETWORK_ID_PROP, IETF_L2_NETWORK_ID);\n lNodeAttrObj.setProperty(IETF_NODE_ID_PROP, neId);\n\n if(neObject.get(\"name\") != null) {\n lNodeAttrObj.setProperty(\"name\", neObject.get(\"name\").toString());\n }\n if(neObject.get(\"mac-address\") != null) {\n String macAddress = convertMacAddress(neObject.get(\"mac-address\").toString());\n if (macAddress != null) {\n lNodeAttrObj.setProperty(\"management-mac\", macAddress);\n }\n }\n if(neObject.get(\"ip-address\") != null) {\n lNodeAttrObj.setProperty(\"management-address\", Collections.singletonList(neObject.get(\"ip-address\").toString()));\n }\n lNodeObj.setProperty(\"ietf-l2-topology:l2-node-attributes\", lNodeAttrObj);\n\n if (!yangDB.exists(nodePath, qp)) {\n handleUpdateEventLogger.debug(\"CREATING L2 NODE {}\", nodePath);\n yangDB.createChild(IETF_L2_NETWORK_PATH, IETF_NODE_PROP, lNodeObj, qp);\n }\n else {\n handleUpdateEventLogger.debug(\"UPDATING L2 NODE {}\", nodePath);\n yangDB.update(nodePath, lNodeObj, qp);\n }\n }\n }\n\n private String convertMacAddress (String aInMacAddress) {\n String macAddress = aInMacAddress.replace(\"-\", \":\").replace(\".\", \"\");\n if (MAC_ADDRESS_PATTERN.matcher(macAddress).matches()) {\n return macAddress;\n }\n if (RAW_MAC_ADDRESS_PATTERN.matcher(macAddress).matches()) {\n StringBuilder macAddressSB = new StringBuilder(macAddress);\n macAddressSB.insert(10, ':')\n .insert(8, ':')\n .insert(6, ':')\n .insert(4, ':')\n .insert(2, ':');\n return macAddressSB.toString();\n }\n return null;\n }\n\n private boolean canDeleteL2Node (String nodeId, IYangDB yangDB) {\n String endpointTableNative = \"service.Endpoint\";\n String serviceTableNative = \"service.Service\";\n String subquery = String.format(\"SELECT DISTINCT svc.dbId FROM %s e JOIN %s svc ON e.service_dbId = svc.dbId \"\n + \"WHERE e.siteId=:siteId AND e.type = :endpointType \"\n + \"AND svc.layer=:layer AND svc.type IN :serviceTypes\",\n endpointTableNative, serviceTableNative);\n String query = String.format(\"SELECT count(*) FROM (SELECT count(e.dbId) FROM %s e \"\n + \"WHERE e.type=:endpointType AND e.service_dbId IN (%s) \"\n + \"GROUP BY e.service_dbId) AS g WHERE g.count = 2\", endpointTableNative, subquery);\n Object count = execute(yangDB.getDb(), tx -> tx.getEntityManager()\n .createNativeQuery(query)\n .setParameter(\"siteId\", nodeId)\n .setParameter(\"endpointType\", EndpointType.physicalPort.getValue())\n .setParameter(\"layer\", Layer.physical.getValue())\n .setParameter(\"serviceTypes\", ImmutableSet.of(ServiceType.cable.getValue(), ServiceType.radioLink.getValue()))\n .getSingleResult());\n return count != null && ((BigInteger) count).longValue() == 0;\n }\n\n private <T> T execute(IDB db, Function<ITransactionContext, T> fn) {\n try {\n if (Transactor.isInTransaction()) {\n return fn.apply(Transactor.getContext());\n } else {\n return Transactor.execute(db, fn, true);\n }\n } catch (DBRuntimeException e) {\n return null;\n }\n }\n\n @Override\n public Fields srcFilterFieldsToInclude(String aInSrcClassPath)\n {\n return NSP_NODE_READ_FIELDS;\n }\n public Fields destFilterFieldsToInclude(String aInDestClassPath)\n {\n return IETF_NODE_READ_FIELDS;\n }\n}\n"
948
+ }
949
+ ]
950
+ }
951
+ ]
952
+ }
953
+ }