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

package org.apache.slider.api.proto;

public final class Messages {
  private Messages() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
  }
  public interface RoleInstanceStateOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string name = 1;
    /**
     * <code>required string name = 1;</code>
     */
    boolean hasName();
    /**
     * <code>required string name = 1;</code>
     */
    java.lang.String getName();
    /**
     * <code>required string name = 1;</code>
     */
    com.google.protobuf.ByteString
        getNameBytes();

    // optional string role = 2;
    /**
     * <code>optional string role = 2;</code>
     */
    boolean hasRole();
    /**
     * <code>optional string role = 2;</code>
     */
    java.lang.String getRole();
    /**
     * <code>optional string role = 2;</code>
     */
    com.google.protobuf.ByteString
        getRoleBytes();

    // required uint32 state = 4;
    /**
     * <code>required uint32 state = 4;</code>
     */
    boolean hasState();
    /**
     * <code>required uint32 state = 4;</code>
     */
    int getState();

    // required uint32 exitCode = 5;
    /**
     * <code>required uint32 exitCode = 5;</code>
     */
    boolean hasExitCode();
    /**
     * <code>required uint32 exitCode = 5;</code>
     */
    int getExitCode();

    // optional string command = 6;
    /**
     * <code>optional string command = 6;</code>
     */
    boolean hasCommand();
    /**
     * <code>optional string command = 6;</code>
     */
    java.lang.String getCommand();
    /**
     * <code>optional string command = 6;</code>
     */
    com.google.protobuf.ByteString
        getCommandBytes();

    // optional string diagnostics = 7;
    /**
     * <code>optional string diagnostics = 7;</code>
     */
    boolean hasDiagnostics();
    /**
     * <code>optional string diagnostics = 7;</code>
     */
    java.lang.String getDiagnostics();
    /**
     * <code>optional string diagnostics = 7;</code>
     */
    com.google.protobuf.ByteString
        getDiagnosticsBytes();

    // repeated string output = 8;
    /**
     * <code>repeated string output = 8;</code>
     */
    java.util.List<java.lang.String>
    getOutputList();
    /**
     * <code>repeated string output = 8;</code>
     */
    int getOutputCount();
    /**
     * <code>repeated string output = 8;</code>
     */
    java.lang.String getOutput(int index);
    /**
     * <code>repeated string output = 8;</code>
     */
    com.google.protobuf.ByteString
        getOutputBytes(int index);

    // repeated string environment = 9;
    /**
     * <code>repeated string environment = 9;</code>
     */
    java.util.List<java.lang.String>
    getEnvironmentList();
    /**
     * <code>repeated string environment = 9;</code>
     */
    int getEnvironmentCount();
    /**
     * <code>repeated string environment = 9;</code>
     */
    java.lang.String getEnvironment(int index);
    /**
     * <code>repeated string environment = 9;</code>
     */
    com.google.protobuf.ByteString
        getEnvironmentBytes(int index);

    // required uint32 roleId = 10;
    /**
     * <code>required uint32 roleId = 10;</code>
     */
    boolean hasRoleId();
    /**
     * <code>required uint32 roleId = 10;</code>
     */
    int getRoleId();

    // required bool released = 11;
    /**
     * <code>required bool released = 11;</code>
     */
    boolean hasReleased();
    /**
     * <code>required bool released = 11;</code>
     */
    boolean getReleased();

    // required int64 createTime = 12;
    /**
     * <code>required int64 createTime = 12;</code>
     */
    boolean hasCreateTime();
    /**
     * <code>required int64 createTime = 12;</code>
     */
    long getCreateTime();

    // required int64 startTime = 13;
    /**
     * <code>required int64 startTime = 13;</code>
     */
    boolean hasStartTime();
    /**
     * <code>required int64 startTime = 13;</code>
     */
    long getStartTime();

    // required string host = 14;
    /**
     * <code>required string host = 14;</code>
     */
    boolean hasHost();
    /**
     * <code>required string host = 14;</code>
     */
    java.lang.String getHost();
    /**
     * <code>required string host = 14;</code>
     */
    com.google.protobuf.ByteString
        getHostBytes();

    // required string hostURL = 15;
    /**
     * <code>required string hostURL = 15;</code>
     */
    boolean hasHostURL();
    /**
     * <code>required string hostURL = 15;</code>
     */
    java.lang.String getHostURL();
    /**
     * <code>required string hostURL = 15;</code>
     */
    com.google.protobuf.ByteString
        getHostURLBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.RoleInstanceState}
   */
  public static final class RoleInstanceState extends
      com.google.protobuf.GeneratedMessage
      implements RoleInstanceStateOrBuilder {
    // Use RoleInstanceState.newBuilder() to construct.
    private RoleInstanceState(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private RoleInstanceState(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final RoleInstanceState defaultInstance;
    public static RoleInstanceState getDefaultInstance() {
      return defaultInstance;
    }

    public RoleInstanceState getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private RoleInstanceState(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              name_ = input.readBytes();
              break;
            }
            case 18: {
              bitField0_ |= 0x00000002;
              role_ = input.readBytes();
              break;
            }
            case 32: {
              bitField0_ |= 0x00000004;
              state_ = input.readUInt32();
              break;
            }
            case 40: {
              bitField0_ |= 0x00000008;
              exitCode_ = input.readUInt32();
              break;
            }
            case 50: {
              bitField0_ |= 0x00000010;
              command_ = input.readBytes();
              break;
            }
            case 58: {
              bitField0_ |= 0x00000020;
              diagnostics_ = input.readBytes();
              break;
            }
            case 66: {
              if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
                output_ = new com.google.protobuf.LazyStringArrayList();
                mutable_bitField0_ |= 0x00000040;
              }
              output_.add(input.readBytes());
              break;
            }
            case 74: {
              if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
                environment_ = new com.google.protobuf.LazyStringArrayList();
                mutable_bitField0_ |= 0x00000080;
              }
              environment_.add(input.readBytes());
              break;
            }
            case 80: {
              bitField0_ |= 0x00000040;
              roleId_ = input.readUInt32();
              break;
            }
            case 88: {
              bitField0_ |= 0x00000080;
              released_ = input.readBool();
              break;
            }
            case 96: {
              bitField0_ |= 0x00000100;
              createTime_ = input.readInt64();
              break;
            }
            case 104: {
              bitField0_ |= 0x00000200;
              startTime_ = input.readInt64();
              break;
            }
            case 114: {
              bitField0_ |= 0x00000400;
              host_ = input.readBytes();
              break;
            }
            case 122: {
              bitField0_ |= 0x00000800;
              hostURL_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
          output_ = new com.google.protobuf.UnmodifiableLazyStringList(output_);
        }
        if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
          environment_ = new com.google.protobuf.UnmodifiableLazyStringList(environment_);
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_RoleInstanceState_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_RoleInstanceState_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.RoleInstanceState.class, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder.class);
    }

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

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

    private int bitField0_;
    // required string name = 1;
    public static final int NAME_FIELD_NUMBER = 1;
    private java.lang.Object name_;
    /**
     * <code>required string name = 1;</code>
     */
    public boolean hasName() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string name = 1;</code>
     */
    public java.lang.String getName() {
      java.lang.Object ref = name_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          name_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string name = 1;</code>
     */
    public com.google.protobuf.ByteString
        getNameBytes() {
      java.lang.Object ref = name_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        name_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // optional string role = 2;
    public static final int ROLE_FIELD_NUMBER = 2;
    private java.lang.Object role_;
    /**
     * <code>optional string role = 2;</code>
     */
    public boolean hasRole() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>optional string role = 2;</code>
     */
    public java.lang.String getRole() {
      java.lang.Object ref = role_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          role_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string role = 2;</code>
     */
    public com.google.protobuf.ByteString
        getRoleBytes() {
      java.lang.Object ref = role_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        role_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required uint32 state = 4;
    public static final int STATE_FIELD_NUMBER = 4;
    private int state_;
    /**
     * <code>required uint32 state = 4;</code>
     */
    public boolean hasState() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required uint32 state = 4;</code>
     */
    public int getState() {
      return state_;
    }

    // required uint32 exitCode = 5;
    public static final int EXITCODE_FIELD_NUMBER = 5;
    private int exitCode_;
    /**
     * <code>required uint32 exitCode = 5;</code>
     */
    public boolean hasExitCode() {
      return ((bitField0_ & 0x00000008) == 0x00000008);
    }
    /**
     * <code>required uint32 exitCode = 5;</code>
     */
    public int getExitCode() {
      return exitCode_;
    }

    // optional string command = 6;
    public static final int COMMAND_FIELD_NUMBER = 6;
    private java.lang.Object command_;
    /**
     * <code>optional string command = 6;</code>
     */
    public boolean hasCommand() {
      return ((bitField0_ & 0x00000010) == 0x00000010);
    }
    /**
     * <code>optional string command = 6;</code>
     */
    public java.lang.String getCommand() {
      java.lang.Object ref = command_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          command_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string command = 6;</code>
     */
    public com.google.protobuf.ByteString
        getCommandBytes() {
      java.lang.Object ref = command_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        command_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // optional string diagnostics = 7;
    public static final int DIAGNOSTICS_FIELD_NUMBER = 7;
    private java.lang.Object diagnostics_;
    /**
     * <code>optional string diagnostics = 7;</code>
     */
    public boolean hasDiagnostics() {
      return ((bitField0_ & 0x00000020) == 0x00000020);
    }
    /**
     * <code>optional string diagnostics = 7;</code>
     */
    public java.lang.String getDiagnostics() {
      java.lang.Object ref = diagnostics_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          diagnostics_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string diagnostics = 7;</code>
     */
    public com.google.protobuf.ByteString
        getDiagnosticsBytes() {
      java.lang.Object ref = diagnostics_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        diagnostics_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // repeated string output = 8;
    public static final int OUTPUT_FIELD_NUMBER = 8;
    private com.google.protobuf.LazyStringList output_;
    /**
     * <code>repeated string output = 8;</code>
     */
    public java.util.List<java.lang.String>
        getOutputList() {
      return output_;
    }
    /**
     * <code>repeated string output = 8;</code>
     */
    public int getOutputCount() {
      return output_.size();
    }
    /**
     * <code>repeated string output = 8;</code>
     */
    public java.lang.String getOutput(int index) {
      return output_.get(index);
    }
    /**
     * <code>repeated string output = 8;</code>
     */
    public com.google.protobuf.ByteString
        getOutputBytes(int index) {
      return output_.getByteString(index);
    }

    // repeated string environment = 9;
    public static final int ENVIRONMENT_FIELD_NUMBER = 9;
    private com.google.protobuf.LazyStringList environment_;
    /**
     * <code>repeated string environment = 9;</code>
     */
    public java.util.List<java.lang.String>
        getEnvironmentList() {
      return environment_;
    }
    /**
     * <code>repeated string environment = 9;</code>
     */
    public int getEnvironmentCount() {
      return environment_.size();
    }
    /**
     * <code>repeated string environment = 9;</code>
     */
    public java.lang.String getEnvironment(int index) {
      return environment_.get(index);
    }
    /**
     * <code>repeated string environment = 9;</code>
     */
    public com.google.protobuf.ByteString
        getEnvironmentBytes(int index) {
      return environment_.getByteString(index);
    }

    // required uint32 roleId = 10;
    public static final int ROLEID_FIELD_NUMBER = 10;
    private int roleId_;
    /**
     * <code>required uint32 roleId = 10;</code>
     */
    public boolean hasRoleId() {
      return ((bitField0_ & 0x00000040) == 0x00000040);
    }
    /**
     * <code>required uint32 roleId = 10;</code>
     */
    public int getRoleId() {
      return roleId_;
    }

    // required bool released = 11;
    public static final int RELEASED_FIELD_NUMBER = 11;
    private boolean released_;
    /**
     * <code>required bool released = 11;</code>
     */
    public boolean hasReleased() {
      return ((bitField0_ & 0x00000080) == 0x00000080);
    }
    /**
     * <code>required bool released = 11;</code>
     */
    public boolean getReleased() {
      return released_;
    }

    // required int64 createTime = 12;
    public static final int CREATETIME_FIELD_NUMBER = 12;
    private long createTime_;
    /**
     * <code>required int64 createTime = 12;</code>
     */
    public boolean hasCreateTime() {
      return ((bitField0_ & 0x00000100) == 0x00000100);
    }
    /**
     * <code>required int64 createTime = 12;</code>
     */
    public long getCreateTime() {
      return createTime_;
    }

    // required int64 startTime = 13;
    public static final int STARTTIME_FIELD_NUMBER = 13;
    private long startTime_;
    /**
     * <code>required int64 startTime = 13;</code>
     */
    public boolean hasStartTime() {
      return ((bitField0_ & 0x00000200) == 0x00000200);
    }
    /**
     * <code>required int64 startTime = 13;</code>
     */
    public long getStartTime() {
      return startTime_;
    }

    // required string host = 14;
    public static final int HOST_FIELD_NUMBER = 14;
    private java.lang.Object host_;
    /**
     * <code>required string host = 14;</code>
     */
    public boolean hasHost() {
      return ((bitField0_ & 0x00000400) == 0x00000400);
    }
    /**
     * <code>required string host = 14;</code>
     */
    public java.lang.String getHost() {
      java.lang.Object ref = host_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          host_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string host = 14;</code>
     */
    public com.google.protobuf.ByteString
        getHostBytes() {
      java.lang.Object ref = host_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        host_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required string hostURL = 15;
    public static final int HOSTURL_FIELD_NUMBER = 15;
    private java.lang.Object hostURL_;
    /**
     * <code>required string hostURL = 15;</code>
     */
    public boolean hasHostURL() {
      return ((bitField0_ & 0x00000800) == 0x00000800);
    }
    /**
     * <code>required string hostURL = 15;</code>
     */
    public java.lang.String getHostURL() {
      java.lang.Object ref = hostURL_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          hostURL_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string hostURL = 15;</code>
     */
    public com.google.protobuf.ByteString
        getHostURLBytes() {
      java.lang.Object ref = hostURL_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        hostURL_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      name_ = "";
      role_ = "";
      state_ = 0;
      exitCode_ = 0;
      command_ = "";
      diagnostics_ = "";
      output_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      environment_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      roleId_ = 0;
      released_ = false;
      createTime_ = 0L;
      startTime_ = 0L;
      host_ = "";
      hostURL_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasName()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasState()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasExitCode()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasRoleId()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasReleased()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasCreateTime()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasStartTime()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasHost()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasHostURL()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getNameBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeBytes(2, getRoleBytes());
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeUInt32(4, state_);
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        output.writeUInt32(5, exitCode_);
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        output.writeBytes(6, getCommandBytes());
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        output.writeBytes(7, getDiagnosticsBytes());
      }
      for (int i = 0; i < output_.size(); i++) {
        output.writeBytes(8, output_.getByteString(i));
      }
      for (int i = 0; i < environment_.size(); i++) {
        output.writeBytes(9, environment_.getByteString(i));
      }
      if (((bitField0_ & 0x00000040) == 0x00000040)) {
        output.writeUInt32(10, roleId_);
      }
      if (((bitField0_ & 0x00000080) == 0x00000080)) {
        output.writeBool(11, released_);
      }
      if (((bitField0_ & 0x00000100) == 0x00000100)) {
        output.writeInt64(12, createTime_);
      }
      if (((bitField0_ & 0x00000200) == 0x00000200)) {
        output.writeInt64(13, startTime_);
      }
      if (((bitField0_ & 0x00000400) == 0x00000400)) {
        output.writeBytes(14, getHostBytes());
      }
      if (((bitField0_ & 0x00000800) == 0x00000800)) {
        output.writeBytes(15, getHostURLBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getNameBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(2, getRoleBytes());
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeUInt32Size(4, state_);
      }
      if (((bitField0_ & 0x00000008) == 0x00000008)) {
        size += com.google.protobuf.CodedOutputStream
          .computeUInt32Size(5, exitCode_);
      }
      if (((bitField0_ & 0x00000010) == 0x00000010)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(6, getCommandBytes());
      }
      if (((bitField0_ & 0x00000020) == 0x00000020)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(7, getDiagnosticsBytes());
      }
      {
        int dataSize = 0;
        for (int i = 0; i < output_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream
            .computeBytesSizeNoTag(output_.getByteString(i));
        }
        size += dataSize;
        size += 1 * getOutputList().size();
      }
      {
        int dataSize = 0;
        for (int i = 0; i < environment_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream
            .computeBytesSizeNoTag(environment_.getByteString(i));
        }
        size += dataSize;
        size += 1 * getEnvironmentList().size();
      }
      if (((bitField0_ & 0x00000040) == 0x00000040)) {
        size += com.google.protobuf.CodedOutputStream
          .computeUInt32Size(10, roleId_);
      }
      if (((bitField0_ & 0x00000080) == 0x00000080)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(11, released_);
      }
      if (((bitField0_ & 0x00000100) == 0x00000100)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(12, createTime_);
      }
      if (((bitField0_ & 0x00000200) == 0x00000200)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(13, startTime_);
      }
      if (((bitField0_ & 0x00000400) == 0x00000400)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(14, getHostBytes());
      }
      if (((bitField0_ & 0x00000800) == 0x00000800)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(15, getHostURLBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.RoleInstanceState)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.RoleInstanceState other = (org.apache.slider.api.proto.Messages.RoleInstanceState) obj;

      boolean result = true;
      result = result && (hasName() == other.hasName());
      if (hasName()) {
        result = result && getName()
            .equals(other.getName());
      }
      result = result && (hasRole() == other.hasRole());
      if (hasRole()) {
        result = result && getRole()
            .equals(other.getRole());
      }
      result = result && (hasState() == other.hasState());
      if (hasState()) {
        result = result && (getState()
            == other.getState());
      }
      result = result && (hasExitCode() == other.hasExitCode());
      if (hasExitCode()) {
        result = result && (getExitCode()
            == other.getExitCode());
      }
      result = result && (hasCommand() == other.hasCommand());
      if (hasCommand()) {
        result = result && getCommand()
            .equals(other.getCommand());
      }
      result = result && (hasDiagnostics() == other.hasDiagnostics());
      if (hasDiagnostics()) {
        result = result && getDiagnostics()
            .equals(other.getDiagnostics());
      }
      result = result && getOutputList()
          .equals(other.getOutputList());
      result = result && getEnvironmentList()
          .equals(other.getEnvironmentList());
      result = result && (hasRoleId() == other.hasRoleId());
      if (hasRoleId()) {
        result = result && (getRoleId()
            == other.getRoleId());
      }
      result = result && (hasReleased() == other.hasReleased());
      if (hasReleased()) {
        result = result && (getReleased()
            == other.getReleased());
      }
      result = result && (hasCreateTime() == other.hasCreateTime());
      if (hasCreateTime()) {
        result = result && (getCreateTime()
            == other.getCreateTime());
      }
      result = result && (hasStartTime() == other.hasStartTime());
      if (hasStartTime()) {
        result = result && (getStartTime()
            == other.getStartTime());
      }
      result = result && (hasHost() == other.hasHost());
      if (hasHost()) {
        result = result && getHost()
            .equals(other.getHost());
      }
      result = result && (hasHostURL() == other.hasHostURL());
      if (hasHostURL()) {
        result = result && getHostURL()
            .equals(other.getHostURL());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasName()) {
        hash = (37 * hash) + NAME_FIELD_NUMBER;
        hash = (53 * hash) + getName().hashCode();
      }
      if (hasRole()) {
        hash = (37 * hash) + ROLE_FIELD_NUMBER;
        hash = (53 * hash) + getRole().hashCode();
      }
      if (hasState()) {
        hash = (37 * hash) + STATE_FIELD_NUMBER;
        hash = (53 * hash) + getState();
      }
      if (hasExitCode()) {
        hash = (37 * hash) + EXITCODE_FIELD_NUMBER;
        hash = (53 * hash) + getExitCode();
      }
      if (hasCommand()) {
        hash = (37 * hash) + COMMAND_FIELD_NUMBER;
        hash = (53 * hash) + getCommand().hashCode();
      }
      if (hasDiagnostics()) {
        hash = (37 * hash) + DIAGNOSTICS_FIELD_NUMBER;
        hash = (53 * hash) + getDiagnostics().hashCode();
      }
      if (getOutputCount() > 0) {
        hash = (37 * hash) + OUTPUT_FIELD_NUMBER;
        hash = (53 * hash) + getOutputList().hashCode();
      }
      if (getEnvironmentCount() > 0) {
        hash = (37 * hash) + ENVIRONMENT_FIELD_NUMBER;
        hash = (53 * hash) + getEnvironmentList().hashCode();
      }
      if (hasRoleId()) {
        hash = (37 * hash) + ROLEID_FIELD_NUMBER;
        hash = (53 * hash) + getRoleId();
      }
      if (hasReleased()) {
        hash = (37 * hash) + RELEASED_FIELD_NUMBER;
        hash = (53 * hash) + hashBoolean(getReleased());
      }
      if (hasCreateTime()) {
        hash = (37 * hash) + CREATETIME_FIELD_NUMBER;
        hash = (53 * hash) + hashLong(getCreateTime());
      }
      if (hasStartTime()) {
        hash = (37 * hash) + STARTTIME_FIELD_NUMBER;
        hash = (53 * hash) + hashLong(getStartTime());
      }
      if (hasHost()) {
        hash = (37 * hash) + HOST_FIELD_NUMBER;
        hash = (53 * hash) + getHost().hashCode();
      }
      if (hasHostURL()) {
        hash = (37 * hash) + HOSTURL_FIELD_NUMBER;
        hash = (53 * hash) + getHostURL().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState 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.slider.api.proto.Messages.RoleInstanceState parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.RoleInstanceState parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.RoleInstanceState prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.RoleInstanceState}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_RoleInstanceState_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_RoleInstanceState_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.RoleInstanceState.class, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.RoleInstanceState.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        name_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        role_ = "";
        bitField0_ = (bitField0_ & ~0x00000002);
        state_ = 0;
        bitField0_ = (bitField0_ & ~0x00000004);
        exitCode_ = 0;
        bitField0_ = (bitField0_ & ~0x00000008);
        command_ = "";
        bitField0_ = (bitField0_ & ~0x00000010);
        diagnostics_ = "";
        bitField0_ = (bitField0_ & ~0x00000020);
        output_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000040);
        environment_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000080);
        roleId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000100);
        released_ = false;
        bitField0_ = (bitField0_ & ~0x00000200);
        createTime_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000400);
        startTime_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000800);
        host_ = "";
        bitField0_ = (bitField0_ & ~0x00001000);
        hostURL_ = "";
        bitField0_ = (bitField0_ & ~0x00002000);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_RoleInstanceState_descriptor;
      }

      public org.apache.slider.api.proto.Messages.RoleInstanceState getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.RoleInstanceState build() {
        org.apache.slider.api.proto.Messages.RoleInstanceState result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.RoleInstanceState buildPartial() {
        org.apache.slider.api.proto.Messages.RoleInstanceState result = new org.apache.slider.api.proto.Messages.RoleInstanceState(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.name_ = name_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.role_ = role_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.state_ = state_;
        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
          to_bitField0_ |= 0x00000008;
        }
        result.exitCode_ = exitCode_;
        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
          to_bitField0_ |= 0x00000010;
        }
        result.command_ = command_;
        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
          to_bitField0_ |= 0x00000020;
        }
        result.diagnostics_ = diagnostics_;
        if (((bitField0_ & 0x00000040) == 0x00000040)) {
          output_ = new com.google.protobuf.UnmodifiableLazyStringList(
              output_);
          bitField0_ = (bitField0_ & ~0x00000040);
        }
        result.output_ = output_;
        if (((bitField0_ & 0x00000080) == 0x00000080)) {
          environment_ = new com.google.protobuf.UnmodifiableLazyStringList(
              environment_);
          bitField0_ = (bitField0_ & ~0x00000080);
        }
        result.environment_ = environment_;
        if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
          to_bitField0_ |= 0x00000040;
        }
        result.roleId_ = roleId_;
        if (((from_bitField0_ & 0x00000200) == 0x00000200)) {
          to_bitField0_ |= 0x00000080;
        }
        result.released_ = released_;
        if (((from_bitField0_ & 0x00000400) == 0x00000400)) {
          to_bitField0_ |= 0x00000100;
        }
        result.createTime_ = createTime_;
        if (((from_bitField0_ & 0x00000800) == 0x00000800)) {
          to_bitField0_ |= 0x00000200;
        }
        result.startTime_ = startTime_;
        if (((from_bitField0_ & 0x00001000) == 0x00001000)) {
          to_bitField0_ |= 0x00000400;
        }
        result.host_ = host_;
        if (((from_bitField0_ & 0x00002000) == 0x00002000)) {
          to_bitField0_ |= 0x00000800;
        }
        result.hostURL_ = hostURL_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.RoleInstanceState) {
          return mergeFrom((org.apache.slider.api.proto.Messages.RoleInstanceState)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.RoleInstanceState other) {
        if (other == org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance()) return this;
        if (other.hasName()) {
          bitField0_ |= 0x00000001;
          name_ = other.name_;
          onChanged();
        }
        if (other.hasRole()) {
          bitField0_ |= 0x00000002;
          role_ = other.role_;
          onChanged();
        }
        if (other.hasState()) {
          setState(other.getState());
        }
        if (other.hasExitCode()) {
          setExitCode(other.getExitCode());
        }
        if (other.hasCommand()) {
          bitField0_ |= 0x00000010;
          command_ = other.command_;
          onChanged();
        }
        if (other.hasDiagnostics()) {
          bitField0_ |= 0x00000020;
          diagnostics_ = other.diagnostics_;
          onChanged();
        }
        if (!other.output_.isEmpty()) {
          if (output_.isEmpty()) {
            output_ = other.output_;
            bitField0_ = (bitField0_ & ~0x00000040);
          } else {
            ensureOutputIsMutable();
            output_.addAll(other.output_);
          }
          onChanged();
        }
        if (!other.environment_.isEmpty()) {
          if (environment_.isEmpty()) {
            environment_ = other.environment_;
            bitField0_ = (bitField0_ & ~0x00000080);
          } else {
            ensureEnvironmentIsMutable();
            environment_.addAll(other.environment_);
          }
          onChanged();
        }
        if (other.hasRoleId()) {
          setRoleId(other.getRoleId());
        }
        if (other.hasReleased()) {
          setReleased(other.getReleased());
        }
        if (other.hasCreateTime()) {
          setCreateTime(other.getCreateTime());
        }
        if (other.hasStartTime()) {
          setStartTime(other.getStartTime());
        }
        if (other.hasHost()) {
          bitField0_ |= 0x00001000;
          host_ = other.host_;
          onChanged();
        }
        if (other.hasHostURL()) {
          bitField0_ |= 0x00002000;
          hostURL_ = other.hostURL_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasName()) {
          
          return false;
        }
        if (!hasState()) {
          
          return false;
        }
        if (!hasExitCode()) {
          
          return false;
        }
        if (!hasRoleId()) {
          
          return false;
        }
        if (!hasReleased()) {
          
          return false;
        }
        if (!hasCreateTime()) {
          
          return false;
        }
        if (!hasStartTime()) {
          
          return false;
        }
        if (!hasHost()) {
          
          return false;
        }
        if (!hasHostURL()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.RoleInstanceState parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.RoleInstanceState) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string name = 1;
      private java.lang.Object name_ = "";
      /**
       * <code>required string name = 1;</code>
       */
      public boolean hasName() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string name = 1;</code>
       */
      public java.lang.String getName() {
        java.lang.Object ref = name_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          name_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string name = 1;</code>
       */
      public com.google.protobuf.ByteString
          getNameBytes() {
        java.lang.Object ref = name_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          name_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string name = 1;</code>
       */
      public Builder setName(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        name_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string name = 1;</code>
       */
      public Builder clearName() {
        bitField0_ = (bitField0_ & ~0x00000001);
        name_ = getDefaultInstance().getName();
        onChanged();
        return this;
      }
      /**
       * <code>required string name = 1;</code>
       */
      public Builder setNameBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        name_ = value;
        onChanged();
        return this;
      }

      // optional string role = 2;
      private java.lang.Object role_ = "";
      /**
       * <code>optional string role = 2;</code>
       */
      public boolean hasRole() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>optional string role = 2;</code>
       */
      public java.lang.String getRole() {
        java.lang.Object ref = role_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          role_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string role = 2;</code>
       */
      public com.google.protobuf.ByteString
          getRoleBytes() {
        java.lang.Object ref = role_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          role_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string role = 2;</code>
       */
      public Builder setRole(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000002;
        role_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string role = 2;</code>
       */
      public Builder clearRole() {
        bitField0_ = (bitField0_ & ~0x00000002);
        role_ = getDefaultInstance().getRole();
        onChanged();
        return this;
      }
      /**
       * <code>optional string role = 2;</code>
       */
      public Builder setRoleBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000002;
        role_ = value;
        onChanged();
        return this;
      }

      // required uint32 state = 4;
      private int state_ ;
      /**
       * <code>required uint32 state = 4;</code>
       */
      public boolean hasState() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required uint32 state = 4;</code>
       */
      public int getState() {
        return state_;
      }
      /**
       * <code>required uint32 state = 4;</code>
       */
      public Builder setState(int value) {
        bitField0_ |= 0x00000004;
        state_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required uint32 state = 4;</code>
       */
      public Builder clearState() {
        bitField0_ = (bitField0_ & ~0x00000004);
        state_ = 0;
        onChanged();
        return this;
      }

      // required uint32 exitCode = 5;
      private int exitCode_ ;
      /**
       * <code>required uint32 exitCode = 5;</code>
       */
      public boolean hasExitCode() {
        return ((bitField0_ & 0x00000008) == 0x00000008);
      }
      /**
       * <code>required uint32 exitCode = 5;</code>
       */
      public int getExitCode() {
        return exitCode_;
      }
      /**
       * <code>required uint32 exitCode = 5;</code>
       */
      public Builder setExitCode(int value) {
        bitField0_ |= 0x00000008;
        exitCode_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required uint32 exitCode = 5;</code>
       */
      public Builder clearExitCode() {
        bitField0_ = (bitField0_ & ~0x00000008);
        exitCode_ = 0;
        onChanged();
        return this;
      }

      // optional string command = 6;
      private java.lang.Object command_ = "";
      /**
       * <code>optional string command = 6;</code>
       */
      public boolean hasCommand() {
        return ((bitField0_ & 0x00000010) == 0x00000010);
      }
      /**
       * <code>optional string command = 6;</code>
       */
      public java.lang.String getCommand() {
        java.lang.Object ref = command_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          command_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string command = 6;</code>
       */
      public com.google.protobuf.ByteString
          getCommandBytes() {
        java.lang.Object ref = command_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          command_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string command = 6;</code>
       */
      public Builder setCommand(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000010;
        command_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string command = 6;</code>
       */
      public Builder clearCommand() {
        bitField0_ = (bitField0_ & ~0x00000010);
        command_ = getDefaultInstance().getCommand();
        onChanged();
        return this;
      }
      /**
       * <code>optional string command = 6;</code>
       */
      public Builder setCommandBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000010;
        command_ = value;
        onChanged();
        return this;
      }

      // optional string diagnostics = 7;
      private java.lang.Object diagnostics_ = "";
      /**
       * <code>optional string diagnostics = 7;</code>
       */
      public boolean hasDiagnostics() {
        return ((bitField0_ & 0x00000020) == 0x00000020);
      }
      /**
       * <code>optional string diagnostics = 7;</code>
       */
      public java.lang.String getDiagnostics() {
        java.lang.Object ref = diagnostics_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          diagnostics_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string diagnostics = 7;</code>
       */
      public com.google.protobuf.ByteString
          getDiagnosticsBytes() {
        java.lang.Object ref = diagnostics_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          diagnostics_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string diagnostics = 7;</code>
       */
      public Builder setDiagnostics(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        diagnostics_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string diagnostics = 7;</code>
       */
      public Builder clearDiagnostics() {
        bitField0_ = (bitField0_ & ~0x00000020);
        diagnostics_ = getDefaultInstance().getDiagnostics();
        onChanged();
        return this;
      }
      /**
       * <code>optional string diagnostics = 7;</code>
       */
      public Builder setDiagnosticsBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        diagnostics_ = value;
        onChanged();
        return this;
      }

      // repeated string output = 8;
      private com.google.protobuf.LazyStringList output_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureOutputIsMutable() {
        if (!((bitField0_ & 0x00000040) == 0x00000040)) {
          output_ = new com.google.protobuf.LazyStringArrayList(output_);
          bitField0_ |= 0x00000040;
         }
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public java.util.List<java.lang.String>
          getOutputList() {
        return java.util.Collections.unmodifiableList(output_);
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public int getOutputCount() {
        return output_.size();
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public java.lang.String getOutput(int index) {
        return output_.get(index);
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public com.google.protobuf.ByteString
          getOutputBytes(int index) {
        return output_.getByteString(index);
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public Builder setOutput(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureOutputIsMutable();
        output_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public Builder addOutput(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureOutputIsMutable();
        output_.add(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public Builder addAllOutput(
          java.lang.Iterable<java.lang.String> values) {
        ensureOutputIsMutable();
        super.addAll(values, output_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public Builder clearOutput() {
        output_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000040);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string output = 8;</code>
       */
      public Builder addOutputBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureOutputIsMutable();
        output_.add(value);
        onChanged();
        return this;
      }

      // repeated string environment = 9;
      private com.google.protobuf.LazyStringList environment_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureEnvironmentIsMutable() {
        if (!((bitField0_ & 0x00000080) == 0x00000080)) {
          environment_ = new com.google.protobuf.LazyStringArrayList(environment_);
          bitField0_ |= 0x00000080;
         }
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public java.util.List<java.lang.String>
          getEnvironmentList() {
        return java.util.Collections.unmodifiableList(environment_);
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public int getEnvironmentCount() {
        return environment_.size();
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public java.lang.String getEnvironment(int index) {
        return environment_.get(index);
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public com.google.protobuf.ByteString
          getEnvironmentBytes(int index) {
        return environment_.getByteString(index);
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public Builder setEnvironment(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureEnvironmentIsMutable();
        environment_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public Builder addEnvironment(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureEnvironmentIsMutable();
        environment_.add(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public Builder addAllEnvironment(
          java.lang.Iterable<java.lang.String> values) {
        ensureEnvironmentIsMutable();
        super.addAll(values, environment_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public Builder clearEnvironment() {
        environment_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000080);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string environment = 9;</code>
       */
      public Builder addEnvironmentBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureEnvironmentIsMutable();
        environment_.add(value);
        onChanged();
        return this;
      }

      // required uint32 roleId = 10;
      private int roleId_ ;
      /**
       * <code>required uint32 roleId = 10;</code>
       */
      public boolean hasRoleId() {
        return ((bitField0_ & 0x00000100) == 0x00000100);
      }
      /**
       * <code>required uint32 roleId = 10;</code>
       */
      public int getRoleId() {
        return roleId_;
      }
      /**
       * <code>required uint32 roleId = 10;</code>
       */
      public Builder setRoleId(int value) {
        bitField0_ |= 0x00000100;
        roleId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required uint32 roleId = 10;</code>
       */
      public Builder clearRoleId() {
        bitField0_ = (bitField0_ & ~0x00000100);
        roleId_ = 0;
        onChanged();
        return this;
      }

      // required bool released = 11;
      private boolean released_ ;
      /**
       * <code>required bool released = 11;</code>
       */
      public boolean hasReleased() {
        return ((bitField0_ & 0x00000200) == 0x00000200);
      }
      /**
       * <code>required bool released = 11;</code>
       */
      public boolean getReleased() {
        return released_;
      }
      /**
       * <code>required bool released = 11;</code>
       */
      public Builder setReleased(boolean value) {
        bitField0_ |= 0x00000200;
        released_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bool released = 11;</code>
       */
      public Builder clearReleased() {
        bitField0_ = (bitField0_ & ~0x00000200);
        released_ = false;
        onChanged();
        return this;
      }

      // required int64 createTime = 12;
      private long createTime_ ;
      /**
       * <code>required int64 createTime = 12;</code>
       */
      public boolean hasCreateTime() {
        return ((bitField0_ & 0x00000400) == 0x00000400);
      }
      /**
       * <code>required int64 createTime = 12;</code>
       */
      public long getCreateTime() {
        return createTime_;
      }
      /**
       * <code>required int64 createTime = 12;</code>
       */
      public Builder setCreateTime(long value) {
        bitField0_ |= 0x00000400;
        createTime_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 createTime = 12;</code>
       */
      public Builder clearCreateTime() {
        bitField0_ = (bitField0_ & ~0x00000400);
        createTime_ = 0L;
        onChanged();
        return this;
      }

      // required int64 startTime = 13;
      private long startTime_ ;
      /**
       * <code>required int64 startTime = 13;</code>
       */
      public boolean hasStartTime() {
        return ((bitField0_ & 0x00000800) == 0x00000800);
      }
      /**
       * <code>required int64 startTime = 13;</code>
       */
      public long getStartTime() {
        return startTime_;
      }
      /**
       * <code>required int64 startTime = 13;</code>
       */
      public Builder setStartTime(long value) {
        bitField0_ |= 0x00000800;
        startTime_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int64 startTime = 13;</code>
       */
      public Builder clearStartTime() {
        bitField0_ = (bitField0_ & ~0x00000800);
        startTime_ = 0L;
        onChanged();
        return this;
      }

      // required string host = 14;
      private java.lang.Object host_ = "";
      /**
       * <code>required string host = 14;</code>
       */
      public boolean hasHost() {
        return ((bitField0_ & 0x00001000) == 0x00001000);
      }
      /**
       * <code>required string host = 14;</code>
       */
      public java.lang.String getHost() {
        java.lang.Object ref = host_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          host_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string host = 14;</code>
       */
      public com.google.protobuf.ByteString
          getHostBytes() {
        java.lang.Object ref = host_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          host_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string host = 14;</code>
       */
      public Builder setHost(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00001000;
        host_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string host = 14;</code>
       */
      public Builder clearHost() {
        bitField0_ = (bitField0_ & ~0x00001000);
        host_ = getDefaultInstance().getHost();
        onChanged();
        return this;
      }
      /**
       * <code>required string host = 14;</code>
       */
      public Builder setHostBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00001000;
        host_ = value;
        onChanged();
        return this;
      }

      // required string hostURL = 15;
      private java.lang.Object hostURL_ = "";
      /**
       * <code>required string hostURL = 15;</code>
       */
      public boolean hasHostURL() {
        return ((bitField0_ & 0x00002000) == 0x00002000);
      }
      /**
       * <code>required string hostURL = 15;</code>
       */
      public java.lang.String getHostURL() {
        java.lang.Object ref = hostURL_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          hostURL_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string hostURL = 15;</code>
       */
      public com.google.protobuf.ByteString
          getHostURLBytes() {
        java.lang.Object ref = hostURL_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          hostURL_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string hostURL = 15;</code>
       */
      public Builder setHostURL(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00002000;
        hostURL_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string hostURL = 15;</code>
       */
      public Builder clearHostURL() {
        bitField0_ = (bitField0_ & ~0x00002000);
        hostURL_ = getDefaultInstance().getHostURL();
        onChanged();
        return this;
      }
      /**
       * <code>required string hostURL = 15;</code>
       */
      public Builder setHostURLBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00002000;
        hostURL_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.RoleInstanceState)
    }

    static {
      defaultInstance = new RoleInstanceState(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.RoleInstanceState)
  }

  public interface StopClusterRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string message = 1;
    /**
     * <code>required string message = 1;</code>
     *
     * <pre>
     **
     *message to include
     * </pre>
     */
    boolean hasMessage();
    /**
     * <code>required string message = 1;</code>
     *
     * <pre>
     **
     *message to include
     * </pre>
     */
    java.lang.String getMessage();
    /**
     * <code>required string message = 1;</code>
     *
     * <pre>
     **
     *message to include
     * </pre>
     */
    com.google.protobuf.ByteString
        getMessageBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.StopClusterRequestProto}
   *
   * <pre>
   **
   * stop the cluster
   * </pre>
   */
  public static final class StopClusterRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements StopClusterRequestProtoOrBuilder {
    // Use StopClusterRequestProto.newBuilder() to construct.
    private StopClusterRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private StopClusterRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final StopClusterRequestProto defaultInstance;
    public static StopClusterRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public StopClusterRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private StopClusterRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              message_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.StopClusterRequestProto.class, org.apache.slider.api.proto.Messages.StopClusterRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string message = 1;
    public static final int MESSAGE_FIELD_NUMBER = 1;
    private java.lang.Object message_;
    /**
     * <code>required string message = 1;</code>
     *
     * <pre>
     **
     *message to include
     * </pre>
     */
    public boolean hasMessage() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string message = 1;</code>
     *
     * <pre>
     **
     *message to include
     * </pre>
     */
    public java.lang.String getMessage() {
      java.lang.Object ref = message_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          message_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string message = 1;</code>
     *
     * <pre>
     **
     *message to include
     * </pre>
     */
    public com.google.protobuf.ByteString
        getMessageBytes() {
      java.lang.Object ref = message_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        message_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      message_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getMessageBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getMessageBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.StopClusterRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.StopClusterRequestProto other = (org.apache.slider.api.proto.Messages.StopClusterRequestProto) obj;

      boolean result = true;
      result = result && (hasMessage() == other.hasMessage());
      if (hasMessage()) {
        result = result && getMessage()
            .equals(other.getMessage());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasMessage()) {
        hash = (37 * hash) + MESSAGE_FIELD_NUMBER;
        hash = (53 * hash) + getMessage().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto 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.slider.api.proto.Messages.StopClusterRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.StopClusterRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.StopClusterRequestProto}
     *
     * <pre>
     **
     * stop the cluster
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.StopClusterRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.StopClusterRequestProto.class, org.apache.slider.api.proto.Messages.StopClusterRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.StopClusterRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        message_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.StopClusterRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.StopClusterRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.StopClusterRequestProto build() {
        org.apache.slider.api.proto.Messages.StopClusterRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.StopClusterRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.StopClusterRequestProto result = new org.apache.slider.api.proto.Messages.StopClusterRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.message_ = message_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.StopClusterRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.StopClusterRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.StopClusterRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.StopClusterRequestProto.getDefaultInstance()) return this;
        if (other.hasMessage()) {
          bitField0_ |= 0x00000001;
          message_ = other.message_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasMessage()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.StopClusterRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.StopClusterRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string message = 1;
      private java.lang.Object message_ = "";
      /**
       * <code>required string message = 1;</code>
       *
       * <pre>
       **
       *message to include
       * </pre>
       */
      public boolean hasMessage() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string message = 1;</code>
       *
       * <pre>
       **
       *message to include
       * </pre>
       */
      public java.lang.String getMessage() {
        java.lang.Object ref = message_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          message_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string message = 1;</code>
       *
       * <pre>
       **
       *message to include
       * </pre>
       */
      public com.google.protobuf.ByteString
          getMessageBytes() {
        java.lang.Object ref = message_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          message_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string message = 1;</code>
       *
       * <pre>
       **
       *message to include
       * </pre>
       */
      public Builder setMessage(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        message_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string message = 1;</code>
       *
       * <pre>
       **
       *message to include
       * </pre>
       */
      public Builder clearMessage() {
        bitField0_ = (bitField0_ & ~0x00000001);
        message_ = getDefaultInstance().getMessage();
        onChanged();
        return this;
      }
      /**
       * <code>required string message = 1;</code>
       *
       * <pre>
       **
       *message to include
       * </pre>
       */
      public Builder setMessageBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        message_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.StopClusterRequestProto)
    }

    static {
      defaultInstance = new StopClusterRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.StopClusterRequestProto)
  }

  public interface StopClusterResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {
  }
  /**
   * Protobuf type {@code org.apache.slider.api.StopClusterResponseProto}
   *
   * <pre>
   **
   * stop the cluster
   * </pre>
   */
  public static final class StopClusterResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements StopClusterResponseProtoOrBuilder {
    // Use StopClusterResponseProto.newBuilder() to construct.
    private StopClusterResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private StopClusterResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final StopClusterResponseProto defaultInstance;
    public static StopClusterResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public StopClusterResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private StopClusterResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            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.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.StopClusterResponseProto.class, org.apache.slider.api.proto.Messages.StopClusterResponseProto.Builder.class);
    }

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

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

    private void initFields() {
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.StopClusterResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.StopClusterResponseProto other = (org.apache.slider.api.proto.Messages.StopClusterResponseProto) obj;

      boolean result = true;
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto 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.slider.api.proto.Messages.StopClusterResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.StopClusterResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.StopClusterResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.StopClusterResponseProto}
     *
     * <pre>
     **
     * stop the cluster
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.StopClusterResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.StopClusterResponseProto.class, org.apache.slider.api.proto.Messages.StopClusterResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.StopClusterResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_StopClusterResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.StopClusterResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.StopClusterResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.StopClusterResponseProto build() {
        org.apache.slider.api.proto.Messages.StopClusterResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.StopClusterResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.StopClusterResponseProto result = new org.apache.slider.api.proto.Messages.StopClusterResponseProto(this);
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.StopClusterResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.StopClusterResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.StopClusterResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.StopClusterResponseProto.getDefaultInstance()) return this;
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.StopClusterResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.StopClusterResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.StopClusterResponseProto)
    }

    static {
      defaultInstance = new StopClusterResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.StopClusterResponseProto)
  }

  public interface FlexClusterRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string clusterSpec = 1;
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    boolean hasClusterSpec();
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    java.lang.String getClusterSpec();
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    com.google.protobuf.ByteString
        getClusterSpecBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.FlexClusterRequestProto}
   *
   * <pre>
   **
   * flex the cluster
   * </pre>
   */
  public static final class FlexClusterRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements FlexClusterRequestProtoOrBuilder {
    // Use FlexClusterRequestProto.newBuilder() to construct.
    private FlexClusterRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private FlexClusterRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final FlexClusterRequestProto defaultInstance;
    public static FlexClusterRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public FlexClusterRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private FlexClusterRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              clusterSpec_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.FlexClusterRequestProto.class, org.apache.slider.api.proto.Messages.FlexClusterRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string clusterSpec = 1;
    public static final int CLUSTERSPEC_FIELD_NUMBER = 1;
    private java.lang.Object clusterSpec_;
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    public boolean hasClusterSpec() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    public java.lang.String getClusterSpec() {
      java.lang.Object ref = clusterSpec_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          clusterSpec_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    public com.google.protobuf.ByteString
        getClusterSpecBytes() {
      java.lang.Object ref = clusterSpec_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        clusterSpec_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      clusterSpec_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getClusterSpecBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getClusterSpecBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.FlexClusterRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.FlexClusterRequestProto other = (org.apache.slider.api.proto.Messages.FlexClusterRequestProto) obj;

      boolean result = true;
      result = result && (hasClusterSpec() == other.hasClusterSpec());
      if (hasClusterSpec()) {
        result = result && getClusterSpec()
            .equals(other.getClusterSpec());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasClusterSpec()) {
        hash = (37 * hash) + CLUSTERSPEC_FIELD_NUMBER;
        hash = (53 * hash) + getClusterSpec().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto 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.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.FlexClusterRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.FlexClusterRequestProto}
     *
     * <pre>
     **
     * flex the cluster
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.FlexClusterRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.FlexClusterRequestProto.class, org.apache.slider.api.proto.Messages.FlexClusterRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.FlexClusterRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        clusterSpec_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.FlexClusterRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.FlexClusterRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.FlexClusterRequestProto build() {
        org.apache.slider.api.proto.Messages.FlexClusterRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.FlexClusterRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.FlexClusterRequestProto result = new org.apache.slider.api.proto.Messages.FlexClusterRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.clusterSpec_ = clusterSpec_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.FlexClusterRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.FlexClusterRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.FlexClusterRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.FlexClusterRequestProto.getDefaultInstance()) return this;
        if (other.hasClusterSpec()) {
          bitField0_ |= 0x00000001;
          clusterSpec_ = other.clusterSpec_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasClusterSpec()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.FlexClusterRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.FlexClusterRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string clusterSpec = 1;
      private java.lang.Object clusterSpec_ = "";
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public boolean hasClusterSpec() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public java.lang.String getClusterSpec() {
        java.lang.Object ref = clusterSpec_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          clusterSpec_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public com.google.protobuf.ByteString
          getClusterSpecBytes() {
        java.lang.Object ref = clusterSpec_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          clusterSpec_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public Builder setClusterSpec(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        clusterSpec_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public Builder clearClusterSpec() {
        bitField0_ = (bitField0_ & ~0x00000001);
        clusterSpec_ = getDefaultInstance().getClusterSpec();
        onChanged();
        return this;
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public Builder setClusterSpecBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        clusterSpec_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.FlexClusterRequestProto)
    }

    static {
      defaultInstance = new FlexClusterRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.FlexClusterRequestProto)
  }

  public interface FlexClusterResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required bool response = 1;
    /**
     * <code>required bool response = 1;</code>
     */
    boolean hasResponse();
    /**
     * <code>required bool response = 1;</code>
     */
    boolean getResponse();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.FlexClusterResponseProto}
   *
   * <pre>
   **
   * stop the cluster
   * </pre>
   */
  public static final class FlexClusterResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements FlexClusterResponseProtoOrBuilder {
    // Use FlexClusterResponseProto.newBuilder() to construct.
    private FlexClusterResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private FlexClusterResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final FlexClusterResponseProto defaultInstance;
    public static FlexClusterResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public FlexClusterResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private FlexClusterResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              response_ = input.readBool();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.FlexClusterResponseProto.class, org.apache.slider.api.proto.Messages.FlexClusterResponseProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required bool response = 1;
    public static final int RESPONSE_FIELD_NUMBER = 1;
    private boolean response_;
    /**
     * <code>required bool response = 1;</code>
     */
    public boolean hasResponse() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required bool response = 1;</code>
     */
    public boolean getResponse() {
      return response_;
    }

    private void initFields() {
      response_ = false;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBool(1, response_);
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(1, response_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.FlexClusterResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.FlexClusterResponseProto other = (org.apache.slider.api.proto.Messages.FlexClusterResponseProto) obj;

      boolean result = true;
      result = result && (hasResponse() == other.hasResponse());
      if (hasResponse()) {
        result = result && (getResponse()
            == other.getResponse());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasResponse()) {
        hash = (37 * hash) + RESPONSE_FIELD_NUMBER;
        hash = (53 * hash) + hashBoolean(getResponse());
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto 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.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.FlexClusterResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.FlexClusterResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.FlexClusterResponseProto}
     *
     * <pre>
     **
     * stop the cluster
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.FlexClusterResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.FlexClusterResponseProto.class, org.apache.slider.api.proto.Messages.FlexClusterResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.FlexClusterResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        response_ = false;
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_FlexClusterResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.FlexClusterResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.FlexClusterResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.FlexClusterResponseProto build() {
        org.apache.slider.api.proto.Messages.FlexClusterResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.FlexClusterResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.FlexClusterResponseProto result = new org.apache.slider.api.proto.Messages.FlexClusterResponseProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.response_ = response_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.FlexClusterResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.FlexClusterResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.FlexClusterResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.FlexClusterResponseProto.getDefaultInstance()) return this;
        if (other.hasResponse()) {
          setResponse(other.getResponse());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasResponse()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.FlexClusterResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.FlexClusterResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required bool response = 1;
      private boolean response_ ;
      /**
       * <code>required bool response = 1;</code>
       */
      public boolean hasResponse() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required bool response = 1;</code>
       */
      public boolean getResponse() {
        return response_;
      }
      /**
       * <code>required bool response = 1;</code>
       */
      public Builder setResponse(boolean value) {
        bitField0_ |= 0x00000001;
        response_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bool response = 1;</code>
       */
      public Builder clearResponse() {
        bitField0_ = (bitField0_ & ~0x00000001);
        response_ = false;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.FlexClusterResponseProto)
    }

    static {
      defaultInstance = new FlexClusterResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.FlexClusterResponseProto)
  }

  public interface GetJSONClusterStatusRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetJSONClusterStatusRequestProto}
   *
   * <pre>
   **
   * void request
   * </pre>
   */
  public static final class GetJSONClusterStatusRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements GetJSONClusterStatusRequestProtoOrBuilder {
    // Use GetJSONClusterStatusRequestProto.newBuilder() to construct.
    private GetJSONClusterStatusRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetJSONClusterStatusRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetJSONClusterStatusRequestProto defaultInstance;
    public static GetJSONClusterStatusRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetJSONClusterStatusRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetJSONClusterStatusRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            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.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.class, org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.Builder.class);
    }

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

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

    private void initFields() {
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto other = (org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto) obj;

      boolean result = true;
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto 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.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetJSONClusterStatusRequestProto}
     *
     * <pre>
     **
     * void request
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.class, org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto build() {
        org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto result = new org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto(this);
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto.getDefaultInstance()) return this;
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetJSONClusterStatusRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetJSONClusterStatusRequestProto)
    }

    static {
      defaultInstance = new GetJSONClusterStatusRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetJSONClusterStatusRequestProto)
  }

  public interface GetJSONClusterStatusResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string clusterSpec = 1;
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    boolean hasClusterSpec();
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    java.lang.String getClusterSpec();
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    com.google.protobuf.ByteString
        getClusterSpecBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetJSONClusterStatusResponseProto}
   *
   * <pre>
   **
   * response
   * </pre>
   */
  public static final class GetJSONClusterStatusResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements GetJSONClusterStatusResponseProtoOrBuilder {
    // Use GetJSONClusterStatusResponseProto.newBuilder() to construct.
    private GetJSONClusterStatusResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetJSONClusterStatusResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetJSONClusterStatusResponseProto defaultInstance;
    public static GetJSONClusterStatusResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetJSONClusterStatusResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetJSONClusterStatusResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              clusterSpec_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.class, org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string clusterSpec = 1;
    public static final int CLUSTERSPEC_FIELD_NUMBER = 1;
    private java.lang.Object clusterSpec_;
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    public boolean hasClusterSpec() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    public java.lang.String getClusterSpec() {
      java.lang.Object ref = clusterSpec_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          clusterSpec_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string clusterSpec = 1;</code>
     */
    public com.google.protobuf.ByteString
        getClusterSpecBytes() {
      java.lang.Object ref = clusterSpec_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        clusterSpec_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      clusterSpec_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getClusterSpecBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getClusterSpecBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto other = (org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto) obj;

      boolean result = true;
      result = result && (hasClusterSpec() == other.hasClusterSpec());
      if (hasClusterSpec()) {
        result = result && getClusterSpec()
            .equals(other.getClusterSpec());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasClusterSpec()) {
        hash = (37 * hash) + CLUSTERSPEC_FIELD_NUMBER;
        hash = (53 * hash) + getClusterSpec().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto 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.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetJSONClusterStatusResponseProto}
     *
     * <pre>
     **
     * response
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.class, org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        clusterSpec_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto build() {
        org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto result = new org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.clusterSpec_ = clusterSpec_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto.getDefaultInstance()) return this;
        if (other.hasClusterSpec()) {
          bitField0_ |= 0x00000001;
          clusterSpec_ = other.clusterSpec_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasClusterSpec()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetJSONClusterStatusResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string clusterSpec = 1;
      private java.lang.Object clusterSpec_ = "";
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public boolean hasClusterSpec() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public java.lang.String getClusterSpec() {
        java.lang.Object ref = clusterSpec_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          clusterSpec_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public com.google.protobuf.ByteString
          getClusterSpecBytes() {
        java.lang.Object ref = clusterSpec_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          clusterSpec_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public Builder setClusterSpec(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        clusterSpec_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public Builder clearClusterSpec() {
        bitField0_ = (bitField0_ & ~0x00000001);
        clusterSpec_ = getDefaultInstance().getClusterSpec();
        onChanged();
        return this;
      }
      /**
       * <code>required string clusterSpec = 1;</code>
       */
      public Builder setClusterSpecBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        clusterSpec_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetJSONClusterStatusResponseProto)
    }

    static {
      defaultInstance = new GetJSONClusterStatusResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetJSONClusterStatusResponseProto)
  }

  public interface ListNodeUUIDsByRoleRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string role = 1;
    /**
     * <code>required string role = 1;</code>
     */
    boolean hasRole();
    /**
     * <code>required string role = 1;</code>
     */
    java.lang.String getRole();
    /**
     * <code>required string role = 1;</code>
     */
    com.google.protobuf.ByteString
        getRoleBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.ListNodeUUIDsByRoleRequestProto}
   *
   * <pre>
   **
   * list the nodes in a role
   * </pre>
   */
  public static final class ListNodeUUIDsByRoleRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements ListNodeUUIDsByRoleRequestProtoOrBuilder {
    // Use ListNodeUUIDsByRoleRequestProto.newBuilder() to construct.
    private ListNodeUUIDsByRoleRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private ListNodeUUIDsByRoleRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final ListNodeUUIDsByRoleRequestProto defaultInstance;
    public static ListNodeUUIDsByRoleRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public ListNodeUUIDsByRoleRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private ListNodeUUIDsByRoleRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              role_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.class, org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string role = 1;
    public static final int ROLE_FIELD_NUMBER = 1;
    private java.lang.Object role_;
    /**
     * <code>required string role = 1;</code>
     */
    public boolean hasRole() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string role = 1;</code>
     */
    public java.lang.String getRole() {
      java.lang.Object ref = role_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          role_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string role = 1;</code>
     */
    public com.google.protobuf.ByteString
        getRoleBytes() {
      java.lang.Object ref = role_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        role_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      role_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getRoleBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getRoleBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto other = (org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto) obj;

      boolean result = true;
      result = result && (hasRole() == other.hasRole());
      if (hasRole()) {
        result = result && getRole()
            .equals(other.getRole());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasRole()) {
        hash = (37 * hash) + ROLE_FIELD_NUMBER;
        hash = (53 * hash) + getRole().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto 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.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.ListNodeUUIDsByRoleRequestProto}
     *
     * <pre>
     **
     * list the nodes in a role
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.class, org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        role_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto build() {
        org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto result = new org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.role_ = role_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto.getDefaultInstance()) return this;
        if (other.hasRole()) {
          bitField0_ |= 0x00000001;
          role_ = other.role_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasRole()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string role = 1;
      private java.lang.Object role_ = "";
      /**
       * <code>required string role = 1;</code>
       */
      public boolean hasRole() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string role = 1;</code>
       */
      public java.lang.String getRole() {
        java.lang.Object ref = role_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          role_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string role = 1;</code>
       */
      public com.google.protobuf.ByteString
          getRoleBytes() {
        java.lang.Object ref = role_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          role_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string role = 1;</code>
       */
      public Builder setRole(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        role_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string role = 1;</code>
       */
      public Builder clearRole() {
        bitField0_ = (bitField0_ & ~0x00000001);
        role_ = getDefaultInstance().getRole();
        onChanged();
        return this;
      }
      /**
       * <code>required string role = 1;</code>
       */
      public Builder setRoleBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        role_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.ListNodeUUIDsByRoleRequestProto)
    }

    static {
      defaultInstance = new ListNodeUUIDsByRoleRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.ListNodeUUIDsByRoleRequestProto)
  }

  public interface ListNodeUUIDsByRoleResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // repeated string uuid = 1;
    /**
     * <code>repeated string uuid = 1;</code>
     */
    java.util.List<java.lang.String>
    getUuidList();
    /**
     * <code>repeated string uuid = 1;</code>
     */
    int getUuidCount();
    /**
     * <code>repeated string uuid = 1;</code>
     */
    java.lang.String getUuid(int index);
    /**
     * <code>repeated string uuid = 1;</code>
     */
    com.google.protobuf.ByteString
        getUuidBytes(int index);
  }
  /**
   * Protobuf type {@code org.apache.slider.api.ListNodeUUIDsByRoleResponseProto}
   *
   * <pre>
   **
   * list the nodes in a role
   * </pre>
   */
  public static final class ListNodeUUIDsByRoleResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements ListNodeUUIDsByRoleResponseProtoOrBuilder {
    // Use ListNodeUUIDsByRoleResponseProto.newBuilder() to construct.
    private ListNodeUUIDsByRoleResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private ListNodeUUIDsByRoleResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final ListNodeUUIDsByRoleResponseProto defaultInstance;
    public static ListNodeUUIDsByRoleResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public ListNodeUUIDsByRoleResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private ListNodeUUIDsByRoleResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
                uuid_ = new com.google.protobuf.LazyStringArrayList();
                mutable_bitField0_ |= 0x00000001;
              }
              uuid_.add(input.readBytes());
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
          uuid_ = new com.google.protobuf.UnmodifiableLazyStringList(uuid_);
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.class, org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.Builder.class);
    }

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

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

    // repeated string uuid = 1;
    public static final int UUID_FIELD_NUMBER = 1;
    private com.google.protobuf.LazyStringList uuid_;
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public java.util.List<java.lang.String>
        getUuidList() {
      return uuid_;
    }
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public int getUuidCount() {
      return uuid_.size();
    }
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public java.lang.String getUuid(int index) {
      return uuid_.get(index);
    }
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public com.google.protobuf.ByteString
        getUuidBytes(int index) {
      return uuid_.getByteString(index);
    }

    private void initFields() {
      uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      for (int i = 0; i < uuid_.size(); i++) {
        output.writeBytes(1, uuid_.getByteString(i));
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      {
        int dataSize = 0;
        for (int i = 0; i < uuid_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream
            .computeBytesSizeNoTag(uuid_.getByteString(i));
        }
        size += dataSize;
        size += 1 * getUuidList().size();
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto other = (org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto) obj;

      boolean result = true;
      result = result && getUuidList()
          .equals(other.getUuidList());
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (getUuidCount() > 0) {
        hash = (37 * hash) + UUID_FIELD_NUMBER;
        hash = (53 * hash) + getUuidList().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto 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.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.ListNodeUUIDsByRoleResponseProto}
     *
     * <pre>
     **
     * list the nodes in a role
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.class, org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto build() {
        org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto result = new org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto(this);
        int from_bitField0_ = bitField0_;
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
          uuid_ = new com.google.protobuf.UnmodifiableLazyStringList(
              uuid_);
          bitField0_ = (bitField0_ & ~0x00000001);
        }
        result.uuid_ = uuid_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto.getDefaultInstance()) return this;
        if (!other.uuid_.isEmpty()) {
          if (uuid_.isEmpty()) {
            uuid_ = other.uuid_;
            bitField0_ = (bitField0_ & ~0x00000001);
          } else {
            ensureUuidIsMutable();
            uuid_.addAll(other.uuid_);
          }
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.ListNodeUUIDsByRoleResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // repeated string uuid = 1;
      private com.google.protobuf.LazyStringList uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureUuidIsMutable() {
        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
          uuid_ = new com.google.protobuf.LazyStringArrayList(uuid_);
          bitField0_ |= 0x00000001;
         }
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public java.util.List<java.lang.String>
          getUuidList() {
        return java.util.Collections.unmodifiableList(uuid_);
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public int getUuidCount() {
        return uuid_.size();
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public java.lang.String getUuid(int index) {
        return uuid_.get(index);
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public com.google.protobuf.ByteString
          getUuidBytes(int index) {
        return uuid_.getByteString(index);
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder setUuid(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUuidIsMutable();
        uuid_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder addUuid(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUuidIsMutable();
        uuid_.add(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder addAllUuid(
          java.lang.Iterable<java.lang.String> values) {
        ensureUuidIsMutable();
        super.addAll(values, uuid_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder clearUuid() {
        uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000001);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder addUuidBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUuidIsMutable();
        uuid_.add(value);
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.ListNodeUUIDsByRoleResponseProto)
    }

    static {
      defaultInstance = new ListNodeUUIDsByRoleResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.ListNodeUUIDsByRoleResponseProto)
  }

  public interface GetNodeRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string uuid = 1;
    /**
     * <code>required string uuid = 1;</code>
     */
    boolean hasUuid();
    /**
     * <code>required string uuid = 1;</code>
     */
    java.lang.String getUuid();
    /**
     * <code>required string uuid = 1;</code>
     */
    com.google.protobuf.ByteString
        getUuidBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetNodeRequestProto}
   *
   * <pre>
   **
   * get a node
   * </pre>
   */
  public static final class GetNodeRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements GetNodeRequestProtoOrBuilder {
    // Use GetNodeRequestProto.newBuilder() to construct.
    private GetNodeRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetNodeRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetNodeRequestProto defaultInstance;
    public static GetNodeRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetNodeRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetNodeRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              uuid_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetNodeRequestProto.class, org.apache.slider.api.proto.Messages.GetNodeRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string uuid = 1;
    public static final int UUID_FIELD_NUMBER = 1;
    private java.lang.Object uuid_;
    /**
     * <code>required string uuid = 1;</code>
     */
    public boolean hasUuid() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string uuid = 1;</code>
     */
    public java.lang.String getUuid() {
      java.lang.Object ref = uuid_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          uuid_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string uuid = 1;</code>
     */
    public com.google.protobuf.ByteString
        getUuidBytes() {
      java.lang.Object ref = uuid_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        uuid_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      uuid_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getUuidBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getUuidBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetNodeRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetNodeRequestProto other = (org.apache.slider.api.proto.Messages.GetNodeRequestProto) obj;

      boolean result = true;
      result = result && (hasUuid() == other.hasUuid());
      if (hasUuid()) {
        result = result && getUuid()
            .equals(other.getUuid());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasUuid()) {
        hash = (37 * hash) + UUID_FIELD_NUMBER;
        hash = (53 * hash) + getUuid().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto 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.slider.api.proto.Messages.GetNodeRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetNodeRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetNodeRequestProto}
     *
     * <pre>
     **
     * get a node
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetNodeRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetNodeRequestProto.class, org.apache.slider.api.proto.Messages.GetNodeRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetNodeRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        uuid_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetNodeRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetNodeRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetNodeRequestProto build() {
        org.apache.slider.api.proto.Messages.GetNodeRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetNodeRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetNodeRequestProto result = new org.apache.slider.api.proto.Messages.GetNodeRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.uuid_ = uuid_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetNodeRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetNodeRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetNodeRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetNodeRequestProto.getDefaultInstance()) return this;
        if (other.hasUuid()) {
          bitField0_ |= 0x00000001;
          uuid_ = other.uuid_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasUuid()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetNodeRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetNodeRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string uuid = 1;
      private java.lang.Object uuid_ = "";
      /**
       * <code>required string uuid = 1;</code>
       */
      public boolean hasUuid() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string uuid = 1;</code>
       */
      public java.lang.String getUuid() {
        java.lang.Object ref = uuid_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          uuid_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string uuid = 1;</code>
       */
      public com.google.protobuf.ByteString
          getUuidBytes() {
        java.lang.Object ref = uuid_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          uuid_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string uuid = 1;</code>
       */
      public Builder setUuid(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        uuid_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string uuid = 1;</code>
       */
      public Builder clearUuid() {
        bitField0_ = (bitField0_ & ~0x00000001);
        uuid_ = getDefaultInstance().getUuid();
        onChanged();
        return this;
      }
      /**
       * <code>required string uuid = 1;</code>
       */
      public Builder setUuidBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        uuid_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetNodeRequestProto)
    }

    static {
      defaultInstance = new GetNodeRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetNodeRequestProto)
  }

  public interface GetNodeResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required .org.apache.slider.api.RoleInstanceState clusterNode = 1;
    /**
     * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    boolean hasClusterNode();
    /**
     * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    org.apache.slider.api.proto.Messages.RoleInstanceState getClusterNode();
    /**
     * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder getClusterNodeOrBuilder();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetNodeResponseProto}
   *
   * <pre>
   **
   * response on a node
   * </pre>
   */
  public static final class GetNodeResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements GetNodeResponseProtoOrBuilder {
    // Use GetNodeResponseProto.newBuilder() to construct.
    private GetNodeResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetNodeResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetNodeResponseProto defaultInstance;
    public static GetNodeResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetNodeResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetNodeResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              org.apache.slider.api.proto.Messages.RoleInstanceState.Builder subBuilder = null;
              if (((bitField0_ & 0x00000001) == 0x00000001)) {
                subBuilder = clusterNode_.toBuilder();
              }
              clusterNode_ = input.readMessage(org.apache.slider.api.proto.Messages.RoleInstanceState.PARSER, extensionRegistry);
              if (subBuilder != null) {
                subBuilder.mergeFrom(clusterNode_);
                clusterNode_ = subBuilder.buildPartial();
              }
              bitField0_ |= 0x00000001;
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetNodeResponseProto.class, org.apache.slider.api.proto.Messages.GetNodeResponseProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required .org.apache.slider.api.RoleInstanceState clusterNode = 1;
    public static final int CLUSTERNODE_FIELD_NUMBER = 1;
    private org.apache.slider.api.proto.Messages.RoleInstanceState clusterNode_;
    /**
     * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public boolean hasClusterNode() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public org.apache.slider.api.proto.Messages.RoleInstanceState getClusterNode() {
      return clusterNode_;
    }
    /**
     * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder getClusterNodeOrBuilder() {
      return clusterNode_;
    }

    private void initFields() {
      clusterNode_ = org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance();
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasClusterNode()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!getClusterNode().isInitialized()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeMessage(1, clusterNode_);
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(1, clusterNode_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetNodeResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetNodeResponseProto other = (org.apache.slider.api.proto.Messages.GetNodeResponseProto) obj;

      boolean result = true;
      result = result && (hasClusterNode() == other.hasClusterNode());
      if (hasClusterNode()) {
        result = result && getClusterNode()
            .equals(other.getClusterNode());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasClusterNode()) {
        hash = (37 * hash) + CLUSTERNODE_FIELD_NUMBER;
        hash = (53 * hash) + getClusterNode().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto 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.slider.api.proto.Messages.GetNodeResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetNodeResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetNodeResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetNodeResponseProto}
     *
     * <pre>
     **
     * response on a node
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetNodeResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetNodeResponseProto.class, org.apache.slider.api.proto.Messages.GetNodeResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetNodeResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
          getClusterNodeFieldBuilder();
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        if (clusterNodeBuilder_ == null) {
          clusterNode_ = org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance();
        } else {
          clusterNodeBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetNodeResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetNodeResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetNodeResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetNodeResponseProto build() {
        org.apache.slider.api.proto.Messages.GetNodeResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetNodeResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetNodeResponseProto result = new org.apache.slider.api.proto.Messages.GetNodeResponseProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        if (clusterNodeBuilder_ == null) {
          result.clusterNode_ = clusterNode_;
        } else {
          result.clusterNode_ = clusterNodeBuilder_.build();
        }
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetNodeResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetNodeResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetNodeResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetNodeResponseProto.getDefaultInstance()) return this;
        if (other.hasClusterNode()) {
          mergeClusterNode(other.getClusterNode());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasClusterNode()) {
          
          return false;
        }
        if (!getClusterNode().isInitialized()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetNodeResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetNodeResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required .org.apache.slider.api.RoleInstanceState clusterNode = 1;
      private org.apache.slider.api.proto.Messages.RoleInstanceState clusterNode_ = org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance();
      private com.google.protobuf.SingleFieldBuilder<
          org.apache.slider.api.proto.Messages.RoleInstanceState, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder, org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> clusterNodeBuilder_;
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public boolean hasClusterNode() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceState getClusterNode() {
        if (clusterNodeBuilder_ == null) {
          return clusterNode_;
        } else {
          return clusterNodeBuilder_.getMessage();
        }
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder setClusterNode(org.apache.slider.api.proto.Messages.RoleInstanceState value) {
        if (clusterNodeBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          clusterNode_ = value;
          onChanged();
        } else {
          clusterNodeBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder setClusterNode(
          org.apache.slider.api.proto.Messages.RoleInstanceState.Builder builderForValue) {
        if (clusterNodeBuilder_ == null) {
          clusterNode_ = builderForValue.build();
          onChanged();
        } else {
          clusterNodeBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder mergeClusterNode(org.apache.slider.api.proto.Messages.RoleInstanceState value) {
        if (clusterNodeBuilder_ == null) {
          if (((bitField0_ & 0x00000001) == 0x00000001) &&
              clusterNode_ != org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance()) {
            clusterNode_ =
              org.apache.slider.api.proto.Messages.RoleInstanceState.newBuilder(clusterNode_).mergeFrom(value).buildPartial();
          } else {
            clusterNode_ = value;
          }
          onChanged();
        } else {
          clusterNodeBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder clearClusterNode() {
        if (clusterNodeBuilder_ == null) {
          clusterNode_ = org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance();
          onChanged();
        } else {
          clusterNodeBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceState.Builder getClusterNodeBuilder() {
        bitField0_ |= 0x00000001;
        onChanged();
        return getClusterNodeFieldBuilder().getBuilder();
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder getClusterNodeOrBuilder() {
        if (clusterNodeBuilder_ != null) {
          return clusterNodeBuilder_.getMessageOrBuilder();
        } else {
          return clusterNode_;
        }
      }
      /**
       * <code>required .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      private com.google.protobuf.SingleFieldBuilder<
          org.apache.slider.api.proto.Messages.RoleInstanceState, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder, org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> 
          getClusterNodeFieldBuilder() {
        if (clusterNodeBuilder_ == null) {
          clusterNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
              org.apache.slider.api.proto.Messages.RoleInstanceState, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder, org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder>(
                  clusterNode_,
                  getParentForChildren(),
                  isClean());
          clusterNode_ = null;
        }
        return clusterNodeBuilder_;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetNodeResponseProto)
    }

    static {
      defaultInstance = new GetNodeResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetNodeResponseProto)
  }

  public interface GetClusterNodesRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // repeated string uuid = 1;
    /**
     * <code>repeated string uuid = 1;</code>
     */
    java.util.List<java.lang.String>
    getUuidList();
    /**
     * <code>repeated string uuid = 1;</code>
     */
    int getUuidCount();
    /**
     * <code>repeated string uuid = 1;</code>
     */
    java.lang.String getUuid(int index);
    /**
     * <code>repeated string uuid = 1;</code>
     */
    com.google.protobuf.ByteString
        getUuidBytes(int index);
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetClusterNodesRequestProto}
   *
   * <pre>
   **
   * list the nodes for the UUDs
   * </pre>
   */
  public static final class GetClusterNodesRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements GetClusterNodesRequestProtoOrBuilder {
    // Use GetClusterNodesRequestProto.newBuilder() to construct.
    private GetClusterNodesRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetClusterNodesRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetClusterNodesRequestProto defaultInstance;
    public static GetClusterNodesRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetClusterNodesRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetClusterNodesRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
                uuid_ = new com.google.protobuf.LazyStringArrayList();
                mutable_bitField0_ |= 0x00000001;
              }
              uuid_.add(input.readBytes());
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
          uuid_ = new com.google.protobuf.UnmodifiableLazyStringList(uuid_);
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.class, org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.Builder.class);
    }

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

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

    // repeated string uuid = 1;
    public static final int UUID_FIELD_NUMBER = 1;
    private com.google.protobuf.LazyStringList uuid_;
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public java.util.List<java.lang.String>
        getUuidList() {
      return uuid_;
    }
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public int getUuidCount() {
      return uuid_.size();
    }
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public java.lang.String getUuid(int index) {
      return uuid_.get(index);
    }
    /**
     * <code>repeated string uuid = 1;</code>
     */
    public com.google.protobuf.ByteString
        getUuidBytes(int index) {
      return uuid_.getByteString(index);
    }

    private void initFields() {
      uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      for (int i = 0; i < uuid_.size(); i++) {
        output.writeBytes(1, uuid_.getByteString(i));
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      {
        int dataSize = 0;
        for (int i = 0; i < uuid_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream
            .computeBytesSizeNoTag(uuid_.getByteString(i));
        }
        size += dataSize;
        size += 1 * getUuidList().size();
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto other = (org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto) obj;

      boolean result = true;
      result = result && getUuidList()
          .equals(other.getUuidList());
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (getUuidCount() > 0) {
        hash = (37 * hash) + UUID_FIELD_NUMBER;
        hash = (53 * hash) + getUuidList().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto 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.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetClusterNodesRequestProto}
     *
     * <pre>
     **
     * list the nodes for the UUDs
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetClusterNodesRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.class, org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto build() {
        org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto result = new org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto(this);
        int from_bitField0_ = bitField0_;
        if (((bitField0_ & 0x00000001) == 0x00000001)) {
          uuid_ = new com.google.protobuf.UnmodifiableLazyStringList(
              uuid_);
          bitField0_ = (bitField0_ & ~0x00000001);
        }
        result.uuid_ = uuid_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto.getDefaultInstance()) return this;
        if (!other.uuid_.isEmpty()) {
          if (uuid_.isEmpty()) {
            uuid_ = other.uuid_;
            bitField0_ = (bitField0_ & ~0x00000001);
          } else {
            ensureUuidIsMutable();
            uuid_.addAll(other.uuid_);
          }
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetClusterNodesRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // repeated string uuid = 1;
      private com.google.protobuf.LazyStringList uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureUuidIsMutable() {
        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
          uuid_ = new com.google.protobuf.LazyStringArrayList(uuid_);
          bitField0_ |= 0x00000001;
         }
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public java.util.List<java.lang.String>
          getUuidList() {
        return java.util.Collections.unmodifiableList(uuid_);
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public int getUuidCount() {
        return uuid_.size();
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public java.lang.String getUuid(int index) {
        return uuid_.get(index);
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public com.google.protobuf.ByteString
          getUuidBytes(int index) {
        return uuid_.getByteString(index);
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder setUuid(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUuidIsMutable();
        uuid_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder addUuid(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUuidIsMutable();
        uuid_.add(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder addAllUuid(
          java.lang.Iterable<java.lang.String> values) {
        ensureUuidIsMutable();
        super.addAll(values, uuid_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder clearUuid() {
        uuid_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000001);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string uuid = 1;</code>
       */
      public Builder addUuidBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureUuidIsMutable();
        uuid_.add(value);
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetClusterNodesRequestProto)
    }

    static {
      defaultInstance = new GetClusterNodesRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetClusterNodesRequestProto)
  }

  public interface GetClusterNodesResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    java.util.List<org.apache.slider.api.proto.Messages.RoleInstanceState> 
        getClusterNodeList();
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    org.apache.slider.api.proto.Messages.RoleInstanceState getClusterNode(int index);
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    int getClusterNodeCount();
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    java.util.List<? extends org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> 
        getClusterNodeOrBuilderList();
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder getClusterNodeOrBuilder(
        int index);
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetClusterNodesResponseProto}
   *
   * <pre>
   **
   * list the nodes in a role
   * </pre>
   */
  public static final class GetClusterNodesResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements GetClusterNodesResponseProtoOrBuilder {
    // Use GetClusterNodesResponseProto.newBuilder() to construct.
    private GetClusterNodesResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetClusterNodesResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetClusterNodesResponseProto defaultInstance;
    public static GetClusterNodesResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetClusterNodesResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetClusterNodesResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
                clusterNode_ = new java.util.ArrayList<org.apache.slider.api.proto.Messages.RoleInstanceState>();
                mutable_bitField0_ |= 0x00000001;
              }
              clusterNode_.add(input.readMessage(org.apache.slider.api.proto.Messages.RoleInstanceState.PARSER, extensionRegistry));
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
          clusterNode_ = java.util.Collections.unmodifiableList(clusterNode_);
        }
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.class, org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.Builder.class);
    }

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

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

    // repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;
    public static final int CLUSTERNODE_FIELD_NUMBER = 1;
    private java.util.List<org.apache.slider.api.proto.Messages.RoleInstanceState> clusterNode_;
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public java.util.List<org.apache.slider.api.proto.Messages.RoleInstanceState> getClusterNodeList() {
      return clusterNode_;
    }
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public java.util.List<? extends org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> 
        getClusterNodeOrBuilderList() {
      return clusterNode_;
    }
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public int getClusterNodeCount() {
      return clusterNode_.size();
    }
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public org.apache.slider.api.proto.Messages.RoleInstanceState getClusterNode(int index) {
      return clusterNode_.get(index);
    }
    /**
     * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
     */
    public org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder getClusterNodeOrBuilder(
        int index) {
      return clusterNode_.get(index);
    }

    private void initFields() {
      clusterNode_ = java.util.Collections.emptyList();
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      for (int i = 0; i < getClusterNodeCount(); i++) {
        if (!getClusterNode(i).isInitialized()) {
          memoizedIsInitialized = 0;
          return false;
        }
      }
      memoizedIsInitialized = 1;
      return true;
    }

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

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

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

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto other = (org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto) obj;

      boolean result = true;
      result = result && getClusterNodeList()
          .equals(other.getClusterNodeList());
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (getClusterNodeCount() > 0) {
        hash = (37 * hash) + CLUSTERNODE_FIELD_NUMBER;
        hash = (53 * hash) + getClusterNodeList().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto 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.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetClusterNodesResponseProto}
     *
     * <pre>
     **
     * list the nodes in a role
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetClusterNodesResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.class, org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
          getClusterNodeFieldBuilder();
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        if (clusterNodeBuilder_ == null) {
          clusterNode_ = java.util.Collections.emptyList();
          bitField0_ = (bitField0_ & ~0x00000001);
        } else {
          clusterNodeBuilder_.clear();
        }
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetClusterNodesResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto build() {
        org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto result = new org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto(this);
        int from_bitField0_ = bitField0_;
        if (clusterNodeBuilder_ == null) {
          if (((bitField0_ & 0x00000001) == 0x00000001)) {
            clusterNode_ = java.util.Collections.unmodifiableList(clusterNode_);
            bitField0_ = (bitField0_ & ~0x00000001);
          }
          result.clusterNode_ = clusterNode_;
        } else {
          result.clusterNode_ = clusterNodeBuilder_.build();
        }
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto.getDefaultInstance()) return this;
        if (clusterNodeBuilder_ == null) {
          if (!other.clusterNode_.isEmpty()) {
            if (clusterNode_.isEmpty()) {
              clusterNode_ = other.clusterNode_;
              bitField0_ = (bitField0_ & ~0x00000001);
            } else {
              ensureClusterNodeIsMutable();
              clusterNode_.addAll(other.clusterNode_);
            }
            onChanged();
          }
        } else {
          if (!other.clusterNode_.isEmpty()) {
            if (clusterNodeBuilder_.isEmpty()) {
              clusterNodeBuilder_.dispose();
              clusterNodeBuilder_ = null;
              clusterNode_ = other.clusterNode_;
              bitField0_ = (bitField0_ & ~0x00000001);
              clusterNodeBuilder_ = 
                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
                   getClusterNodeFieldBuilder() : null;
            } else {
              clusterNodeBuilder_.addAllMessages(other.clusterNode_);
            }
          }
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        for (int i = 0; i < getClusterNodeCount(); i++) {
          if (!getClusterNode(i).isInitialized()) {
            
            return false;
          }
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetClusterNodesResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;
      private java.util.List<org.apache.slider.api.proto.Messages.RoleInstanceState> clusterNode_ =
        java.util.Collections.emptyList();
      private void ensureClusterNodeIsMutable() {
        if (!((bitField0_ & 0x00000001) == 0x00000001)) {
          clusterNode_ = new java.util.ArrayList<org.apache.slider.api.proto.Messages.RoleInstanceState>(clusterNode_);
          bitField0_ |= 0x00000001;
         }
      }

      private com.google.protobuf.RepeatedFieldBuilder<
          org.apache.slider.api.proto.Messages.RoleInstanceState, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder, org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> clusterNodeBuilder_;

      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public java.util.List<org.apache.slider.api.proto.Messages.RoleInstanceState> getClusterNodeList() {
        if (clusterNodeBuilder_ == null) {
          return java.util.Collections.unmodifiableList(clusterNode_);
        } else {
          return clusterNodeBuilder_.getMessageList();
        }
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public int getClusterNodeCount() {
        if (clusterNodeBuilder_ == null) {
          return clusterNode_.size();
        } else {
          return clusterNodeBuilder_.getCount();
        }
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceState getClusterNode(int index) {
        if (clusterNodeBuilder_ == null) {
          return clusterNode_.get(index);
        } else {
          return clusterNodeBuilder_.getMessage(index);
        }
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder setClusterNode(
          int index, org.apache.slider.api.proto.Messages.RoleInstanceState value) {
        if (clusterNodeBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureClusterNodeIsMutable();
          clusterNode_.set(index, value);
          onChanged();
        } else {
          clusterNodeBuilder_.setMessage(index, value);
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder setClusterNode(
          int index, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder builderForValue) {
        if (clusterNodeBuilder_ == null) {
          ensureClusterNodeIsMutable();
          clusterNode_.set(index, builderForValue.build());
          onChanged();
        } else {
          clusterNodeBuilder_.setMessage(index, builderForValue.build());
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder addClusterNode(org.apache.slider.api.proto.Messages.RoleInstanceState value) {
        if (clusterNodeBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureClusterNodeIsMutable();
          clusterNode_.add(value);
          onChanged();
        } else {
          clusterNodeBuilder_.addMessage(value);
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder addClusterNode(
          int index, org.apache.slider.api.proto.Messages.RoleInstanceState value) {
        if (clusterNodeBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          ensureClusterNodeIsMutable();
          clusterNode_.add(index, value);
          onChanged();
        } else {
          clusterNodeBuilder_.addMessage(index, value);
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder addClusterNode(
          org.apache.slider.api.proto.Messages.RoleInstanceState.Builder builderForValue) {
        if (clusterNodeBuilder_ == null) {
          ensureClusterNodeIsMutable();
          clusterNode_.add(builderForValue.build());
          onChanged();
        } else {
          clusterNodeBuilder_.addMessage(builderForValue.build());
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder addClusterNode(
          int index, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder builderForValue) {
        if (clusterNodeBuilder_ == null) {
          ensureClusterNodeIsMutable();
          clusterNode_.add(index, builderForValue.build());
          onChanged();
        } else {
          clusterNodeBuilder_.addMessage(index, builderForValue.build());
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder addAllClusterNode(
          java.lang.Iterable<? extends org.apache.slider.api.proto.Messages.RoleInstanceState> values) {
        if (clusterNodeBuilder_ == null) {
          ensureClusterNodeIsMutable();
          super.addAll(values, clusterNode_);
          onChanged();
        } else {
          clusterNodeBuilder_.addAllMessages(values);
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder clearClusterNode() {
        if (clusterNodeBuilder_ == null) {
          clusterNode_ = java.util.Collections.emptyList();
          bitField0_ = (bitField0_ & ~0x00000001);
          onChanged();
        } else {
          clusterNodeBuilder_.clear();
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public Builder removeClusterNode(int index) {
        if (clusterNodeBuilder_ == null) {
          ensureClusterNodeIsMutable();
          clusterNode_.remove(index);
          onChanged();
        } else {
          clusterNodeBuilder_.remove(index);
        }
        return this;
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceState.Builder getClusterNodeBuilder(
          int index) {
        return getClusterNodeFieldBuilder().getBuilder(index);
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder getClusterNodeOrBuilder(
          int index) {
        if (clusterNodeBuilder_ == null) {
          return clusterNode_.get(index);  } else {
          return clusterNodeBuilder_.getMessageOrBuilder(index);
        }
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public java.util.List<? extends org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> 
           getClusterNodeOrBuilderList() {
        if (clusterNodeBuilder_ != null) {
          return clusterNodeBuilder_.getMessageOrBuilderList();
        } else {
          return java.util.Collections.unmodifiableList(clusterNode_);
        }
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceState.Builder addClusterNodeBuilder() {
        return getClusterNodeFieldBuilder().addBuilder(
            org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance());
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public org.apache.slider.api.proto.Messages.RoleInstanceState.Builder addClusterNodeBuilder(
          int index) {
        return getClusterNodeFieldBuilder().addBuilder(
            index, org.apache.slider.api.proto.Messages.RoleInstanceState.getDefaultInstance());
      }
      /**
       * <code>repeated .org.apache.slider.api.RoleInstanceState clusterNode = 1;</code>
       */
      public java.util.List<org.apache.slider.api.proto.Messages.RoleInstanceState.Builder> 
           getClusterNodeBuilderList() {
        return getClusterNodeFieldBuilder().getBuilderList();
      }
      private com.google.protobuf.RepeatedFieldBuilder<
          org.apache.slider.api.proto.Messages.RoleInstanceState, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder, org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder> 
          getClusterNodeFieldBuilder() {
        if (clusterNodeBuilder_ == null) {
          clusterNodeBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
              org.apache.slider.api.proto.Messages.RoleInstanceState, org.apache.slider.api.proto.Messages.RoleInstanceState.Builder, org.apache.slider.api.proto.Messages.RoleInstanceStateOrBuilder>(
                  clusterNode_,
                  ((bitField0_ & 0x00000001) == 0x00000001),
                  getParentForChildren(),
                  isClean());
          clusterNode_ = null;
        }
        return clusterNodeBuilder_;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetClusterNodesResponseProto)
    }

    static {
      defaultInstance = new GetClusterNodesResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetClusterNodesResponseProto)
  }

  public interface EchoRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string text = 1;
    /**
     * <code>required string text = 1;</code>
     */
    boolean hasText();
    /**
     * <code>required string text = 1;</code>
     */
    java.lang.String getText();
    /**
     * <code>required string text = 1;</code>
     */
    com.google.protobuf.ByteString
        getTextBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.EchoRequestProto}
   *
   * <pre>
   **
   * Echo
   * </pre>
   */
  public static final class EchoRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements EchoRequestProtoOrBuilder {
    // Use EchoRequestProto.newBuilder() to construct.
    private EchoRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private EchoRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final EchoRequestProto defaultInstance;
    public static EchoRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public EchoRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private EchoRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              text_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.EchoRequestProto.class, org.apache.slider.api.proto.Messages.EchoRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string text = 1;
    public static final int TEXT_FIELD_NUMBER = 1;
    private java.lang.Object text_;
    /**
     * <code>required string text = 1;</code>
     */
    public boolean hasText() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string text = 1;</code>
     */
    public java.lang.String getText() {
      java.lang.Object ref = text_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          text_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string text = 1;</code>
     */
    public com.google.protobuf.ByteString
        getTextBytes() {
      java.lang.Object ref = text_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        text_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      text_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getTextBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getTextBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.EchoRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.EchoRequestProto other = (org.apache.slider.api.proto.Messages.EchoRequestProto) obj;

      boolean result = true;
      result = result && (hasText() == other.hasText());
      if (hasText()) {
        result = result && getText()
            .equals(other.getText());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasText()) {
        hash = (37 * hash) + TEXT_FIELD_NUMBER;
        hash = (53 * hash) + getText().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto 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.slider.api.proto.Messages.EchoRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.EchoRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.EchoRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.EchoRequestProto}
     *
     * <pre>
     **
     * Echo
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.EchoRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.EchoRequestProto.class, org.apache.slider.api.proto.Messages.EchoRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.EchoRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        text_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.EchoRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.EchoRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.EchoRequestProto build() {
        org.apache.slider.api.proto.Messages.EchoRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.EchoRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.EchoRequestProto result = new org.apache.slider.api.proto.Messages.EchoRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.text_ = text_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.EchoRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.EchoRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.EchoRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.EchoRequestProto.getDefaultInstance()) return this;
        if (other.hasText()) {
          bitField0_ |= 0x00000001;
          text_ = other.text_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasText()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.EchoRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.EchoRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string text = 1;
      private java.lang.Object text_ = "";
      /**
       * <code>required string text = 1;</code>
       */
      public boolean hasText() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string text = 1;</code>
       */
      public java.lang.String getText() {
        java.lang.Object ref = text_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          text_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string text = 1;</code>
       */
      public com.google.protobuf.ByteString
          getTextBytes() {
        java.lang.Object ref = text_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          text_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder setText(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        text_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder clearText() {
        bitField0_ = (bitField0_ & ~0x00000001);
        text_ = getDefaultInstance().getText();
        onChanged();
        return this;
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder setTextBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        text_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.EchoRequestProto)
    }

    static {
      defaultInstance = new EchoRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.EchoRequestProto)
  }

  public interface EchoResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string text = 1;
    /**
     * <code>required string text = 1;</code>
     */
    boolean hasText();
    /**
     * <code>required string text = 1;</code>
     */
    java.lang.String getText();
    /**
     * <code>required string text = 1;</code>
     */
    com.google.protobuf.ByteString
        getTextBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.EchoResponseProto}
   *
   * <pre>
   **
   * Echo reply
   * </pre>
   */
  public static final class EchoResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements EchoResponseProtoOrBuilder {
    // Use EchoResponseProto.newBuilder() to construct.
    private EchoResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private EchoResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final EchoResponseProto defaultInstance;
    public static EchoResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public EchoResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private EchoResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              text_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.EchoResponseProto.class, org.apache.slider.api.proto.Messages.EchoResponseProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string text = 1;
    public static final int TEXT_FIELD_NUMBER = 1;
    private java.lang.Object text_;
    /**
     * <code>required string text = 1;</code>
     */
    public boolean hasText() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string text = 1;</code>
     */
    public java.lang.String getText() {
      java.lang.Object ref = text_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          text_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string text = 1;</code>
     */
    public com.google.protobuf.ByteString
        getTextBytes() {
      java.lang.Object ref = text_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        text_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      text_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getTextBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getTextBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.EchoResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.EchoResponseProto other = (org.apache.slider.api.proto.Messages.EchoResponseProto) obj;

      boolean result = true;
      result = result && (hasText() == other.hasText());
      if (hasText()) {
        result = result && getText()
            .equals(other.getText());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasText()) {
        hash = (37 * hash) + TEXT_FIELD_NUMBER;
        hash = (53 * hash) + getText().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto 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.slider.api.proto.Messages.EchoResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.EchoResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.EchoResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.EchoResponseProto}
     *
     * <pre>
     **
     * Echo reply
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.EchoResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.EchoResponseProto.class, org.apache.slider.api.proto.Messages.EchoResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.EchoResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        text_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_EchoResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.EchoResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.EchoResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.EchoResponseProto build() {
        org.apache.slider.api.proto.Messages.EchoResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.EchoResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.EchoResponseProto result = new org.apache.slider.api.proto.Messages.EchoResponseProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.text_ = text_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.EchoResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.EchoResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.EchoResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.EchoResponseProto.getDefaultInstance()) return this;
        if (other.hasText()) {
          bitField0_ |= 0x00000001;
          text_ = other.text_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasText()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.EchoResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.EchoResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string text = 1;
      private java.lang.Object text_ = "";
      /**
       * <code>required string text = 1;</code>
       */
      public boolean hasText() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string text = 1;</code>
       */
      public java.lang.String getText() {
        java.lang.Object ref = text_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          text_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string text = 1;</code>
       */
      public com.google.protobuf.ByteString
          getTextBytes() {
        java.lang.Object ref = text_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          text_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder setText(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        text_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder clearText() {
        bitField0_ = (bitField0_ & ~0x00000001);
        text_ = getDefaultInstance().getText();
        onChanged();
        return this;
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder setTextBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        text_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.EchoResponseProto)
    }

    static {
      defaultInstance = new EchoResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.EchoResponseProto)
  }

  public interface KillContainerRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string id = 1;
    /**
     * <code>required string id = 1;</code>
     */
    boolean hasId();
    /**
     * <code>required string id = 1;</code>
     */
    java.lang.String getId();
    /**
     * <code>required string id = 1;</code>
     */
    com.google.protobuf.ByteString
        getIdBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.KillContainerRequestProto}
   *
   * <pre>
   **
   * Kill a container
   * </pre>
   */
  public static final class KillContainerRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements KillContainerRequestProtoOrBuilder {
    // Use KillContainerRequestProto.newBuilder() to construct.
    private KillContainerRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private KillContainerRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final KillContainerRequestProto defaultInstance;
    public static KillContainerRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public KillContainerRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private KillContainerRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              id_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.KillContainerRequestProto.class, org.apache.slider.api.proto.Messages.KillContainerRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string id = 1;
    public static final int ID_FIELD_NUMBER = 1;
    private java.lang.Object id_;
    /**
     * <code>required string id = 1;</code>
     */
    public boolean hasId() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string id = 1;</code>
     */
    public java.lang.String getId() {
      java.lang.Object ref = id_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          id_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string id = 1;</code>
     */
    public com.google.protobuf.ByteString
        getIdBytes() {
      java.lang.Object ref = id_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        id_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      id_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getIdBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getIdBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.KillContainerRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.KillContainerRequestProto other = (org.apache.slider.api.proto.Messages.KillContainerRequestProto) obj;

      boolean result = true;
      result = result && (hasId() == other.hasId());
      if (hasId()) {
        result = result && getId()
            .equals(other.getId());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasId()) {
        hash = (37 * hash) + ID_FIELD_NUMBER;
        hash = (53 * hash) + getId().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto 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.slider.api.proto.Messages.KillContainerRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.KillContainerRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.KillContainerRequestProto}
     *
     * <pre>
     **
     * Kill a container
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.KillContainerRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.KillContainerRequestProto.class, org.apache.slider.api.proto.Messages.KillContainerRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.KillContainerRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        id_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.KillContainerRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.KillContainerRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.KillContainerRequestProto build() {
        org.apache.slider.api.proto.Messages.KillContainerRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.KillContainerRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.KillContainerRequestProto result = new org.apache.slider.api.proto.Messages.KillContainerRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.id_ = id_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.KillContainerRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.KillContainerRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.KillContainerRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.KillContainerRequestProto.getDefaultInstance()) return this;
        if (other.hasId()) {
          bitField0_ |= 0x00000001;
          id_ = other.id_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasId()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.KillContainerRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.KillContainerRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string id = 1;
      private java.lang.Object id_ = "";
      /**
       * <code>required string id = 1;</code>
       */
      public boolean hasId() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string id = 1;</code>
       */
      public java.lang.String getId() {
        java.lang.Object ref = id_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          id_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string id = 1;</code>
       */
      public com.google.protobuf.ByteString
          getIdBytes() {
        java.lang.Object ref = id_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          id_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string id = 1;</code>
       */
      public Builder setId(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        id_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string id = 1;</code>
       */
      public Builder clearId() {
        bitField0_ = (bitField0_ & ~0x00000001);
        id_ = getDefaultInstance().getId();
        onChanged();
        return this;
      }
      /**
       * <code>required string id = 1;</code>
       */
      public Builder setIdBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        id_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.KillContainerRequestProto)
    }

    static {
      defaultInstance = new KillContainerRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.KillContainerRequestProto)
  }

  public interface KillContainerResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required bool success = 1;
    /**
     * <code>required bool success = 1;</code>
     */
    boolean hasSuccess();
    /**
     * <code>required bool success = 1;</code>
     */
    boolean getSuccess();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.KillContainerResponseProto}
   *
   * <pre>
   **
   * Kill reply
   * </pre>
   */
  public static final class KillContainerResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements KillContainerResponseProtoOrBuilder {
    // Use KillContainerResponseProto.newBuilder() to construct.
    private KillContainerResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private KillContainerResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final KillContainerResponseProto defaultInstance;
    public static KillContainerResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public KillContainerResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private KillContainerResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 8: {
              bitField0_ |= 0x00000001;
              success_ = input.readBool();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.KillContainerResponseProto.class, org.apache.slider.api.proto.Messages.KillContainerResponseProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required bool success = 1;
    public static final int SUCCESS_FIELD_NUMBER = 1;
    private boolean success_;
    /**
     * <code>required bool success = 1;</code>
     */
    public boolean hasSuccess() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required bool success = 1;</code>
     */
    public boolean getSuccess() {
      return success_;
    }

    private void initFields() {
      success_ = false;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

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

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBool(1, success_);
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(1, success_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.KillContainerResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.KillContainerResponseProto other = (org.apache.slider.api.proto.Messages.KillContainerResponseProto) obj;

      boolean result = true;
      result = result && (hasSuccess() == other.hasSuccess());
      if (hasSuccess()) {
        result = result && (getSuccess()
            == other.getSuccess());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasSuccess()) {
        hash = (37 * hash) + SUCCESS_FIELD_NUMBER;
        hash = (53 * hash) + hashBoolean(getSuccess());
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto 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.slider.api.proto.Messages.KillContainerResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.KillContainerResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.KillContainerResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.KillContainerResponseProto}
     *
     * <pre>
     **
     * Kill reply
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.KillContainerResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.KillContainerResponseProto.class, org.apache.slider.api.proto.Messages.KillContainerResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.KillContainerResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        success_ = false;
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_KillContainerResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.KillContainerResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.KillContainerResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.KillContainerResponseProto build() {
        org.apache.slider.api.proto.Messages.KillContainerResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.KillContainerResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.KillContainerResponseProto result = new org.apache.slider.api.proto.Messages.KillContainerResponseProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.success_ = success_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.KillContainerResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.KillContainerResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.KillContainerResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.KillContainerResponseProto.getDefaultInstance()) return this;
        if (other.hasSuccess()) {
          setSuccess(other.getSuccess());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasSuccess()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.KillContainerResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.KillContainerResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required bool success = 1;
      private boolean success_ ;
      /**
       * <code>required bool success = 1;</code>
       */
      public boolean hasSuccess() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required bool success = 1;</code>
       */
      public boolean getSuccess() {
        return success_;
      }
      /**
       * <code>required bool success = 1;</code>
       */
      public Builder setSuccess(boolean value) {
        bitField0_ |= 0x00000001;
        success_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required bool success = 1;</code>
       */
      public Builder clearSuccess() {
        bitField0_ = (bitField0_ & ~0x00000001);
        success_ = false;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.KillContainerResponseProto)
    }

    static {
      defaultInstance = new KillContainerResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.KillContainerResponseProto)
  }

  public interface AMSuicideRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string text = 1;
    /**
     * <code>required string text = 1;</code>
     */
    boolean hasText();
    /**
     * <code>required string text = 1;</code>
     */
    java.lang.String getText();
    /**
     * <code>required string text = 1;</code>
     */
    com.google.protobuf.ByteString
        getTextBytes();

    // required int32 signal = 2;
    /**
     * <code>required int32 signal = 2;</code>
     */
    boolean hasSignal();
    /**
     * <code>required int32 signal = 2;</code>
     */
    int getSignal();

    // required int32 delay = 3;
    /**
     * <code>required int32 delay = 3;</code>
     */
    boolean hasDelay();
    /**
     * <code>required int32 delay = 3;</code>
     */
    int getDelay();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.AMSuicideRequestProto}
   *
   * <pre>
   **
   * AM suicide
   * </pre>
   */
  public static final class AMSuicideRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements AMSuicideRequestProtoOrBuilder {
    // Use AMSuicideRequestProto.newBuilder() to construct.
    private AMSuicideRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private AMSuicideRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final AMSuicideRequestProto defaultInstance;
    public static AMSuicideRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public AMSuicideRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private AMSuicideRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              text_ = input.readBytes();
              break;
            }
            case 16: {
              bitField0_ |= 0x00000002;
              signal_ = input.readInt32();
              break;
            }
            case 24: {
              bitField0_ |= 0x00000004;
              delay_ = input.readInt32();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.AMSuicideRequestProto.class, org.apache.slider.api.proto.Messages.AMSuicideRequestProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string text = 1;
    public static final int TEXT_FIELD_NUMBER = 1;
    private java.lang.Object text_;
    /**
     * <code>required string text = 1;</code>
     */
    public boolean hasText() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string text = 1;</code>
     */
    public java.lang.String getText() {
      java.lang.Object ref = text_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          text_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string text = 1;</code>
     */
    public com.google.protobuf.ByteString
        getTextBytes() {
      java.lang.Object ref = text_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        text_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required int32 signal = 2;
    public static final int SIGNAL_FIELD_NUMBER = 2;
    private int signal_;
    /**
     * <code>required int32 signal = 2;</code>
     */
    public boolean hasSignal() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required int32 signal = 2;</code>
     */
    public int getSignal() {
      return signal_;
    }

    // required int32 delay = 3;
    public static final int DELAY_FIELD_NUMBER = 3;
    private int delay_;
    /**
     * <code>required int32 delay = 3;</code>
     */
    public boolean hasDelay() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required int32 delay = 3;</code>
     */
    public int getDelay() {
      return delay_;
    }

    private void initFields() {
      text_ = "";
      signal_ = 0;
      delay_ = 0;
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasText()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasSignal()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasDelay()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getTextBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeInt32(2, signal_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeInt32(3, delay_);
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getTextBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, signal_);
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(3, delay_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.AMSuicideRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.AMSuicideRequestProto other = (org.apache.slider.api.proto.Messages.AMSuicideRequestProto) obj;

      boolean result = true;
      result = result && (hasText() == other.hasText());
      if (hasText()) {
        result = result && getText()
            .equals(other.getText());
      }
      result = result && (hasSignal() == other.hasSignal());
      if (hasSignal()) {
        result = result && (getSignal()
            == other.getSignal());
      }
      result = result && (hasDelay() == other.hasDelay());
      if (hasDelay()) {
        result = result && (getDelay()
            == other.getDelay());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasText()) {
        hash = (37 * hash) + TEXT_FIELD_NUMBER;
        hash = (53 * hash) + getText().hashCode();
      }
      if (hasSignal()) {
        hash = (37 * hash) + SIGNAL_FIELD_NUMBER;
        hash = (53 * hash) + getSignal();
      }
      if (hasDelay()) {
        hash = (37 * hash) + DELAY_FIELD_NUMBER;
        hash = (53 * hash) + getDelay();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto 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.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.AMSuicideRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.AMSuicideRequestProto}
     *
     * <pre>
     **
     * AM suicide
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.AMSuicideRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.AMSuicideRequestProto.class, org.apache.slider.api.proto.Messages.AMSuicideRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.AMSuicideRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        text_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        signal_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        delay_ = 0;
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.AMSuicideRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.AMSuicideRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.AMSuicideRequestProto build() {
        org.apache.slider.api.proto.Messages.AMSuicideRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.AMSuicideRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.AMSuicideRequestProto result = new org.apache.slider.api.proto.Messages.AMSuicideRequestProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.text_ = text_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.signal_ = signal_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.delay_ = delay_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.AMSuicideRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.AMSuicideRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.AMSuicideRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.AMSuicideRequestProto.getDefaultInstance()) return this;
        if (other.hasText()) {
          bitField0_ |= 0x00000001;
          text_ = other.text_;
          onChanged();
        }
        if (other.hasSignal()) {
          setSignal(other.getSignal());
        }
        if (other.hasDelay()) {
          setDelay(other.getDelay());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasText()) {
          
          return false;
        }
        if (!hasSignal()) {
          
          return false;
        }
        if (!hasDelay()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.AMSuicideRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.AMSuicideRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string text = 1;
      private java.lang.Object text_ = "";
      /**
       * <code>required string text = 1;</code>
       */
      public boolean hasText() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string text = 1;</code>
       */
      public java.lang.String getText() {
        java.lang.Object ref = text_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          text_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string text = 1;</code>
       */
      public com.google.protobuf.ByteString
          getTextBytes() {
        java.lang.Object ref = text_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          text_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder setText(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        text_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder clearText() {
        bitField0_ = (bitField0_ & ~0x00000001);
        text_ = getDefaultInstance().getText();
        onChanged();
        return this;
      }
      /**
       * <code>required string text = 1;</code>
       */
      public Builder setTextBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        text_ = value;
        onChanged();
        return this;
      }

      // required int32 signal = 2;
      private int signal_ ;
      /**
       * <code>required int32 signal = 2;</code>
       */
      public boolean hasSignal() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required int32 signal = 2;</code>
       */
      public int getSignal() {
        return signal_;
      }
      /**
       * <code>required int32 signal = 2;</code>
       */
      public Builder setSignal(int value) {
        bitField0_ |= 0x00000002;
        signal_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 signal = 2;</code>
       */
      public Builder clearSignal() {
        bitField0_ = (bitField0_ & ~0x00000002);
        signal_ = 0;
        onChanged();
        return this;
      }

      // required int32 delay = 3;
      private int delay_ ;
      /**
       * <code>required int32 delay = 3;</code>
       */
      public boolean hasDelay() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required int32 delay = 3;</code>
       */
      public int getDelay() {
        return delay_;
      }
      /**
       * <code>required int32 delay = 3;</code>
       */
      public Builder setDelay(int value) {
        bitField0_ |= 0x00000004;
        delay_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required int32 delay = 3;</code>
       */
      public Builder clearDelay() {
        bitField0_ = (bitField0_ & ~0x00000004);
        delay_ = 0;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.AMSuicideRequestProto)
    }

    static {
      defaultInstance = new AMSuicideRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.AMSuicideRequestProto)
  }

  public interface AMSuicideResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {
  }
  /**
   * Protobuf type {@code org.apache.slider.api.AMSuicideResponseProto}
   *
   * <pre>
   **
   * AM suicide reply. For this to be returned implies
   * a failure of the AM to kill itself
   * </pre>
   */
  public static final class AMSuicideResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements AMSuicideResponseProtoOrBuilder {
    // Use AMSuicideResponseProto.newBuilder() to construct.
    private AMSuicideResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private AMSuicideResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final AMSuicideResponseProto defaultInstance;
    public static AMSuicideResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public AMSuicideResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private AMSuicideResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            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.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.AMSuicideResponseProto.class, org.apache.slider.api.proto.Messages.AMSuicideResponseProto.Builder.class);
    }

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

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

    private void initFields() {
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.AMSuicideResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.AMSuicideResponseProto other = (org.apache.slider.api.proto.Messages.AMSuicideResponseProto) obj;

      boolean result = true;
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto 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.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.AMSuicideResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.AMSuicideResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.AMSuicideResponseProto}
     *
     * <pre>
     **
     * AM suicide reply. For this to be returned implies
     * a failure of the AM to kill itself
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.AMSuicideResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.AMSuicideResponseProto.class, org.apache.slider.api.proto.Messages.AMSuicideResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.AMSuicideResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_AMSuicideResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.AMSuicideResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.AMSuicideResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.AMSuicideResponseProto build() {
        org.apache.slider.api.proto.Messages.AMSuicideResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.AMSuicideResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.AMSuicideResponseProto result = new org.apache.slider.api.proto.Messages.AMSuicideResponseProto(this);
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.AMSuicideResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.AMSuicideResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.AMSuicideResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.AMSuicideResponseProto.getDefaultInstance()) return this;
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.AMSuicideResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.AMSuicideResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.AMSuicideResponseProto)
    }

    static {
      defaultInstance = new AMSuicideResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.AMSuicideResponseProto)
  }

  public interface GetInstanceDefinitionRequestProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetInstanceDefinitionRequestProto}
   *
   * <pre>
   **
   * Ask for the instance definition details
   * </pre>
   */
  public static final class GetInstanceDefinitionRequestProto extends
      com.google.protobuf.GeneratedMessage
      implements GetInstanceDefinitionRequestProtoOrBuilder {
    // Use GetInstanceDefinitionRequestProto.newBuilder() to construct.
    private GetInstanceDefinitionRequestProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetInstanceDefinitionRequestProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetInstanceDefinitionRequestProto defaultInstance;
    public static GetInstanceDefinitionRequestProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetInstanceDefinitionRequestProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetInstanceDefinitionRequestProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            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.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.class, org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.Builder.class);
    }

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

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

    private void initFields() {
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto other = (org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto) obj;

      boolean result = true;
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto 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.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetInstanceDefinitionRequestProto}
     *
     * <pre>
     **
     * Ask for the instance definition details
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.class, org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto build() {
        org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto result = new org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto(this);
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto.getDefaultInstance()) return this;
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetInstanceDefinitionRequestProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetInstanceDefinitionRequestProto)
    }

    static {
      defaultInstance = new GetInstanceDefinitionRequestProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetInstanceDefinitionRequestProto)
  }

  public interface GetInstanceDefinitionResponseProtoOrBuilder
      extends com.google.protobuf.MessageOrBuilder {

    // required string internal = 1;
    /**
     * <code>required string internal = 1;</code>
     */
    boolean hasInternal();
    /**
     * <code>required string internal = 1;</code>
     */
    java.lang.String getInternal();
    /**
     * <code>required string internal = 1;</code>
     */
    com.google.protobuf.ByteString
        getInternalBytes();

    // required string resources = 2;
    /**
     * <code>required string resources = 2;</code>
     */
    boolean hasResources();
    /**
     * <code>required string resources = 2;</code>
     */
    java.lang.String getResources();
    /**
     * <code>required string resources = 2;</code>
     */
    com.google.protobuf.ByteString
        getResourcesBytes();

    // required string application = 3;
    /**
     * <code>required string application = 3;</code>
     */
    boolean hasApplication();
    /**
     * <code>required string application = 3;</code>
     */
    java.lang.String getApplication();
    /**
     * <code>required string application = 3;</code>
     */
    com.google.protobuf.ByteString
        getApplicationBytes();
  }
  /**
   * Protobuf type {@code org.apache.slider.api.GetInstanceDefinitionResponseProto}
   *
   * <pre>
   **
   * Get the definition back as three separate JSON strings
   * </pre>
   */
  public static final class GetInstanceDefinitionResponseProto extends
      com.google.protobuf.GeneratedMessage
      implements GetInstanceDefinitionResponseProtoOrBuilder {
    // Use GetInstanceDefinitionResponseProto.newBuilder() to construct.
    private GetInstanceDefinitionResponseProto(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
      super(builder);
      this.unknownFields = builder.getUnknownFields();
    }
    private GetInstanceDefinitionResponseProto(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }

    private static final GetInstanceDefinitionResponseProto defaultInstance;
    public static GetInstanceDefinitionResponseProto getDefaultInstance() {
      return defaultInstance;
    }

    public GetInstanceDefinitionResponseProto getDefaultInstanceForType() {
      return defaultInstance;
    }

    private final com.google.protobuf.UnknownFieldSet unknownFields;
    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
        getUnknownFields() {
      return this.unknownFields;
    }
    private GetInstanceDefinitionResponseProto(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      initFields();
      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;
            default: {
              if (!parseUnknownField(input, unknownFields,
                                     extensionRegistry, tag)) {
                done = true;
              }
              break;
            }
            case 10: {
              bitField0_ |= 0x00000001;
              internal_ = input.readBytes();
              break;
            }
            case 18: {
              bitField0_ |= 0x00000002;
              resources_ = input.readBytes();
              break;
            }
            case 26: {
              bitField0_ |= 0x00000004;
              application_ = input.readBytes();
              break;
            }
          }
        }
      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
        throw e.setUnfinishedMessage(this);
      } catch (java.io.IOException e) {
        throw new com.google.protobuf.InvalidProtocolBufferException(
            e.getMessage()).setUnfinishedMessage(this);
      } finally {
        this.unknownFields = unknownFields.build();
        makeExtensionsImmutable();
      }
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_descriptor;
    }

    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.class, org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.Builder.class);
    }

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

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

    private int bitField0_;
    // required string internal = 1;
    public static final int INTERNAL_FIELD_NUMBER = 1;
    private java.lang.Object internal_;
    /**
     * <code>required string internal = 1;</code>
     */
    public boolean hasInternal() {
      return ((bitField0_ & 0x00000001) == 0x00000001);
    }
    /**
     * <code>required string internal = 1;</code>
     */
    public java.lang.String getInternal() {
      java.lang.Object ref = internal_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          internal_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string internal = 1;</code>
     */
    public com.google.protobuf.ByteString
        getInternalBytes() {
      java.lang.Object ref = internal_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        internal_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required string resources = 2;
    public static final int RESOURCES_FIELD_NUMBER = 2;
    private java.lang.Object resources_;
    /**
     * <code>required string resources = 2;</code>
     */
    public boolean hasResources() {
      return ((bitField0_ & 0x00000002) == 0x00000002);
    }
    /**
     * <code>required string resources = 2;</code>
     */
    public java.lang.String getResources() {
      java.lang.Object ref = resources_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          resources_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string resources = 2;</code>
     */
    public com.google.protobuf.ByteString
        getResourcesBytes() {
      java.lang.Object ref = resources_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        resources_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    // required string application = 3;
    public static final int APPLICATION_FIELD_NUMBER = 3;
    private java.lang.Object application_;
    /**
     * <code>required string application = 3;</code>
     */
    public boolean hasApplication() {
      return ((bitField0_ & 0x00000004) == 0x00000004);
    }
    /**
     * <code>required string application = 3;</code>
     */
    public java.lang.String getApplication() {
      java.lang.Object ref = application_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          application_ = s;
        }
        return s;
      }
    }
    /**
     * <code>required string application = 3;</code>
     */
    public com.google.protobuf.ByteString
        getApplicationBytes() {
      java.lang.Object ref = application_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        application_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private void initFields() {
      internal_ = "";
      resources_ = "";
      application_ = "";
    }
    private byte memoizedIsInitialized = -1;
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized != -1) return isInitialized == 1;

      if (!hasInternal()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasResources()) {
        memoizedIsInitialized = 0;
        return false;
      }
      if (!hasApplication()) {
        memoizedIsInitialized = 0;
        return false;
      }
      memoizedIsInitialized = 1;
      return true;
    }

    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      getSerializedSize();
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        output.writeBytes(1, getInternalBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        output.writeBytes(2, getResourcesBytes());
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        output.writeBytes(3, getApplicationBytes());
      }
      getUnknownFields().writeTo(output);
    }

    private int memoizedSerializedSize = -1;
    public int getSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) == 0x00000001)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(1, getInternalBytes());
      }
      if (((bitField0_ & 0x00000002) == 0x00000002)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(2, getResourcesBytes());
      }
      if (((bitField0_ & 0x00000004) == 0x00000004)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBytesSize(3, getApplicationBytes());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSerializedSize = size;
      return size;
    }

    private static final long serialVersionUID = 0L;
    @java.lang.Override
    protected java.lang.Object writeReplace()
        throws java.io.ObjectStreamException {
      return super.writeReplace();
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto)) {
        return super.equals(obj);
      }
      org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto other = (org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto) obj;

      boolean result = true;
      result = result && (hasInternal() == other.hasInternal());
      if (hasInternal()) {
        result = result && getInternal()
            .equals(other.getInternal());
      }
      result = result && (hasResources() == other.hasResources());
      if (hasResources()) {
        result = result && getResources()
            .equals(other.getResources());
      }
      result = result && (hasApplication() == other.hasApplication());
      if (hasApplication()) {
        result = result && getApplication()
            .equals(other.getApplication());
      }
      result = result &&
          getUnknownFields().equals(other.getUnknownFields());
      return result;
    }

    private int memoizedHashCode = 0;
    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptorForType().hashCode();
      if (hasInternal()) {
        hash = (37 * hash) + INTERNAL_FIELD_NUMBER;
        hash = (53 * hash) + getInternal().hashCode();
      }
      if (hasResources()) {
        hash = (37 * hash) + RESOURCES_FIELD_NUMBER;
        hash = (53 * hash) + getResources().hashCode();
      }
      if (hasApplication()) {
        hash = (37 * hash) + APPLICATION_FIELD_NUMBER;
        hash = (53 * hash) + getApplication().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto 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.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseDelimitedFrom(input, extensionRegistry);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return PARSER.parseFrom(input);
    }
    public static org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return PARSER.parseFrom(input, extensionRegistry);
    }

    public static Builder newBuilder() { return Builder.create(); }
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder(org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto prototype) {
      return newBuilder().mergeFrom(prototype);
    }
    public Builder toBuilder() { return newBuilder(this); }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code org.apache.slider.api.GetInstanceDefinitionResponseProto}
     *
     * <pre>
     **
     * Get the definition back as three separate JSON strings
     * </pre>
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProtoOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_descriptor;
      }

      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.class, org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.Builder.class);
      }

      // Construct using org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
        }
      }
      private static Builder create() {
        return new Builder();
      }

      public Builder clear() {
        super.clear();
        internal_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        resources_ = "";
        bitField0_ = (bitField0_ & ~0x00000002);
        application_ = "";
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }

      public Builder clone() {
        return create().mergeFrom(buildPartial());
      }

      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.slider.api.proto.Messages.internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_descriptor;
      }

      public org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto getDefaultInstanceForType() {
        return org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.getDefaultInstance();
      }

      public org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto build() {
        org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      public org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto buildPartial() {
        org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto result = new org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
          to_bitField0_ |= 0x00000001;
        }
        result.internal_ = internal_;
        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
          to_bitField0_ |= 0x00000002;
        }
        result.resources_ = resources_;
        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
          to_bitField0_ |= 0x00000004;
        }
        result.application_ = application_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto) {
          return mergeFrom((org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto other) {
        if (other == org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto.getDefaultInstance()) return this;
        if (other.hasInternal()) {
          bitField0_ |= 0x00000001;
          internal_ = other.internal_;
          onChanged();
        }
        if (other.hasResources()) {
          bitField0_ |= 0x00000002;
          resources_ = other.resources_;
          onChanged();
        }
        if (other.hasApplication()) {
          bitField0_ |= 0x00000004;
          application_ = other.application_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        return this;
      }

      public final boolean isInitialized() {
        if (!hasInternal()) {
          
          return false;
        }
        if (!hasResources()) {
          
          return false;
        }
        if (!hasApplication()) {
          
          return false;
        }
        return true;
      }

      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto parsedMessage = null;
        try {
          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          parsedMessage = (org.apache.slider.api.proto.Messages.GetInstanceDefinitionResponseProto) e.getUnfinishedMessage();
          throw e;
        } finally {
          if (parsedMessage != null) {
            mergeFrom(parsedMessage);
          }
        }
        return this;
      }
      private int bitField0_;

      // required string internal = 1;
      private java.lang.Object internal_ = "";
      /**
       * <code>required string internal = 1;</code>
       */
      public boolean hasInternal() {
        return ((bitField0_ & 0x00000001) == 0x00000001);
      }
      /**
       * <code>required string internal = 1;</code>
       */
      public java.lang.String getInternal() {
        java.lang.Object ref = internal_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          internal_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string internal = 1;</code>
       */
      public com.google.protobuf.ByteString
          getInternalBytes() {
        java.lang.Object ref = internal_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          internal_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string internal = 1;</code>
       */
      public Builder setInternal(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        internal_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string internal = 1;</code>
       */
      public Builder clearInternal() {
        bitField0_ = (bitField0_ & ~0x00000001);
        internal_ = getDefaultInstance().getInternal();
        onChanged();
        return this;
      }
      /**
       * <code>required string internal = 1;</code>
       */
      public Builder setInternalBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        internal_ = value;
        onChanged();
        return this;
      }

      // required string resources = 2;
      private java.lang.Object resources_ = "";
      /**
       * <code>required string resources = 2;</code>
       */
      public boolean hasResources() {
        return ((bitField0_ & 0x00000002) == 0x00000002);
      }
      /**
       * <code>required string resources = 2;</code>
       */
      public java.lang.String getResources() {
        java.lang.Object ref = resources_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          resources_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string resources = 2;</code>
       */
      public com.google.protobuf.ByteString
          getResourcesBytes() {
        java.lang.Object ref = resources_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          resources_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string resources = 2;</code>
       */
      public Builder setResources(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000002;
        resources_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string resources = 2;</code>
       */
      public Builder clearResources() {
        bitField0_ = (bitField0_ & ~0x00000002);
        resources_ = getDefaultInstance().getResources();
        onChanged();
        return this;
      }
      /**
       * <code>required string resources = 2;</code>
       */
      public Builder setResourcesBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000002;
        resources_ = value;
        onChanged();
        return this;
      }

      // required string application = 3;
      private java.lang.Object application_ = "";
      /**
       * <code>required string application = 3;</code>
       */
      public boolean hasApplication() {
        return ((bitField0_ & 0x00000004) == 0x00000004);
      }
      /**
       * <code>required string application = 3;</code>
       */
      public java.lang.String getApplication() {
        java.lang.Object ref = application_;
        if (!(ref instanceof java.lang.String)) {
          java.lang.String s = ((com.google.protobuf.ByteString) ref)
              .toStringUtf8();
          application_ = s;
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>required string application = 3;</code>
       */
      public com.google.protobuf.ByteString
          getApplicationBytes() {
        java.lang.Object ref = application_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          application_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>required string application = 3;</code>
       */
      public Builder setApplication(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        application_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>required string application = 3;</code>
       */
      public Builder clearApplication() {
        bitField0_ = (bitField0_ & ~0x00000004);
        application_ = getDefaultInstance().getApplication();
        onChanged();
        return this;
      }
      /**
       * <code>required string application = 3;</code>
       */
      public Builder setApplicationBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000004;
        application_ = value;
        onChanged();
        return this;
      }

      // @@protoc_insertion_point(builder_scope:org.apache.slider.api.GetInstanceDefinitionResponseProto)
    }

    static {
      defaultInstance = new GetInstanceDefinitionResponseProto(true);
      defaultInstance.initFields();
    }

    // @@protoc_insertion_point(class_scope:org.apache.slider.api.GetInstanceDefinitionResponseProto)
  }

  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_RoleInstanceState_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_RoleInstanceState_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_StopClusterRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_StopClusterRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_StopClusterResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_StopClusterResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_FlexClusterRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_FlexClusterRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_FlexClusterResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_FlexClusterResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetNodeRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetNodeRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetNodeResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetNodeResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetClusterNodesRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetClusterNodesRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetClusterNodesResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetClusterNodesResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_EchoRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_EchoRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_EchoResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_EchoResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_KillContainerRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_KillContainerRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_KillContainerResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_KillContainerResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_AMSuicideRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_AMSuicideRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_AMSuicideResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_AMSuicideResponseProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_fieldAccessorTable;
  private static com.google.protobuf.Descriptors.Descriptor
    internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_descriptor;
  private static
    com.google.protobuf.GeneratedMessage.FieldAccessorTable
      internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_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\033SliderClusterMessages.proto\022\025org.apach" +
      "e.slider.api\"\203\002\n\021RoleInstanceState\022\014\n\004na" +
      "me\030\001 \002(\t\022\014\n\004role\030\002 \001(\t\022\r\n\005state\030\004 \002(\r\022\020\n" +
      "\010exitCode\030\005 \002(\r\022\017\n\007command\030\006 \001(\t\022\023\n\013diag" +
      "nostics\030\007 \001(\t\022\016\n\006output\030\010 \003(\t\022\023\n\013environ" +
      "ment\030\t \003(\t\022\016\n\006roleId\030\n \002(\r\022\020\n\010released\030\013" +
      " \002(\010\022\022\n\ncreateTime\030\014 \002(\003\022\021\n\tstartTime\030\r " +
      "\002(\003\022\014\n\004host\030\016 \002(\t\022\017\n\007hostURL\030\017 \002(\t\"*\n\027St" +
      "opClusterRequestProto\022\017\n\007message\030\001 \002(\t\"\032" +
      "\n\030StopClusterResponseProto\".\n\027FlexCluste",
      "rRequestProto\022\023\n\013clusterSpec\030\001 \002(\t\",\n\030Fl" +
      "exClusterResponseProto\022\020\n\010response\030\001 \002(\010" +
      "\"\"\n GetJSONClusterStatusRequestProto\"8\n!" +
      "GetJSONClusterStatusResponseProto\022\023\n\013clu" +
      "sterSpec\030\001 \002(\t\"/\n\037ListNodeUUIDsByRoleReq" +
      "uestProto\022\014\n\004role\030\001 \002(\t\"0\n ListNodeUUIDs" +
      "ByRoleResponseProto\022\014\n\004uuid\030\001 \003(\t\"#\n\023Get" +
      "NodeRequestProto\022\014\n\004uuid\030\001 \002(\t\"U\n\024GetNod" +
      "eResponseProto\022=\n\013clusterNode\030\001 \002(\0132(.or" +
      "g.apache.slider.api.RoleInstanceState\"+\n",
      "\033GetClusterNodesRequestProto\022\014\n\004uuid\030\001 \003" +
      "(\t\"]\n\034GetClusterNodesResponseProto\022=\n\013cl" +
      "usterNode\030\001 \003(\0132(.org.apache.slider.api." +
      "RoleInstanceState\" \n\020EchoRequestProto\022\014\n" +
      "\004text\030\001 \002(\t\"!\n\021EchoResponseProto\022\014\n\004text" +
      "\030\001 \002(\t\"\'\n\031KillContainerRequestProto\022\n\n\002i" +
      "d\030\001 \002(\t\"-\n\032KillContainerResponseProto\022\017\n" +
      "\007success\030\001 \002(\010\"D\n\025AMSuicideRequestProto\022" +
      "\014\n\004text\030\001 \002(\t\022\016\n\006signal\030\002 \002(\005\022\r\n\005delay\030\003" +
      " \002(\005\"\030\n\026AMSuicideResponseProto\"#\n!GetIns",
      "tanceDefinitionRequestProto\"^\n\"GetInstan" +
      "ceDefinitionResponseProto\022\020\n\010internal\030\001 " +
      "\002(\t\022\021\n\tresources\030\002 \002(\t\022\023\n\013application\030\003 " +
      "\002(\tB-\n\033org.apache.slider.api.protoB\010Mess" +
      "ages\210\001\001\240\001\001"
    };
    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
      new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
        public com.google.protobuf.ExtensionRegistry assignDescriptors(
            com.google.protobuf.Descriptors.FileDescriptor root) {
          descriptor = root;
          internal_static_org_apache_slider_api_RoleInstanceState_descriptor =
            getDescriptor().getMessageTypes().get(0);
          internal_static_org_apache_slider_api_RoleInstanceState_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_RoleInstanceState_descriptor,
              new java.lang.String[] { "Name", "Role", "State", "ExitCode", "Command", "Diagnostics", "Output", "Environment", "RoleId", "Released", "CreateTime", "StartTime", "Host", "HostURL", });
          internal_static_org_apache_slider_api_StopClusterRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(1);
          internal_static_org_apache_slider_api_StopClusterRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_StopClusterRequestProto_descriptor,
              new java.lang.String[] { "Message", });
          internal_static_org_apache_slider_api_StopClusterResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(2);
          internal_static_org_apache_slider_api_StopClusterResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_StopClusterResponseProto_descriptor,
              new java.lang.String[] { });
          internal_static_org_apache_slider_api_FlexClusterRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(3);
          internal_static_org_apache_slider_api_FlexClusterRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_FlexClusterRequestProto_descriptor,
              new java.lang.String[] { "ClusterSpec", });
          internal_static_org_apache_slider_api_FlexClusterResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(4);
          internal_static_org_apache_slider_api_FlexClusterResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_FlexClusterResponseProto_descriptor,
              new java.lang.String[] { "Response", });
          internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(5);
          internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetJSONClusterStatusRequestProto_descriptor,
              new java.lang.String[] { });
          internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(6);
          internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetJSONClusterStatusResponseProto_descriptor,
              new java.lang.String[] { "ClusterSpec", });
          internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(7);
          internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_ListNodeUUIDsByRoleRequestProto_descriptor,
              new java.lang.String[] { "Role", });
          internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(8);
          internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_ListNodeUUIDsByRoleResponseProto_descriptor,
              new java.lang.String[] { "Uuid", });
          internal_static_org_apache_slider_api_GetNodeRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(9);
          internal_static_org_apache_slider_api_GetNodeRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetNodeRequestProto_descriptor,
              new java.lang.String[] { "Uuid", });
          internal_static_org_apache_slider_api_GetNodeResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(10);
          internal_static_org_apache_slider_api_GetNodeResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetNodeResponseProto_descriptor,
              new java.lang.String[] { "ClusterNode", });
          internal_static_org_apache_slider_api_GetClusterNodesRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(11);
          internal_static_org_apache_slider_api_GetClusterNodesRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetClusterNodesRequestProto_descriptor,
              new java.lang.String[] { "Uuid", });
          internal_static_org_apache_slider_api_GetClusterNodesResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(12);
          internal_static_org_apache_slider_api_GetClusterNodesResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetClusterNodesResponseProto_descriptor,
              new java.lang.String[] { "ClusterNode", });
          internal_static_org_apache_slider_api_EchoRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(13);
          internal_static_org_apache_slider_api_EchoRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_EchoRequestProto_descriptor,
              new java.lang.String[] { "Text", });
          internal_static_org_apache_slider_api_EchoResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(14);
          internal_static_org_apache_slider_api_EchoResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_EchoResponseProto_descriptor,
              new java.lang.String[] { "Text", });
          internal_static_org_apache_slider_api_KillContainerRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(15);
          internal_static_org_apache_slider_api_KillContainerRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_KillContainerRequestProto_descriptor,
              new java.lang.String[] { "Id", });
          internal_static_org_apache_slider_api_KillContainerResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(16);
          internal_static_org_apache_slider_api_KillContainerResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_KillContainerResponseProto_descriptor,
              new java.lang.String[] { "Success", });
          internal_static_org_apache_slider_api_AMSuicideRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(17);
          internal_static_org_apache_slider_api_AMSuicideRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_AMSuicideRequestProto_descriptor,
              new java.lang.String[] { "Text", "Signal", "Delay", });
          internal_static_org_apache_slider_api_AMSuicideResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(18);
          internal_static_org_apache_slider_api_AMSuicideResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_AMSuicideResponseProto_descriptor,
              new java.lang.String[] { });
          internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_descriptor =
            getDescriptor().getMessageTypes().get(19);
          internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetInstanceDefinitionRequestProto_descriptor,
              new java.lang.String[] { });
          internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_descriptor =
            getDescriptor().getMessageTypes().get(20);
          internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_fieldAccessorTable = new
            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
              internal_static_org_apache_slider_api_GetInstanceDefinitionResponseProto_descriptor,
              new java.lang.String[] { "Internal", "Resources", "Application", });
          return null;
        }
      };
    com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
        }, assigner);
  }

  // @@protoc_insertion_point(outer_class_scope)
}
