public boolean equals(Object o) {
    if (o == this) {
      return true;
    }

    if (!(o instanceof X509AttributeCertificate)) {
      return false;
    }

    X509AttributeCertificate other = (X509AttributeCertificate) o;

    try {
      byte[] b1 = this.getEncoded();
      byte[] b2 = other.getEncoded();

      return Arrays.areEqual(b1, b2);
    } catch (IOException e) {
      return false;
    }
  }
  /**
   * Decides if the given attribute certificate should be selected.
   *
   * @param obj The attribute certificate which should be checked.
   * @return <code>true</code> if the attribute certificate can be selected, <code>false</code>
   *     otherwise.
   */
  public boolean match(Object obj) {
    if (!(obj instanceof X509AttributeCertificate)) {
      return false;
    }

    X509AttributeCertificate attrCert = (X509AttributeCertificate) obj;

    if (this.attributeCert != null) {
      if (!this.attributeCert.equals(attrCert)) {
        return false;
      }
    }
    if (serialNumber != null) {
      if (!attrCert.getSerialNumber().equals(serialNumber)) {
        return false;
      }
    }
    if (holder != null) {
      if (!attrCert.getHolder().equals(holder)) {
        return false;
      }
    }
    if (issuer != null) {
      if (!attrCert.getIssuer().equals(issuer)) {
        return false;
      }
    }

    if (attributeCertificateValid != null) {
      try {
        attrCert.checkValidity(attributeCertificateValid);
      } catch (CertificateExpiredException e) {
        return false;
      } catch (CertificateNotYetValidException e) {
        return false;
      }
    }
    if (!targetNames.isEmpty() || !targetGroups.isEmpty()) {

      byte[] targetInfoExt = attrCert.getExtensionValue(X509Extensions.TargetInformation.getId());
      if (targetInfoExt != null) {
        TargetInformation targetinfo;
        try {
          targetinfo =
              TargetInformation.getInstance(
                  new ASN1InputStream(
                          ((DEROctetString) DEROctetString.fromByteArray(targetInfoExt))
                              .getOctets())
                      .readObject());
        } catch (IOException e) {
          return false;
        } catch (IllegalArgumentException e) {
          return false;
        }
        Targets[] targetss = targetinfo.getTargetsObjects();
        if (!targetNames.isEmpty()) {
          boolean found = false;

          for (int i = 0; i < targetss.length; i++) {
            Targets t = targetss[i];
            Target[] targets = t.getTargets();
            for (int j = 0; j < targets.length; j++) {
              if (targetNames.contains(GeneralName.getInstance(targets[j].getTargetName()))) {
                found = true;
                break;
              }
            }
          }
          if (!found) {
            return false;
          }
        }
        if (!targetGroups.isEmpty()) {
          boolean found = false;

          for (int i = 0; i < targetss.length; i++) {
            Targets t = targetss[i];
            Target[] targets = t.getTargets();
            for (int j = 0; j < targets.length; j++) {
              if (targetGroups.contains(GeneralName.getInstance(targets[j].getTargetGroup()))) {
                found = true;
                break;
              }
            }
          }
          if (!found) {
            return false;
          }
        }
      }
    }
    return true;
  }