/**
 * 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-7-27")
public class NettyMetric implements org.apache.thrift.TBase<NettyMetric, NettyMetric._Fields>, java.io.Serializable, Cloneable, Comparable<NettyMetric> {
  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("NettyMetric");

  private static final org.apache.thrift.protocol.TField CONNECTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("connections", org.apache.thrift.protocol.TType.MAP, (short)1);
  private static final org.apache.thrift.protocol.TField CONNECTION_NUM_FIELD_DESC = new org.apache.thrift.protocol.TField("connectionNum", org.apache.thrift.protocol.TType.I32, (short)2);

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

  private Map<String,MetricInfo> connections; // required
  private int connectionNum; // 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 {
    CONNECTIONS((short)1, "connections"),
    CONNECTION_NUM((short)2, "connectionNum");

    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: // CONNECTIONS
          return CONNECTIONS;
        case 2: // CONNECTION_NUM
          return CONNECTION_NUM;
        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 __CONNECTIONNUM_ISSET_ID = 0;
  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.CONNECTIONS, new org.apache.thrift.meta_data.FieldMetaData("connections", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, 
            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING), 
            new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, MetricInfo.class))));
    tmpMap.put(_Fields.CONNECTION_NUM, new org.apache.thrift.meta_data.FieldMetaData("connectionNum", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
    metaDataMap = Collections.unmodifiableMap(tmpMap);
    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(NettyMetric.class, metaDataMap);
  }

  public NettyMetric() {
  }

  public NettyMetric(
    Map<String,MetricInfo> connections,
    int connectionNum)
  {
    this();
    this.connections = connections;
    this.connectionNum = connectionNum;
    set_connectionNum_isSet(true);
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public NettyMetric(NettyMetric other) {
    __isset_bitfield = other.__isset_bitfield;
    if (other.is_set_connections()) {
      Map<String,MetricInfo> __this__connections = new HashMap<String,MetricInfo>(other.connections.size());
      for (Map.Entry<String, MetricInfo> other_element : other.connections.entrySet()) {

        String other_element_key = other_element.getKey();
        MetricInfo other_element_value = other_element.getValue();

        String __this__connections_copy_key = other_element_key;

        MetricInfo __this__connections_copy_value = new MetricInfo(other_element_value);

        __this__connections.put(__this__connections_copy_key, __this__connections_copy_value);
      }
      this.connections = __this__connections;
    }
    this.connectionNum = other.connectionNum;
  }

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

  @Override
  public void clear() {
    this.connections = null;
    set_connectionNum_isSet(false);
    this.connectionNum = 0;
  }

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

  public void put_to_connections(String key, MetricInfo val) {
    if (this.connections == null) {
      this.connections = new HashMap<String,MetricInfo>();
    }
    this.connections.put(key, val);
  }

  public Map<String,MetricInfo> get_connections() {
    return this.connections;
  }

  public void set_connections(Map<String,MetricInfo> connections) {
    this.connections = connections;
  }

  public void unset_connections() {
    this.connections = null;
  }

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

  public void set_connections_isSet(boolean value) {
    if (!value) {
      this.connections = null;
    }
  }

  public int get_connectionNum() {
    return this.connectionNum;
  }

  public void set_connectionNum(int connectionNum) {
    this.connectionNum = connectionNum;
    set_connectionNum_isSet(true);
  }

  public void unset_connectionNum() {
    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __CONNECTIONNUM_ISSET_ID);
  }

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

  public void set_connectionNum_isSet(boolean value) {
    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __CONNECTIONNUM_ISSET_ID, value);
  }

  public void setFieldValue(_Fields field, Object value) {
    switch (field) {
    case CONNECTIONS:
      if (value == null) {
        unset_connections();
      } else {
        set_connections((Map<String,MetricInfo>)value);
      }
      break;

    case CONNECTION_NUM:
      if (value == null) {
        unset_connectionNum();
      } else {
        set_connectionNum((Integer)value);
      }
      break;

    }
  }

  public Object getFieldValue(_Fields field) {
    switch (field) {
    case CONNECTIONS:
      return get_connections();

    case CONNECTION_NUM:
      return Integer.valueOf(get_connectionNum());

    }
    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 CONNECTIONS:
      return is_set_connections();
    case CONNECTION_NUM:
      return is_set_connectionNum();
    }
    throw new IllegalStateException();
  }

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

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

    boolean this_present_connections = true && this.is_set_connections();
    boolean that_present_connections = true && that.is_set_connections();
    if (this_present_connections || that_present_connections) {
      if (!(this_present_connections && that_present_connections))
        return false;
      if (!this.connections.equals(that.connections))
        return false;
    }

    boolean this_present_connectionNum = true;
    boolean that_present_connectionNum = true;
    if (this_present_connectionNum || that_present_connectionNum) {
      if (!(this_present_connectionNum && that_present_connectionNum))
        return false;
      if (this.connectionNum != that.connectionNum)
        return false;
    }

    return true;
  }

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

    boolean present_connections = true && (is_set_connections());
    list.add(present_connections);
    if (present_connections)
      list.add(connections);

    boolean present_connectionNum = true;
    list.add(present_connectionNum);
    if (present_connectionNum)
      list.add(connectionNum);

    return list.hashCode();
  }

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

    int lastComparison = 0;

    lastComparison = Boolean.valueOf(is_set_connections()).compareTo(other.is_set_connections());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_connections()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.connections, other.connections);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = Boolean.valueOf(is_set_connectionNum()).compareTo(other.is_set_connectionNum());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_connectionNum()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.connectionNum, other.connectionNum);
      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 org.apache.thrift.TException {
    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
  }

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

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

    sb.append("connections:");
    if (this.connections == null) {
      sb.append("null");
    } else {
      sb.append(this.connections);
    }
    first = false;
    if (!first) sb.append(", ");
    sb.append("connectionNum:");
    sb.append(this.connectionNum);
    first = false;
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws org.apache.thrift.TException {
    // check for required fields
    if (!is_set_connections()) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'connections' is unset! Struct:" + toString());
    }

    if (!is_set_connectionNum()) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'connectionNum' 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 (org.apache.thrift.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 (org.apache.thrift.TException te) {
      throw new java.io.IOException(te);
    }
  }

  private static class NettyMetricStandardSchemeFactory implements SchemeFactory {
    public NettyMetricStandardScheme getScheme() {
      return new NettyMetricStandardScheme();
    }
  }

  private static class NettyMetricStandardScheme extends StandardScheme<NettyMetric> {

    public void read(org.apache.thrift.protocol.TProtocol iprot, NettyMetric struct) throws org.apache.thrift.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: // CONNECTIONS
            if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
              {
                org.apache.thrift.protocol.TMap _map274 = iprot.readMapBegin();
                struct.connections = new HashMap<String,MetricInfo>(2*_map274.size);
                String _key275;
                MetricInfo _val276;
                for (int _i277 = 0; _i277 < _map274.size; ++_i277)
                {
                  _key275 = iprot.readString();
                  _val276 = new MetricInfo();
                  _val276.read(iprot);
                  struct.connections.put(_key275, _val276);
                }
                iprot.readMapEnd();
              }
              struct.set_connections_isSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 2: // CONNECTION_NUM
            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
              struct.connectionNum = iprot.readI32();
              struct.set_connectionNum_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, NettyMetric struct) throws org.apache.thrift.TException {
      struct.validate();

      oprot.writeStructBegin(STRUCT_DESC);
      if (struct.connections != null) {
        oprot.writeFieldBegin(CONNECTIONS_FIELD_DESC);
        {
          oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRUCT, struct.connections.size()));
          for (Map.Entry<String, MetricInfo> _iter278 : struct.connections.entrySet())
          {
            oprot.writeString(_iter278.getKey());
            _iter278.getValue().write(oprot);
          }
          oprot.writeMapEnd();
        }
        oprot.writeFieldEnd();
      }
      oprot.writeFieldBegin(CONNECTION_NUM_FIELD_DESC);
      oprot.writeI32(struct.connectionNum);
      oprot.writeFieldEnd();
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }

  private static class NettyMetricTupleSchemeFactory implements SchemeFactory {
    public NettyMetricTupleScheme getScheme() {
      return new NettyMetricTupleScheme();
    }
  }

  private static class NettyMetricTupleScheme extends TupleScheme<NettyMetric> {

    @Override
    public void write(org.apache.thrift.protocol.TProtocol prot, NettyMetric struct) throws org.apache.thrift.TException {
      TTupleProtocol oprot = (TTupleProtocol) prot;
      {
        oprot.writeI32(struct.connections.size());
        for (Map.Entry<String, MetricInfo> _iter279 : struct.connections.entrySet())
        {
          oprot.writeString(_iter279.getKey());
          _iter279.getValue().write(oprot);
        }
      }
      oprot.writeI32(struct.connectionNum);
    }

    @Override
    public void read(org.apache.thrift.protocol.TProtocol prot, NettyMetric struct) throws org.apache.thrift.TException {
      TTupleProtocol iprot = (TTupleProtocol) prot;
      {
        org.apache.thrift.protocol.TMap _map280 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
        struct.connections = new HashMap<String,MetricInfo>(2*_map280.size);
        String _key281;
        MetricInfo _val282;
        for (int _i283 = 0; _i283 < _map280.size; ++_i283)
        {
          _key281 = iprot.readString();
          _val282 = new MetricInfo();
          _val282.read(iprot);
          struct.connections.put(_key281, _val282);
        }
      }
      struct.set_connections_isSet(true);
      struct.connectionNum = iprot.readI32();
      struct.set_connectionNum_isSet(true);
    }
  }

}

