// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: phonenumber.proto

package com.google.i18n.phonenumbers;

public final class Phonenumber {
  private Phonenumber() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }
  public static final class PhoneNumber extends
      com.google.protobuf.GeneratedMessageLite {
    // Use PhoneNumber.newBuilder() to construct.
    private PhoneNumber() {
      initFields();
    }
    private PhoneNumber(boolean noInit) {}
    
    private static final PhoneNumber defaultInstance;
    public static PhoneNumber getDefaultInstance() {
      return defaultInstance;
    }
    
    public PhoneNumber getDefaultInstanceForType() {
      return defaultInstance;
    }
    
    // required int32 country_code = 1;
    public static final int COUNTRY_CODE_FIELD_NUMBER = 1;
    private boolean hasCountryCode;
    private int countryCode_ = 0;
    public boolean hasCountryCode() { return hasCountryCode; }
    public int getCountryCode() { return countryCode_; }
    
    // required uint64 national_number = 2;
    public static final int NATIONAL_NUMBER_FIELD_NUMBER = 2;
    private boolean hasNationalNumber;
    private long nationalNumber_ = 0L;
    public boolean hasNationalNumber() { return hasNationalNumber; }
    public long getNationalNumber() { return nationalNumber_; }
    
    // optional string extension = 3;
    public static final int EXTENSION_FIELD_NUMBER = 3;
    private boolean hasExtension;
    private java.lang.String extension_ = "";
    public boolean hasExtension() { return hasExtension; }
    public java.lang.String getExtension() { return extension_; }
    
    // optional bool italian_leading_zero = 4;
    public static final int ITALIAN_LEADING_ZERO_FIELD_NUMBER = 4;
    private boolean hasItalianLeadingZero;
    private boolean italianLeadingZero_ = false;
    public boolean hasItalianLeadingZero() { return hasItalianLeadingZero; }
    public boolean getItalianLeadingZero() { return italianLeadingZero_; }
    
    private void initFields() {
    }
    public final boolean isInitialized() {
      if (!hasCountryCode) return false;
      if (!hasNationalNumber) return false;
      return true;
    }
    
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (hasCountryCode()) {
        output.writeInt32(1, getCountryCode());
      }
      if (hasNationalNumber()) {
        output.writeUInt64(2, getNationalNumber());
      }
      if (hasExtension()) {
        output.writeString(3, getExtension());
      }
      if (hasItalianLeadingZero()) {
        output.writeBool(4, getItalianLeadingZero());
      }
    }
    
    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;
    
      size = 0;
      if (hasCountryCode()) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(1, getCountryCode());
      }
      if (hasNationalNumber()) {
        size += com.google.protobuf.CodedOutputStream
          .computeUInt64Size(2, getNationalNumber());
      }
      if (hasExtension()) {
        size += com.google.protobuf.CodedOutputStream
          .computeStringSize(3, getExtension());
      }
      if (hasItalianLeadingZero()) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(4, getItalianLeadingZero());
      }
      memoizedSerializedSize = size;
      return size;
    }
    
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data).buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data, extensionRegistry)
               .buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data).buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return newBuilder().mergeFrom(data, extensionRegistry)
               .buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input).buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input, extensionRegistry)
               .buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      Builder builder = newBuilder();
      if (builder.mergeDelimitedFrom(input)) {
        return builder.buildParsed();
      } else {
        return null;
      }
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      Builder builder = newBuilder();
      if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
        return builder.buildParsed();
      } else {
        return null;
      }
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input).buildParsed();
    }
    public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return newBuilder().mergeFrom(input, extensionRegistry)
               .buildParsed();
    }
    
    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(com.google.i18n.phonenumbers.Phonenumber.PhoneNumber prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }
    
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageLite.Builder<
          com.google.i18n.phonenumbers.Phonenumber.PhoneNumber, Builder> {
      private com.google.i18n.phonenumbers.Phonenumber.PhoneNumber result;
      
      // Construct using com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.newBuilder()
      private Builder() {}
      
      private static Builder create() {
        Builder builder = new Builder();
        builder.result = new com.google.i18n.phonenumbers.Phonenumber.PhoneNumber();
        return builder;
      }
      
      protected com.google.i18n.phonenumbers.Phonenumber.PhoneNumber internalGetResult() {
        return result;
      }
      
      public Builder clear() {
        if (result == null) {
          throw new IllegalStateException(
            "Cannot call clear() after build().");
        }
        result = new com.google.i18n.phonenumbers.Phonenumber.PhoneNumber();
        return this;
      }
      
      public Builder clone() {
        return create().mergeFrom(result);
      }
      
      public com.google.i18n.phonenumbers.Phonenumber.PhoneNumber getDefaultInstanceForType() {
        return com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.getDefaultInstance();
      }
      
      public boolean isInitialized() {
        return result.isInitialized();
      }
      public com.google.i18n.phonenumbers.Phonenumber.PhoneNumber build() {
        if (result != null && !isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return buildPartial();
      }
      
      private com.google.i18n.phonenumbers.Phonenumber.PhoneNumber buildParsed()
          throws com.google.protobuf.InvalidProtocolBufferException {
        if (!isInitialized()) {
          throw newUninitializedMessageException(
            result).asInvalidProtocolBufferException();
        }
        return buildPartial();
      }
      
      public com.google.i18n.phonenumbers.Phonenumber.PhoneNumber buildPartial() {
        if (result == null) {
          throw new IllegalStateException(
            "build() has already been called on this Builder.");
        }
        com.google.i18n.phonenumbers.Phonenumber.PhoneNumber returnMe = result;
        result = null;
        return returnMe;
      }
      
      public Builder mergeFrom(com.google.i18n.phonenumbers.Phonenumber.PhoneNumber other) {
        if (other == com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.getDefaultInstance()) return this;
        if (other.hasCountryCode()) {
          setCountryCode(other.getCountryCode());
        }
        if (other.hasNationalNumber()) {
          setNationalNumber(other.getNationalNumber());
        }
        if (other.hasExtension()) {
          setExtension(other.getExtension());
        }
        if (other.hasItalianLeadingZero()) {
          setItalianLeadingZero(other.getItalianLeadingZero());
        }
        return this;
      }
      
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        while (true) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              return this;
            default: {
              if (!parseUnknownField(input, extensionRegistry, tag)) {
                return this;
              }
              break;
            }
            case 8: {
              setCountryCode(input.readInt32());
              break;
            }
            case 16: {
              setNationalNumber(input.readUInt64());
              break;
            }
            case 26: {
              setExtension(input.readString());
              break;
            }
            case 32: {
              setItalianLeadingZero(input.readBool());
              break;
            }
          }
        }
      }
      
      
      // required int32 country_code = 1;
      public boolean hasCountryCode() {
        return result.hasCountryCode();
      }
      public int getCountryCode() {
        return result.getCountryCode();
      }
      public Builder setCountryCode(int value) {
        result.hasCountryCode = true;
        result.countryCode_ = value;
        return this;
      }
      public Builder clearCountryCode() {
        result.hasCountryCode = false;
        result.countryCode_ = 0;
        return this;
      }
      
      // required uint64 national_number = 2;
      public boolean hasNationalNumber() {
        return result.hasNationalNumber();
      }
      public long getNationalNumber() {
        return result.getNationalNumber();
      }
      public Builder setNationalNumber(long value) {
        result.hasNationalNumber = true;
        result.nationalNumber_ = value;
        return this;
      }
      public Builder clearNationalNumber() {
        result.hasNationalNumber = false;
        result.nationalNumber_ = 0L;
        return this;
      }
      
      // optional string extension = 3;
      public boolean hasExtension() {
        return result.hasExtension();
      }
      public java.lang.String getExtension() {
        return result.getExtension();
      }
      public Builder setExtension(java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  result.hasExtension = true;
        result.extension_ = value;
        return this;
      }
      public Builder clearExtension() {
        result.hasExtension = false;
        result.extension_ = getDefaultInstance().getExtension();
        return this;
      }
      
      // optional bool italian_leading_zero = 4;
      public boolean hasItalianLeadingZero() {
        return result.hasItalianLeadingZero();
      }
      public boolean getItalianLeadingZero() {
        return result.getItalianLeadingZero();
      }
      public Builder setItalianLeadingZero(boolean value) {
        result.hasItalianLeadingZero = true;
        result.italianLeadingZero_ = value;
        return this;
      }
      public Builder clearItalianLeadingZero() {
        result.hasItalianLeadingZero = false;
        result.italianLeadingZero_ = false;
        return this;
      }
      
      // @@protoc_insertion_point(builder_scope:i18n.phonenumbers.PhoneNumber)
    }
    
    static {
      defaultInstance = new PhoneNumber(true);
      com.google.i18n.phonenumbers.Phonenumber.internalForceInit();
      defaultInstance.initFields();
    }
    
    // @@protoc_insertion_point(class_scope:i18n.phonenumbers.PhoneNumber)
  }
  
  
  static {
  }
  
  public static void internalForceInit() {}
  
  // @@protoc_insertion_point(outer_class_scope)
}
