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

import org.apache.commons.lang.builder.HashCodeBuilder;
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.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.thrift.*;
import org.apache.thrift.async.*;
import org.apache.thrift.meta_data.*;
import org.apache.thrift.transport.*;
import org.apache.thrift.protocol.*;

public class BoltStats implements TBase<BoltStats, BoltStats._Fields>, java.io.Serializable, Cloneable {
  private static final TStruct STRUCT_DESC = new TStruct("BoltStats");

  private static final TField ACKED_FIELD_DESC = new TField("acked", TType.MAP, (short)1);
  private static final TField FAILED_FIELD_DESC = new TField("failed", TType.MAP, (short)2);
  private static final TField PROCESS_MS_AVG_FIELD_DESC = new TField("process_ms_avg", TType.MAP, (short)3);

  private Map<String,Map<GlobalStreamId,Long>> acked;
  private Map<String,Map<GlobalStreamId,Long>> failed;
  private Map<String,Map<GlobalStreamId,Double>> process_ms_avg;

  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
  public enum _Fields implements TFieldIdEnum {
    ACKED((short)1, "acked"),
    FAILED((short)2, "failed"),
    PROCESS_MS_AVG((short)3, "process_ms_avg");

    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: // ACKED
          return ACKED;
        case 2: // FAILED
          return FAILED;
        case 3: // PROCESS_MS_AVG
          return PROCESS_MS_AVG;
        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

  public static final Map<_Fields, FieldMetaData> metaDataMap;
  static {
    Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class);
    tmpMap.put(_Fields.ACKED, new FieldMetaData("acked", TFieldRequirementType.REQUIRED, 
        new MapMetaData(TType.MAP, 
            new FieldValueMetaData(TType.STRING), 
            new MapMetaData(TType.MAP, 
                new StructMetaData(TType.STRUCT, GlobalStreamId.class), 
                new FieldValueMetaData(TType.I64)))));
    tmpMap.put(_Fields.FAILED, new FieldMetaData("failed", TFieldRequirementType.REQUIRED, 
        new MapMetaData(TType.MAP, 
            new FieldValueMetaData(TType.STRING), 
            new MapMetaData(TType.MAP, 
                new StructMetaData(TType.STRUCT, GlobalStreamId.class), 
                new FieldValueMetaData(TType.I64)))));
    tmpMap.put(_Fields.PROCESS_MS_AVG, new FieldMetaData("process_ms_avg", TFieldRequirementType.REQUIRED, 
        new MapMetaData(TType.MAP, 
            new FieldValueMetaData(TType.STRING), 
            new MapMetaData(TType.MAP, 
                new StructMetaData(TType.STRUCT, GlobalStreamId.class), 
                new FieldValueMetaData(TType.DOUBLE)))));
    metaDataMap = Collections.unmodifiableMap(tmpMap);
    FieldMetaData.addStructMetaDataMap(BoltStats.class, metaDataMap);
  }

  public BoltStats() {
  }

  public BoltStats(
    Map<String,Map<GlobalStreamId,Long>> acked,
    Map<String,Map<GlobalStreamId,Long>> failed,
    Map<String,Map<GlobalStreamId,Double>> process_ms_avg)
  {
    this();
    this.acked = acked;
    this.failed = failed;
    this.process_ms_avg = process_ms_avg;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public BoltStats(BoltStats other) {
    if (other.is_set_acked()) {
      Map<String,Map<GlobalStreamId,Long>> __this__acked = new HashMap<String,Map<GlobalStreamId,Long>>();
      for (Map.Entry<String, Map<GlobalStreamId,Long>> other_element : other.acked.entrySet()) {

        String other_element_key = other_element.getKey();
        Map<GlobalStreamId,Long> other_element_value = other_element.getValue();

        String __this__acked_copy_key = other_element_key;

        Map<GlobalStreamId,Long> __this__acked_copy_value = new HashMap<GlobalStreamId,Long>();
        for (Map.Entry<GlobalStreamId, Long> other_element_value_element : other_element_value.entrySet()) {

          GlobalStreamId other_element_value_element_key = other_element_value_element.getKey();
          Long other_element_value_element_value = other_element_value_element.getValue();

          GlobalStreamId __this__acked_copy_value_copy_key = new GlobalStreamId(other_element_value_element_key);

          Long __this__acked_copy_value_copy_value = other_element_value_element_value;

          __this__acked_copy_value.put(__this__acked_copy_value_copy_key, __this__acked_copy_value_copy_value);
        }

        __this__acked.put(__this__acked_copy_key, __this__acked_copy_value);
      }
      this.acked = __this__acked;
    }
    if (other.is_set_failed()) {
      Map<String,Map<GlobalStreamId,Long>> __this__failed = new HashMap<String,Map<GlobalStreamId,Long>>();
      for (Map.Entry<String, Map<GlobalStreamId,Long>> other_element : other.failed.entrySet()) {

        String other_element_key = other_element.getKey();
        Map<GlobalStreamId,Long> other_element_value = other_element.getValue();

        String __this__failed_copy_key = other_element_key;

        Map<GlobalStreamId,Long> __this__failed_copy_value = new HashMap<GlobalStreamId,Long>();
        for (Map.Entry<GlobalStreamId, Long> other_element_value_element : other_element_value.entrySet()) {

          GlobalStreamId other_element_value_element_key = other_element_value_element.getKey();
          Long other_element_value_element_value = other_element_value_element.getValue();

          GlobalStreamId __this__failed_copy_value_copy_key = new GlobalStreamId(other_element_value_element_key);

          Long __this__failed_copy_value_copy_value = other_element_value_element_value;

          __this__failed_copy_value.put(__this__failed_copy_value_copy_key, __this__failed_copy_value_copy_value);
        }

        __this__failed.put(__this__failed_copy_key, __this__failed_copy_value);
      }
      this.failed = __this__failed;
    }
    if (other.is_set_process_ms_avg()) {
      Map<String,Map<GlobalStreamId,Double>> __this__process_ms_avg = new HashMap<String,Map<GlobalStreamId,Double>>();
      for (Map.Entry<String, Map<GlobalStreamId,Double>> other_element : other.process_ms_avg.entrySet()) {

        String other_element_key = other_element.getKey();
        Map<GlobalStreamId,Double> other_element_value = other_element.getValue();

        String __this__process_ms_avg_copy_key = other_element_key;

        Map<GlobalStreamId,Double> __this__process_ms_avg_copy_value = new HashMap<GlobalStreamId,Double>();
        for (Map.Entry<GlobalStreamId, Double> other_element_value_element : other_element_value.entrySet()) {

          GlobalStreamId other_element_value_element_key = other_element_value_element.getKey();
          Double other_element_value_element_value = other_element_value_element.getValue();

          GlobalStreamId __this__process_ms_avg_copy_value_copy_key = new GlobalStreamId(other_element_value_element_key);

          Double __this__process_ms_avg_copy_value_copy_value = other_element_value_element_value;

          __this__process_ms_avg_copy_value.put(__this__process_ms_avg_copy_value_copy_key, __this__process_ms_avg_copy_value_copy_value);
        }

        __this__process_ms_avg.put(__this__process_ms_avg_copy_key, __this__process_ms_avg_copy_value);
      }
      this.process_ms_avg = __this__process_ms_avg;
    }
  }

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

  @Deprecated
  public BoltStats clone() {
    return new BoltStats(this);
  }

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

  public void put_to_acked(String key, Map<GlobalStreamId,Long> val) {
    if (this.acked == null) {
      this.acked = new HashMap<String,Map<GlobalStreamId,Long>>();
    }
    this.acked.put(key, val);
  }

  public Map<String,Map<GlobalStreamId,Long>> get_acked() {
    return this.acked;
  }

  public void set_acked(Map<String,Map<GlobalStreamId,Long>> acked) {
    this.acked = acked;
  }

  public void unset_acked() {
    this.acked = null;
  }

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

  public void set_acked_isSet(boolean value) {
    if (!value) {
      this.acked = null;
    }
  }

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

  public void put_to_failed(String key, Map<GlobalStreamId,Long> val) {
    if (this.failed == null) {
      this.failed = new HashMap<String,Map<GlobalStreamId,Long>>();
    }
    this.failed.put(key, val);
  }

  public Map<String,Map<GlobalStreamId,Long>> get_failed() {
    return this.failed;
  }

  public void set_failed(Map<String,Map<GlobalStreamId,Long>> failed) {
    this.failed = failed;
  }

  public void unset_failed() {
    this.failed = null;
  }

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

  public void set_failed_isSet(boolean value) {
    if (!value) {
      this.failed = null;
    }
  }

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

  public void put_to_process_ms_avg(String key, Map<GlobalStreamId,Double> val) {
    if (this.process_ms_avg == null) {
      this.process_ms_avg = new HashMap<String,Map<GlobalStreamId,Double>>();
    }
    this.process_ms_avg.put(key, val);
  }

  public Map<String,Map<GlobalStreamId,Double>> get_process_ms_avg() {
    return this.process_ms_avg;
  }

  public void set_process_ms_avg(Map<String,Map<GlobalStreamId,Double>> process_ms_avg) {
    this.process_ms_avg = process_ms_avg;
  }

  public void unset_process_ms_avg() {
    this.process_ms_avg = null;
  }

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

  public void set_process_ms_avg_isSet(boolean value) {
    if (!value) {
      this.process_ms_avg = null;
    }
  }

  public void setFieldValue(_Fields field, Object value) {
    switch (field) {
    case ACKED:
      if (value == null) {
        unset_acked();
      } else {
        set_acked((Map<String,Map<GlobalStreamId,Long>>)value);
      }
      break;

    case FAILED:
      if (value == null) {
        unset_failed();
      } else {
        set_failed((Map<String,Map<GlobalStreamId,Long>>)value);
      }
      break;

    case PROCESS_MS_AVG:
      if (value == null) {
        unset_process_ms_avg();
      } else {
        set_process_ms_avg((Map<String,Map<GlobalStreamId,Double>>)value);
      }
      break;

    }
  }

  public void setFieldValue(int fieldID, Object value) {
    setFieldValue(_Fields.findByThriftIdOrThrow(fieldID), value);
  }

  public Object getFieldValue(_Fields field) {
    switch (field) {
    case ACKED:
      return get_acked();

    case FAILED:
      return get_failed();

    case PROCESS_MS_AVG:
      return get_process_ms_avg();

    }
    throw new IllegalStateException();
  }

  public Object getFieldValue(int fieldId) {
    return getFieldValue(_Fields.findByThriftIdOrThrow(fieldId));
  }

  /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */
  public boolean isSet(_Fields field) {
    switch (field) {
    case ACKED:
      return is_set_acked();
    case FAILED:
      return is_set_failed();
    case PROCESS_MS_AVG:
      return is_set_process_ms_avg();
    }
    throw new IllegalStateException();
  }

  public boolean isSet(int fieldID) {
    return isSet(_Fields.findByThriftIdOrThrow(fieldID));
  }

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

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

    boolean this_present_acked = true && this.is_set_acked();
    boolean that_present_acked = true && that.is_set_acked();
    if (this_present_acked || that_present_acked) {
      if (!(this_present_acked && that_present_acked))
        return false;
      if (!this.acked.equals(that.acked))
        return false;
    }

    boolean this_present_failed = true && this.is_set_failed();
    boolean that_present_failed = true && that.is_set_failed();
    if (this_present_failed || that_present_failed) {
      if (!(this_present_failed && that_present_failed))
        return false;
      if (!this.failed.equals(that.failed))
        return false;
    }

    boolean this_present_process_ms_avg = true && this.is_set_process_ms_avg();
    boolean that_present_process_ms_avg = true && that.is_set_process_ms_avg();
    if (this_present_process_ms_avg || that_present_process_ms_avg) {
      if (!(this_present_process_ms_avg && that_present_process_ms_avg))
        return false;
      if (!this.process_ms_avg.equals(that.process_ms_avg))
        return false;
    }

    return true;
  }

  @Override
  public int hashCode() {
    HashCodeBuilder builder = new HashCodeBuilder();

    boolean present_acked = true && (is_set_acked());
    builder.append(present_acked);
    if (present_acked)
      builder.append(acked);

    boolean present_failed = true && (is_set_failed());
    builder.append(present_failed);
    if (present_failed)
      builder.append(failed);

    boolean present_process_ms_avg = true && (is_set_process_ms_avg());
    builder.append(present_process_ms_avg);
    if (present_process_ms_avg)
      builder.append(process_ms_avg);

    return builder.toHashCode();
  }

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

    int lastComparison = 0;
    BoltStats typedOther = (BoltStats)other;

    lastComparison = Boolean.valueOf(is_set_acked()).compareTo(typedOther.is_set_acked());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_acked()) {      lastComparison = TBaseHelper.compareTo(this.acked, typedOther.acked);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = Boolean.valueOf(is_set_failed()).compareTo(typedOther.is_set_failed());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_failed()) {      lastComparison = TBaseHelper.compareTo(this.failed, typedOther.failed);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = Boolean.valueOf(is_set_process_ms_avg()).compareTo(typedOther.is_set_process_ms_avg());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_process_ms_avg()) {      lastComparison = TBaseHelper.compareTo(this.process_ms_avg, typedOther.process_ms_avg);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    return 0;
  }

  public void read(TProtocol iprot) throws TException {
    TField field;
    iprot.readStructBegin();
    while (true)
    {
      field = iprot.readFieldBegin();
      if (field.type == TType.STOP) { 
        break;
      }
      switch (field.id) {
        case 1: // ACKED
          if (field.type == TType.MAP) {
            {
              TMap _map41 = iprot.readMapBegin();
              this.acked = new HashMap<String,Map<GlobalStreamId,Long>>(2*_map41.size);
              for (int _i42 = 0; _i42 < _map41.size; ++_i42)
              {
                String _key43;
                Map<GlobalStreamId,Long> _val44;
                _key43 = iprot.readString();
                {
                  TMap _map45 = iprot.readMapBegin();
                  _val44 = new HashMap<GlobalStreamId,Long>(2*_map45.size);
                  for (int _i46 = 0; _i46 < _map45.size; ++_i46)
                  {
                    GlobalStreamId _key47;
                    long _val48;
                    _key47 = new GlobalStreamId();
                    _key47.read(iprot);
                    _val48 = iprot.readI64();
                    _val44.put(_key47, _val48);
                  }
                  iprot.readMapEnd();
                }
                this.acked.put(_key43, _val44);
              }
              iprot.readMapEnd();
            }
          } else { 
            TProtocolUtil.skip(iprot, field.type);
          }
          break;
        case 2: // FAILED
          if (field.type == TType.MAP) {
            {
              TMap _map49 = iprot.readMapBegin();
              this.failed = new HashMap<String,Map<GlobalStreamId,Long>>(2*_map49.size);
              for (int _i50 = 0; _i50 < _map49.size; ++_i50)
              {
                String _key51;
                Map<GlobalStreamId,Long> _val52;
                _key51 = iprot.readString();
                {
                  TMap _map53 = iprot.readMapBegin();
                  _val52 = new HashMap<GlobalStreamId,Long>(2*_map53.size);
                  for (int _i54 = 0; _i54 < _map53.size; ++_i54)
                  {
                    GlobalStreamId _key55;
                    long _val56;
                    _key55 = new GlobalStreamId();
                    _key55.read(iprot);
                    _val56 = iprot.readI64();
                    _val52.put(_key55, _val56);
                  }
                  iprot.readMapEnd();
                }
                this.failed.put(_key51, _val52);
              }
              iprot.readMapEnd();
            }
          } else { 
            TProtocolUtil.skip(iprot, field.type);
          }
          break;
        case 3: // PROCESS_MS_AVG
          if (field.type == TType.MAP) {
            {
              TMap _map57 = iprot.readMapBegin();
              this.process_ms_avg = new HashMap<String,Map<GlobalStreamId,Double>>(2*_map57.size);
              for (int _i58 = 0; _i58 < _map57.size; ++_i58)
              {
                String _key59;
                Map<GlobalStreamId,Double> _val60;
                _key59 = iprot.readString();
                {
                  TMap _map61 = iprot.readMapBegin();
                  _val60 = new HashMap<GlobalStreamId,Double>(2*_map61.size);
                  for (int _i62 = 0; _i62 < _map61.size; ++_i62)
                  {
                    GlobalStreamId _key63;
                    double _val64;
                    _key63 = new GlobalStreamId();
                    _key63.read(iprot);
                    _val64 = iprot.readDouble();
                    _val60.put(_key63, _val64);
                  }
                  iprot.readMapEnd();
                }
                this.process_ms_avg.put(_key59, _val60);
              }
              iprot.readMapEnd();
            }
          } else { 
            TProtocolUtil.skip(iprot, field.type);
          }
          break;
        default:
          TProtocolUtil.skip(iprot, field.type);
      }
      iprot.readFieldEnd();
    }
    iprot.readStructEnd();
    validate();
  }

  public void write(TProtocol oprot) throws TException {
    validate();

    oprot.writeStructBegin(STRUCT_DESC);
    if (this.acked != null) {
      oprot.writeFieldBegin(ACKED_FIELD_DESC);
      {
        oprot.writeMapBegin(new TMap(TType.STRING, TType.MAP, this.acked.size()));
        for (Map.Entry<String, Map<GlobalStreamId,Long>> _iter65 : this.acked.entrySet())
        {
          oprot.writeString(_iter65.getKey());
          {
            oprot.writeMapBegin(new TMap(TType.STRUCT, TType.I64, _iter65.getValue().size()));
            for (Map.Entry<GlobalStreamId, Long> _iter66 : _iter65.getValue().entrySet())
            {
              _iter66.getKey().write(oprot);
              oprot.writeI64(_iter66.getValue());
            }
            oprot.writeMapEnd();
          }
        }
        oprot.writeMapEnd();
      }
      oprot.writeFieldEnd();
    }
    if (this.failed != null) {
      oprot.writeFieldBegin(FAILED_FIELD_DESC);
      {
        oprot.writeMapBegin(new TMap(TType.STRING, TType.MAP, this.failed.size()));
        for (Map.Entry<String, Map<GlobalStreamId,Long>> _iter67 : this.failed.entrySet())
        {
          oprot.writeString(_iter67.getKey());
          {
            oprot.writeMapBegin(new TMap(TType.STRUCT, TType.I64, _iter67.getValue().size()));
            for (Map.Entry<GlobalStreamId, Long> _iter68 : _iter67.getValue().entrySet())
            {
              _iter68.getKey().write(oprot);
              oprot.writeI64(_iter68.getValue());
            }
            oprot.writeMapEnd();
          }
        }
        oprot.writeMapEnd();
      }
      oprot.writeFieldEnd();
    }
    if (this.process_ms_avg != null) {
      oprot.writeFieldBegin(PROCESS_MS_AVG_FIELD_DESC);
      {
        oprot.writeMapBegin(new TMap(TType.STRING, TType.MAP, this.process_ms_avg.size()));
        for (Map.Entry<String, Map<GlobalStreamId,Double>> _iter69 : this.process_ms_avg.entrySet())
        {
          oprot.writeString(_iter69.getKey());
          {
            oprot.writeMapBegin(new TMap(TType.STRUCT, TType.DOUBLE, _iter69.getValue().size()));
            for (Map.Entry<GlobalStreamId, Double> _iter70 : _iter69.getValue().entrySet())
            {
              _iter70.getKey().write(oprot);
              oprot.writeDouble(_iter70.getValue());
            }
            oprot.writeMapEnd();
          }
        }
        oprot.writeMapEnd();
      }
      oprot.writeFieldEnd();
    }
    oprot.writeFieldStop();
    oprot.writeStructEnd();
  }

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

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

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

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

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

  }

}

