gt:             if (ofent.getCookie().longValue() == MISS_COOKIE) {
context: /*
   * Copyright (c) 2016 NEC Corporation. All rights reserved.
   *
   * This program and the accompanying materials are made available under the
   * terms of the Eclipse Public License v1.0 which accompanies this distribution,
   * and is available at http://www.eclipse.org/legal/epl-v10.html
   */
  
  package org.opendaylight.vtn.manager.it.ofmock.impl;
  
  import static org.opendaylight.vtn.manager.it.ofmock.OfMockUtils.isOpenflow13;
  import static org.opendaylight.vtn.manager.it.ofmock.OfMockUtils.isOutput;
  import static org.opendaylight.vtn.manager.it.ofmock.OfMockUtils.verify;
  import static org.opendaylight.vtn.manager.it.ofmock.impl.FlowMatcher.EMPTY_MATCH;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.concurrent.TimeoutException;
  
  import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  
  import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.VtnOpenflowVersion;
  
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
  import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
  
  /**
   * {@code FlowTable} describes the flow table in a OpenFlow switch.
   */
  public final class FlowTable {
      /**
       * The prefix of the MD-SAL flow ID.
       */
      private static final String  FLOW_ID_PREFIX = "#OFMOCK*TABLE*";
  
      /**
       * A fixed cookie value for a table miss flow entry.
       */
      private static final long  MISS_COOKIE = 0x7f57ffffffffffffL;
  
      /**
       * A flow timeout to be configured in a table miss flow entry.
       */
      private static final Integer  MISS_TIMEOUT = 0;
  
      /**
       * A flow priority to be configured in a table miss flow entry.
       */
      private static final Integer  MISS_PRIORITY = 0;
  
      /**
       * The ofmock provider service.
       */
      private final OfMockProvider  ofMockProvider;
  
      /**
       * OpenFlow protocol version.
       */
      private final VtnOpenflowVersion  ofVersion;
  
      /**
       * The table ID.
       */
      private final Short  tableId;
  
      /**
       * The path to this flow table.
       */
      private final InstanceIdentifier<Table>  tablePath;
  
      /**
       * The MD-SAL flow ID to be associated with a table miss flow entry.
       */
      private final String  missFlowId;
  
      /**
       * A map that associates flow entries with flow IDs.
       */
      private final Map<OfMockFlowEntry, String>  flowMap = new HashMap<>();
  
      /**
       * A map that keeps flow entries installed into the MD-SAL datastore.
       */
      private final Map<String, OfMockFlowEntry>  idMap = new HashMap<>();
  
      /**
       * The identifier for the next flow entry.
       */
      private int  nextFlowId;
  
      /**
       * {@code TableCond} describes the condition to be satisfied.
       */
      private interface TableCond {
          /**
           * Determine whether the specified condition is satisfied or not.
           *
           * @return  {@code true} if the specified condition is satisfied.
           *          {@code false} otherwise.
           */
          boolean check();
  
          /**
           * Return an error message that indicates timeout.
           *
           * @return  An error message.
           */
          String getTimeoutError();
      }
  
      /**
       * {@code FlowAdded} describes the table condition used to check whether
       * the specified flow entry is added to the flow table.
       */
      private final class FlowAdded implements TableCond {
          /**
           * The target flow entry.
           */
          private final OfMockFlowEntry  targetFlow;
  
          /**
           * The flow entry found in the flow table.
           */
          private OfMockFlowEntry  result;
  
          /**
           * Construct a new instance.
           *
           * @param ofent  The target flow entry.
           */
          private FlowAdded(OfMockFlowEntry ofent) {
              targetFlow = ofent;
          }
  
          /**
           * Return the flow entry found in the flow table.
           *
           * @return  A {@link OfMockFlowEntry} instance if found.
           *          {@code null} if not found.
           */
          private OfMockFlowEntry getResult() {
              return result;
          }
  
          // TableCond
  
          /**
           * Determine whether the specified flow entry is present in the
           * flow table or not.
           *
           * @return  {@code true} if the specified flow entry is present in the
           *          flow table. {@code false} otherwise.
           */
          @Override
          public boolean check() {
              OfMockFlowEntry ofent = getFlow(targetFlow);
              boolean found = (ofent != null);
              if (found) {
                  result = ofent;
              }
  
              return found;
          }
  
          /**
           * {@inheritDoc}
           */
          @Override
          public String getTimeoutError() {
              return "Flow entry did not added: " + targetFlow;
          }
      }
  
      /**
       * {@code FlowRemoved} describes the table condition used to check whether
       * the specified flow entry is removed from the flow table.
       */
      private final class FlowRemoved implements TableCond {
          /**
           * The ID for the target flow entry.
           */
          private final String  flowId;
  
          /**
           * Construct a new instance.
           *
           * @param id  The ID for the target flow entry.
           */
          private FlowRemoved(String id) {
              flowId = id;
          }
  
          // TableCond
  
          /**
           * Determine whether the specified flow entry is not present in the
           * flow table or not.
           *
           * @return  {@code true} if the specified flow entry is not present in
           *          the flow table. {@code false} otherwise.
           */
          @Override
          public boolean check() {
              return (getFlow(flowId) == null);
          }
  
          /**
           * {@inheritDoc}
           */
          @Override
          public String getTimeoutError() {
              return "Flow entry did not removed: " + flowId;
          }
      }
  
      /**
       * {@code TableCleared} describes the table condition used to check whether
       * the flow table is empty or not.
       */
      private final class TableCleared implements TableCond {
          /**
           * Construct a new instance.
           */
          private TableCleared() {
          }
  
          // TableCond
  
          /**
           * Determine whether the flow table is empty or not.
           *
           * @return  {@code true} if the flow table is empty.
           *          {@code false} otherwise.
           */
          @Override
          public boolean check() {
              return isEmpty();
          }
  
          /**
           * {@inheritDoc}
           */
          @Override
          public String getTimeoutError() {
              String nodeId = getTablePath().firstKeyOf(Node.class).
                  getId().getValue();
              return "Flow entry was not cleared: " + nodeId;
          }
      }
  
      /**
       * Construct a new instance.
       *
       * @param node  The node that owns this flow table.
       * @param id    The flow table ID.
       */
      public FlowTable(OfNode node, Short id) {
          ofMockProvider = node.getOfMockProvider();
          ofVersion = node.getOfVersion();
          tableId = id;
          tablePath = node.getNodePath().builder().
              augmentation(FlowCapableNode.class).
              child(Table.class, new TableKey(id)).
              build();
          missFlowId = "vtn:table-miss:" + node.getNodeIdentifier();
      }
  
      /**
       * Return the flow table ID.
       *
       * @return  The flow table ID.
       */
      public Short getTableId() {
          return tableId;
      }
  
      /**
       * Return the path to the flow table.
       *
       * @return  The path to the flow table.
       */
      public InstanceIdentifier<Table> getTablePath() {
          return tablePath;
      }
  
      /**
       * Associate a new flow ID with the specified flow entry.
       *
       * @param nid    The MD-SAL node ID that specifies the target switch.
       * @param input  An add-flow input.
       * @return  An {@link OfMockFlowEntry} instance.
       * @throws IllegalArgumentException
       *    The specified flow entry is invalid.
       */
      public OfMockFlowEntry newFlowId(String nid, AddFlowInput input) {
          OfMockFlowEntry ofent = new OfMockFlowEntry(nid, input);
  
          // Verify the flow table ID.
          int tid = ofent.getTableId();
          if (tid != tableId) {
              throw new IllegalArgumentException("Unsupported table-id: " + tid);
          }
  
          FlowRef fref = input.getFlowRef();
          String id;
          if (fref != null) {
              // Use MD-SAL flow ID specified by flow-ref.
              id = getFlowId(fref);
  