@Override
 public int hashCode() {
   int result = address.hashCode();
   result = 31 * result + type.hashCode();
   result = 31 * result + hosts.hashCode();
   result = 31 * result + passives.hashCode();
   result = 31 * result + arbiters.hashCode();
   result = 31 * result + (primary != null ? primary.hashCode() : 0);
   result = 31 * result + maxDocumentSize;
   result = 31 * result + maxMessageSize;
   result = 31 * result + tags.hashCode();
   result = 31 * result + (setName != null ? setName.hashCode() : 0);
   result = 31 * result + (setVersion != null ? setVersion.hashCode() : 0);
   result = 31 * result + (ok ? 1 : 0);
   result = 31 * result + state.hashCode();
   result = 31 * result + version.hashCode();
   result = 31 * result + minWireVersion;
   result = 31 * result + maxWireVersion;
   return result;
 }
 @Override
 public int hashCode() {
   int result = address.hashCode();
   result = 31 * result + type.hashCode();
   result = 31 * result + (canonicalAddress != null ? canonicalAddress.hashCode() : 0);
   result = 31 * result + hosts.hashCode();
   result = 31 * result + passives.hashCode();
   result = 31 * result + arbiters.hashCode();
   result = 31 * result + (primary != null ? primary.hashCode() : 0);
   result = 31 * result + maxDocumentSize;
   result = 31 * result + tagSet.hashCode();
   result = 31 * result + (setName != null ? setName.hashCode() : 0);
   result = 31 * result + (electionId != null ? electionId.hashCode() : 0);
   result = 31 * result + (setVersion != null ? setVersion.hashCode() : 0);
   result = 31 * result + (ok ? 1 : 0);
   result = 31 * result + state.hashCode();
   result = 31 * result + version.hashCode();
   result = 31 * result + minWireVersion;
   result = 31 * result + maxWireVersion;
   result = 31 * result + (exception == null ? 0 : exception.getClass().hashCode());
   result = 31 * result + (exception == null ? 0 : exception.getMessage().hashCode());
   return result;
 }
  /**
   * Returns true if this instance is equals to @code{o}. Note that equality is defined to NOT
   * include the average ping time.
   *
   * @param o the object to compare to
   * @return true if this instance is equals to @code{o}
   */
  @Override
  public boolean equals(final Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    final ServerDescription that = (ServerDescription) o;

    if (maxDocumentSize != that.maxDocumentSize) {
      return false;
    }
    if (maxMessageSize != that.maxMessageSize) {
      return false;
    }
    if (ok != that.ok) {
      return false;
    }
    if (!address.equals(that.address)) {
      return false;
    }
    if (!arbiters.equals(that.arbiters)) {
      return false;
    }
    if (!hosts.equals(that.hosts)) {
      return false;
    }
    if (!passives.equals(that.passives)) {
      return false;
    }
    if (primary != null ? !primary.equals(that.primary) : that.primary != null) {
      return false;
    }
    if (setName != null ? !setName.equals(that.setName) : that.setName != null) {
      return false;
    }
    if (setVersion != null ? !setVersion.equals(that.setVersion) : that.setVersion != null) {
      return false;
    }
    if (state != that.state) {
      return false;
    }
    if (!tags.equals(that.tags)) {
      return false;
    }
    if (type != that.type) {
      return false;
    }
    if (!version.equals(that.version)) {
      return false;
    }
    if (minWireVersion != that.minWireVersion) {
      return false;
    }
    if (maxWireVersion != that.maxWireVersion) {
      return false;
    }

    return true;
  }
  /**
   * Returns true if this instance is equals to @code{o}. Note that equality is defined to NOT
   * include the round trip time.
   *
   * @param o the object to compare to
   * @return true if this instance is equals to @code{o}
   */
  @Override
  public boolean equals(final Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    ServerDescription that = (ServerDescription) o;

    if (maxDocumentSize != that.maxDocumentSize) {
      return false;
    }
    if (ok != that.ok) {
      return false;
    }
    if (!address.equals(that.address)) {
      return false;
    }
    if (!arbiters.equals(that.arbiters)) {
      return false;
    }
    if (canonicalAddress != null
        ? !canonicalAddress.equals(that.canonicalAddress)
        : that.canonicalAddress != null) {
      return false;
    }
    if (!hosts.equals(that.hosts)) {
      return false;
    }
    if (!passives.equals(that.passives)) {
      return false;
    }
    if (primary != null ? !primary.equals(that.primary) : that.primary != null) {
      return false;
    }
    if (setName != null ? !setName.equals(that.setName) : that.setName != null) {
      return false;
    }
    if (state != that.state) {
      return false;
    }
    if (!tagSet.equals(that.tagSet)) {
      return false;
    }
    if (type != that.type) {
      return false;
    }
    if (!version.equals(that.version)) {
      return false;
    }
    if (minWireVersion != that.minWireVersion) {
      return false;
    }
    if (maxWireVersion != that.maxWireVersion) {
      return false;
    }
    if (electionId != null ? !electionId.equals(that.electionId) : that.electionId != null) {
      return false;
    }
    if (setVersion != null ? !setVersion.equals(that.setVersion) : that.setVersion != null) {
      return false;
    }

    // Compare class equality and message as exceptions rarely override equals
    Class<?> thisExceptionClass = exception != null ? exception.getClass() : null;
    Class<?> thatExceptionClass = that.exception != null ? that.exception.getClass() : null;
    if (thisExceptionClass != null
        ? !thisExceptionClass.equals(thatExceptionClass)
        : thatExceptionClass != null) {
      return false;
    }

    String thisExceptionMessage = exception != null ? exception.getMessage() : null;
    String thatExceptionMessage = that.exception != null ? that.exception.getMessage() : null;
    if (thisExceptionMessage != null
        ? !thisExceptionMessage.equals(thatExceptionMessage)
        : thatExceptionMessage != null) {
      return false;
    }

    return true;
  }