private void processBridgeDeletion(
      AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {

    for (InstanceIdentifier<?> removedBridge : changes.getRemovedPaths()) {
      if (removedBridge.getTargetType().equals(OvsdbBridgeAugmentation.class)) {
        Node bridgeParentNode = getNode(changes.getOriginalData(), removedBridge);
        if (bridgeParentNode == null) {
          // Throwing this warning to catch the behavior change of southbound plugin.
          LOG.warn(
              "Bridge's {} parent node details are not present in original data"
                  + ", it should not happen",
              removedBridge);
          continue;
        }
        // Fetch data of removed bridge from original data
        @SuppressWarnings("unchecked")
        OvsdbBridgeAugmentation removedBridgeAugmentationData =
            getDataChanges(
                changes.getOriginalData(),
                (InstanceIdentifier<OvsdbBridgeAugmentation>) removedBridge);

        LOG.debug(
            "processBridgeDeletion <{}> deletion on Node <{}>", removedBridge, bridgeParentNode);
        ovsdbUpdate(
            bridgeParentNode,
            removedBridgeAugmentationData,
            OvsdbInventoryListener.OvsdbType.BRIDGE,
            Action.DELETE);
      }
    }
  }
  private void processOvsdbDisconnect(
      AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {

    for (InstanceIdentifier<?> removedOvsdbNode : changes.getRemovedPaths()) {
      if (removedOvsdbNode.getTargetType().equals(OvsdbNodeAugmentation.class)) {
        // Get top node to get details of all the bridge/termination point augmentation
        // in case we want to do any cleanup task while processing node disconnection
        Node parentNode = getNode(changes.getOriginalData(), removedOvsdbNode);
        if (parentNode == null) {
          // Throwing this warning in case behavior of southbound plugin changes.
          LOG.warn(
              "OvsdbNode's {} parent node details are not present in original data,"
                  + " it should not happen",
              parentNode);
          continue;
        }
        // Fetch data of removed connection info from original data
        @SuppressWarnings("unchecked")
        OvsdbNodeAugmentation removedOvsdbNodeAugmentationData =
            getDataChanges(
                changes.getOriginalData(),
                (InstanceIdentifier<OvsdbNodeAugmentation>) removedOvsdbNode);

        LOG.trace("processOvsdbDisconnect: {} ", removedOvsdbNode);
        //// Assuming Openvswitch type represent the ovsdb node connection and not OvsdbType.NODE

        ovsdbUpdate(
            parentNode,
            removedOvsdbNodeAugmentationData,
            OvsdbInventoryListener.OvsdbType.NODE,
            Action.DELETE);
      }
    }
  }
  private void processPortDeletion(
      AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {

    for (InstanceIdentifier<?> removedPort : changes.getRemovedPaths()) {
      if (removedPort.getTargetType().equals(OvsdbTerminationPointAugmentation.class)) {
        Node tpParentNode = getNode(changes.getOriginalData(), removedPort);
        if (tpParentNode == null) {
          // Throwing this warning in case behavior of southbound plugin changes.
          LOG.warn(
              "Port's {} parent node details are not present in original data, "
                  + "it should not happen",
              removedPort);
          continue;
        }
        // Fetch data of removed port from original data
        @SuppressWarnings("unchecked")
        OvsdbTerminationPointAugmentation removedTPAugmentationData =
            getDataChanges(
                changes.getOriginalData(),
                (InstanceIdentifier<OvsdbTerminationPointAugmentation>) removedPort);

        LOG.trace("processPortDeletion <{}> deletion on Node <{}>", removedPort, tpParentNode);
        ovsdbUpdate(
            tpParentNode,
            removedTPAugmentationData,
            OvsdbInventoryListener.OvsdbType.PORT,
            Action.DELETE);
      }
    }
  }
  private <T extends DataObject> T getDataChanges(
      Map<InstanceIdentifier<?>, DataObject> changes, InstanceIdentifier<T> path) {

    for (Map.Entry<InstanceIdentifier<?>, DataObject> change : changes.entrySet()) {
      if (change.getKey().getTargetType().equals(path.getTargetType())) {
        @SuppressWarnings("unchecked")
        T dataObject = (T) change.getValue();
        return dataObject;
      }
    }
    return null;
  }
  @Override
  public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
    for (InstanceIdentifier<?> key : change.getCreatedConfigurationData().keySet()) {
      if (Meter.class.equals(key.getTargetType())) {
        request();
      }
    }

    final DataModificationTransaction trans = startTransaction();
    for (InstanceIdentifier<?> key : change.getRemovedConfigurationData()) {
      if (Meter.class.equals(key.getTargetType())) {
        @SuppressWarnings("unchecked")
        InstanceIdentifier<Meter> meter = (InstanceIdentifier<Meter>) key;

        InstanceIdentifier<?> nodeMeterStatisticsAugmentation =
            InstanceIdentifier.builder(meter).augmentation(NodeMeterStatistics.class).toInstance();
        trans.removeOperationalData(nodeMeterStatisticsAugmentation);
      }
    }
    trans.commit();
  }