/**
 * Autogenerated by Thrift Compiler (0.9.2)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package backtype.storm.generated;

import org.apache.thrift.scheme.IScheme;
import org.apache.thrift.scheme.SchemeFactory;
import org.apache.thrift.scheme.StandardScheme;

import org.apache.thrift.scheme.TupleScheme;
import org.apache.thrift.protocol.TTupleProtocol;
import org.apache.thrift.protocol.TProtocolException;
import org.apache.thrift.EncodingUtils;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import org.apache.thrift.server.AbstractNonblockingServer.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.annotation.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-10-20")
public class WorkerSummary implements org.apache.thrift.TBase<WorkerSummary, WorkerSummary._Fields>, java.io.Serializable, Cloneable, Comparable<WorkerSummary> {
  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("WorkerSummary");

  private static final org.apache.thrift.protocol.TField PORT_FIELD_DESC = new org.apache.thrift.protocol.TField("port", org.apache.thrift.protocol.TType.I32, (short)1);
  private static final org.apache.thrift.protocol.TField UPTIME_FIELD_DESC = new org.apache.thrift.protocol.TField("uptime", org.apache.thrift.protocol.TType.I32, (short)2);
  private static final org.apache.thrift.protocol.TField TOPOLOGY_FIELD_DESC = new org.apache.thrift.protocol.TField("topology", org.apache.thrift.protocol.TType.STRING, (short)3);
  private static final org.apache.thrift.protocol.TField TASKS_FIELD_DESC = new org.apache.thrift.protocol.TField("tasks", org.apache.thrift.protocol.TType.LIST, (short)4);

  private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
  static {
    schemes.put(StandardScheme.class, new WorkerSummaryStandardSchemeFactory());
    schemes.put(TupleScheme.class, new WorkerSummaryTupleSchemeFactory());
  }

  private int port; // required
  private int uptime; // required
  private String topology; // required
  private List<TaskComponent> tasks; // required

  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
    PORT((short)1, "port"),
    UPTIME((short)2, "uptime"),
    TOPOLOGY((short)3, "topology"),
    TASKS((short)4, "tasks");

    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

    static {
      for (_Fields field : EnumSet.allOf(_Fields.class)) {
        byName.put(field.getFieldName(), field);
      }
    }

    /**
     * Find the _Fields constant that matches fieldId, or null if its not found.
     */
    public static _Fields findByThriftId(int fieldId) {
      switch(fieldId) {
        case 1: // PORT
          return PORT;
        case 2: // UPTIME
          return UPTIME;
        case 3: // TOPOLOGY
          return TOPOLOGY;
        case 4: // TASKS
          return TASKS;
        default:
          return null;
      }
    }

    /**
     * Find the _Fields constant that matches fieldId, throwing an exception
     * if it is not found.
     */
    public static _Fields findByThriftIdOrThrow(int fieldId) {
      _Fields fields = findByThriftId(fieldId);
      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
      return fields;
    }

    /**
     * Find the _Fields constant that matches name, or null if its not found.
     */
    public static _Fields findByName(String name) {
      return byName.get(name);
    }

    private final short _thriftId;
    private final String _fieldName;

    _Fields(short thriftId, String fieldName) {
      _thriftId = thriftId;
      _fieldName = fieldName;
    }

    public short getThriftFieldId() {
      return _thriftId;
    }

    public String getFieldName() {
      return _fieldName;
    }
  }

  // isset id assignments
  private static final int __PORT_ISSET_ID = 0;
  private static final int __UPTIME_ISSET_ID = 1;
  private byte __isset_bitfield = 0;
  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
  static {
    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
    tmpMap.put(_Fields.PORT, new org.apache.thrift.meta_data.FieldMetaData("port", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
    tmpMap.put(_Fields.UPTIME, new org.apache.thrift.meta_data.FieldMetaData("uptime", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
    tmpMap.put(_Fields.TOPOLOGY, new org.apache.thrift.meta_data.FieldMetaData("topology", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
    tmpMap.put(_Fields.TASKS, new org.apache.thrift.meta_data.FieldMetaData("tasks", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
            new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, TaskComponent.class))));
    metaDataMap = Collections.unmodifiableMap(tmpMap);
    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(WorkerSummary.class, metaDataMap);
  }

  public WorkerSummary() {
  }

  public WorkerSummary(
    int port,
    int uptime,
    String topology,
    List<TaskComponent> tasks)
  {
    this();
    this.port = port;
    set_port_isSet(true);
    this.uptime = uptime;
    set_uptime_isSet(true);
    this.topology = topology;
    this.tasks = tasks;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public WorkerSummary(WorkerSummary other) {
    __isset_bitfield = other.__isset_bitfield;
    this.port = other.port;
    this.uptime = other.uptime;
    if (other.is_set_topology()) {
      this.topology = other.topology;
    }
    if (other.is_set_tasks()) {
      List<TaskComponent> __this__tasks = new ArrayList<TaskComponent>(other.tasks.size());
      for (TaskComponent other_element : other.tasks) {
        __this__tasks.add(new TaskComponent(other_element));
      }
      this.tasks = __this__tasks;
    }
  }

  public WorkerSummary deepCopy() {
    return new WorkerSummary(this);
  }

  @Override
  public void clear() {
    set_port_isSet(false);
    this.port = 0;
    set_uptime_isSet(false);
    this.uptime = 0;
    this.topology = null;
    this.tasks = null;
  }

  public int get_port() {
    return this.port;
  }

  public void set_port(int port) {
    this.port = port;
    set_port_isSet(true);
  }

  public void unset_port() {
    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PORT_ISSET_ID);
  }

  /** Returns true if field port is set (has been assigned a value) and false otherwise */
  public boolean is_set_port() {
    return EncodingUtils.testBit(__isset_bitfield, __PORT_ISSET_ID);
  }

  public void set_port_isSet(boolean value) {
    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PORT_ISSET_ID, value);
  }

  public int get_uptime() {
    return this.uptime;
  }

  public void set_uptime(int uptime) {
    this.uptime = uptime;
    set_uptime_isSet(true);
  }

  public void unset_uptime() {
    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __UPTIME_ISSET_ID);
  }

  /** Returns true if field uptime is set (has been assigned a value) and false otherwise */
  public boolean is_set_uptime() {
    return EncodingUtils.testBit(__isset_bitfield, __UPTIME_ISSET_ID);
  }

  public void set_uptime_isSet(boolean value) {
    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __UPTIME_ISSET_ID, value);
  }

  public String get_topology() {
    return this.topology;
  }

  public void set_topology(String topology) {
    this.topology = topology;
  }

  public void unset_topology() {
    this.topology = null;
  }

  /** Returns true if field topology is set (has been assigned a value) and false otherwise */
  public boolean is_set_topology() {
    return this.topology != null;
  }

  public void set_topology_isSet(boolean value) {
    if (!value) {
      this.topology = null;
    }
  }

  public int get_tasks_size() {
    return (this.tasks == null) ? 0 : this.tasks.size();
  }

  public java.util.Iterator<TaskComponent> get_tasks_iterator() {
    return (this.tasks == null) ? null : this.tasks.iterator();
  }

  public void add_to_tasks(TaskComponent elem) {
    if (this.tasks == null) {
      this.tasks = new ArrayList<TaskComponent>();
    }
    this.tasks.add(elem);
  }

  public List<TaskComponent> get_tasks() {
    return this.tasks;
  }

  public void set_tasks(List<TaskComponent> tasks) {
    this.tasks = tasks;
  }

  public void unset_tasks() {
    this.tasks = null;
  }

  /** Returns true if field tasks is set (has been assigned a value) and false otherwise */
  public boolean is_set_tasks() {
    return this.tasks != null;
  }

  public void set_tasks_isSet(boolean value) {
    if (!value) {
      this.tasks = null;
    }
  }

  public void setFieldValue(_Fields field, Object value) {
    switch (field) {
    case PORT:
      if (value == null) {
        unset_port();
      } else {
        set_port((Integer)value);
      }
      break;

    case UPTIME:
      if (value == null) {
        unset_uptime();
      } else {
        set_uptime((Integer)value);
      }
      break;

    case TOPOLOGY:
      if (value == null) {
        unset_topology();
      } else {
        set_topology((String)value);
      }
      break;

    case TASKS:
      if (value == null) {
        unset_tasks();
      } else {
        set_tasks((List<TaskComponent>)value);
      }
      break;

    }
  }

  public Object getFieldValue(_Fields field) {
    switch (field) {
    case PORT:
      return Integer.valueOf(get_port());

    case UPTIME:
      return Integer.valueOf(get_uptime());

    case TOPOLOGY:
      return get_topology();

    case TASKS:
      return get_tasks();

    }
    throw new IllegalStateException();
  }

  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
  public boolean isSet(_Fields field) {
    if (field == null) {
      throw new IllegalArgumentException();
    }

    switch (field) {
    case PORT:
      return is_set_port();
    case UPTIME:
      return is_set_uptime();
    case TOPOLOGY:
      return is_set_topology();
    case TASKS:
      return is_set_tasks();
    }
    throw new IllegalStateException();
  }

  @Override
  public boolean equals(Object that) {
    if (that == null)
      return false;
    if (that instanceof WorkerSummary)
      return this.equals((WorkerSummary)that);
    return false;
  }

  public boolean equals(WorkerSummary that) {
    if (that == null)
      return false;

    boolean this_present_port = true;
    boolean that_present_port = true;
    if (this_present_port || that_present_port) {
      if (!(this_present_port && that_present_port))
        return false;
      if (this.port != that.port)
        return false;
    }

    boolean this_present_uptime = true;
    boolean that_present_uptime = true;
    if (this_present_uptime || that_present_uptime) {
      if (!(this_present_uptime && that_present_uptime))
        return false;
      if (this.uptime != that.uptime)
        return false;
    }

    boolean this_present_topology = true && this.is_set_topology();
    boolean that_present_topology = true && that.is_set_topology();
    if (this_present_topology || that_present_topology) {
      if (!(this_present_topology && that_present_topology))
        return false;
      if (!this.topology.equals(that.topology))
        return false;
    }

    boolean this_present_tasks = true && this.is_set_tasks();
    boolean that_present_tasks = true && that.is_set_tasks();
    if (this_present_tasks || that_present_tasks) {
      if (!(this_present_tasks && that_present_tasks))
        return false;
      if (!this.tasks.equals(that.tasks))
        return false;
    }

    return true;
  }

  @Override
  public int hashCode() {
    List<Object> list = new ArrayList<Object>();

    boolean present_port = true;
    list.add(present_port);
    if (present_port)
      list.add(port);

    boolean present_uptime = true;
    list.add(present_uptime);
    if (present_uptime)
      list.add(uptime);

    boolean present_topology = true && (is_set_topology());
    list.add(present_topology);
    if (present_topology)
      list.add(topology);

    boolean present_tasks = true && (is_set_tasks());
    list.add(present_tasks);
    if (present_tasks)
      list.add(tasks);

    return list.hashCode();
  }

  @Override
  public int compareTo(WorkerSummary other) {
    if (!getClass().equals(other.getClass())) {
      return getClass().getName().compareTo(other.getClass().getName());
    }

    int lastComparison = 0;

    lastComparison = Boolean.valueOf(is_set_port()).compareTo(other.is_set_port());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_port()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.port, other.port);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = Boolean.valueOf(is_set_uptime()).compareTo(other.is_set_uptime());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_uptime()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uptime, other.uptime);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = Boolean.valueOf(is_set_topology()).compareTo(other.is_set_topology());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_topology()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.topology, other.topology);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = Boolean.valueOf(is_set_tasks()).compareTo(other.is_set_tasks());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_tasks()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tasks, other.tasks);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    return 0;
  }

  public _Fields fieldForId(int fieldId) {
    return _Fields.findByThriftId(fieldId);
  }

  public void read(org.apache.thrift.protocol.TProtocol iprot) throws TException {
    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
  }

  public void write(org.apache.thrift.protocol.TProtocol oprot) throws TException {
    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder("WorkerSummary(");
    boolean first = true;

    sb.append("port:");
    sb.append(this.port);
    first = false;
    if (!first) sb.append(", ");
    sb.append("uptime:");
    sb.append(this.uptime);
    first = false;
    if (!first) sb.append(", ");
    sb.append("topology:");
    if (this.topology == null) {
      sb.append("null");
    } else {
      sb.append(this.topology);
    }
    first = false;
    if (!first) sb.append(", ");
    sb.append("tasks:");
    if (this.tasks == null) {
      sb.append("null");
    } else {
      sb.append(this.tasks);
    }
    first = false;
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws TException {
    // check for required fields
    if (!is_set_port()) {
      throw new TProtocolException("Required field 'port' is unset! Struct:" + toString());
    }

    if (!is_set_uptime()) {
      throw new TProtocolException("Required field 'uptime' is unset! Struct:" + toString());
    }

    if (!is_set_topology()) {
      throw new TProtocolException("Required field 'topology' is unset! Struct:" + toString());
    }

    if (!is_set_tasks()) {
      throw new TProtocolException("Required field 'tasks' is unset! Struct:" + toString());
    }

    // check for sub-struct validity
  }

  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
    try {
      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
    } catch (TException te) {
      throw new java.io.IOException(te);
    }
  }

  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
    try {
      // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
      __isset_bitfield = 0;
      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
    } catch (TException te) {
      throw new java.io.IOException(te);
    }
  }

  private static class WorkerSummaryStandardSchemeFactory implements SchemeFactory {
    public WorkerSummaryStandardScheme getScheme() {
      return new WorkerSummaryStandardScheme();
    }
  }

  private static class WorkerSummaryStandardScheme extends StandardScheme<WorkerSummary> {

    public void read(org.apache.thrift.protocol.TProtocol iprot, WorkerSummary struct) throws TException {
      org.apache.thrift.protocol.TField schemeField;
      iprot.readStructBegin();
      while (true)
      {
        schemeField = iprot.readFieldBegin();
        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
          break;
        }
        switch (schemeField.id) {
          case 1: // PORT
            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
              struct.port = iprot.readI32();
              struct.set_port_isSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 2: // UPTIME
            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
              struct.uptime = iprot.readI32();
              struct.set_uptime_isSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 3: // TOPOLOGY
            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
              struct.topology = iprot.readString();
              struct.set_topology_isSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 4: // TASKS
            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
              {
                org.apache.thrift.protocol.TList _list98 = iprot.readListBegin();
                struct.tasks = new ArrayList<TaskComponent>(_list98.size);
                TaskComponent _elem99;
                for (int _i100 = 0; _i100 < _list98.size; ++_i100)
                {
                  _elem99 = new TaskComponent();
                  _elem99.read(iprot);
                  struct.tasks.add(_elem99);
                }
                iprot.readListEnd();
              }
              struct.set_tasks_isSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          default:
            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
        }
        iprot.readFieldEnd();
      }
      iprot.readStructEnd();
      struct.validate();
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot, WorkerSummary struct) throws TException {
      struct.validate();

      oprot.writeStructBegin(STRUCT_DESC);
      oprot.writeFieldBegin(PORT_FIELD_DESC);
      oprot.writeI32(struct.port);
      oprot.writeFieldEnd();
      oprot.writeFieldBegin(UPTIME_FIELD_DESC);
      oprot.writeI32(struct.uptime);
      oprot.writeFieldEnd();
      if (struct.topology != null) {
        oprot.writeFieldBegin(TOPOLOGY_FIELD_DESC);
        oprot.writeString(struct.topology);
        oprot.writeFieldEnd();
      }
      if (struct.tasks != null) {
        oprot.writeFieldBegin(TASKS_FIELD_DESC);
        {
          oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.tasks.size()));
          for (TaskComponent _iter101 : struct.tasks)
          {
            _iter101.write(oprot);
          }
          oprot.writeListEnd();
        }
        oprot.writeFieldEnd();
      }
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }

  private static class WorkerSummaryTupleSchemeFactory implements SchemeFactory {
    public WorkerSummaryTupleScheme getScheme() {
      return new WorkerSummaryTupleScheme();
    }
  }

  private static class WorkerSummaryTupleScheme extends TupleScheme<WorkerSummary> {

    @Override
    public void write(org.apache.thrift.protocol.TProtocol prot, WorkerSummary struct) throws TException {
      TTupleProtocol oprot = (TTupleProtocol) prot;
      oprot.writeI32(struct.port);
      oprot.writeI32(struct.uptime);
      oprot.writeString(struct.topology);
      {
        oprot.writeI32(struct.tasks.size());
        for (TaskComponent _iter102 : struct.tasks)
        {
          _iter102.write(oprot);
        }
      }
    }

    @Override
    public void read(org.apache.thrift.protocol.TProtocol prot, WorkerSummary struct) throws TException {
      TTupleProtocol iprot = (TTupleProtocol) prot;
      struct.port = iprot.readI32();
      struct.set_port_isSet(true);
      struct.uptime = iprot.readI32();
      struct.set_uptime_isSet(true);
      struct.topology = iprot.readString();
      struct.set_topology_isSet(true);
      {
        org.apache.thrift.protocol.TList _list103 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
        struct.tasks = new ArrayList<TaskComponent>(_list103.size);
        TaskComponent _elem104;
        for (int _i105 = 0; _i105 < _list103.size; ++_i105)
        {
          _elem104 = new TaskComponent();
          _elem104.read(iprot);
          struct.tasks.add(_elem104);
        }
      }
      struct.set_tasks_isSet(true);
    }
  }

}

