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

package org.apache.accumulo.examples.wikisearch.protobuf;

public final class Uid {
  private Uid() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  public interface ListOrBuilder extends
      // @@protoc_insertion_point(interface_extends:org.apache.accumulo.examples.wikisearch.protobuf.List)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>required bool IGNORE = 1;</code>
     * @return Whether the iGNORE field is set.
     */
    boolean hasIGNORE();
    /**
     * <code>required bool IGNORE = 1;</code>
     * @return The iGNORE.
     */
    boolean getIGNORE();

    /**
     * <code>required uint64 COUNT = 2;</code>
     * @return Whether the cOUNT field is set.
     */
    boolean hasCOUNT();
    /**
     * <code>required uint64 COUNT = 2;</code>
     * @return The cOUNT.
     */
    long getCOUNT();

    /**
     * <code>repeated string UID = 3;</code>
     * @return A list containing the uID.
     */
    java.util.List<java.lang.String>
        getUIDList();
    /**
     * <code>repeated string UID = 3;</code>
     * @return The count of uID.
     */
    int getUIDCount();
    /**
     * <code>repeated string UID = 3;</code>
     * @param index The index of the element to return.
     * @return The uID at the given index.
     */
    java.lang.String getUID(int index);
    /**
     * <code>repeated string UID = 3;</code>
     * @param index The index of the value to return.
     * @return The bytes of the uID at the given index.
     */
    com.google.protobuf.ByteString
        getUIDBytes(int index);
  }
  /**
   * Protobuf type {@code org.apache.accumulo.examples.wikisearch.protobuf.List}
   */
  public static final class List extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:org.apache.accumulo.examples.wikisearch.protobuf.List)
      ListOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use List.newBuilder() to construct.
    private List(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private List() {
      uID_ = com.google.protobuf.LazyStringArrayList.EMPTY;
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new List();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    private List(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      this();
      if (extensionRegistry == null) {
        throw new java.lang.NullPointerException();
      }
      int mutable_bitField0_ = 0;
      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
          com.google.protobuf.UnknownFieldSet.newBuilder();
      try {
        boolean done = false;
        while (!done) {
          int tag = input.readTag();
          switch (tag) {
            case 0:
              done = true;
              break;
            case 8: {
              bitField0_ |= 0x00000001;
              iGNORE_ = input.readBool();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              cOUNT_ = input.readUInt64();
              break;
            }
            case 26: {
              com.google.protobuf.ByteString bs = input.readBytes();
              if (!((mutable_bitField0_ & 0x00000004) != 0)) {
                uID_ = new com.google.protobuf.LazyStringArrayList();
                mutable_bitField0_ |= 0x00000004;
              }
              uID_.add(bs);
              break;
            }
            default: {
              if (!parseUnknownField(
                  input, unknownFields, extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000004) != 0)) {
          uID_ = uID_.getUnmodifiableView();
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.accumulo.examples.wikisearch.protobuf.Uid.internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.accumulo.examples.wikisearch.protobuf.Uid.internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.class, org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.Builder.class);
    }

    private int bitField0_;
    public static final int IGNORE_FIELD_NUMBER = 1;
    private boolean iGNORE_;
    /**
     * <code>required bool IGNORE = 1;</code>
     * @return Whether the iGNORE field is set.
     */
    @java.lang.Override
    public boolean hasIGNORE() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>required bool IGNORE = 1;</code>
     * @return The iGNORE.
     */
    @java.lang.Override
    public boolean getIGNORE() {
      return iGNORE_;
    }

    public static final int COUNT_FIELD_NUMBER = 2;
    private long cOUNT_;
    /**
     * <code>required uint64 COUNT = 2;</code>
     * @return Whether the cOUNT field is set.
     */
    @java.lang.Override
    public boolean hasCOUNT() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>required uint64 COUNT = 2;</code>
     * @return The cOUNT.
     */
    @java.lang.Override
    public long getCOUNT() {
      return cOUNT_;
    }

    public static final int UID_FIELD_NUMBER = 3;
    private com.google.protobuf.LazyStringList uID_;
    /**
     * <code>repeated string UID = 3;</code>
     * @return A list containing the uID.
     */
    public com.google.protobuf.ProtocolStringList
        getUIDList() {
      return uID_;
    }
    /**
     * <code>repeated string UID = 3;</code>
     * @return The count of uID.
     */
    public int getUIDCount() {
      return uID_.size();
    }
    /**
     * <code>repeated string UID = 3;</code>
     * @param index The index of the element to return.
     * @return The uID at the given index.
     */
    public java.lang.String getUID(int index) {
      return uID_.get(index);
    }
    /**
     * <code>repeated string UID = 3;</code>
     * @param index The index of the value to return.
     * @return The bytes of the uID at the given index.
     */
    public com.google.protobuf.ByteString
        getUIDBytes(int index) {
      return uID_.getByteString(index);
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      if (!hasIGNORE()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasCOUNT()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        output.writeBool(1, iGNORE_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeUInt64(2, cOUNT_);
      }
      for (int i = 0; i < uID_.size(); i++) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 3, uID_.getRaw(i));
      }
      unknownFields.writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(1, iGNORE_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeUInt64Size(2, cOUNT_);
      }
      {
        int dataSize = 0;
        for (int i = 0; i < uID_.size(); i++) {
          dataSize += computeStringSizeNoTag(uID_.getRaw(i));
        }
        size += dataSize;
        size += 1 * getUIDList().size();
      }
      size += unknownFields.getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.accumulo.examples.wikisearch.protobuf.Uid.List)) {
        return super.equals(obj);
      }
      org.apache.accumulo.examples.wikisearch.protobuf.Uid.List other = (org.apache.accumulo.examples.wikisearch.protobuf.Uid.List) obj;

      if (hasIGNORE() != other.hasIGNORE()) return false;
      if (hasIGNORE()) {
        if (getIGNORE()
            != other.getIGNORE()) return false;
      }
      if (hasCOUNT() != other.hasCOUNT()) return false;
      if (hasCOUNT()) {
        if (getCOUNT()
            != other.getCOUNT()) return false;
      }
      if (!getUIDList()
          .equals(other.getUIDList())) return false;
      if (!unknownFields.equals(other.unknownFields)) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasIGNORE()) {
        hash = (37 * hash) + IGNORE_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getIGNORE());
      }
      if (hasCOUNT()) {
        hash = (37 * hash) + COUNT_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
            getCOUNT());
      }
      if (getUIDCount() > 0) {
        hash = (37 * hash) + UID_FIELD_NUMBER;
        hash = (53 * hash) + getUIDList().hashCode();
      }
      hash = (29 * hash) + unknownFields.hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(org.apache.accumulo.examples.wikisearch.protobuf.Uid.List prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.accumulo.examples.wikisearch.protobuf.List}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:org.apache.accumulo.examples.wikisearch.protobuf.List)
        org.apache.accumulo.examples.wikisearch.protobuf.Uid.ListOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.accumulo.examples.wikisearch.protobuf.Uid.internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.accumulo.examples.wikisearch.protobuf.Uid.internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.class, org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.Builder.class);
      }

      // Construct using org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        iGNORE_ = false;
        bitField0_ = (bitField0_ & ~0x00000001);
        cOUNT_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000002);
        uID_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.accumulo.examples.wikisearch.protobuf.Uid.internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_descriptor;
      }

      @java.lang.Override
      public org.apache.accumulo.examples.wikisearch.protobuf.Uid.List getDefaultInstanceForType() {
        return org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.accumulo.examples.wikisearch.protobuf.Uid.List build() {
        org.apache.accumulo.examples.wikisearch.protobuf.Uid.List result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.accumulo.examples.wikisearch.protobuf.Uid.List buildPartial() {
        org.apache.accumulo.examples.wikisearch.protobuf.Uid.List result = new org.apache.accumulo.examples.wikisearch.protobuf.Uid.List(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          result.iGNORE_ = iGNORE_;
          to_bitField0_ |= 0x00000001;
        }
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.cOUNT_ = cOUNT_;
          to_bitField0_ |= 0x00000002;
        }
        if (((bitField0_ & 0x00000004) != 0)) {
          uID_ = uID_.getUnmodifiableView();
          bitField0_ = (bitField0_ & ~0x00000004);
        }
        result.uID_ = uID_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.accumulo.examples.wikisearch.protobuf.Uid.List) {
          return mergeFrom((org.apache.accumulo.examples.wikisearch.protobuf.Uid.List)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.accumulo.examples.wikisearch.protobuf.Uid.List other) {
        if (other == org.apache.accumulo.examples.wikisearch.protobuf.Uid.List.getDefaultInstance()) return this;
        if (other.hasIGNORE()) {
          setIGNORE(other.getIGNORE());
        }
        if (other.hasCOUNT()) {
          setCOUNT(other.getCOUNT());
        }
        if (!other.uID_.isEmpty()) {
          if (uID_.isEmpty()) {
            uID_ = other.uID_;
            bitField0_ = (bitField0_ & ~0x00000004);
          } else {
            ensureUIDIsMutable();
            uID_.addAll(other.uID_);
          }
          onChanged();
        }
        this.mergeUnknownFields(other.unknownFields);
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        if (!hasIGNORE()) {
          return false;
        }
        if (!hasCOUNT()) {
          return false;
        }
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.accumulo.examples.wikisearch.protobuf.Uid.List parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.accumulo.examples.wikisearch.protobuf.Uid.List) e.getUnfinishedMessage();
          throw e.unwrapIOException();
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      private boolean iGNORE_ ;
      /**
       * <code>required bool IGNORE = 1;</code>
       * @return Whether the iGNORE field is set.
       */
      @java.lang.Override
      public boolean hasIGNORE() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>required bool IGNORE = 1;</code>
       * @return The iGNORE.
       */
      @java.lang.Override
      public boolean getIGNORE() {
        return iGNORE_;
      }
      /**
       * <code>required bool IGNORE = 1;</code>
       * @param value The iGNORE to set.
       * @return This builder for chaining.
       */
      public Builder setIGNORE(boolean value) {
        bitField0_ |= 0x00000001;
        iGNORE_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bool IGNORE = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearIGNORE() {
        bitField0_ = (bitField0_ & ~0x00000001);
        iGNORE_ = false;
        onChanged();
        return this;
      }

      private long cOUNT_ ;
      /**
       * <code>required uint64 COUNT = 2;</code>
       * @return Whether the cOUNT field is set.
       */
      @java.lang.Override
      public boolean hasCOUNT() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>required uint64 COUNT = 2;</code>
       * @return The cOUNT.
       */
      @java.lang.Override
      public long getCOUNT() {
        return cOUNT_;
      }
      /**
       * <code>required uint64 COUNT = 2;</code>
       * @param value The cOUNT to set.
       * @return This builder for chaining.
       */
      public Builder setCOUNT(long value) {
        bitField0_ |= 0x00000002;
        cOUNT_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required uint64 COUNT = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearCOUNT() {
        bitField0_ = (bitField0_ & ~0x00000002);
        cOUNT_ = 0L;
        onChanged();
        return this;
      }

      private com.google.protobuf.LazyStringList uID_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureUIDIsMutable() {
        if (!((bitField0_ & 0x00000004) != 0)) {
          uID_ = new com.google.protobuf.LazyStringArrayList(uID_);
          bitField0_ |= 0x00000004;
         }
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @return A list containing the uID.
       */
      public com.google.protobuf.ProtocolStringList
          getUIDList() {
        return uID_.getUnmodifiableView();
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @return The count of uID.
       */
      public int getUIDCount() {
        return uID_.size();
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @param index The index of the element to return.
       * @return The uID at the given index.
       */
      public java.lang.String getUID(int index) {
        return uID_.get(index);
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @param index The index of the value to return.
       * @return The bytes of the uID at the given index.
       */
      public com.google.protobuf.ByteString
          getUIDBytes(int index) {
        return uID_.getByteString(index);
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @param index The index to set the value at.
       * @param value The uID to set.
       * @return This builder for chaining.
       */
      public Builder setUID(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUIDIsMutable();
        uID_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @param value The uID to add.
       * @return This builder for chaining.
       */
      public Builder addUID(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUIDIsMutable();
        uID_.add(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @param values The uID to add.
       * @return This builder for chaining.
       */
      public Builder addAllUID(
          java.lang.Iterable<java.lang.String> values) {
        ensureUIDIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(
            values, uID_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @return This builder for chaining.
       */
      public Builder clearUID() {
        uID_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000004);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string UID = 3;</code>
       * @param value The bytes of the uID to add.
       * @return This builder for chaining.
       */
      public Builder addUIDBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUIDIsMutable();
        uID_.add(value);
        onChanged();
        return this;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:org.apache.accumulo.examples.wikisearch.protobuf.List)
    }

    // @@protoc_insertion_point(class_scope:org.apache.accumulo.examples.wikisearch.protobuf.List)
    private static final org.apache.accumulo.examples.wikisearch.protobuf.Uid.List DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.accumulo.examples.wikisearch.protobuf.Uid.List();
    }

    public static org.apache.accumulo.examples.wikisearch.protobuf.Uid.List getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    @java.lang.Deprecated public static final com.google.protobuf.Parser<List>
        PARSER = new com.google.protobuf.AbstractParser<List>() {
      @java.lang.Override
      public List parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        return new List(input, extensionRegistry);
      }
    };

    public static com.google.protobuf.Parser<List> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<List> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.accumulo.examples.wikisearch.protobuf.Uid.List getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_fieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor
      getDescriptor() {
    return descriptor;
  }
  private static  com.google.protobuf.Descriptors.FileDescriptor
      descriptor;
  static {
    java.lang.String[] descriptorData = {
      "\n\tUid.proto\0220org.apache.accumulo.example" +
      "s.wikisearch.protobuf\"2\n\004List\022\016\n\006IGNORE\030" +
      "\001 \002(\010\022\r\n\005COUNT\030\002 \002(\004\022\013\n\003UID\030\003 \003(\tB4\n0org" +
      ".apache.accumulo.examples.wikisearch.pro" +
      "tobufH\001"
    };
    descriptor = com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
        });
    internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_descriptor =
      getDescriptor().getMessageTypes().get(0);
    internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_org_apache_accumulo_examples_wikisearch_protobuf_List_descriptor,
        new java.lang.String[] { "IGNORE", "COUNT", "UID", });
  }

  // @@protoc_insertion_point(outer_class_scope)
}
