/*
 * Copyright (C) 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Definition of the class representing metadata for international telephone numbers. This class is
 * hand created based on the class file compiled from phonemetadata.proto. Please refer to that file
 * for detailed descriptions of the meaning of each field.
 */

package com.google.i18n.phonenumbers;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public final class Phonemetadata {
  private Phonemetadata() {}
  public static class NumberFormat implements Externalizable {
    private static final long serialVersionUID = 1;
    public NumberFormat() {}

    /**
     * Provides a dummy builder to 'emulate' the API of the code generated by the latest version of
     * Protocol Buffers. This lets BuildMetadataFromXml class to build with both this hand created
     * class and the one generated by the latest version of Protocol Buffers.
     */
    public static final class Builder extends NumberFormat {
      public NumberFormat build() {
        return this;
      }
    }
    public static Builder newBuilder() {
      return new Builder();
    }

    // required string pattern = 1;
    private boolean hasPattern;
    private String pattern_ = "";
    public boolean hasPattern() { return hasPattern; }
    public String getPattern() { return pattern_; }
    public NumberFormat setPattern(String value) {
      hasPattern = true;
      pattern_ = value;
      return this;
    }

    // required string format = 2;
    private boolean hasFormat;
    private String format_ = "";
    public boolean hasFormat() { return hasFormat; }
    public String getFormat() { return format_; }
    public NumberFormat setFormat(String value) {
      hasFormat = true;
      format_ = value;
      return this;
    }

    // repeated string leading_digits_pattern = 3;
    private java.util.List<String> leadingDigitsPattern_ = new java.util.ArrayList<String>();
    public java.util.List<String> leadingDigitPatterns() {
      return leadingDigitsPattern_;
    }
    public int leadingDigitsPatternSize() { return leadingDigitsPattern_.size(); }
    public String getLeadingDigitsPattern(int index) {
      return leadingDigitsPattern_.get(index);
    }
    public NumberFormat addLeadingDigitsPattern(String value) {
      if (value == null) {
        throw new NullPointerException();
      }
      leadingDigitsPattern_.add(value);
      return this;
    }

    // optional string national_prefix_formatting_rule = 4;
    private boolean hasNationalPrefixFormattingRule;
    private String nationalPrefixFormattingRule_ = "";
    public boolean hasNationalPrefixFormattingRule() { return hasNationalPrefixFormattingRule; }
    public String getNationalPrefixFormattingRule() { return nationalPrefixFormattingRule_; }
    public NumberFormat setNationalPrefixFormattingRule(String value) {
      hasNationalPrefixFormattingRule = true;
      nationalPrefixFormattingRule_ = value;
      return this;
    }
    public NumberFormat clearNationalPrefixFormattingRule() {
      hasNationalPrefixFormattingRule = false;
      nationalPrefixFormattingRule_ = "";
      return this;
    }

    // optional string domestic_carrier_code_formatting_rule = 5;
    private boolean hasDomesticCarrierCodeFormattingRule;
    private String domesticCarrierCodeFormattingRule_ = "";
    public boolean hasDomesticCarrierCodeFormattingRule() {
      return hasDomesticCarrierCodeFormattingRule; }
    public String getDomesticCarrierCodeFormattingRule() {
      return domesticCarrierCodeFormattingRule_; }
    public NumberFormat setDomesticCarrierCodeFormattingRule(String value) {
      hasDomesticCarrierCodeFormattingRule = true;
      domesticCarrierCodeFormattingRule_ = value;
      return this;
    }

    public NumberFormat mergeFrom(NumberFormat other) {
      if (other.hasPattern()) {
        setPattern(other.getPattern());
      }
      if (other.hasFormat()) {
        setFormat(other.getFormat());
      }
      int leadingDigitsPatternSize = other.leadingDigitsPatternSize();
      for (int i = 0; i < leadingDigitsPatternSize; i++) {
        addLeadingDigitsPattern(other.getLeadingDigitsPattern(i));
      }
      if (other.hasNationalPrefixFormattingRule()) {
        setNationalPrefixFormattingRule(other.getNationalPrefixFormattingRule());
      }
      if (other.hasDomesticCarrierCodeFormattingRule()) {
        setDomesticCarrierCodeFormattingRule(other.getDomesticCarrierCodeFormattingRule());
      }
      return this;
    }

    public void writeExternal(ObjectOutput objectOutput) throws IOException {
      objectOutput.writeUTF(pattern_);
      objectOutput.writeUTF(format_);
      int leadingDigitsPatternSize = leadingDigitsPatternSize();
      objectOutput.writeInt(leadingDigitsPatternSize);
      for (int i = 0; i < leadingDigitsPatternSize; i++) {
        objectOutput.writeUTF(leadingDigitsPattern_.get(i));
      }

      objectOutput.writeBoolean(hasNationalPrefixFormattingRule);
      if (hasNationalPrefixFormattingRule) {
        objectOutput.writeUTF(nationalPrefixFormattingRule_);
      }
      objectOutput.writeBoolean(hasDomesticCarrierCodeFormattingRule);
      if (hasDomesticCarrierCodeFormattingRule) {
        objectOutput.writeUTF(domesticCarrierCodeFormattingRule_);
      }
    }

    public void readExternal(ObjectInput objectInput) throws IOException {
      setPattern(objectInput.readUTF());
      setFormat(objectInput.readUTF());
      int leadingDigitsPatternSize = objectInput.readInt();
      for (int i = 0; i < leadingDigitsPatternSize; i++) {
        leadingDigitsPattern_.add(objectInput.readUTF());
      }
      if (objectInput.readBoolean()) {
        setNationalPrefixFormattingRule(objectInput.readUTF());
      }
      if (objectInput.readBoolean()) {
        setDomesticCarrierCodeFormattingRule(objectInput.readUTF());
      }
    }
  }

  public static class PhoneNumberDesc implements Externalizable {
    private static final long serialVersionUID = 1;
    public PhoneNumberDesc() {}

    /**
     * Provides a dummy builder.
     *
     * @see NumberFormat.Builder
     */
    public static final class Builder extends PhoneNumberDesc {
      public PhoneNumberDesc build() {
        return this;
      }
    }
    public static Builder newBuilder() {
      return new Builder();
    }

    // optional string national_number_pattern = 2;
    private boolean hasNationalNumberPattern;
    private String nationalNumberPattern_ = "";
    public boolean hasNationalNumberPattern() { return hasNationalNumberPattern; }
    public String getNationalNumberPattern() { return nationalNumberPattern_; }
    public PhoneNumberDesc setNationalNumberPattern(String value) {
      hasNationalNumberPattern = true;
      nationalNumberPattern_ = value;
      return this;
    }

    // optional string possible_number_pattern = 3;
    private boolean hasPossibleNumberPattern;
    private String possibleNumberPattern_ = "";
    public boolean hasPossibleNumberPattern() { return hasPossibleNumberPattern; }
    public String getPossibleNumberPattern() { return possibleNumberPattern_; }
    public PhoneNumberDesc setPossibleNumberPattern(String value) {
      hasPossibleNumberPattern = true;
      possibleNumberPattern_ = value;
      return this;
    }

    // optional string example_number = 6;
    private boolean hasExampleNumber;
    private String exampleNumber_ = "";
    public boolean hasExampleNumber() { return hasExampleNumber; }
    public String getExampleNumber() { return exampleNumber_; }
    public PhoneNumberDesc setExampleNumber(String value) {
      hasExampleNumber = true;
      exampleNumber_ = value;
      return this;
    }

    public PhoneNumberDesc mergeFrom(PhoneNumberDesc other) {
      if (other.hasNationalNumberPattern()) {
        setNationalNumberPattern(other.getNationalNumberPattern());
      }
      if (other.hasPossibleNumberPattern()) {
        setPossibleNumberPattern(other.getPossibleNumberPattern());
      }
      if (other.hasExampleNumber()) {
        setExampleNumber(other.getExampleNumber());
      }
      return this;
    }

    public boolean exactlySameAs(PhoneNumberDesc other) {
      return nationalNumberPattern_.equals(other.nationalNumberPattern_) &&
          possibleNumberPattern_.equals(other.possibleNumberPattern_) &&
          exampleNumber_.equals(other.exampleNumber_);
    }

    public void writeExternal(ObjectOutput objectOutput) throws IOException {
      objectOutput.writeBoolean(hasNationalNumberPattern);
      if (hasNationalNumberPattern) {
        objectOutput.writeUTF(nationalNumberPattern_);
      }

      objectOutput.writeBoolean(hasPossibleNumberPattern);
      if (hasPossibleNumberPattern) {
        objectOutput.writeUTF(possibleNumberPattern_);
      }

      objectOutput.writeBoolean(hasExampleNumber);
      if (hasExampleNumber) {
        objectOutput.writeUTF(exampleNumber_);
      }
    }

    public void readExternal(ObjectInput objectInput) throws IOException {
      if (objectInput.readBoolean()) {
        setNationalNumberPattern(objectInput.readUTF());
      }

      if (objectInput.readBoolean()) {
        setPossibleNumberPattern(objectInput.readUTF());
      }

      if (objectInput.readBoolean()) {
        setExampleNumber(objectInput.readUTF());
      }
    }
  }

  public static class PhoneMetadata implements Externalizable {
    private static final long serialVersionUID = 1;
    public PhoneMetadata() {}

    /**
     * Provides a dummy builder.
     *
     * @see NumberFormat.Builder
     */
    public static final class Builder extends PhoneMetadata {
      public PhoneMetadata build() {
        return this;
      }
    }
    public static Builder newBuilder() {
      return new Builder();
    }

    // required PhoneNumberDesc general_desc = 1;
    private boolean hasGeneralDesc;
    private PhoneNumberDesc generalDesc_ = null;
    public boolean hasGeneralDesc() { return hasGeneralDesc; }
    public PhoneNumberDesc getGeneralDesc() { return generalDesc_; }
    public PhoneMetadata setGeneralDesc(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasGeneralDesc = true;
      generalDesc_ = value;
      return this;
    }

    // required PhoneNumberDesc fixed_line = 2;
    private boolean hasFixedLine;
    private PhoneNumberDesc fixedLine_ = null;
    public boolean hasFixedLine() { return hasFixedLine; }
    public PhoneNumberDesc getFixedLine() { return fixedLine_; }
    public PhoneMetadata setFixedLine(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasFixedLine = true;
      fixedLine_ = value;
      return this;
    }

    // required PhoneNumberDesc mobile = 3;
    private boolean hasMobile;
    private PhoneNumberDesc mobile_ = null;
    public boolean hasMobile() { return hasMobile; }
    public PhoneNumberDesc getMobile() { return mobile_; }
    public PhoneMetadata setMobile(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasMobile = true;
      mobile_ = value;
      return this;
    }

    // required PhoneNumberDesc toll_free = 4;
    private boolean hasTollFree;
    private PhoneNumberDesc tollFree_ = null;
    public boolean hasTollFree() { return hasTollFree; }
    public PhoneNumberDesc getTollFree() { return tollFree_; }
    public PhoneMetadata setTollFree(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasTollFree = true;
      tollFree_ = value;
      return this;
    }

    // required PhoneNumberDesc premium_rate = 5;
    private boolean hasPremiumRate;
    private PhoneNumberDesc premiumRate_ = null;
    public boolean hasPremiumRate() { return hasPremiumRate; }
    public PhoneNumberDesc getPremiumRate() { return premiumRate_; }
    public PhoneMetadata setPremiumRate(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasPremiumRate = true;
      premiumRate_ = value;
      return this;
    }

    // required PhoneNumberDesc shared_cost = 6;
    private boolean hasSharedCost;
    private PhoneNumberDesc sharedCost_ = null;
    public boolean hasSharedCost() { return hasSharedCost; }
    public PhoneNumberDesc getSharedCost() { return sharedCost_; }
    public PhoneMetadata setSharedCost(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasSharedCost = true;
      sharedCost_ = value;
      return this;
    }

    // required PhoneNumberDesc personal_number = 7;
    private boolean hasPersonalNumber;
    private PhoneNumberDesc personalNumber_ = null;
    public boolean hasPersonalNumber() { return hasPersonalNumber; }
    public PhoneNumberDesc getPersonalNumber() { return personalNumber_; }
    public PhoneMetadata setPersonalNumber(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasPersonalNumber = true;
      personalNumber_ = value;
      return this;
    }

    // required PhoneNumberDesc voip = 8;
    private boolean hasVoip;
    private PhoneNumberDesc voip_ = null;
    public boolean hasVoip() { return hasVoip; }
    public PhoneNumberDesc getVoip() { return voip_; }
    public PhoneMetadata setVoip(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasVoip = true;
      voip_ = value;
      return this;
    }

    // required PhoneNumberDesc pager = 21;
    private boolean hasPager;
    private PhoneNumberDesc pager_ = null;
    public boolean hasPager() { return hasPager; }
    public PhoneNumberDesc getPager() { return pager_; }
    public PhoneMetadata setPager(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasPager = true;
      pager_ = value;
      return this;
    }

    // required PhoneNumberDesc uan = 25;
    private boolean hasUan;
    private PhoneNumberDesc uan_ = null;
    public boolean hasUan() { return hasUan; }
    public PhoneNumberDesc getUan() { return uan_; }
    public PhoneMetadata setUan(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasUan = true;
      uan_ = value;
      return this;
    }

    // required PhoneNumberDesc noInternationalDialling = 24;
    private boolean hasNoInternationalDialling;
    private PhoneNumberDesc noInternationalDialling_ = null;
    public boolean hasNoInternationalDialling() { return hasNoInternationalDialling; }
    public PhoneNumberDesc getNoInternationalDialling() { return noInternationalDialling_; }
    public PhoneMetadata setNoInternationalDialling(PhoneNumberDesc value) {
      if (value == null) {
        throw new NullPointerException();
      }
      hasNoInternationalDialling = true;
      noInternationalDialling_ = value;
      return this;
    }

    // required string id = 9;
    private boolean hasId;
    private String id_ = "";
    public boolean hasId() { return hasId; }
    public String getId() { return id_; }
    public PhoneMetadata setId(String value) {
      hasId = true;
      id_ = value;
      return this;
    }

    // required int32 country_code = 10;
    private boolean hasCountryCode;
    private int countryCode_ = 0;
    public boolean hasCountryCode() { return hasCountryCode; }
    public int getCountryCode() { return countryCode_; }
    public PhoneMetadata setCountryCode(int value) {
      hasCountryCode = true;
      countryCode_ = value;
      return this;
    }

    // required string international_prefix = 11;
    private boolean hasInternationalPrefix;
    private String internationalPrefix_ = "";
    public boolean hasInternationalPrefix() { return hasInternationalPrefix; }
    public String getInternationalPrefix() { return internationalPrefix_; }
    public PhoneMetadata setInternationalPrefix(String value) {
      hasInternationalPrefix = true;
      internationalPrefix_ = value;
      return this;
    }

    // optional string preferred_international_prefix = 17;
    private boolean hasPreferredInternationalPrefix;
    private String preferredInternationalPrefix_ = "";
    public boolean hasPreferredInternationalPrefix() { return hasPreferredInternationalPrefix; }
    public String getPreferredInternationalPrefix() { return preferredInternationalPrefix_; }
    public PhoneMetadata setPreferredInternationalPrefix(String value) {
      hasPreferredInternationalPrefix = true;
      preferredInternationalPrefix_ = value;
      return this;
    }

    // optional string national_prefix = 12;
    private boolean hasNationalPrefix;
    private String nationalPrefix_ = "";
    public boolean hasNationalPrefix() { return hasNationalPrefix; }
    public String getNationalPrefix() { return nationalPrefix_; }
    public PhoneMetadata setNationalPrefix(String value) {
      hasNationalPrefix = true;
      nationalPrefix_ = value;
      return this;
    }

    // optional string preferred_extn_prefix = 13;
    private boolean hasPreferredExtnPrefix;
    private String preferredExtnPrefix_ = "";
    public boolean hasPreferredExtnPrefix() { return hasPreferredExtnPrefix; }
    public String getPreferredExtnPrefix() { return preferredExtnPrefix_; }
    public PhoneMetadata setPreferredExtnPrefix(String value) {
      hasPreferredExtnPrefix = true;
      preferredExtnPrefix_ = value;
      return this;
    }

    // optional string national_prefix_for_parsing = 15;
    private boolean hasNationalPrefixForParsing;
    private String nationalPrefixForParsing_ = "";
    public boolean hasNationalPrefixForParsing() { return hasNationalPrefixForParsing; }
    public String getNationalPrefixForParsing() { return nationalPrefixForParsing_; }
    public PhoneMetadata setNationalPrefixForParsing(String value) {
      hasNationalPrefixForParsing = true;
      nationalPrefixForParsing_ = value;
      return this;
    }

    // optional string national_prefix_transform_rule = 16;
    private boolean hasNationalPrefixTransformRule;
    private String nationalPrefixTransformRule_ = "";
    public boolean hasNationalPrefixTransformRule() { return hasNationalPrefixTransformRule; }
    public String getNationalPrefixTransformRule() { return nationalPrefixTransformRule_; }
    public PhoneMetadata setNationalPrefixTransformRule(String value) {
      hasNationalPrefixTransformRule = true;
      nationalPrefixTransformRule_ = value;
      return this;
    }

    // optional bool same_mobile_and_fixed_line_pattern = 18 [default = false];
    private boolean hasSameMobileAndFixedLinePattern;
    private boolean sameMobileAndFixedLinePattern_ = false;
    public boolean hasSameMobileAndFixedLinePattern() { return hasSameMobileAndFixedLinePattern; }
    public boolean getSameMobileAndFixedLinePattern() { return sameMobileAndFixedLinePattern_; }
    public PhoneMetadata setSameMobileAndFixedLinePattern(boolean value) {
      hasSameMobileAndFixedLinePattern = true;
      sameMobileAndFixedLinePattern_ = value;
      return this;
    }

    // repeated NumberFormat number_format = 19;
    private java.util.List<NumberFormat> numberFormat_ = new java.util.ArrayList<NumberFormat>();
    public java.util.List<NumberFormat> numberFormats() {
      return numberFormat_;
    }
    public int numberFormatSize() { return numberFormat_.size(); }
    public NumberFormat getNumberFormat(int index) {
      return numberFormat_.get(index);
    }
    public PhoneMetadata addNumberFormat(NumberFormat value) {
      if (value == null) {
        throw new NullPointerException();
      }
      numberFormat_.add(value);
      return this;
    }

    // repeated NumberFormat intl_number_format = 20;
    private java.util.List<NumberFormat> intlNumberFormat_ =
        new java.util.ArrayList<NumberFormat>();
    public java.util.List<NumberFormat> intlNumberFormats() {
      return intlNumberFormat_;
    }
    public int intlNumberFormatSize() { return intlNumberFormat_.size(); }
    public NumberFormat getIntlNumberFormat(int index) {
      return intlNumberFormat_.get(index);
    }

    public PhoneMetadata addIntlNumberFormat(NumberFormat value) {
      if (value == null) {
        throw new NullPointerException();
      }
      intlNumberFormat_.add(value);
      return this;
    }
    public PhoneMetadata clearIntlNumberFormat() {
      intlNumberFormat_.clear();
      return this;
    }

    // optional bool main_country_for_code = 22 [default = false];
    private boolean hasMainCountryForCode;
    private boolean mainCountryForCode_ = false;
    public boolean hasMainCountryForCode() { return hasMainCountryForCode; }
    public boolean isMainCountryForCode() { return mainCountryForCode_; }
    public PhoneMetadata setMainCountryForCode(boolean value) {
      hasMainCountryForCode = true;
      mainCountryForCode_ = value;
      return this;
    }

    // optional string leading_digits = 23;
    private boolean hasLeadingDigits;
    private String leadingDigits_ = "";
    public boolean hasLeadingDigits() { return hasLeadingDigits; }
    public String getLeadingDigits() { return leadingDigits_; }
    public PhoneMetadata setLeadingDigits(String value) {
      hasLeadingDigits = true;
      leadingDigits_ = value;
      return this;
    }

    // optional bool leading_zero_possible = 26 [default = false];
    private boolean hasLeadingZeroPossible;
    private boolean leadingZeroPossible_ = false;
    public boolean hasLeadingZeroPossible() { return hasLeadingZeroPossible; }
    public boolean isLeadingZeroPossible() { return leadingZeroPossible_; }
    public PhoneMetadata setLeadingZeroPossible(boolean value) {
      hasLeadingZeroPossible = true;
      leadingZeroPossible_ = value;
      return this;
    }

    public void writeExternal(ObjectOutput objectOutput) throws IOException {
      objectOutput.writeBoolean(hasGeneralDesc);
      if (hasGeneralDesc) {
        generalDesc_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasFixedLine);
      if (hasFixedLine) {
        fixedLine_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasMobile);
      if (hasMobile) {
        mobile_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasTollFree);
      if (hasTollFree) {
        tollFree_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasPremiumRate);
      if (hasPremiumRate) {
        premiumRate_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasSharedCost);
      if (hasSharedCost) {
        sharedCost_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasPersonalNumber);
      if (hasPersonalNumber) {
        personalNumber_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasVoip);
      if (hasVoip) {
        voip_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasPager);
      if (hasPager) {
        pager_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasUan);
      if (hasUan) {
        uan_.writeExternal(objectOutput);
      }
      objectOutput.writeBoolean(hasNoInternationalDialling);
      if (hasNoInternationalDialling) {
        noInternationalDialling_.writeExternal(objectOutput);
      }

      objectOutput.writeUTF(id_);
      objectOutput.writeInt(countryCode_);
      objectOutput.writeUTF(internationalPrefix_);

      objectOutput.writeBoolean(hasPreferredInternationalPrefix);
      if (hasPreferredInternationalPrefix) {
        objectOutput.writeUTF(preferredInternationalPrefix_);
      }

      objectOutput.writeBoolean(hasNationalPrefix);
      if (hasNationalPrefix) {
        objectOutput.writeUTF(nationalPrefix_);
      }

      objectOutput.writeBoolean(hasPreferredExtnPrefix);
      if (hasPreferredExtnPrefix) {
        objectOutput.writeUTF(preferredExtnPrefix_);
      }

      objectOutput.writeBoolean(hasNationalPrefixForParsing);
      if (hasNationalPrefixForParsing) {
        objectOutput.writeUTF(nationalPrefixForParsing_);
      }

      objectOutput.writeBoolean(hasNationalPrefixTransformRule);
      if (hasNationalPrefixTransformRule) {
        objectOutput.writeUTF(nationalPrefixTransformRule_);
      }

      objectOutput.writeBoolean(sameMobileAndFixedLinePattern_);

      int numberFormatSize = numberFormatSize();
      objectOutput.writeInt(numberFormatSize);
      for (int i = 0; i < numberFormatSize; i++) {
        numberFormat_.get(i).writeExternal(objectOutput);
      }

      int intlNumberFormatSize = intlNumberFormatSize();
      objectOutput.writeInt(intlNumberFormatSize);
      for (int i = 0; i < intlNumberFormatSize; i++) {
        intlNumberFormat_.get(i).writeExternal(objectOutput);
      }

      objectOutput.writeBoolean(mainCountryForCode_);

      objectOutput.writeBoolean(hasLeadingDigits);
      if (hasLeadingDigits) {
        objectOutput.writeUTF(leadingDigits_);
      }

      objectOutput.writeBoolean(leadingZeroPossible_);
    }

    public void readExternal(ObjectInput objectInput) throws IOException {
      boolean hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setGeneralDesc(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setFixedLine(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setMobile(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setTollFree(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setPremiumRate(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setSharedCost(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setPersonalNumber(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setVoip(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setPager(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setUan(desc);
      }
      hasDesc = objectInput.readBoolean();
      if (hasDesc) {
        PhoneNumberDesc desc = new PhoneNumberDesc();
        desc.readExternal(objectInput);
        setNoInternationalDialling(desc);
      }

      setId(objectInput.readUTF());
      setCountryCode(objectInput.readInt());
      setInternationalPrefix(objectInput.readUTF());

      boolean hasString = objectInput.readBoolean();
      if (hasString) {
        setPreferredInternationalPrefix(objectInput.readUTF());
      }

      hasString = objectInput.readBoolean();
      if (hasString) {
        setNationalPrefix(objectInput.readUTF());
      }

      hasString = objectInput.readBoolean();
      if (hasString) {
        setPreferredExtnPrefix(objectInput.readUTF());
      }

      hasString = objectInput.readBoolean();
      if (hasString) {
        setNationalPrefixForParsing(objectInput.readUTF());
      }

      hasString = objectInput.readBoolean();
      if (hasString) {
        setNationalPrefixTransformRule(objectInput.readUTF());
      }

      setSameMobileAndFixedLinePattern(objectInput.readBoolean());

      int nationalFormatSize = objectInput.readInt();
      for (int i = 0; i < nationalFormatSize; i++) {
        NumberFormat numFormat = new NumberFormat();
        numFormat.readExternal(objectInput);
        numberFormat_.add(numFormat);
      }

      int intlNumberFormatSize = objectInput.readInt();
      for (int i = 0; i < intlNumberFormatSize; i++) {
        NumberFormat numFormat = new NumberFormat();
        numFormat.readExternal(objectInput);
        intlNumberFormat_.add(numFormat);
      }

      setMainCountryForCode(objectInput.readBoolean());

      hasString = objectInput.readBoolean();
      if (hasString) {
        setLeadingDigits(objectInput.readUTF());
      }

      setLeadingZeroPossible(objectInput.readBoolean());
    }
  }

  public static class PhoneMetadataCollection implements Externalizable {
    private static final long serialVersionUID = 1;
    public PhoneMetadataCollection() {}

    /**
     * Provides a dummy builder.
     *
     * @see NumberFormat.Builder
     */
    public static final class Builder extends PhoneMetadataCollection {
      public PhoneMetadataCollection build() {
        return this;
      }
    }
    public static Builder newBuilder() {
      return new Builder();
    }

    // repeated PhoneMetadata metadata = 1;
    private java.util.List<PhoneMetadata> metadata_ = new java.util.ArrayList<PhoneMetadata>();

    public java.util.List<PhoneMetadata> getMetadataList() {
      return metadata_;
    }
    public int getMetadataCount() { return metadata_.size(); }

    public PhoneMetadataCollection addMetadata(PhoneMetadata value) {
      if (value == null) {
        throw new NullPointerException();
      }
      metadata_.add(value);
      return this;
    }

    public void writeExternal(ObjectOutput objectOutput) throws IOException {
      int size = getMetadataCount();
      objectOutput.writeInt(size);
      for (int i = 0; i < size; i++) {
        metadata_.get(i).writeExternal(objectOutput);
      }
    }

    public void readExternal(ObjectInput objectInput) throws IOException {
      int size = objectInput.readInt();
      for (int i = 0; i < size; i++) {
        PhoneMetadata metadata = new PhoneMetadata();
        metadata.readExternal(objectInput);
        metadata_.add(metadata);
      }
    }

    public PhoneMetadataCollection clear() {
      metadata_.clear();
      return this;
    }
  }
}
