/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// 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)
}
