/**
 * 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 TopologyActionOptions extends org.apache.storm.thrift.TUnion<TopologyActionOptions, TopologyActionOptions._Fields> {
  private static final org.apache.storm.thrift.protocol.TStruct STRUCT_DESC = new org.apache.storm.thrift.protocol.TStruct("TopologyActionOptions");
  private static final org.apache.storm.thrift.protocol.TField KILL_OPTIONS_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("kill_options", org.apache.storm.thrift.protocol.TType.STRUCT, (short)1);
  private static final org.apache.storm.thrift.protocol.TField REBALANCE_OPTIONS_FIELD_DESC = new org.apache.storm.thrift.protocol.TField("rebalance_options", org.apache.storm.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.storm.thrift.TFieldIdEnum {
    KILL_OPTIONS((short)1, "kill_options"),
    REBALANCE_OPTIONS((short)2, "rebalance_options");

    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: // 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 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;
    }
  }

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

  public TopologyActionOptions() {
    super();
  }

  public TopologyActionOptions(_Fields setField, java.lang.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, java.lang.Object value) throws java.lang.ClassCastException {
    switch (setField) {
      case KILL_OPTIONS:
        if (value instanceof KillOptions) {
          break;
        }
        throw new java.lang.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 java.lang.ClassCastException("Was expecting value of type RebalanceOptions for field 'rebalance_options', but got " + value.getClass().getSimpleName());
      default:
        throw new java.lang.IllegalArgumentException("Unknown field id " + setField);
    }
  }

  @Override
  protected java.lang.Object standardSchemeReadValue(org.apache.storm.thrift.protocol.TProtocol iprot, org.apache.storm.thrift.protocol.TField field) throws org.apache.storm.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.storm.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.storm.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
            return null;
          }
        default:
          throw new java.lang.IllegalStateException("setField wasn't null, but didn't match any of the case statements!");
      }
    } else {
      org.apache.storm.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
      return null;
    }
  }

  @Override
  protected void standardSchemeWriteValue(org.apache.storm.thrift.protocol.TProtocol oprot) throws org.apache.storm.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 java.lang.IllegalStateException("Cannot write union with unknown field " + setField_);
    }
  }

  @Override
  protected java.lang.Object tupleSchemeReadValue(org.apache.storm.thrift.protocol.TProtocol iprot, short fieldID) throws org.apache.storm.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 java.lang.IllegalStateException("setField wasn't null, but didn't match any of the case statements!");
      }
    } else {
      throw new org.apache.storm.thrift.protocol.TProtocolException("Couldn't find a field with field id " + fieldID);
    }
  }

  @Override
  protected void tupleSchemeWriteValue(org.apache.storm.thrift.protocol.TProtocol oprot) throws org.apache.storm.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 java.lang.IllegalStateException("Cannot write union with unknown field " + setField_);
    }
  }

  @Override
  protected org.apache.storm.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 java.lang.IllegalArgumentException("Unknown field id " + setField);
    }
  }

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

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

  @org.apache.storm.thrift.annotation.Nullable
  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 java.lang.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 java.lang.NullPointerException();
    setField_ = _Fields.KILL_OPTIONS;
    value_ = value;
  }

  public RebalanceOptions get_rebalance_options() {
    if (getSetField() == _Fields.REBALANCE_OPTIONS) {
      return (RebalanceOptions)getFieldValue();
    } else {
      throw new java.lang.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 java.lang.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(java.lang.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.storm.thrift.TBaseHelper.compareTo(getSetField(), other.getSetField());
    if (lastComparison == 0) {
      return org.apache.storm.thrift.TBaseHelper.compareTo(getFieldValue(), other.getFieldValue());
    }
    return lastComparison;
  }


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


}
