@Override
 public <F extends OFValueType<F>> F get(MatchField<F> field)
     throws UnsupportedOperationException {
   OFOxm<F> value = getOxm(field);
   if (value == null) return null;
   return value.getValue();
 }
  @Override
  public ExtensionSelector mapOxm(OFOxm<?> oxm) {
    VlanId vlanId;

    if (oxm.getMatchField().equals(MatchField.VLAN_VID)) {
      if (oxm.isMasked()) {
        OFVlanVidMatch vid = ((OFOxmVlanVidMasked) oxm).getValue();
        OFVlanVidMatch mask = ((OFOxmVlanVidMasked) oxm).getMask();

        if (vid.equals(OFVlanVidMatch.ofRawVid((short) 0))) {
          vlanId = VlanId.NONE;
        } else if (vid.equals(OFVlanVidMatch.PRESENT) && mask.equals(OFVlanVidMatch.PRESENT)) {
          vlanId = VlanId.ANY;
        } else {
          vlanId = VlanId.vlanId(vid.getVlan());
        }
      } else {
        OFVlanVidMatch vid = ((OFOxmVlanVid) oxm).getValue();

        if (!vid.isPresentBitSet()) {
          vlanId = VlanId.NONE;
        } else {
          vlanId = VlanId.vlanId(vid.getVlan());
        }
      }
      return new OfdpaMatchVlanVid(vlanId);
    }
    throw new UnsupportedOperationException("Unexpected OXM: " + oxm.toString());
  }
 @Override
 public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
     throws UnsupportedOperationException {
   OFOxm<F> value = getOxm(field);
   if (value == null || !value.isMasked()) return null;
   // TODO: If changing OXMs to extend Masked, then use it here
   return Masked.of(value.getValue(), value.getMask());
 }
 @Override
 protected MatchField<?> computeNext() {
   while (oxmIterator.hasNext()) {
     OFOxm<?> oxm = oxmIterator.next();
     if (oxm.getMatchField().arePrerequisitesOK(OFMatchV3Ver14.this)) return oxm.getMatchField();
   }
   endOfData();
   return null;
 }
  @Override
  public boolean isPartiallyMasked(MatchField<?> field) {
    if (!supports(field))
      throw new UnsupportedOperationException(
          "OFMatchV3Ver14 does not support matching on field " + field.getName());

    OFOxm<?> oxm = this.oxmList.get(field);

    return oxm != null && oxm.isMasked();
  }
  @Override
  public <F extends OFValueType<F>> F get(MatchField<F> field)
      throws UnsupportedOperationException {
    if (!supports(field))
      throw new UnsupportedOperationException(
          "OFMatchV3Ver14 does not support matching on field " + field.getName());

    OFOxm<F> oxm = this.oxmList.get(field);

    if (oxm == null || !field.arePrerequisitesOK(this)) return null;

    return oxm.getValue();
  }
  @Override
  public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
      throws UnsupportedOperationException {
    if (!supportsMasked(field))
      throw new UnsupportedOperationException(
          "OFMatchV3Ver14 does not support masked matching on field " + field.getName());

    OFOxm<F> oxm = this.oxmList.get(field);

    if (oxm == null || !field.arePrerequisitesOK(this)) return null;

    if (oxm.getMask() == null) return null;

    // TODO: Make OfOxm extend Masked and just return the OXM?
    return Masked.of(oxm.getValue(), oxm.getMask());
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;

    result = prime * result + ((field == null) ? 0 : field.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    OFActionSetFieldVer12 other = (OFActionSetFieldVer12) obj;

    if (field == null) {
      if (other.field != null) return false;
    } else if (!field.equals(other.field)) return false;
    return true;
  }
 @Override
 public boolean isPartiallyMasked(MatchField<?> field) {
   OFOxm<?> value = getOxm(field);
   return (value != null && value.isMasked());
 }
 @Override
 public boolean isExact(MatchField<?> field) {
   OFOxm<?> value = getOxm(field);
   return (value != null && !value.isMasked());
 }