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

package org.apache.flink.statefun.e2e.smoke.generated;

/**
 * Protobuf type {@code org.apache.flink.statefun.e2e.smoke.Commands}
 */
public  final class Commands extends
    com.google.protobuf.GeneratedMessageV3 implements
    // @@protoc_insertion_point(message_implements:org.apache.flink.statefun.e2e.smoke.Commands)
    CommandsOrBuilder {
private static final long serialVersionUID = 0L;
  // Use Commands.newBuilder() to construct.
  private Commands(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
    super(builder);
  }
  private Commands() {
    command_ = java.util.Collections.emptyList();
  }

  @Override
  public final com.google.protobuf.UnknownFieldSet
  getUnknownFields() {
    return this.unknownFields;
  }
  private Commands(
      com.google.protobuf.CodedInputStream input,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws com.google.protobuf.InvalidProtocolBufferException {
    this();
    if (extensionRegistry == null) {
      throw new 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 10: {
            if (!((mutable_bitField0_ & 0x00000001) != 0)) {
              command_ = new java.util.ArrayList<Command>();
              mutable_bitField0_ |= 0x00000001;
            }
            command_.add(
                input.readMessage(Command.parser(), extensionRegistry));
            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_ & 0x00000001) != 0)) {
        command_ = java.util.Collections.unmodifiableList(command_);
      }
      this.unknownFields = unknownFields.build();
      makeExtensionsImmutable();
    }
  }
  public static final com.google.protobuf.Descriptors.Descriptor
      getDescriptor() {
    return CommandsOuterClass.internal_static_org_apache_flink_statefun_e2e_smoke_Commands_descriptor;
  }

  @Override
  protected FieldAccessorTable
      internalGetFieldAccessorTable() {
    return CommandsOuterClass.internal_static_org_apache_flink_statefun_e2e_smoke_Commands_fieldAccessorTable
        .ensureFieldAccessorsInitialized(
            Commands.class, Builder.class);
  }

  public static final int COMMAND_FIELD_NUMBER = 1;
  private java.util.List<Command> command_;
  /**
   * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
   */
  public java.util.List<Command> getCommandList() {
    return command_;
  }
  /**
   * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
   */
  public java.util.List<? extends CommandOrBuilder>
      getCommandOrBuilderList() {
    return command_;
  }
  /**
   * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
   */
  public int getCommandCount() {
    return command_.size();
  }
  /**
   * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
   */
  public Command getCommand(int index) {
    return command_.get(index);
  }
  /**
   * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
   */
  public CommandOrBuilder getCommandOrBuilder(
      int index) {
    return command_.get(index);
  }

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

    memoizedIsInitialized = 1;
    return true;
  }

  @Override
  public void writeTo(com.google.protobuf.CodedOutputStream output)
                      throws java.io.IOException {
    for (int i = 0; i < command_.size(); i++) {
      output.writeMessage(1, command_.get(i));
    }
    unknownFields.writeTo(output);
  }

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

    size = 0;
    for (int i = 0; i < command_.size(); i++) {
      size += com.google.protobuf.CodedOutputStream
        .computeMessageSize(1, command_.get(i));
    }
    size += unknownFields.getSerializedSize();
    memoizedSize = size;
    return size;
  }

  @Override
  public boolean equals(final Object obj) {
    if (obj == this) {
     return true;
    }
    if (!(obj instanceof Commands)) {
      return super.equals(obj);
    }
    Commands other = (Commands) obj;

    if (!getCommandList()
        .equals(other.getCommandList())) return false;
    if (!unknownFields.equals(other.unknownFields)) return false;
    return true;
  }

  @Override
  public int hashCode() {
    if (memoizedHashCode != 0) {
      return memoizedHashCode;
    }
    int hash = 41;
    hash = (19 * hash) + getDescriptor().hashCode();
    if (getCommandCount() > 0) {
      hash = (37 * hash) + COMMAND_FIELD_NUMBER;
      hash = (53 * hash) + getCommandList().hashCode();
    }
    hash = (29 * hash) + unknownFields.hashCode();
    memoizedHashCode = hash;
    return hash;
  }

  public static Commands parseFrom(
      java.nio.ByteBuffer data)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return PARSER.parseFrom(data);
  }
  public static Commands parseFrom(
      java.nio.ByteBuffer data,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return PARSER.parseFrom(data, extensionRegistry);
  }
  public static Commands parseFrom(
      com.google.protobuf.ByteString data)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return PARSER.parseFrom(data);
  }
  public static Commands parseFrom(
      com.google.protobuf.ByteString data,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return PARSER.parseFrom(data, extensionRegistry);
  }
  public static Commands parseFrom(byte[] data)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return PARSER.parseFrom(data);
  }
  public static Commands parseFrom(
      byte[] data,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws com.google.protobuf.InvalidProtocolBufferException {
    return PARSER.parseFrom(data, extensionRegistry);
  }
  public static Commands parseFrom(java.io.InputStream input)
      throws java.io.IOException {
    return com.google.protobuf.GeneratedMessageV3
        .parseWithIOException(PARSER, input);
  }
  public static Commands 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 Commands parseDelimitedFrom(java.io.InputStream input)
      throws java.io.IOException {
    return com.google.protobuf.GeneratedMessageV3
        .parseDelimitedWithIOException(PARSER, input);
  }
  public static Commands 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 Commands parseFrom(
      com.google.protobuf.CodedInputStream input)
      throws java.io.IOException {
    return com.google.protobuf.GeneratedMessageV3
        .parseWithIOException(PARSER, input);
  }
  public static Commands parseFrom(
      com.google.protobuf.CodedInputStream input,
      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
      throws java.io.IOException {
    return com.google.protobuf.GeneratedMessageV3
        .parseWithIOException(PARSER, input, extensionRegistry);
  }

  @Override
  public Builder newBuilderForType() { return newBuilder(); }
  public static Builder newBuilder() {
    return DEFAULT_INSTANCE.toBuilder();
  }
  public static Builder newBuilder(Commands prototype) {
    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
  }
  @Override
  public Builder toBuilder() {
    return this == DEFAULT_INSTANCE
        ? new Builder() : new Builder().mergeFrom(this);
  }

  @Override
  protected Builder newBuilderForType(
      BuilderParent parent) {
    Builder builder = new Builder(parent);
    return builder;
  }
  /**
   * Protobuf type {@code org.apache.flink.statefun.e2e.smoke.Commands}
   */
  public static final class Builder extends
      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
      // @@protoc_insertion_point(builder_implements:org.apache.flink.statefun.e2e.smoke.Commands)
      CommandsOrBuilder {
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return CommandsOuterClass.internal_static_org_apache_flink_statefun_e2e_smoke_Commands_descriptor;
    }

    @Override
    protected FieldAccessorTable
        internalGetFieldAccessorTable() {
      return CommandsOuterClass.internal_static_org_apache_flink_statefun_e2e_smoke_Commands_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              Commands.class, Builder.class);
    }

    // Construct using org.apache.flink.statefun.e2e.smoke.generated.Commands.newBuilder()
    private Builder() {
      maybeForceBuilderInitialization();
    }

    private Builder(
        BuilderParent parent) {
      super(parent);
      maybeForceBuilderInitialization();
    }
    private void maybeForceBuilderInitialization() {
      if (com.google.protobuf.GeneratedMessageV3
              .alwaysUseFieldBuilders) {
        getCommandFieldBuilder();
      }
    }
    @Override
    public Builder clear() {
      super.clear();
      if (commandBuilder_ == null) {
        command_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00000001);
      } else {
        commandBuilder_.clear();
      }
      return this;
    }

    @Override
    public com.google.protobuf.Descriptors.Descriptor
        getDescriptorForType() {
      return CommandsOuterClass.internal_static_org_apache_flink_statefun_e2e_smoke_Commands_descriptor;
    }

    @Override
    public Commands getDefaultInstanceForType() {
      return Commands.getDefaultInstance();
    }

    @Override
    public Commands build() {
      Commands result = buildPartial();
      if (!result.isInitialized()) {
        throw newUninitializedMessageException(result);
      }
      return result;
    }

    @Override
    public Commands buildPartial() {
      Commands result = new Commands(this);
      int from_bitField0_ = bitField0_;
      if (commandBuilder_ == null) {
        if (((bitField0_ & 0x00000001) != 0)) {
          command_ = java.util.Collections.unmodifiableList(command_);
          bitField0_ = (bitField0_ & ~0x00000001);
        }
        result.command_ = command_;
      } else {
        result.command_ = commandBuilder_.build();
      }
      onBuilt();
      return result;
    }

    @Override
    public Builder clone() {
      return super.clone();
    }
    @Override
    public Builder setField(
        com.google.protobuf.Descriptors.FieldDescriptor field,
        Object value) {
      return super.setField(field, value);
    }
    @Override
    public Builder clearField(
        com.google.protobuf.Descriptors.FieldDescriptor field) {
      return super.clearField(field);
    }
    @Override
    public Builder clearOneof(
        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
      return super.clearOneof(oneof);
    }
    @Override
    public Builder setRepeatedField(
        com.google.protobuf.Descriptors.FieldDescriptor field,
        int index, Object value) {
      return super.setRepeatedField(field, index, value);
    }
    @Override
    public Builder addRepeatedField(
        com.google.protobuf.Descriptors.FieldDescriptor field,
        Object value) {
      return super.addRepeatedField(field, value);
    }
    @Override
    public Builder mergeFrom(com.google.protobuf.Message other) {
      if (other instanceof Commands) {
        return mergeFrom((Commands)other);
      } else {
        super.mergeFrom(other);
        return this;
      }
    }

    public Builder mergeFrom(Commands other) {
      if (other == Commands.getDefaultInstance()) return this;
      if (commandBuilder_ == null) {
        if (!other.command_.isEmpty()) {
          if (command_.isEmpty()) {
            command_ = other.command_;
            bitField0_ = (bitField0_ & ~0x00000001);
          } else {
            ensureCommandIsMutable();
            command_.addAll(other.command_);
          }
          onChanged();
        }
      } else {
        if (!other.command_.isEmpty()) {
          if (commandBuilder_.isEmpty()) {
            commandBuilder_.dispose();
            commandBuilder_ = null;
            command_ = other.command_;
            bitField0_ = (bitField0_ & ~0x00000001);
            commandBuilder_ = 
              com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
                 getCommandFieldBuilder() : null;
          } else {
            commandBuilder_.addAllMessages(other.command_);
          }
        }
      }
      this.mergeUnknownFields(other.unknownFields);
      onChanged();
      return this;
    }

    @Override
    public final boolean isInitialized() {
      return true;
    }

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

    private java.util.List<Command> command_ =
      java.util.Collections.emptyList();
    private void ensureCommandIsMutable() {
      if (!((bitField0_ & 0x00000001) != 0)) {
        command_ = new java.util.ArrayList<Command>(command_);
        bitField0_ |= 0x00000001;
       }
    }

    private com.google.protobuf.RepeatedFieldBuilderV3<
        Command, Command.Builder, CommandOrBuilder> commandBuilder_;

    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public java.util.List<Command> getCommandList() {
      if (commandBuilder_ == null) {
        return java.util.Collections.unmodifiableList(command_);
      } else {
        return commandBuilder_.getMessageList();
      }
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public int getCommandCount() {
      if (commandBuilder_ == null) {
        return command_.size();
      } else {
        return commandBuilder_.getCount();
      }
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Command getCommand(int index) {
      if (commandBuilder_ == null) {
        return command_.get(index);
      } else {
        return commandBuilder_.getMessage(index);
      }
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder setCommand(
        int index, Command value) {
      if (commandBuilder_ == null) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureCommandIsMutable();
        command_.set(index, value);
        onChanged();
      } else {
        commandBuilder_.setMessage(index, value);
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder setCommand(
        int index, Command.Builder builderForValue) {
      if (commandBuilder_ == null) {
        ensureCommandIsMutable();
        command_.set(index, builderForValue.build());
        onChanged();
      } else {
        commandBuilder_.setMessage(index, builderForValue.build());
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder addCommand(Command value) {
      if (commandBuilder_ == null) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureCommandIsMutable();
        command_.add(value);
        onChanged();
      } else {
        commandBuilder_.addMessage(value);
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder addCommand(
        int index, Command value) {
      if (commandBuilder_ == null) {
        if (value == null) {
          throw new NullPointerException();
        }
        ensureCommandIsMutable();
        command_.add(index, value);
        onChanged();
      } else {
        commandBuilder_.addMessage(index, value);
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder addCommand(
        Command.Builder builderForValue) {
      if (commandBuilder_ == null) {
        ensureCommandIsMutable();
        command_.add(builderForValue.build());
        onChanged();
      } else {
        commandBuilder_.addMessage(builderForValue.build());
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder addCommand(
        int index, Command.Builder builderForValue) {
      if (commandBuilder_ == null) {
        ensureCommandIsMutable();
        command_.add(index, builderForValue.build());
        onChanged();
      } else {
        commandBuilder_.addMessage(index, builderForValue.build());
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder addAllCommand(
        Iterable<? extends Command> values) {
      if (commandBuilder_ == null) {
        ensureCommandIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(
            values, command_);
        onChanged();
      } else {
        commandBuilder_.addAllMessages(values);
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder clearCommand() {
      if (commandBuilder_ == null) {
        command_ = java.util.Collections.emptyList();
        bitField0_ = (bitField0_ & ~0x00000001);
        onChanged();
      } else {
        commandBuilder_.clear();
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Builder removeCommand(int index) {
      if (commandBuilder_ == null) {
        ensureCommandIsMutable();
        command_.remove(index);
        onChanged();
      } else {
        commandBuilder_.remove(index);
      }
      return this;
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Command.Builder getCommandBuilder(
        int index) {
      return getCommandFieldBuilder().getBuilder(index);
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public CommandOrBuilder getCommandOrBuilder(
        int index) {
      if (commandBuilder_ == null) {
        return command_.get(index);  } else {
        return commandBuilder_.getMessageOrBuilder(index);
      }
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public java.util.List<? extends CommandOrBuilder>
         getCommandOrBuilderList() {
      if (commandBuilder_ != null) {
        return commandBuilder_.getMessageOrBuilderList();
      } else {
        return java.util.Collections.unmodifiableList(command_);
      }
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Command.Builder addCommandBuilder() {
      return getCommandFieldBuilder().addBuilder(
          Command.getDefaultInstance());
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public Command.Builder addCommandBuilder(
        int index) {
      return getCommandFieldBuilder().addBuilder(
          index, Command.getDefaultInstance());
    }
    /**
     * <code>repeated .org.apache.flink.statefun.e2e.smoke.Command command = 1;</code>
     */
    public java.util.List<Command.Builder>
         getCommandBuilderList() {
      return getCommandFieldBuilder().getBuilderList();
    }
    private com.google.protobuf.RepeatedFieldBuilderV3<
        Command, Command.Builder, CommandOrBuilder>
        getCommandFieldBuilder() {
      if (commandBuilder_ == null) {
        commandBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
            Command, Command.Builder, CommandOrBuilder>(
                command_,
                ((bitField0_ & 0x00000001) != 0),
                getParentForChildren(),
                isClean());
        command_ = null;
      }
      return commandBuilder_;
    }
    @Override
    public final Builder setUnknownFields(
        final com.google.protobuf.UnknownFieldSet unknownFields) {
      return super.setUnknownFields(unknownFields);
    }

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


    // @@protoc_insertion_point(builder_scope:org.apache.flink.statefun.e2e.smoke.Commands)
  }

  // @@protoc_insertion_point(class_scope:org.apache.flink.statefun.e2e.smoke.Commands)
  private static final Commands DEFAULT_INSTANCE;
  static {
    DEFAULT_INSTANCE = new Commands();
  }

  public static Commands getDefaultInstance() {
    return DEFAULT_INSTANCE;
  }

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

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

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

  @Override
  public Commands getDefaultInstanceForType() {
    return DEFAULT_INSTANCE;
  }

}

