/** Describes an instant messaging address. */
public class Im extends Element {

  /** Im protocol. */
  public static final class Protocol {

    /** AIM. */
    public static final String AIM = Namespaces.gPrefix + "AIM";

    /** Google Talk. */
    public static final String GOOGLE_TALK = Namespaces.gPrefix + "GOOGLE_TALK";

    /** ICQ. */
    public static final String ICQ = Namespaces.gPrefix + "ICQ";

    /** Jabber. */
    public static final String JABBER = Namespaces.gPrefix + "JABBER";

    /** MSN. */
    public static final String MSN = Namespaces.gPrefix + "MSN";

    /** NetMeeting. */
    public static final String NETMEETING = Namespaces.gPrefix + "NETMEETING";

    /** Tencent QQ. */
    public static final String QQ = Namespaces.gPrefix + "QQ";

    /** Skype. */
    public static final String SKYPE = Namespaces.gPrefix + "SKYPE";

    /** Yahoo. */
    public static final String YAHOO = Namespaces.gPrefix + "YAHOO";

    /** Array containing all available values. */
    private static final String[] ALL_VALUES = {
      AIM, GOOGLE_TALK, ICQ, JABBER, MSN, NETMEETING, QQ, SKYPE, YAHOO
    };

    /** Returns an array of all values defined in this class. */
    public static String[] values() {
      return ALL_VALUES;
    }

    private Protocol() {}
  }

  /** Im type. */
  public static final class Rel {

    /** Home instant messaging address. */
    public static final String HOME = Namespaces.gPrefix + "home";

    /** Other instant messaging address. */
    public static final String OTHER = Namespaces.gPrefix + "other";

    /** Work instant messaging address. */
    public static final String WORK = Namespaces.gPrefix + "work";

    /** Array containing all available values. */
    private static final String[] ALL_VALUES = {HOME, OTHER, WORK};

    /** Returns an array of all values defined in this class. */
    public static String[] values() {
      return ALL_VALUES;
    }

    private Rel() {}
  }

  /** The key for this element. */
  public static final ElementKey<Void, Im> KEY =
      ElementKey.of(new QName(Namespaces.gNs, "im"), Void.class, Im.class);

  /** IM address. */
  public static final AttributeKey<String> ADDRESS =
      AttributeKey.of(new QName(null, "address"), String.class);

  /** Label. */
  public static final AttributeKey<String> LABEL =
      AttributeKey.of(new QName(null, "label"), String.class);

  /** Whether this is the primary instant messaging address. */
  public static final AttributeKey<Boolean> PRIMARY =
      AttributeKey.of(new QName(null, "primary"), Boolean.class);

  /** Im protocol. */
  public static final AttributeKey<String> PROTOCOL =
      AttributeKey.of(new QName(null, "protocol"), String.class);

  /** Im type. */
  public static final AttributeKey<String> REL =
      AttributeKey.of(new QName(null, "rel"), String.class);

  /** Registers the metadata for this element. */
  public static void registerMetadata(MetadataRegistry registry) {
    if (registry.isRegistered(KEY)) {
      return;
    }

    // The builder for this element
    ElementCreator builder = registry.build(KEY);

    // Local properties
    builder.addAttribute(ADDRESS).setRequired(true);
    builder.addAttribute(LABEL);
    builder.addAttribute(PRIMARY);
    builder.addAttribute(PROTOCOL);
    builder.addAttribute(REL);
  }

  /** Constructs an instance using the default key. */
  public Im() {
    super(KEY);
  }

  /** Subclass constructor, allows subclasses to supply their own element key. */
  protected Im(ElementKey<?, ? extends Im> key) {
    super(key);
  }

  /**
   * Constructs a new instance by doing a shallow copy of data from an existing {@link Element}
   * instance. Will use the given {@link ElementKey} as the key for the element. This constructor is
   * used when adapting from one element key to another. You cannot call this constructor directly,
   * instead use {@link Element#createElement(ElementKey, Element)}.
   *
   * @param key The key to use for this element.
   * @param source source element
   */
  protected Im(ElementKey<?, ? extends Im> key, Element source) {
    super(key, source);
  }

  @Override
  public Im lock() {
    return (Im) super.lock();
  }

  /**
   * Returns the IM address.
   *
   * @return IM address
   */
  public String getAddress() {
    return super.getAttributeValue(ADDRESS);
  }

  /**
   * Sets the IM address.
   *
   * @param address IM address or {@code null} to reset
   * @return this to enable chaining setters
   */
  public Im setAddress(String address) {
    super.setAttributeValue(ADDRESS, address);
    return this;
  }

  /**
   * Returns whether it has the IM address.
   *
   * @return whether it has the IM address
   */
  public boolean hasAddress() {
    return super.hasAttribute(ADDRESS);
  }

  /**
   * Returns the label.
   *
   * @return label
   */
  public String getLabel() {
    return super.getAttributeValue(LABEL);
  }

  /**
   * Sets the label.
   *
   * @param label label or {@code null} to reset
   * @return this to enable chaining setters
   */
  public Im setLabel(String label) {
    super.setAttributeValue(LABEL, label);
    return this;
  }

  /**
   * Returns whether it has the label.
   *
   * @return whether it has the label
   */
  public boolean hasLabel() {
    return super.hasAttribute(LABEL);
  }

  /**
   * Returns the whether this is the primary instant messaging address.
   *
   * @return whether this is the primary instant messaging address
   */
  public Boolean getPrimary() {
    return super.getAttributeValue(PRIMARY);
  }

  /**
   * Sets the whether this is the primary instant messaging address.
   *
   * @param primary whether this is the primary instant messaging address or {@code null} to reset
   * @return this to enable chaining setters
   */
  public Im setPrimary(Boolean primary) {
    super.setAttributeValue(PRIMARY, primary);
    return this;
  }

  /**
   * Returns whether it has the whether this is the primary instant messaging address.
   *
   * @return whether it has the whether this is the primary instant messaging address
   */
  public boolean hasPrimary() {
    return super.hasAttribute(PRIMARY);
  }

  /**
   * Returns the im protocol.
   *
   * @return im protocol
   */
  public String getProtocol() {
    return super.getAttributeValue(PROTOCOL);
  }

  /**
   * Sets the im protocol.
   *
   * @param protocol im protocol or {@code null} to reset
   * @return this to enable chaining setters
   */
  public Im setProtocol(String protocol) {
    super.setAttributeValue(PROTOCOL, protocol);
    return this;
  }

  /**
   * Returns whether it has the im protocol.
   *
   * @return whether it has the im protocol
   */
  public boolean hasProtocol() {
    return super.hasAttribute(PROTOCOL);
  }

  /**
   * Returns the im type.
   *
   * @return im type
   */
  public String getRel() {
    return super.getAttributeValue(REL);
  }

  /**
   * Sets the im type.
   *
   * @param rel im type or {@code null} to reset
   * @return this to enable chaining setters
   */
  public Im setRel(String rel) {
    super.setAttributeValue(REL, rel);
    return this;
  }

  /**
   * Returns whether it has the im type.
   *
   * @return whether it has the im type
   */
  public boolean hasRel() {
    return super.hasAttribute(REL);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!sameClassAs(obj)) {
      return false;
    }
    Im other = (Im) obj;
    return eq(getAddress(), other.getAddress())
        && eq(getLabel(), other.getLabel())
        && eq(getPrimary(), other.getPrimary())
        && eq(getProtocol(), other.getProtocol())
        && eq(getRel(), other.getRel());
  }

  @Override
  public int hashCode() {
    int result = getClass().hashCode();
    if (getAddress() != null) {
      result = 37 * result + getAddress().hashCode();
    }
    if (getLabel() != null) {
      result = 37 * result + getLabel().hashCode();
    }
    if (getPrimary() != null) {
      result = 37 * result + getPrimary().hashCode();
    }
    if (getProtocol() != null) {
      result = 37 * result + getProtocol().hashCode();
    }
    if (getRel() != null) {
      result = 37 * result + getRel().hashCode();
    }
    return result;
  }
}
/** Person's family name. */
public class FamilyName extends Element {

  /** The key for this element. */
  public static final ElementKey<String, FamilyName> KEY =
      ElementKey.of(new QName(Namespaces.gNs, "familyName"), String.class, FamilyName.class);

  /** Pronunciation help. */
  public static final AttributeKey<String> YOMI =
      AttributeKey.of(new QName(null, "yomi"), String.class);

  /** Registers the metadata for this element. */
  public static void registerMetadata(MetadataRegistry registry) {
    if (registry.isRegistered(KEY)) {
      return;
    }

    // The builder for this element
    ElementCreator builder = registry.build(KEY);

    // Local properties
    builder.addAttribute(YOMI);
  }

  /** Constructs an instance using the default key. */
  public FamilyName() {
    super(KEY);
  }

  /** Subclass constructor, allows subclasses to supply their own element key. */
  protected FamilyName(ElementKey<String, ? extends FamilyName> key) {
    super(key);
  }

  /**
   * Constructs a new instance by doing a shallow copy of data from an existing {@link Element}
   * instance. Will use the given {@link ElementKey} as the key for the element. This constructor is
   * used when adapting from one element key to another. You cannot call this constructor directly,
   * instead use {@link Element#createElement(ElementKey, Element)}.
   *
   * @param key The key to use for this element.
   * @param source source element
   */
  protected FamilyName(ElementKey<String, ? extends FamilyName> key, Element source) {
    super(key, source);
  }

  /**
   * Constructs a new instance with the given value.
   *
   * @param value value.
   */
  public FamilyName(String value) {
    this();
    setValue(value);
  }

  @Override
  public FamilyName lock() {
    return (FamilyName) super.lock();
  }

  /**
   * Returns the value.
   *
   * @return value
   */
  public String getValue() {
    return super.getTextValue(KEY);
  }

  /**
   * Sets the value.
   *
   * @param value value or {@code null} to reset
   * @return this to enable chaining setters
   */
  public FamilyName setValue(String value) {
    super.setTextValue(value);
    return this;
  }

  /**
   * Returns whether it has the value.
   *
   * @return whether it has the value
   */
  public boolean hasValue() {
    return super.hasTextValue();
  }

  /**
   * Returns the pronunciation help.
   *
   * @return pronunciation help
   */
  public String getYomi() {
    return super.getAttributeValue(YOMI);
  }

  /**
   * Sets the pronunciation help.
   *
   * @param yomi pronunciation help or {@code null} to reset
   * @return this to enable chaining setters
   */
  public FamilyName setYomi(String yomi) {
    super.setAttributeValue(YOMI, yomi);
    return this;
  }

  /**
   * Returns whether it has the pronunciation help.
   *
   * @return whether it has the pronunciation help
   */
  public boolean hasYomi() {
    return super.hasAttribute(YOMI);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!sameClassAs(obj)) {
      return false;
    }
    FamilyName other = (FamilyName) obj;
    return eq(getValue(), other.getValue()) && eq(getYomi(), other.getYomi());
  }

  @Override
  public int hashCode() {
    int result = getClass().hashCode();
    if (getValue() != null) {
      result = 37 * result + getValue().hashCode();
    }
    if (getYomi() != null) {
      result = 37 * result + getYomi().hashCode();
    }
    return result;
  }
}
/** Signals that feed processing was interrupted. */
public class BatchInterrupted extends Element implements IBatchInterrupted {

  /** The key for this element. */
  public static final ElementKey<String, BatchInterrupted> KEY =
      ElementKey.of(
          new QName(Namespaces.batchNs, "interrupted"), String.class, BatchInterrupted.class);

  /** The MIME type of the content of this element. */
  public static final AttributeKey<ContentType> CONTENT_TYPE =
      AttributeKey.of(new QName("content-type"), ContentType.class);

  /** The number of entries for which processing failed. */
  public static final AttributeKey<Integer> ERROR_COUNT =
      AttributeKey.of(new QName("error"), Integer.class);

  /** The reason. */
  public static final AttributeKey<String> REASON = AttributeKey.of(new QName("reason"));

  /** The number of entries parsed but not processed. */
  public static final AttributeKey<Integer> SKIPPED_COUNT =
      AttributeKey.of(new QName("unprocessed"), Integer.class);

  /** The number of entries processed successfully. */
  public static final AttributeKey<Integer> SUCCESS_COUNT =
      AttributeKey.of(new QName("success"), Integer.class);

  /** The number of entries that were parsed. */
  public static final AttributeKey<Integer> TOTAL_COUNT =
      AttributeKey.of(new QName("parsed"), Integer.class);

  /** Registers the metadata for this element. */
  public static void registerMetadata(MetadataRegistry registry) {
    if (registry.isRegistered(KEY)) {
      return;
    }

    ElementCreator builder = registry.build(KEY).setContentRequired(false);
    builder.addAttribute(CONTENT_TYPE);
    builder.addAttribute(ERROR_COUNT).setRequired(true);
    builder.addAttribute(TOTAL_COUNT).setRequired(true);
    builder.addAttribute(REASON);
    builder.addAttribute(SUCCESS_COUNT).setRequired(true);
    builder.addAttribute(SKIPPED_COUNT).setRequired(true);
  }

  /** Default mutable constructor. */
  public BatchInterrupted() {
    super(KEY);
  }

  /**
   * Creates and initializes a BatchInterrupted object.
   *
   * @param reason exception that caused batch processing to stop
   * @param totalCount number of entries parsed so far, note that it is to be expected that {@code
   *     totalCount >= successCount + errorCount}
   * @param successCount number of entries processed successfully so far
   * @param errorCount number of entries rejected so far
   * @throws IllegalArgumentException if the total count is less than successCount - errorCount
   */
  public BatchInterrupted(String reason, int totalCount, int successCount, int errorCount) {
    this();
    if (totalCount < (successCount - errorCount)) {
      throw new IllegalArgumentException(
          "total < success + error. total = "
              + totalCount
              + " success="
              + successCount
              + " error="
              + errorCount);
    }
    setReason(reason);
    setTotalCount(totalCount);
    setSuccessCount(successCount);
    setErrorCount(errorCount);
    setSkippedCount(totalCount - (successCount + errorCount));
  }

  /**
   * Creates and initializes a BatchInterrupted object.
   *
   * @param cause exception that caused batch processing to stop
   * @param totalCount number of entries parsed so far, note that it is to be expected that {@code
   *     totalCount >= successCount + errorCount}
   * @param successCount number of entries processed successfully so far
   * @param errorCount number of entries rejected so far
   */
  public BatchInterrupted(Throwable cause, int totalCount, int successCount, int errorCount) {
    this(getReasonFromException(cause), totalCount, successCount, errorCount);
    if (cause instanceof ServiceException) {
      ServiceException se = (ServiceException) cause;
      setContent(se.getResponseBody());
      setContentType(se.getResponseContentType());
    }
  }

  /**
   * Returns the error message explaining what went wrong while processing the request.
   *
   * @return error message explaining what went wrong while processing the request
   */
  public String getContent() {
    return getTextValue(KEY);
  }

  /**
   * Sets the error message explaining what went wrong while processing the request.
   *
   * @param content error message explaining what went wrong while processing the request or <code>
   *     null</code> to reset
   */
  public BatchInterrupted setContent(String content) {
    setTextValue(content);
    return this;
  }

  /**
   * Returns whether it has the error message explaining what went wrong while processing the
   * request.
   *
   * @return whether it has the error message explaining what went wrong while processing the
   *     request
   */
  public boolean hasContent() {
    return hasTextValue();
  }

  /**
   * Returns the MIME type of the content of this element.
   *
   * @return MIME type of the content of this element
   */
  public ContentType getContentType() {
    return getAttributeValue(CONTENT_TYPE);
  }

  /**
   * Sets the MIME type of the content of this element.
   *
   * @param contentType MIME type of the content of this element or <code>null</code> to reset
   */
  public BatchInterrupted setContentType(ContentType contentType) {
    setAttributeValue(
        CONTENT_TYPE, (contentType == null) ? null : new ContentType(contentType.getMediaType()));
    return this;
  }

  /**
   * Returns whether it has the MIME type of the content of this element.
   *
   * @return whether it has the MIME type of the content of this element
   */
  public boolean hasContentType() {
    return getContentType() != null;
  }

  /**
   * Returns the number of entries for which processing failed.
   *
   * @return number of entries for which processing failed
   */
  public int getErrorCount() {
    Integer count = getAttributeValue(ERROR_COUNT);
    return count == null ? 0 : count.intValue();
  }

  /**
   * Sets the number of entries for which processing failed.
   *
   * @param errorCount number of entries for which processing failed or <code>null</code> to reset
   */
  public BatchInterrupted setErrorCount(Integer errorCount) {
    setAttributeValue(ERROR_COUNT, errorCount);
    return this;
  }

  /** Returns true if the error count exists. */
  public boolean hasErrorCount() {
    return getErrorCount() != 0;
  }

  /**
   * Returns the reason.
   *
   * @return reason
   */
  public String getReason() {
    return getAttributeValue(REASON);
  }

  /**
   * Sets the reason.
   *
   * @param reason reason or <code>null</code> to reset
   */
  public BatchInterrupted setReason(String reason) {
    setAttributeValue(REASON, reason);
    return this;
  }

  /**
   * Returns whether it has the reason.
   *
   * @return whether it has the reason
   */
  public boolean hasReason() {
    return getReason() != null;
  }

  /**
   * Returns the number of entries parsed but not processed.
   *
   * @return number of entries parsed but not processed
   */
  public int getSkippedCount() {
    Integer count = getAttributeValue(SKIPPED_COUNT);
    return count == null ? 0 : count.intValue();
  }

  /**
   * Sets the number of entries parsed but not processed.
   *
   * @param skippedCount number of entries parsed but not processed or <code>null</code> to reset
   */
  public BatchInterrupted setSkippedCount(Integer skippedCount) {
    setAttributeValue(SKIPPED_COUNT, skippedCount);
    return this;
  }

  /**
   * Returns whether it has the number of entries parsed but not processed.
   *
   * @return whether it has the number of entries parsed but not processed
   */
  public boolean hasSkippedCount() {
    return getSkippedCount() != 0;
  }

  /**
   * Returns the number of entries processed successfully.
   *
   * @return number of entries processed successfully
   */
  public int getSuccessCount() {
    Integer count = getAttributeValue(SUCCESS_COUNT);
    return count == null ? 0 : count.intValue();
  }

  /**
   * Sets the number of entries processed successfully.
   *
   * @param successCount number of entries processed successfully or <code>null</code> to reset
   */
  public BatchInterrupted setSuccessCount(Integer successCount) {
    setAttributeValue(SUCCESS_COUNT, successCount);
    return this;
  }

  /**
   * Returns whether it has the number of entries processed successfully.
   *
   * @return whether it has the number of entries processed successfully
   */
  public boolean hasSuccessCount() {
    return getSuccessCount() != 0;
  }

  /**
   * Returns the number of entries that were parsed.
   *
   * @return number of entries that were parsed
   */
  public int getTotalCount() {
    Integer count = getAttributeValue(TOTAL_COUNT);
    return count == null ? 0 : count.intValue();
  }

  /**
   * Sets the number of entries that were parsed.
   *
   * @param totalCount number of entries that were parsed or <code>null</code> to reset
   */
  public BatchInterrupted setTotalCount(Integer totalCount) {
    setAttributeValue(TOTAL_COUNT, totalCount);
    return this;
  }

  /**
   * Returns whether it has the number of entries that were parsed.
   *
   * @return whether it has the number of entries that were parsed
   */
  public boolean hasTotalCount() {
    return getTotalCount() != 0;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!sameClassAs(obj)) {
      return false;
    }
    BatchInterrupted other = (BatchInterrupted) obj;
    return eq(getContent(), other.getContent())
        && eq(getContentType(), other.getContentType())
        && eq(getErrorCount(), other.getErrorCount())
        && eq(getReason(), other.getReason())
        && eq(getSkippedCount(), other.getSkippedCount())
        && eq(getSuccessCount(), other.getSuccessCount())
        && eq(getTotalCount(), other.getTotalCount());
  }

  @Override
  public int hashCode() {
    int result = getClass().hashCode();
    if (getContent() != null) {
      result = 37 * result + getContent().hashCode();
    }
    if (getContentType() != null) {
      result = 37 * result + getContentType().hashCode();
    }
    result = 37 * result + getErrorCount();
    if (getReason() != null) {
      result = 37 * result + getReason().hashCode();
    }
    result = 37 * result + getSkippedCount();
    result = 37 * result + getSuccessCount();
    result = 37 * result + getTotalCount();
    return result;
  }

  @Override
  public String toString() {
    return "{BatchInterrupted content="
        + getTextValue()
        + " contentType="
        + getAttributeValue(CONTENT_TYPE)
        + " errorCount="
        + getAttributeValue(ERROR_COUNT)
        + " reason="
        + getAttributeValue(REASON)
        + " skippedCount="
        + getAttributeValue(SKIPPED_COUNT)
        + " successCount="
        + getAttributeValue(SUCCESS_COUNT)
        + " totalCount="
        + getAttributeValue(TOTAL_COUNT)
        + "}";
  }

  private static String getReasonFromException(Throwable cause) {
    String message = cause.getMessage();
    if (message == null) {
      return "Unexpected error";
    } else {
      return message;
    }
  }
}
/** Describes a postal address. */
public class PostalAddress extends Element {

  /** Postal address type. */
  public static final class Rel {

    /** Home address. */
    public static final String HOME = Namespaces.gPrefix + "home";

    /** Other address. */
    public static final String OTHER = Namespaces.gPrefix + "other";

    /** Work address. */
    public static final String WORK = Namespaces.gPrefix + "work";

    /** Array containing all available values. */
    private static final String[] ALL_VALUES = {HOME, OTHER, WORK};

    /** Returns an array of all values defined in this class. */
    public static String[] values() {
      return ALL_VALUES;
    }

    private Rel() {}
  }

  /** The key for this element. */
  public static final ElementKey<String, PostalAddress> KEY =
      ElementKey.of(new QName(Namespaces.gNs, "postalAddress"), String.class, PostalAddress.class);

  /** Simple string value used to name this address. */
  public static final AttributeKey<String> LABEL =
      AttributeKey.of(new QName(null, "label"), String.class);

  /** Whether this is the primary postal address. */
  public static final AttributeKey<Boolean> PRIMARY =
      AttributeKey.of(new QName(null, "primary"), Boolean.class);

  /** Postal address type. */
  public static final AttributeKey<String> REL =
      AttributeKey.of(new QName(null, "rel"), String.class);

  /** Registers the metadata for this element. */
  public static void registerMetadata(MetadataRegistry registry) {
    if (registry.isRegistered(KEY)) {
      return;
    }

    // The builder for this element
    ElementCreator builder = registry.build(KEY);

    // Local properties
    builder.addAttribute(LABEL);
    builder.addAttribute(PRIMARY);
    builder.addAttribute(REL);
  }

  /** Constructs an instance using the default key. */
  public PostalAddress() {
    super(KEY);
  }

  /** Subclass constructor, allows subclasses to supply their own element key. */
  protected PostalAddress(ElementKey<String, ? extends PostalAddress> key) {
    super(key);
  }

  /**
   * Constructs a new instance by doing a shallow copy of data from an existing {@link Element}
   * instance. Will use the given {@link ElementKey} as the key for the element. This constructor is
   * used when adapting from one element key to another. You cannot call this constructor directly,
   * instead use {@link Element#createElement(ElementKey, Element)}.
   *
   * @param key The key to use for this element.
   * @param source source element
   */
  protected PostalAddress(ElementKey<String, ? extends PostalAddress> key, Element source) {
    super(key, source);
  }

  /**
   * Constructs a new instance with the given value.
   *
   * @param value address string.
   */
  public PostalAddress(String value) {
    this();
    setValue(value);
  }

  @Override
  public PostalAddress lock() {
    return (PostalAddress) super.lock();
  }

  /**
   * Returns the simple string value used to name this address.
   *
   * @return simple string value used to name this address
   */
  public String getLabel() {
    return super.getAttributeValue(LABEL);
  }

  /**
   * Sets the simple string value used to name this address.
   *
   * @param label simple string value used to name this address or {@code null} to reset
   * @return this to enable chaining setters
   */
  public PostalAddress setLabel(String label) {
    super.setAttributeValue(LABEL, label);
    return this;
  }

  /**
   * Returns whether it has the simple string value used to name this address.
   *
   * @return whether it has the simple string value used to name this address
   */
  public boolean hasLabel() {
    return getLabel() != null;
  }

  /**
   * Returns the whether this is the primary postal address.
   *
   * @return whether this is the primary postal address
   */
  public Boolean getPrimary() {
    return super.getAttributeValue(PRIMARY);
  }

  /**
   * Sets the whether this is the primary postal address.
   *
   * @param primary whether this is the primary postal address or {@code null} to reset
   * @return this to enable chaining setters
   */
  public PostalAddress setPrimary(Boolean primary) {
    super.setAttributeValue(PRIMARY, primary);
    return this;
  }

  /**
   * Returns whether it has the whether this is the primary postal address.
   *
   * @return whether it has the whether this is the primary postal address
   */
  public boolean hasPrimary() {
    return getPrimary() != null;
  }

  /**
   * Returns the postal address type.
   *
   * @return postal address type
   */
  public String getRel() {
    return super.getAttributeValue(REL);
  }

  /**
   * Sets the postal address type.
   *
   * @param rel postal address type or {@code null} to reset
   * @return this to enable chaining setters
   */
  public PostalAddress setRel(String rel) {
    super.setAttributeValue(REL, rel);
    return this;
  }

  /**
   * Returns whether it has the postal address type.
   *
   * @return whether it has the postal address type
   */
  public boolean hasRel() {
    return getRel() != null;
  }

  /**
   * Returns the address string.
   *
   * @return address string
   */
  public String getValue() {
    return super.getTextValue(KEY);
  }

  /**
   * Sets the address string.
   *
   * @param value address string or {@code null} to reset
   * @return this to enable chaining setters
   */
  public PostalAddress setValue(String value) {
    super.setTextValue(value);
    return this;
  }

  /**
   * Returns whether it has the address string.
   *
   * @return whether it has the address string
   */
  public boolean hasValue() {
    return super.hasTextValue();
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!sameClassAs(obj)) {
      return false;
    }
    PostalAddress other = (PostalAddress) obj;
    return eq(getLabel(), other.getLabel())
        && eq(getPrimary(), other.getPrimary())
        && eq(getRel(), other.getRel())
        && eq(getValue(), other.getValue());
  }

  @Override
  public int hashCode() {
    int result = getClass().hashCode();
    if (getLabel() != null) {
      result = 37 * result + getLabel().hashCode();
    }
    if (getPrimary() != null) {
      result = 37 * result + getPrimary().hashCode();
    }
    if (getRel() != null) {
      result = 37 * result + getRel().hashCode();
    }
    if (getValue() != null) {
      result = 37 * result + getValue().hashCode();
    }
    return result;
  }
}