/**
 * 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.
 */
/**
 * Autogenerated by Thrift Compiler (0.12.0)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package org.apache.storm.generated;

@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)")
public class TopologyStats implements org.apache.storm.thrift.TBase<TopologyStats, TopologyStats._Fields>, java.io.Serializable, Cloneable, Comparable<TopologyStats> {
  private static final org.apache.storm.thrift.protocol.TStruct STRUCT_DESC = new org.apache.storm.thrift.protocol.TStruct("TopologyStats");

  private static final org.apache.storm.thrift.protocol.TField WINDOW_TO_EMITTED_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("window_to_emitted", org.apache.storm.thrift.protocol.TType.MAP, (short)1);
  private static final org.apache.storm.thrift.protocol.TField WINDOW_TO_TRANSFERRED_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("window_to_transferred", org.apache.storm.thrift.protocol.TType.MAP, (short)2);
  private static final org.apache.storm.thrift.protocol.TField WINDOW_TO_COMPLETE_LATENCIES_MS_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("window_to_complete_latencies_ms", org.apache.storm.thrift.protocol.TType.MAP, (short)3);
  private static final org.apache.storm.thrift.protocol.TField WINDOW_TO_ACKED_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("window_to_acked", org.apache.storm.thrift.protocol.TType.MAP, (short)4);
  private static final org.apache.storm.thrift.protocol.TField WINDOW_TO_FAILED_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("window_to_failed", org.apache.storm.thrift.protocol.TType.MAP, (short)5);

  private static final org.apache.storm.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new TopologyStatsStandardSchemeFactory();
  private static final org.apache.storm.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new TopologyStatsTupleSchemeFactory();

  private @org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_emitted; // optional
  private @org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_transferred; // optional
  private @org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Double> window_to_complete_latencies_ms; // optional
  private @org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_acked; // optional
  private @org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_failed; // optional

  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
  public enum _Fields implements org.apache.storm.thrift.TFieldIdEnum {
    WINDOW_TO_EMITTED((short)1, "window_to_emitted"),
    WINDOW_TO_TRANSFERRED((short)2, "window_to_transferred"),
    WINDOW_TO_COMPLETE_LATENCIES_MS((short)3, "window_to_complete_latencies_ms"),
    WINDOW_TO_ACKED((short)4, "window_to_acked"),
    WINDOW_TO_FAILED((short)5, "window_to_failed");

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

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

    /**
     * Find the _Fields constant that matches fieldId, or null if its not found.
     */
    @org.apache.storm.thrift.annotation.Nullable
    public static _Fields findByThriftId(int fieldId) {
      switch(fieldId) {
        case 1: // WINDOW_TO_EMITTED
          return WINDOW_TO_EMITTED;
        case 2: // WINDOW_TO_TRANSFERRED
          return WINDOW_TO_TRANSFERRED;
        case 3: // WINDOW_TO_COMPLETE_LATENCIES_MS
          return WINDOW_TO_COMPLETE_LATENCIES_MS;
        case 4: // WINDOW_TO_ACKED
          return WINDOW_TO_ACKED;
        case 5: // WINDOW_TO_FAILED
          return WINDOW_TO_FAILED;
        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 java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
      return fields;
    }

    /**
     * Find the _Fields constant that matches name, or null if its not found.
     */
    @org.apache.storm.thrift.annotation.Nullable
    public static _Fields findByName(java.lang.String name) {
      return byName.get(name);
    }

    private final short _thriftId;
    private final java.lang.String _fieldName;

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

    public short getThriftFieldId() {
      return _thriftId;
    }

    public java.lang.String getFieldName() {
      return _fieldName;
    }
  }

  // isset id assignments
  private static final _Fields optionals[] = {_Fields.WINDOW_TO_EMITTED,_Fields.WINDOW_TO_TRANSFERRED,_Fields.WINDOW_TO_COMPLETE_LATENCIES_MS,_Fields.WINDOW_TO_ACKED,_Fields.WINDOW_TO_FAILED};
  public static final java.util.Map<_Fields, org.apache.storm.thrift.meta_data.FieldMetaData> metaDataMap;
  static {
    java.util.Map<_Fields, org.apache.storm.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.storm.thrift.meta_data.FieldMetaData>(_Fields.class);
    tmpMap.put(_Fields.WINDOW_TO_EMITTED, new org.apache.storm.thrift.meta_data.FieldMetaData("window_to_emitted", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.storm.thrift.meta_data.MapMetaData(org.apache.storm.thrift.protocol.TType.MAP, 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.STRING), 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.I64))));
    tmpMap.put(_Fields.WINDOW_TO_TRANSFERRED, new org.apache.storm.thrift.meta_data.FieldMetaData("window_to_transferred", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.storm.thrift.meta_data.MapMetaData(org.apache.storm.thrift.protocol.TType.MAP, 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.STRING), 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.I64))));
    tmpMap.put(_Fields.WINDOW_TO_COMPLETE_LATENCIES_MS, new org.apache.storm.thrift.meta_data.FieldMetaData("window_to_complete_latencies_ms", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.storm.thrift.meta_data.MapMetaData(org.apache.storm.thrift.protocol.TType.MAP, 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.STRING), 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.DOUBLE))));
    tmpMap.put(_Fields.WINDOW_TO_ACKED, new org.apache.storm.thrift.meta_data.FieldMetaData("window_to_acked", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.storm.thrift.meta_data.MapMetaData(org.apache.storm.thrift.protocol.TType.MAP, 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.STRING), 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.I64))));
    tmpMap.put(_Fields.WINDOW_TO_FAILED, new org.apache.storm.thrift.meta_data.FieldMetaData("window_to_failed", org.apache.storm.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.storm.thrift.meta_data.MapMetaData(org.apache.storm.thrift.protocol.TType.MAP, 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.STRING), 
            new org.apache.storm.thrift.meta_data.FieldValueMetaData(org.apache.storm.thrift.protocol.TType.I64))));
    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
    org.apache.storm.thrift.meta_data.FieldMetaData.addStructMetaDataMap(TopologyStats.class, metaDataMap);
  }

  public TopologyStats() {
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public TopologyStats(TopologyStats other) {
    if (other.is_set_window_to_emitted()) {
      java.util.Map<java.lang.String,java.lang.Long> __this__window_to_emitted = new java.util.HashMap<java.lang.String,java.lang.Long>(other.window_to_emitted);
      this.window_to_emitted = __this__window_to_emitted;
    }
    if (other.is_set_window_to_transferred()) {
      java.util.Map<java.lang.String,java.lang.Long> __this__window_to_transferred = new java.util.HashMap<java.lang.String,java.lang.Long>(other.window_to_transferred);
      this.window_to_transferred = __this__window_to_transferred;
    }
    if (other.is_set_window_to_complete_latencies_ms()) {
      java.util.Map<java.lang.String,java.lang.Double> __this__window_to_complete_latencies_ms = new java.util.HashMap<java.lang.String,java.lang.Double>(other.window_to_complete_latencies_ms);
      this.window_to_complete_latencies_ms = __this__window_to_complete_latencies_ms;
    }
    if (other.is_set_window_to_acked()) {
      java.util.Map<java.lang.String,java.lang.Long> __this__window_to_acked = new java.util.HashMap<java.lang.String,java.lang.Long>(other.window_to_acked);
      this.window_to_acked = __this__window_to_acked;
    }
    if (other.is_set_window_to_failed()) {
      java.util.Map<java.lang.String,java.lang.Long> __this__window_to_failed = new java.util.HashMap<java.lang.String,java.lang.Long>(other.window_to_failed);
      this.window_to_failed = __this__window_to_failed;
    }
  }

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

  @Override
  public void clear() {
    this.window_to_emitted = null;
    this.window_to_transferred = null;
    this.window_to_complete_latencies_ms = null;
    this.window_to_acked = null;
    this.window_to_failed = null;
  }

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

  public void put_to_window_to_emitted(java.lang.String key, long val) {
    if (this.window_to_emitted == null) {
      this.window_to_emitted = new java.util.HashMap<java.lang.String,java.lang.Long>();
    }
    this.window_to_emitted.put(key, val);
  }

  @org.apache.storm.thrift.annotation.Nullable
  public java.util.Map<java.lang.String,java.lang.Long> get_window_to_emitted() {
    return this.window_to_emitted;
  }

  public void set_window_to_emitted(@org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_emitted) {
    this.window_to_emitted = window_to_emitted;
  }

  public void unset_window_to_emitted() {
    this.window_to_emitted = null;
  }

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

  public void set_window_to_emitted_isSet(boolean value) {
    if (!value) {
      this.window_to_emitted = null;
    }
  }

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

  public void put_to_window_to_transferred(java.lang.String key, long val) {
    if (this.window_to_transferred == null) {
      this.window_to_transferred = new java.util.HashMap<java.lang.String,java.lang.Long>();
    }
    this.window_to_transferred.put(key, val);
  }

  @org.apache.storm.thrift.annotation.Nullable
  public java.util.Map<java.lang.String,java.lang.Long> get_window_to_transferred() {
    return this.window_to_transferred;
  }

  public void set_window_to_transferred(@org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_transferred) {
    this.window_to_transferred = window_to_transferred;
  }

  public void unset_window_to_transferred() {
    this.window_to_transferred = null;
  }

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

  public void set_window_to_transferred_isSet(boolean value) {
    if (!value) {
      this.window_to_transferred = null;
    }
  }

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

  public void put_to_window_to_complete_latencies_ms(java.lang.String key, double val) {
    if (this.window_to_complete_latencies_ms == null) {
      this.window_to_complete_latencies_ms = new java.util.HashMap<java.lang.String,java.lang.Double>();
    }
    this.window_to_complete_latencies_ms.put(key, val);
  }

  @org.apache.storm.thrift.annotation.Nullable
  public java.util.Map<java.lang.String,java.lang.Double> get_window_to_complete_latencies_ms() {
    return this.window_to_complete_latencies_ms;
  }

  public void set_window_to_complete_latencies_ms(@org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Double> window_to_complete_latencies_ms) {
    this.window_to_complete_latencies_ms = window_to_complete_latencies_ms;
  }

  public void unset_window_to_complete_latencies_ms() {
    this.window_to_complete_latencies_ms = null;
  }

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

  public void set_window_to_complete_latencies_ms_isSet(boolean value) {
    if (!value) {
      this.window_to_complete_latencies_ms = null;
    }
  }

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

  public void put_to_window_to_acked(java.lang.String key, long val) {
    if (this.window_to_acked == null) {
      this.window_to_acked = new java.util.HashMap<java.lang.String,java.lang.Long>();
    }
    this.window_to_acked.put(key, val);
  }

  @org.apache.storm.thrift.annotation.Nullable
  public java.util.Map<java.lang.String,java.lang.Long> get_window_to_acked() {
    return this.window_to_acked;
  }

  public void set_window_to_acked(@org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_acked) {
    this.window_to_acked = window_to_acked;
  }

  public void unset_window_to_acked() {
    this.window_to_acked = null;
  }

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

  public void set_window_to_acked_isSet(boolean value) {
    if (!value) {
      this.window_to_acked = null;
    }
  }

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

  public void put_to_window_to_failed(java.lang.String key, long val) {
    if (this.window_to_failed == null) {
      this.window_to_failed = new java.util.HashMap<java.lang.String,java.lang.Long>();
    }
    this.window_to_failed.put(key, val);
  }

  @org.apache.storm.thrift.annotation.Nullable
  public java.util.Map<java.lang.String,java.lang.Long> get_window_to_failed() {
    return this.window_to_failed;
  }

  public void set_window_to_failed(@org.apache.storm.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.Long> window_to_failed) {
    this.window_to_failed = window_to_failed;
  }

  public void unset_window_to_failed() {
    this.window_to_failed = null;
  }

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

  public void set_window_to_failed_isSet(boolean value) {
    if (!value) {
      this.window_to_failed = null;
    }
  }

  public void setFieldValue(_Fields field, @org.apache.storm.thrift.annotation.Nullable java.lang.Object value) {
    switch (field) {
    case WINDOW_TO_EMITTED:
      if (value == null) {
        unset_window_to_emitted();
      } else {
        set_window_to_emitted((java.util.Map<java.lang.String,java.lang.Long>)value);
      }
      break;

    case WINDOW_TO_TRANSFERRED:
      if (value == null) {
        unset_window_to_transferred();
      } else {
        set_window_to_transferred((java.util.Map<java.lang.String,java.lang.Long>)value);
      }
      break;

    case WINDOW_TO_COMPLETE_LATENCIES_MS:
      if (value == null) {
        unset_window_to_complete_latencies_ms();
      } else {
        set_window_to_complete_latencies_ms((java.util.Map<java.lang.String,java.lang.Double>)value);
      }
      break;

    case WINDOW_TO_ACKED:
      if (value == null) {
        unset_window_to_acked();
      } else {
        set_window_to_acked((java.util.Map<java.lang.String,java.lang.Long>)value);
      }
      break;

    case WINDOW_TO_FAILED:
      if (value == null) {
        unset_window_to_failed();
      } else {
        set_window_to_failed((java.util.Map<java.lang.String,java.lang.Long>)value);
      }
      break;

    }
  }

  @org.apache.storm.thrift.annotation.Nullable
  public java.lang.Object getFieldValue(_Fields field) {
    switch (field) {
    case WINDOW_TO_EMITTED:
      return get_window_to_emitted();

    case WINDOW_TO_TRANSFERRED:
      return get_window_to_transferred();

    case WINDOW_TO_COMPLETE_LATENCIES_MS:
      return get_window_to_complete_latencies_ms();

    case WINDOW_TO_ACKED:
      return get_window_to_acked();

    case WINDOW_TO_FAILED:
      return get_window_to_failed();

    }
    throw new java.lang.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 java.lang.IllegalArgumentException();
    }

    switch (field) {
    case WINDOW_TO_EMITTED:
      return is_set_window_to_emitted();
    case WINDOW_TO_TRANSFERRED:
      return is_set_window_to_transferred();
    case WINDOW_TO_COMPLETE_LATENCIES_MS:
      return is_set_window_to_complete_latencies_ms();
    case WINDOW_TO_ACKED:
      return is_set_window_to_acked();
    case WINDOW_TO_FAILED:
      return is_set_window_to_failed();
    }
    throw new java.lang.IllegalStateException();
  }

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

  public boolean equals(TopologyStats that) {
    if (that == null)
      return false;
    if (this == that)
      return true;

    boolean this_present_window_to_emitted = true && this.is_set_window_to_emitted();
    boolean that_present_window_to_emitted = true && that.is_set_window_to_emitted();
    if (this_present_window_to_emitted || that_present_window_to_emitted) {
      if (!(this_present_window_to_emitted && that_present_window_to_emitted))
        return false;
      if (!this.window_to_emitted.equals(that.window_to_emitted))
        return false;
    }

    boolean this_present_window_to_transferred = true && this.is_set_window_to_transferred();
    boolean that_present_window_to_transferred = true && that.is_set_window_to_transferred();
    if (this_present_window_to_transferred || that_present_window_to_transferred) {
      if (!(this_present_window_to_transferred && that_present_window_to_transferred))
        return false;
      if (!this.window_to_transferred.equals(that.window_to_transferred))
        return false;
    }

    boolean this_present_window_to_complete_latencies_ms = true && this.is_set_window_to_complete_latencies_ms();
    boolean that_present_window_to_complete_latencies_ms = true && that.is_set_window_to_complete_latencies_ms();
    if (this_present_window_to_complete_latencies_ms || that_present_window_to_complete_latencies_ms) {
      if (!(this_present_window_to_complete_latencies_ms && that_present_window_to_complete_latencies_ms))
        return false;
      if (!this.window_to_complete_latencies_ms.equals(that.window_to_complete_latencies_ms))
        return false;
    }

    boolean this_present_window_to_acked = true && this.is_set_window_to_acked();
    boolean that_present_window_to_acked = true && that.is_set_window_to_acked();
    if (this_present_window_to_acked || that_present_window_to_acked) {
      if (!(this_present_window_to_acked && that_present_window_to_acked))
        return false;
      if (!this.window_to_acked.equals(that.window_to_acked))
        return false;
    }

    boolean this_present_window_to_failed = true && this.is_set_window_to_failed();
    boolean that_present_window_to_failed = true && that.is_set_window_to_failed();
    if (this_present_window_to_failed || that_present_window_to_failed) {
      if (!(this_present_window_to_failed && that_present_window_to_failed))
        return false;
      if (!this.window_to_failed.equals(that.window_to_failed))
        return false;
    }

    return true;
  }

  @Override
  public int hashCode() {
    int hashCode = 1;

    hashCode = hashCode * 8191 + ((is_set_window_to_emitted()) ? 131071 : 524287);
    if (is_set_window_to_emitted())
      hashCode = hashCode * 8191 + window_to_emitted.hashCode();

    hashCode = hashCode * 8191 + ((is_set_window_to_transferred()) ? 131071 : 524287);
    if (is_set_window_to_transferred())
      hashCode = hashCode * 8191 + window_to_transferred.hashCode();

    hashCode = hashCode * 8191 + ((is_set_window_to_complete_latencies_ms()) ? 131071 : 524287);
    if (is_set_window_to_complete_latencies_ms())
      hashCode = hashCode * 8191 + window_to_complete_latencies_ms.hashCode();

    hashCode = hashCode * 8191 + ((is_set_window_to_acked()) ? 131071 : 524287);
    if (is_set_window_to_acked())
      hashCode = hashCode * 8191 + window_to_acked.hashCode();

    hashCode = hashCode * 8191 + ((is_set_window_to_failed()) ? 131071 : 524287);
    if (is_set_window_to_failed())
      hashCode = hashCode * 8191 + window_to_failed.hashCode();

    return hashCode;
  }

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

    int lastComparison = 0;

    lastComparison = java.lang.Boolean.valueOf(is_set_window_to_emitted()).compareTo(other.is_set_window_to_emitted());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_window_to_emitted()) {
      lastComparison = org.apache.storm.thrift.TBaseHelper.compareTo(this.window_to_emitted, other.window_to_emitted);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(is_set_window_to_transferred()).compareTo(other.is_set_window_to_transferred());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_window_to_transferred()) {
      lastComparison = org.apache.storm.thrift.TBaseHelper.compareTo(this.window_to_transferred, other.window_to_transferred);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(is_set_window_to_complete_latencies_ms()).compareTo(other.is_set_window_to_complete_latencies_ms());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_window_to_complete_latencies_ms()) {
      lastComparison = org.apache.storm.thrift.TBaseHelper.compareTo(this.window_to_complete_latencies_ms, other.window_to_complete_latencies_ms);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(is_set_window_to_acked()).compareTo(other.is_set_window_to_acked());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_window_to_acked()) {
      lastComparison = org.apache.storm.thrift.TBaseHelper.compareTo(this.window_to_acked, other.window_to_acked);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(is_set_window_to_failed()).compareTo(other.is_set_window_to_failed());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_window_to_failed()) {
      lastComparison = org.apache.storm.thrift.TBaseHelper.compareTo(this.window_to_failed, other.window_to_failed);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    return 0;
  }

  @org.apache.storm.thrift.annotation.Nullable
  public _Fields fieldForId(int fieldId) {
    return _Fields.findByThriftId(fieldId);
  }

  public void read(org.apache.storm.thrift.protocol.TProtocol iprot) throws org.apache.storm.thrift.TException {
    scheme(iprot).read(iprot, this);
  }

  public void write(org.apache.storm.thrift.protocol.TProtocol oprot) throws org.apache.storm.thrift.TException {
    scheme(oprot).write(oprot, this);
  }

  @Override
  public java.lang.String toString() {
    java.lang.StringBuilder sb = new java.lang.StringBuilder("TopologyStats(");
    boolean first = true;

    if (is_set_window_to_emitted()) {
      sb.append("window_to_emitted:");
      if (this.window_to_emitted == null) {
        sb.append("null");
      } else {
        sb.append(this.window_to_emitted);
      }
      first = false;
    }
    if (is_set_window_to_transferred()) {
      if (!first) sb.append(", ");
      sb.append("window_to_transferred:");
      if (this.window_to_transferred == null) {
        sb.append("null");
      } else {
        sb.append(this.window_to_transferred);
      }
      first = false;
    }
    if (is_set_window_to_complete_latencies_ms()) {
      if (!first) sb.append(", ");
      sb.append("window_to_complete_latencies_ms:");
      if (this.window_to_complete_latencies_ms == null) {
        sb.append("null");
      } else {
        sb.append(this.window_to_complete_latencies_ms);
      }
      first = false;
    }
    if (is_set_window_to_acked()) {
      if (!first) sb.append(", ");
      sb.append("window_to_acked:");
      if (this.window_to_acked == null) {
        sb.append("null");
      } else {
        sb.append(this.window_to_acked);
      }
      first = false;
    }
    if (is_set_window_to_failed()) {
      if (!first) sb.append(", ");
      sb.append("window_to_failed:");
      if (this.window_to_failed == null) {
        sb.append("null");
      } else {
        sb.append(this.window_to_failed);
      }
      first = false;
    }
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws org.apache.storm.thrift.TException {
    // check for required fields
    // check for sub-struct validity
  }

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

  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
    try {
      read(new org.apache.storm.thrift.protocol.TCompactProtocol(new org.apache.storm.thrift.transport.TIOStreamTransport(in)));
    } catch (org.apache.storm.thrift.TException te) {
      throw new java.io.IOException(te);
    }
  }

  private static class TopologyStatsStandardSchemeFactory implements org.apache.storm.thrift.scheme.SchemeFactory {
    public TopologyStatsStandardScheme getScheme() {
      return new TopologyStatsStandardScheme();
    }
  }

  private static class TopologyStatsStandardScheme extends org.apache.storm.thrift.scheme.StandardScheme<TopologyStats> {

    public void read(org.apache.storm.thrift.protocol.TProtocol iprot, TopologyStats struct) throws org.apache.storm.thrift.TException {
      org.apache.storm.thrift.protocol.TField schemeField;
      iprot.readStructBegin();
      while (true)
      {
        schemeField = iprot.readFieldBegin();
        if (schemeField.type == org.apache.storm.thrift.protocol.TType.STOP) { 
          break;
        }
        switch (schemeField.id) {
          case 1: // WINDOW_TO_EMITTED
            if (schemeField.type == org.apache.storm.thrift.protocol.TType.MAP) {
              {
                org.apache.storm.thrift.protocol.TMap _map406 = iprot.readMapBegin();
                struct.window_to_emitted = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map406.size);
                @org.apache.storm.thrift.annotation.Nullable java.lang.String _key407;
                long _val408;
                for (int _i409 = 0; _i409 < _map406.size; ++_i409)
                {
                  _key407 = iprot.readString();
                  _val408 = iprot.readI64();
                  struct.window_to_emitted.put(_key407, _val408);
                }
                iprot.readMapEnd();
              }
              struct.set_window_to_emitted_isSet(true);
            } else { 
              org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 2: // WINDOW_TO_TRANSFERRED
            if (schemeField.type == org.apache.storm.thrift.protocol.TType.MAP) {
              {
                org.apache.storm.thrift.protocol.TMap _map410 = iprot.readMapBegin();
                struct.window_to_transferred = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map410.size);
                @org.apache.storm.thrift.annotation.Nullable java.lang.String _key411;
                long _val412;
                for (int _i413 = 0; _i413 < _map410.size; ++_i413)
                {
                  _key411 = iprot.readString();
                  _val412 = iprot.readI64();
                  struct.window_to_transferred.put(_key411, _val412);
                }
                iprot.readMapEnd();
              }
              struct.set_window_to_transferred_isSet(true);
            } else { 
              org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 3: // WINDOW_TO_COMPLETE_LATENCIES_MS
            if (schemeField.type == org.apache.storm.thrift.protocol.TType.MAP) {
              {
                org.apache.storm.thrift.protocol.TMap _map414 = iprot.readMapBegin();
                struct.window_to_complete_latencies_ms = new java.util.HashMap<java.lang.String,java.lang.Double>(2*_map414.size);
                @org.apache.storm.thrift.annotation.Nullable java.lang.String _key415;
                double _val416;
                for (int _i417 = 0; _i417 < _map414.size; ++_i417)
                {
                  _key415 = iprot.readString();
                  _val416 = iprot.readDouble();
                  struct.window_to_complete_latencies_ms.put(_key415, _val416);
                }
                iprot.readMapEnd();
              }
              struct.set_window_to_complete_latencies_ms_isSet(true);
            } else { 
              org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 4: // WINDOW_TO_ACKED
            if (schemeField.type == org.apache.storm.thrift.protocol.TType.MAP) {
              {
                org.apache.storm.thrift.protocol.TMap _map418 = iprot.readMapBegin();
                struct.window_to_acked = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map418.size);
                @org.apache.storm.thrift.annotation.Nullable java.lang.String _key419;
                long _val420;
                for (int _i421 = 0; _i421 < _map418.size; ++_i421)
                {
                  _key419 = iprot.readString();
                  _val420 = iprot.readI64();
                  struct.window_to_acked.put(_key419, _val420);
                }
                iprot.readMapEnd();
              }
              struct.set_window_to_acked_isSet(true);
            } else { 
              org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 5: // WINDOW_TO_FAILED
            if (schemeField.type == org.apache.storm.thrift.protocol.TType.MAP) {
              {
                org.apache.storm.thrift.protocol.TMap _map422 = iprot.readMapBegin();
                struct.window_to_failed = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map422.size);
                @org.apache.storm.thrift.annotation.Nullable java.lang.String _key423;
                long _val424;
                for (int _i425 = 0; _i425 < _map422.size; ++_i425)
                {
                  _key423 = iprot.readString();
                  _val424 = iprot.readI64();
                  struct.window_to_failed.put(_key423, _val424);
                }
                iprot.readMapEnd();
              }
              struct.set_window_to_failed_isSet(true);
            } else { 
              org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          default:
            org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
        }
        iprot.readFieldEnd();
      }
      iprot.readStructEnd();
      struct.validate();
    }

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

      oprot.writeStructBegin(STRUCT_DESC);
      if (struct.window_to_emitted != null) {
        if (struct.is_set_window_to_emitted()) {
          oprot.writeFieldBegin(WINDOW_TO_EMITTED_FIELD_DESC);
          {
            oprot.writeMapBegin(new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, struct.window_to_emitted.size()));
            for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter426 : struct.window_to_emitted.entrySet())
            {
              oprot.writeString(_iter426.getKey());
              oprot.writeI64(_iter426.getValue());
            }
            oprot.writeMapEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      if (struct.window_to_transferred != null) {
        if (struct.is_set_window_to_transferred()) {
          oprot.writeFieldBegin(WINDOW_TO_TRANSFERRED_FIELD_DESC);
          {
            oprot.writeMapBegin(new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, struct.window_to_transferred.size()));
            for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter427 : struct.window_to_transferred.entrySet())
            {
              oprot.writeString(_iter427.getKey());
              oprot.writeI64(_iter427.getValue());
            }
            oprot.writeMapEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      if (struct.window_to_complete_latencies_ms != null) {
        if (struct.is_set_window_to_complete_latencies_ms()) {
          oprot.writeFieldBegin(WINDOW_TO_COMPLETE_LATENCIES_MS_FIELD_DESC);
          {
            oprot.writeMapBegin(new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.DOUBLE, struct.window_to_complete_latencies_ms.size()));
            for (java.util.Map.Entry<java.lang.String, java.lang.Double> _iter428 : struct.window_to_complete_latencies_ms.entrySet())
            {
              oprot.writeString(_iter428.getKey());
              oprot.writeDouble(_iter428.getValue());
            }
            oprot.writeMapEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      if (struct.window_to_acked != null) {
        if (struct.is_set_window_to_acked()) {
          oprot.writeFieldBegin(WINDOW_TO_ACKED_FIELD_DESC);
          {
            oprot.writeMapBegin(new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, struct.window_to_acked.size()));
            for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter429 : struct.window_to_acked.entrySet())
            {
              oprot.writeString(_iter429.getKey());
              oprot.writeI64(_iter429.getValue());
            }
            oprot.writeMapEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      if (struct.window_to_failed != null) {
        if (struct.is_set_window_to_failed()) {
          oprot.writeFieldBegin(WINDOW_TO_FAILED_FIELD_DESC);
          {
            oprot.writeMapBegin(new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, struct.window_to_failed.size()));
            for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter430 : struct.window_to_failed.entrySet())
            {
              oprot.writeString(_iter430.getKey());
              oprot.writeI64(_iter430.getValue());
            }
            oprot.writeMapEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }

  private static class TopologyStatsTupleSchemeFactory implements org.apache.storm.thrift.scheme.SchemeFactory {
    public TopologyStatsTupleScheme getScheme() {
      return new TopologyStatsTupleScheme();
    }
  }

  private static class TopologyStatsTupleScheme extends org.apache.storm.thrift.scheme.TupleScheme<TopologyStats> {

    @Override
    public void write(org.apache.storm.thrift.protocol.TProtocol prot, TopologyStats struct) throws org.apache.storm.thrift.TException {
      org.apache.storm.thrift.protocol.TTupleProtocol oprot = (org.apache.storm.thrift.protocol.TTupleProtocol) prot;
      java.util.BitSet optionals = new java.util.BitSet();
      if (struct.is_set_window_to_emitted()) {
        optionals.set(0);
      }
      if (struct.is_set_window_to_transferred()) {
        optionals.set(1);
      }
      if (struct.is_set_window_to_complete_latencies_ms()) {
        optionals.set(2);
      }
      if (struct.is_set_window_to_acked()) {
        optionals.set(3);
      }
      if (struct.is_set_window_to_failed()) {
        optionals.set(4);
      }
      oprot.writeBitSet(optionals, 5);
      if (struct.is_set_window_to_emitted()) {
        {
          oprot.writeI32(struct.window_to_emitted.size());
          for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter431 : struct.window_to_emitted.entrySet())
          {
            oprot.writeString(_iter431.getKey());
            oprot.writeI64(_iter431.getValue());
          }
        }
      }
      if (struct.is_set_window_to_transferred()) {
        {
          oprot.writeI32(struct.window_to_transferred.size());
          for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter432 : struct.window_to_transferred.entrySet())
          {
            oprot.writeString(_iter432.getKey());
            oprot.writeI64(_iter432.getValue());
          }
        }
      }
      if (struct.is_set_window_to_complete_latencies_ms()) {
        {
          oprot.writeI32(struct.window_to_complete_latencies_ms.size());
          for (java.util.Map.Entry<java.lang.String, java.lang.Double> _iter433 : struct.window_to_complete_latencies_ms.entrySet())
          {
            oprot.writeString(_iter433.getKey());
            oprot.writeDouble(_iter433.getValue());
          }
        }
      }
      if (struct.is_set_window_to_acked()) {
        {
          oprot.writeI32(struct.window_to_acked.size());
          for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter434 : struct.window_to_acked.entrySet())
          {
            oprot.writeString(_iter434.getKey());
            oprot.writeI64(_iter434.getValue());
          }
        }
      }
      if (struct.is_set_window_to_failed()) {
        {
          oprot.writeI32(struct.window_to_failed.size());
          for (java.util.Map.Entry<java.lang.String, java.lang.Long> _iter435 : struct.window_to_failed.entrySet())
          {
            oprot.writeString(_iter435.getKey());
            oprot.writeI64(_iter435.getValue());
          }
        }
      }
    }

    @Override
    public void read(org.apache.storm.thrift.protocol.TProtocol prot, TopologyStats struct) throws org.apache.storm.thrift.TException {
      org.apache.storm.thrift.protocol.TTupleProtocol iprot = (org.apache.storm.thrift.protocol.TTupleProtocol) prot;
      java.util.BitSet incoming = iprot.readBitSet(5);
      if (incoming.get(0)) {
        {
          org.apache.storm.thrift.protocol.TMap _map436 = new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, iprot.readI32());
          struct.window_to_emitted = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map436.size);
          @org.apache.storm.thrift.annotation.Nullable java.lang.String _key437;
          long _val438;
          for (int _i439 = 0; _i439 < _map436.size; ++_i439)
          {
            _key437 = iprot.readString();
            _val438 = iprot.readI64();
            struct.window_to_emitted.put(_key437, _val438);
          }
        }
        struct.set_window_to_emitted_isSet(true);
      }
      if (incoming.get(1)) {
        {
          org.apache.storm.thrift.protocol.TMap _map440 = new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, iprot.readI32());
          struct.window_to_transferred = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map440.size);
          @org.apache.storm.thrift.annotation.Nullable java.lang.String _key441;
          long _val442;
          for (int _i443 = 0; _i443 < _map440.size; ++_i443)
          {
            _key441 = iprot.readString();
            _val442 = iprot.readI64();
            struct.window_to_transferred.put(_key441, _val442);
          }
        }
        struct.set_window_to_transferred_isSet(true);
      }
      if (incoming.get(2)) {
        {
          org.apache.storm.thrift.protocol.TMap _map444 = new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.DOUBLE, iprot.readI32());
          struct.window_to_complete_latencies_ms = new java.util.HashMap<java.lang.String,java.lang.Double>(2*_map444.size);
          @org.apache.storm.thrift.annotation.Nullable java.lang.String _key445;
          double _val446;
          for (int _i447 = 0; _i447 < _map444.size; ++_i447)
          {
            _key445 = iprot.readString();
            _val446 = iprot.readDouble();
            struct.window_to_complete_latencies_ms.put(_key445, _val446);
          }
        }
        struct.set_window_to_complete_latencies_ms_isSet(true);
      }
      if (incoming.get(3)) {
        {
          org.apache.storm.thrift.protocol.TMap _map448 = new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, iprot.readI32());
          struct.window_to_acked = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map448.size);
          @org.apache.storm.thrift.annotation.Nullable java.lang.String _key449;
          long _val450;
          for (int _i451 = 0; _i451 < _map448.size; ++_i451)
          {
            _key449 = iprot.readString();
            _val450 = iprot.readI64();
            struct.window_to_acked.put(_key449, _val450);
          }
        }
        struct.set_window_to_acked_isSet(true);
      }
      if (incoming.get(4)) {
        {
          org.apache.storm.thrift.protocol.TMap _map452 = new org.apache.storm.thrift.protocol.TMap(org.apache.storm.thrift.protocol.TType.STRING, org.apache.storm.thrift.protocol.TType.I64, iprot.readI32());
          struct.window_to_failed = new java.util.HashMap<java.lang.String,java.lang.Long>(2*_map452.size);
          @org.apache.storm.thrift.annotation.Nullable java.lang.String _key453;
          long _val454;
          for (int _i455 = 0; _i455 < _map452.size; ++_i455)
          {
            _key453 = iprot.readString();
            _val454 = iprot.readI64();
            struct.window_to_failed.put(_key453, _val454);
          }
        }
        struct.set_window_to_failed_isSet(true);
      }
    }
  }

  private static <S extends org.apache.storm.thrift.scheme.IScheme> S scheme(org.apache.storm.thrift.protocol.TProtocol proto) {
    return (org.apache.storm.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
  }
}

