/**
 * 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.9.3)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package org.apache.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"})
public class TopologyActionOptions extends org.apache.thrift.TUnion<TopologyActionOptions, TopologyActionOptions._Fields> {
  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("TopologyActionOptions");
  private static final org.apache.thrift.protocol.TField KILL_OPTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("kill_options", org.apache.thrift.protocol.TType.STRUCT, (short)1);
  private static final org.apache.thrift.protocol.TField REBALANCE_OPTIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("rebalance_options", org.apache.thrift.protocol.TType.STRUCT, (short)2);

  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
    KILL_OPTIONS((short)1, "kill_options"),
    REBALANCE_OPTIONS((short)2, "rebalance_options");

    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: // KILL_OPTIONS
          return KILL_OPTIONS;
        case 2: // REBALANCE_OPTIONS
          return REBALANCE_OPTIONS;
        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;
    }
  }

  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.KILL_OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("kill_options", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, KillOptions.class)));
    tmpMap.put(_Fields.REBALANCE_OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("rebalance_options", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, RebalanceOptions.class)));
    metaDataMap = Collections.unmodifiableMap(tmpMap);
    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(TopologyActionOptions.class, metaDataMap);
  }

  public TopologyActionOptions() {
    super();
  }

  public TopologyActionOptions(_Fields setField, Object value) {
    super(setField, value);
  }

  public TopologyActionOptions(TopologyActionOptions other) {
    super(other);
  }
  public TopologyActionOptions deepCopy() {
    return new TopologyActionOptions(this);
  }

  public static TopologyActionOptions kill_options(KillOptions value) {
    TopologyActionOptions x = new TopologyActionOptions();
    x.set_kill_options(value);
    return x;
  }

  public static TopologyActionOptions rebalance_options(RebalanceOptions value) {
    TopologyActionOptions x = new TopologyActionOptions();
    x.set_rebalance_options(value);
    return x;
  }


  @Override
  protected void checkType(_Fields setField, Object value) throws ClassCastException {
    switch (setField) {
      case KILL_OPTIONS:
        if (value instanceof KillOptions) {
          break;
        }
        throw new ClassCastException("Was expecting value of type KillOptions for field 'kill_options', but got " + value.getClass().getSimpleName());
      case REBALANCE_OPTIONS:
        if (value instanceof RebalanceOptions) {
          break;
        }
        throw new ClassCastException("Was expecting value of type RebalanceOptions for field 'rebalance_options', but got " + value.getClass().getSimpleName());
      default:
        throw new IllegalArgumentException("Unknown field id " + setField);
    }
  }

  @Override
  protected Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TField field) throws org.apache.thrift.TException {
    _Fields setField = _Fields.findByThriftId(field.id);
    if (setField != null) {
      switch (setField) {
        case KILL_OPTIONS:
          if (field.type == KILL_OPTIONS_FIELD_DESC.type) {
            KillOptions kill_options;
            kill_options = new KillOptions();
            kill_options.read(iprot);
            return kill_options;
          } else {
            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
            return null;
          }
        case REBALANCE_OPTIONS:
          if (field.type == REBALANCE_OPTIONS_FIELD_DESC.type) {
            RebalanceOptions rebalance_options;
            rebalance_options = new RebalanceOptions();
            rebalance_options.read(iprot);
            return rebalance_options;
          } else {
            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
            return null;
          }
        default:
          throw new IllegalStateException("setField wasn't null, but didn't match any of the case statements!");
      }
    } else {
      org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
      return null;
    }
  }

  @Override
  protected void standardSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
    switch (setField_) {
      case KILL_OPTIONS:
        KillOptions kill_options = (KillOptions)value_;
        kill_options.write(oprot);
        return;
      case REBALANCE_OPTIONS:
        RebalanceOptions rebalance_options = (RebalanceOptions)value_;
        rebalance_options.write(oprot);
        return;
      default:
        throw new IllegalStateException("Cannot write union with unknown field " + setField_);
    }
  }

  @Override
  protected Object tupleSchemeReadValue(org.apache.thrift.protocol.TProtocol iprot, short fieldID) throws org.apache.thrift.TException {
    _Fields setField = _Fields.findByThriftId(fieldID);
    if (setField != null) {
      switch (setField) {
        case KILL_OPTIONS:
          KillOptions kill_options;
          kill_options = new KillOptions();
          kill_options.read(iprot);
          return kill_options;
        case REBALANCE_OPTIONS:
          RebalanceOptions rebalance_options;
          rebalance_options = new RebalanceOptions();
          rebalance_options.read(iprot);
          return rebalance_options;
        default:
          throw new IllegalStateException("setField wasn't null, but didn't match any of the case statements!");
      }
    } else {
      throw new TProtocolException("Couldn't find a field with field id " + fieldID);
    }
  }

  @Override
  protected void tupleSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
    switch (setField_) {
      case KILL_OPTIONS:
        KillOptions kill_options = (KillOptions)value_;
        kill_options.write(oprot);
        return;
      case REBALANCE_OPTIONS:
        RebalanceOptions rebalance_options = (RebalanceOptions)value_;
        rebalance_options.write(oprot);
        return;
      default:
        throw new IllegalStateException("Cannot write union with unknown field " + setField_);
    }
  }

  @Override
  protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {
    switch (setField) {
      case KILL_OPTIONS:
        return KILL_OPTIONS_FIELD_DESC;
      case REBALANCE_OPTIONS:
        return REBALANCE_OPTIONS_FIELD_DESC;
      default:
        throw new IllegalArgumentException("Unknown field id " + setField);
    }
  }

  @Override
  protected org.apache.thrift.protocol.TStruct getStructDesc() {
    return STRUCT_DESC;
  }

  @Override
  protected _Fields enumForId(short id) {
    return _Fields.findByThriftIdOrThrow(id);
  }

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


  public KillOptions get_kill_options() {
    if (getSetField() == _Fields.KILL_OPTIONS) {
      return (KillOptions)getFieldValue();
    } else {
      throw new RuntimeException("Cannot get field 'kill_options' because union is currently set to " + getFieldDesc(getSetField()).name);
    }
  }

  public void set_kill_options(KillOptions value) {
    if (value == null) throw new NullPointerException();
    setField_ = _Fields.KILL_OPTIONS;
    value_ = value;
  }

  public RebalanceOptions get_rebalance_options() {
    if (getSetField() == _Fields.REBALANCE_OPTIONS) {
      return (RebalanceOptions)getFieldValue();
    } else {
      throw new RuntimeException("Cannot get field 'rebalance_options' because union is currently set to " + getFieldDesc(getSetField()).name);
    }
  }

  public void set_rebalance_options(RebalanceOptions value) {
    if (value == null) throw new NullPointerException();
    setField_ = _Fields.REBALANCE_OPTIONS;
    value_ = value;
  }

  public boolean is_set_kill_options() {
    return setField_ == _Fields.KILL_OPTIONS;
  }


  public boolean is_set_rebalance_options() {
    return setField_ == _Fields.REBALANCE_OPTIONS;
  }


  public boolean equals(Object other) {
    if (other instanceof TopologyActionOptions) {
      return equals((TopologyActionOptions)other);
    } else {
      return false;
    }
  }

  public boolean equals(TopologyActionOptions other) {
    return other != null && getSetField() == other.getSetField() && getFieldValue().equals(other.getFieldValue());
  }

  @Override
  public int compareTo(TopologyActionOptions other) {
    int lastComparison = org.apache.thrift.TBaseHelper.compareTo(getSetField(), other.getSetField());
    if (lastComparison == 0) {
      return org.apache.thrift.TBaseHelper.compareTo(getFieldValue(), other.getFieldValue());
    }
    return lastComparison;
  }


  @Override
  public int hashCode() {
    List<Object> list = new ArrayList<Object>();
    list.add(this.getClass().getName());
    org.apache.thrift.TFieldIdEnum setField = getSetField();
    if (setField != null) {
      list.add(setField.getThriftFieldId());
      Object value = getFieldValue();
      if (value instanceof org.apache.thrift.TEnum) {
        list.add(((org.apache.thrift.TEnum)getFieldValue()).getValue());
      } else {
        list.add(value);
      }
    }
    return list.hashCode();
  }
  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 {
      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);
    }
  }


}
