/**
   * Test method for {@link org.opendaylight.unimgr.command.uniAddCommandTest#execute()}.
   *
   * @throws Exception
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  @Test
  public void testExecute() throws Exception {
    final Optional<Node> optionalOvsdbNode = mock(Optional.class);
    final UniAugmentation uniAugmentation = mock(UniAugmentation.class);
    final OvsdbNodeAugmentation ovsdbNodeAugmentation = mock(OvsdbNodeAugmentation.class);
    final ConnectionInfo connectionInfo = mock(ConnectionInfo.class);
    final IpAddress ipAddress = mock(IpAddress.class);
    final Ipv4Address ipv4Address = mock(Ipv4Address.class);
    final OvsdbNodeRef ovsNodedRef = mock(OvsdbNodeRef.class);
    final Node node = mock(Node.class);
    final NodeId nodeId = mock(NodeId.class);
    final List<Node> nodes = new ArrayList<Node>();
    final InstanceIdentifier uniKey =
        InstanceIdentifier.create(NetworkTopology.class)
            .child(Topology.class, new TopologyKey(UnimgrConstants.UNI_TOPOLOGY_ID))
            .child(Node.class, new NodeKey(OVSDB_NODE_ID));
    nodes.add(node);

    // Case UNI1 : uni.getOvsdbNodeRef() != null, !optionalNode.isPresent()
    when(uniNode.getAugmentation(UniAugmentation.class)).thenReturn(uniAugmentation);
    when(optUniNode.isPresent()).thenReturn(false);
    when(MdsalUtils.readNode(
            any(DataBroker.class), any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
        .thenReturn(optUniNode)
        .thenReturn(optionalOvsdbNode);
    when(optionalOvsdbNode.isPresent()).thenReturn(false).thenReturn(true);
    when(optionalOvsdbNode.get()).thenReturn(node);
    when(uniAugmentation.getIpAddress()).thenReturn(ipAddress);
    when(uniAugmentation.getSpeed()).thenReturn(mock(Speed.class));
    when(uniAugmentation.getOvsdbNodeRef()).thenReturn(ovsNodedRef);
    when(ovsdbNodeAugmentation.getConnectionInfo()).thenReturn(connectionInfo);
    when(connectionInfo.getRemoteIp()).thenReturn(ipAddress);
    when(ipAddress.getIpv4Address()).thenReturn(ipv4Address);
    when(ipv4Address.toString()).thenReturn("ipv4Address_test");
    when(ipv4Address.getValue()).thenReturn("ipv4AddressValue_test");
    when(ovsNodedRef.getValue()).thenReturn(uniKey);
    when(node.getAugmentation(any(Class.class))).thenReturn(uniAugmentation);
    when(node.getNodeId()).thenReturn(nodeId);
    when(nodeId.toString()).thenReturn("ovsdbNodeId_test");
    when(OvsdbUtils.findOvsdbNode(any(DataBroker.class), any(UniAugmentation.class)))
        .thenReturn(optionalOvsdbNode);
    when(OvsdbUtils.createQoSForOvsdbNode(any(DataBroker.class), any(UniAugmentation.class)))
        .thenReturn(null);
    when(UniUtils.updateUniNode(
            any(LogicalDatastoreType.class),
            any(InstanceIdentifier.class),
            any(UniAugmentation.class),
            any(Node.class),
            any(DataBroker.class)))
        .thenReturn(true);
    when(UniUtils.updateUniNode(
            any(LogicalDatastoreType.class),
            any(InstanceIdentifier.class),
            any(UniAugmentation.class),
            any(InstanceIdentifier.class),
            any(DataBroker.class)))
        .thenReturn(true);
    when(OvsdbUtils.createOvsdbNode(any(DataBroker.class), any(UniAugmentation.class)))
        .thenReturn(node);
    PowerMockito.doNothing()
        .when(
            OvsdbUtils.class,
            "createBridgeNode",
            dataBroker,
            uniKey,
            uniAugmentation,
            UnimgrConstants.DEFAULT_BRIDGE_NAME);
    when(UniUtils.getUniNodes(any(DataBroker.class))).thenReturn(nodes);
    when(UnimgrMapper.getOvsdbNodeIid(any(NodeId.class))).thenReturn(uniKey);
    when(UnimgrMapper.getUniIid(
            any(DataBroker.class), any(IpAddress.class), any(LogicalDatastoreType.class)))
        .thenReturn(uniKey);
    verifyExecute(1, 0, 1, 0);

    // Case UNI2 : optionalNode.isPresent()
    when(MdsalUtils.readNode(
            any(DataBroker.class), any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
        .thenReturn(optionalOvsdbNode);
    verifyExecute(1, 0, 1, 0);

    // Case UNI3 : uni.getOvsdbNodeRef() == null, optionalNode.isPresent()
    when(uniAugmentation.getOvsdbNodeRef()).thenReturn(null);
    when(optionalOvsdbNode.isPresent()).thenReturn(true);
    when(MdsalUtils.readNode(
            any(DataBroker.class), any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
        .thenReturn(optUniNode)
        .thenReturn(optionalOvsdbNode);
    verifyExecute(2, 1, 3, 0);

    // Case UNI4 : uni.getOvsdbNodeRef() == null, !optionalNode.isPresent()
    when(optionalOvsdbNode.isPresent()).thenReturn(false);
    verifyExecute(2, 1, 4, 0);
  }
  @Override
  public void execute() {
    final Link evcLink = dataObject.getRootNode().getDataAfter();
    final EvcAugmentation evc = evcLink.getAugmentation(EvcAugmentation.class);
    final InstanceIdentifier<Link> evcKey = dataObject.getRootPath().getRootIdentifier();
    if (evc != null) {
      // FIXME: For now, we assume that there is 1 uni per
      // source/destination
      if ((evc.getUniDest() == null) || evc.getUniDest().isEmpty()) {
        LOG.error("Destination UNI cannot be null.");
        return;
      }
      if ((evc.getUniSource() == null) || evc.getUniSource().isEmpty()) {
        LOG.error("Source UNI cannot be null.");
        return;
      }

      final Ipv4Address laterUni1Ip =
          evc.getUniSource().iterator().next().getIpAddress().getIpv4Address();
      final Ipv4Address laterUni2Ip =
          evc.getUniDest().iterator().next().getIpAddress().getIpv4Address();
      LOG.trace("New EVC created, source IP: {} destination IP {}.", laterUni1Ip, laterUni2Ip);

      final ReadTransaction readTransac = dataBroker.newReadOnlyTransaction();
      final CheckedFuture<Optional<Link>, ReadFailedException> retFormerEvc =
          readTransac.read(LogicalDatastoreType.OPERATIONAL, evcKey);
      EvcAugmentation formerEvc;
      try {
        Optional<Link> optLinks = retFormerEvc.get();
        if (optLinks != null && optLinks.isPresent()) {
          formerEvc = optLinks.get().getAugmentation(EvcAugmentation.class);
          final Ipv4Address formerUni1ip =
              formerEvc.getUniSource().iterator().next().getIpAddress().getIpv4Address();
          final Ipv4Address formerUni2ip =
              formerEvc.getUniDest().iterator().next().getIpAddress().getIpv4Address();

          if (formerUni1ip.equals(laterUni1Ip)) {
            // do nothing
          } else if (formerUni1ip.equals(laterUni2Ip)) {
            // do nothing
          } else {
            LOG.info("{} is not part of the EVC, removing configuration", formerUni1ip);
            final InstanceIdentifier<?> formerUniIID =
                UnimgrMapper.getUniIid(
                    dataBroker, new IpAddress(formerUni1ip), LogicalDatastoreType.OPERATIONAL);
            final Optional<Node> formerUni =
                MdsalUtils.readNode(dataBroker, LogicalDatastoreType.OPERATIONAL, formerUniIID);
            EvcUtils.deleteEvcData(dataBroker, formerUni);
          }
          if (formerUni2ip.equals(laterUni1Ip)) {
            // do nothing
          } else if (formerUni2ip.equals(laterUni2Ip)) {
            // do nothing
          } else {
            LOG.info("{} is not part of the EVC, removing configuration", formerUni2ip);
            final InstanceIdentifier<?> formerUniIID =
                UnimgrMapper.getUniIid(
                    dataBroker, new IpAddress(formerUni2ip), LogicalDatastoreType.OPERATIONAL);
            final Optional<Node> formerUni =
                MdsalUtils.readNode(dataBroker, LogicalDatastoreType.OPERATIONAL, formerUniIID);
            EvcUtils.deleteEvcData(dataBroker, formerUni);
          }
        }
      } catch (final InterruptedException | ExecutionException e) {
        LOG.error("Failed to retrieve former EVC {}", evcKey, e);
      }

      InstanceIdentifier<Node> sourceUniIid;
      InstanceIdentifier<Node> destinationUniIid;

      final InstanceIdentifier<?> iidSource = evc.getUniSource().iterator().next().getUni();
      if (iidSource != null) {
        sourceUniIid = iidSource.firstIdentifierOf(Node.class);
      } else {
        sourceUniIid =
            UnimgrMapper.getUniIid(
                dataBroker,
                evc.getUniSource().iterator().next().getIpAddress(),
                LogicalDatastoreType.OPERATIONAL);
      }
      final InstanceIdentifier<?> iidDest = evc.getUniDest().iterator().next().getUni();
      if (iidDest != null) {
        destinationUniIid = iidDest.firstIdentifierOf(Node.class);
      } else {
        destinationUniIid =
            UnimgrMapper.getUniIid(
                dataBroker,
                evc.getUniDest().iterator().next().getIpAddress(),
                LogicalDatastoreType.OPERATIONAL);
      }

      // Retrieve the source and destination UNIs
      final Optional<Node> optionalUniSource =
          MdsalUtils.readNode(dataBroker, LogicalDatastoreType.OPERATIONAL, sourceUniIid);
      final Optional<Node> optionalUniDestination =
          MdsalUtils.readNode(dataBroker, LogicalDatastoreType.OPERATIONAL, destinationUniIid);

      Node uniSource = null;
      Node uniDestination = null;

      if (optionalUniSource.isPresent() && optionalUniDestination.isPresent()) {
        uniSource = optionalUniSource.get();
        uniDestination = optionalUniDestination.get();

        // Retrieve the source and/or destination OVSDB node
        final UniAugmentation sourceUniAugmentation =
            uniSource.getAugmentation(UniAugmentation.class);
        final UniAugmentation destinationUniAugmentation =
            uniDestination.getAugmentation(UniAugmentation.class);
        final Optional<Node> optionalSourceOvsdbNode =
            MdsalUtils.readNode(
                dataBroker,
                LogicalDatastoreType.OPERATIONAL,
                sourceUniAugmentation.getOvsdbNodeRef().getValue());
        final Optional<Node> optionalDestinationOvsdbNode =
            MdsalUtils.readNode(
                dataBroker,
                LogicalDatastoreType.OPERATIONAL,
                destinationUniAugmentation.getOvsdbNodeRef().getValue());
        if (optionalSourceOvsdbNode.isPresent() && optionalDestinationOvsdbNode.isPresent()) {
          // Retrieve the source and/or destination bridge
          final InstanceIdentifier<Node> sourceBridgeIid =
              UnimgrMapper.getOvsdbBridgeNodeIid(optionalSourceOvsdbNode.get());
          final Optional<Node> optionalSourceBr =
              MdsalUtils.readNode(dataBroker, LogicalDatastoreType.OPERATIONAL, sourceBridgeIid);
          final InstanceIdentifier<Node> destinationBridgeIid =
              UnimgrMapper.getOvsdbBridgeNodeIid(optionalDestinationOvsdbNode.get());
          final Optional<Node> optionalDestinationBr =
              MdsalUtils.readNode(
                  dataBroker, LogicalDatastoreType.OPERATIONAL, destinationBridgeIid);
          // update ovsdb qos-entry and queues with max-rate to match evc ingress BW
          OvsdbUtils.updateMaxRate(
              dataBroker, sourceUniAugmentation, destinationUniAugmentation, evc);
          Node sourceBr = null;
          Node destinationBr = null;
          if (optionalSourceBr.isPresent() && optionalDestinationBr.isPresent()) {
            sourceBr = optionalSourceBr.get();
            destinationBr = optionalDestinationBr.get();

            // Creating termination points (OVSDB CONFIG
            // datastore)
            OvsdbUtils.createTerminationPointNode(
                dataBroker,
                uniSource.getAugmentation(UniAugmentation.class),
                sourceBr,
                UnimgrConstants.DEFAULT_BRIDGE_NAME,
                UnimgrConstants.DEFAULT_TUNNEL_IFACE);

            // Create GRE tunnel (OVSDB CONFIG datastore)
            OvsdbUtils.createGreTunnel(
                dataBroker,
                uniSource.getAugmentation(UniAugmentation.class),
                uniDestination.getAugmentation(UniAugmentation.class),
                sourceBr,
                UnimgrConstants.DEFAULT_BRIDGE_NAME,
                UnimgrConstants.DEFAULT_GRE_TUNNEL_NAME);

            // Create termination points (CONFIG datastore)
            OvsdbUtils.createTerminationPointNode(
                dataBroker,
                uniSource.getAugmentation(UniAugmentation.class),
                destinationBr,
                UnimgrConstants.DEFAULT_BRIDGE_NAME,
                UnimgrConstants.DEFAULT_TUNNEL_IFACE);

            // Create GRE tunnel (OVSDB CONFIG datastore)
            OvsdbUtils.createGreTunnel(
                dataBroker,
                uniDestination.getAugmentation(UniAugmentation.class),
                uniSource.getAugmentation(UniAugmentation.class),
                destinationBr,
                UnimgrConstants.DEFAULT_BRIDGE_NAME,
                UnimgrConstants.DEFAULT_GRE_TUNNEL_NAME);

            // Update EVC
            EvcUtils.updateEvcNode(
                LogicalDatastoreType.CONFIGURATION,
                evcKey,
                evc,
                sourceUniIid,
                destinationUniIid,
                dataBroker);
            EvcUtils.updateEvcNode(
                LogicalDatastoreType.OPERATIONAL,
                evcKey,
                evc,
                sourceUniIid,
                destinationUniIid,
                dataBroker);
          } else {
            LOG.info("Unable to retrieve the source and/or destination bridge.");
          }
        } else {
          LOG.info("Unable to retrieve the source and/or destination ovsdbNode.");
        }
      } else {
        LOG.info("Unable to retrieve the source and/or destination Uni.");
      }
    }
  }