// 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_; }
    
    // optional string raw_input = 5;
    public static final int RAW_INPUT_FIELD_NUMBER = 5;
    private boolean hasRawInput;
    private java.lang.String rawInput_ = "";
    public boolean hasRawInput() { return hasRawInput; }
    public java.lang.String getRawInput() { return rawInput_; }

    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());
      }
      if (hasRawInput()) {
        output.writeString(5, getRawInput());
      }
    }
    
    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());
      }
      if (hasRawInput()) {
        size += com.google.protobuf.CodedOutputStream
          .computeStringSize(5, getRawInput());
      }
      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());
        }
        if (other.hasRawInput()) {
          setRawInput(other.getRawInput());
        }
        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;
            }
            case 42: {
              setRawInput(input.readString());
              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;
      }
      
      // optional string raw_input = 5;
      public boolean hasRawInput() {
        return result.hasRawInput();
      }
      public java.lang.String getRawInput() {
        return result.getRawInput();
      }
      public Builder setRawInput(java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  result.hasRawInput = true;
        result.rawInput_ = value;
        return this;
      }
      public Builder clearRawInput() {
        result.hasRawInput = false;
        result.rawInput_ = getDefaultInstance().getRawInput();
        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)
}
