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

  private static final org.apache.thrift.protocol.TField METRIC_WINDOW_FIELD_DESC = new org.apache.thrift.protocol.TField("metricWindow", org.apache.thrift.protocol.TType.MAP, (short)1);

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

  private Map<Integer,Double> metricWindow; // 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 {
    METRIC_WINDOW((short)1, "metricWindow");

    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: // METRIC_WINDOW
          return METRIC_WINDOW;
        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, 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.METRIC_WINDOW, new org.apache.thrift.meta_data.FieldMetaData("metricWindow", 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.I32), 
            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE))));
    metaDataMap = Collections.unmodifiableMap(tmpMap);
    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(MetricWindow.class, metaDataMap);
  }

  public MetricWindow() {
  }

  public MetricWindow(
    Map<Integer,Double> metricWindow)
  {
    this();
    this.metricWindow = metricWindow;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public MetricWindow(MetricWindow other) {
    if (other.is_set_metricWindow()) {
      Map<Integer,Double> __this__metricWindow = new HashMap<Integer,Double>(other.metricWindow);
      this.metricWindow = __this__metricWindow;
    }
  }

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

  @Override
  public void clear() {
    this.metricWindow = null;
  }

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

  public void put_to_metricWindow(int key, double val) {
    if (this.metricWindow == null) {
      this.metricWindow = new HashMap<Integer,Double>();
    }
    this.metricWindow.put(key, val);
  }

  public Map<Integer,Double> get_metricWindow() {
    return this.metricWindow;
  }

  public void set_metricWindow(Map<Integer,Double> metricWindow) {
    this.metricWindow = metricWindow;
  }

  public void unset_metricWindow() {
    this.metricWindow = null;
  }

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

  public void set_metricWindow_isSet(boolean value) {
    if (!value) {
      this.metricWindow = null;
    }
  }

  public void setFieldValue(_Fields field, Object value) {
    switch (field) {
    case METRIC_WINDOW:
      if (value == null) {
        unset_metricWindow();
      } else {
        set_metricWindow((Map<Integer,Double>)value);
      }
      break;

    }
  }

  public Object getFieldValue(_Fields field) {
    switch (field) {
    case METRIC_WINDOW:
      return get_metricWindow();

    }
    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 METRIC_WINDOW:
      return is_set_metricWindow();
    }
    throw new IllegalStateException();
  }

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

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

    boolean this_present_metricWindow = true && this.is_set_metricWindow();
    boolean that_present_metricWindow = true && that.is_set_metricWindow();
    if (this_present_metricWindow || that_present_metricWindow) {
      if (!(this_present_metricWindow && that_present_metricWindow))
        return false;
      if (!this.metricWindow.equals(that.metricWindow))
        return false;
    }

    return true;
  }

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

    boolean present_metricWindow = true && (is_set_metricWindow());
    list.add(present_metricWindow);
    if (present_metricWindow)
      list.add(metricWindow);

    return list.hashCode();
  }

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

    int lastComparison = 0;

    lastComparison = Boolean.valueOf(is_set_metricWindow()).compareTo(other.is_set_metricWindow());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (is_set_metricWindow()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.metricWindow, other.metricWindow);
      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("MetricWindow(");
    boolean first = true;

    sb.append("metricWindow:");
    if (this.metricWindow == null) {
      sb.append("null");
    } else {
      sb.append(this.metricWindow);
    }
    first = false;
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws TException {
    // check for required fields
    if (!is_set_metricWindow()) {
      throw new TProtocolException("Required field 'metricWindow' 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 {
      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 MetricWindowStandardSchemeFactory implements SchemeFactory {
    public MetricWindowStandardScheme getScheme() {
      return new MetricWindowStandardScheme();
    }
  }

  private static class MetricWindowStandardScheme extends StandardScheme<MetricWindow> {

    public void read(org.apache.thrift.protocol.TProtocol iprot, MetricWindow 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: // METRIC_WINDOW
            if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
              {
                org.apache.thrift.protocol.TMap _map106 = iprot.readMapBegin();
                struct.metricWindow = new HashMap<Integer,Double>(2*_map106.size);
                int _key107;
                double _val108;
                for (int _i109 = 0; _i109 < _map106.size; ++_i109)
                {
                  _key107 = iprot.readI32();
                  _val108 = iprot.readDouble();
                  struct.metricWindow.put(_key107, _val108);
                }
                iprot.readMapEnd();
              }
              struct.set_metricWindow_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, MetricWindow struct) throws TException {
      struct.validate();

      oprot.writeStructBegin(STRUCT_DESC);
      if (struct.metricWindow != null) {
        oprot.writeFieldBegin(METRIC_WINDOW_FIELD_DESC);
        {
          oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.I32, org.apache.thrift.protocol.TType.DOUBLE, struct.metricWindow.size()));
          for (Map.Entry<Integer, Double> _iter110 : struct.metricWindow.entrySet())
          {
            oprot.writeI32(_iter110.getKey());
            oprot.writeDouble(_iter110.getValue());
          }
          oprot.writeMapEnd();
        }
        oprot.writeFieldEnd();
      }
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }

  private static class MetricWindowTupleSchemeFactory implements SchemeFactory {
    public MetricWindowTupleScheme getScheme() {
      return new MetricWindowTupleScheme();
    }
  }

  private static class MetricWindowTupleScheme extends TupleScheme<MetricWindow> {

    @Override
    public void write(org.apache.thrift.protocol.TProtocol prot, MetricWindow struct) throws TException {
      TTupleProtocol oprot = (TTupleProtocol) prot;
      {
        oprot.writeI32(struct.metricWindow.size());
        for (Map.Entry<Integer, Double> _iter111 : struct.metricWindow.entrySet())
        {
          oprot.writeI32(_iter111.getKey());
          oprot.writeDouble(_iter111.getValue());
        }
      }
    }

    @Override
    public void read(org.apache.thrift.protocol.TProtocol prot, MetricWindow struct) throws TException {
      TTupleProtocol iprot = (TTupleProtocol) prot;
      {
        org.apache.thrift.protocol.TMap _map112 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.I32, org.apache.thrift.protocol.TType.DOUBLE, iprot.readI32());
        struct.metricWindow = new HashMap<Integer,Double>(2*_map112.size);
        int _key113;
        double _val114;
        for (int _i115 = 0; _i115 < _map112.size; ++_i115)
        {
          _key113 = iprot.readI32();
          _val114 = iprot.readDouble();
          struct.metricWindow.put(_key113, _val114);
        }
      }
      struct.set_metricWindow_isSet(true);
    }
  }

}

