/**
 * 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.18.1)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package org.apache.airavata.model.messaging.event;

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

  private static final org.apache.thrift.protocol.TField EXPERIMENT_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("experimentId", org.apache.thrift.protocol.TType.STRING, (short)1);
  private static final org.apache.thrift.protocol.TField GATEWAY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("gatewayId", org.apache.thrift.protocol.TType.STRING, (short)2);
  private static final org.apache.thrift.protocol.TField OUTPUT_NAMES_FIELD_DESC = new org.apache.thrift.protocol.TField("outputNames", org.apache.thrift.protocol.TType.LIST, (short)3);

  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ExperimentIntermediateOutputsEventStandardSchemeFactory();
  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ExperimentIntermediateOutputsEventTupleSchemeFactory();

  private @org.apache.thrift.annotation.Nullable java.lang.String experimentId; // required
  private @org.apache.thrift.annotation.Nullable java.lang.String gatewayId; // required
  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> outputNames; // 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 {
    EXPERIMENT_ID((short)1, "experimentId"),
    GATEWAY_ID((short)2, "gatewayId"),
    OUTPUT_NAMES((short)3, "outputNames");

    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.thrift.annotation.Nullable
    public static _Fields findByThriftId(int fieldId) {
      switch(fieldId) {
        case 1: // EXPERIMENT_ID
          return EXPERIMENT_ID;
        case 2: // GATEWAY_ID
          return GATEWAY_ID;
        case 3: // OUTPUT_NAMES
          return OUTPUT_NAMES;
        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.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;
    }

    @Override
    public short getThriftFieldId() {
      return _thriftId;
    }

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

  // isset id assignments
  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
  static {
    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
    tmpMap.put(_Fields.EXPERIMENT_ID, new org.apache.thrift.meta_data.FieldMetaData("experimentId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
    tmpMap.put(_Fields.GATEWAY_ID, new org.apache.thrift.meta_data.FieldMetaData("gatewayId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
    tmpMap.put(_Fields.OUTPUT_NAMES, new org.apache.thrift.meta_data.FieldMetaData("outputNames", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ExperimentIntermediateOutputsEvent.class, metaDataMap);
  }

  public ExperimentIntermediateOutputsEvent() {
  }

  public ExperimentIntermediateOutputsEvent(
    java.lang.String experimentId,
    java.lang.String gatewayId,
    java.util.List<java.lang.String> outputNames)
  {
    this();
    this.experimentId = experimentId;
    this.gatewayId = gatewayId;
    this.outputNames = outputNames;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public ExperimentIntermediateOutputsEvent(ExperimentIntermediateOutputsEvent other) {
    if (other.isSetExperimentId()) {
      this.experimentId = other.experimentId;
    }
    if (other.isSetGatewayId()) {
      this.gatewayId = other.gatewayId;
    }
    if (other.isSetOutputNames()) {
      java.util.List<java.lang.String> __this__outputNames = new java.util.ArrayList<java.lang.String>(other.outputNames);
      this.outputNames = __this__outputNames;
    }
  }

  @Override
  public ExperimentIntermediateOutputsEvent deepCopy() {
    return new ExperimentIntermediateOutputsEvent(this);
  }

  @Override
  public void clear() {
    this.experimentId = null;
    this.gatewayId = null;
    this.outputNames = null;
  }

  @org.apache.thrift.annotation.Nullable
  public java.lang.String getExperimentId() {
    return this.experimentId;
  }

  public void setExperimentId(@org.apache.thrift.annotation.Nullable java.lang.String experimentId) {
    this.experimentId = experimentId;
  }

  public void unsetExperimentId() {
    this.experimentId = null;
  }

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

  public void setExperimentIdIsSet(boolean value) {
    if (!value) {
      this.experimentId = null;
    }
  }

  @org.apache.thrift.annotation.Nullable
  public java.lang.String getGatewayId() {
    return this.gatewayId;
  }

  public void setGatewayId(@org.apache.thrift.annotation.Nullable java.lang.String gatewayId) {
    this.gatewayId = gatewayId;
  }

  public void unsetGatewayId() {
    this.gatewayId = null;
  }

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

  public void setGatewayIdIsSet(boolean value) {
    if (!value) {
      this.gatewayId = null;
    }
  }

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

  @org.apache.thrift.annotation.Nullable
  public java.util.Iterator<java.lang.String> getOutputNamesIterator() {
    return (this.outputNames == null) ? null : this.outputNames.iterator();
  }

  public void addToOutputNames(java.lang.String elem) {
    if (this.outputNames == null) {
      this.outputNames = new java.util.ArrayList<java.lang.String>();
    }
    this.outputNames.add(elem);
  }

  @org.apache.thrift.annotation.Nullable
  public java.util.List<java.lang.String> getOutputNames() {
    return this.outputNames;
  }

  public void setOutputNames(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> outputNames) {
    this.outputNames = outputNames;
  }

  public void unsetOutputNames() {
    this.outputNames = null;
  }

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

  public void setOutputNamesIsSet(boolean value) {
    if (!value) {
      this.outputNames = null;
    }
  }

  @Override
  public void setFieldValue(_Fields field, @org.apache.thrift.annotation.Nullable java.lang.Object value) {
    switch (field) {
    case EXPERIMENT_ID:
      if (value == null) {
        unsetExperimentId();
      } else {
        setExperimentId((java.lang.String)value);
      }
      break;

    case GATEWAY_ID:
      if (value == null) {
        unsetGatewayId();
      } else {
        setGatewayId((java.lang.String)value);
      }
      break;

    case OUTPUT_NAMES:
      if (value == null) {
        unsetOutputNames();
      } else {
        setOutputNames((java.util.List<java.lang.String>)value);
      }
      break;

    }
  }

  @org.apache.thrift.annotation.Nullable
  @Override
  public java.lang.Object getFieldValue(_Fields field) {
    switch (field) {
    case EXPERIMENT_ID:
      return getExperimentId();

    case GATEWAY_ID:
      return getGatewayId();

    case OUTPUT_NAMES:
      return getOutputNames();

    }
    throw new java.lang.IllegalStateException();
  }

  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
  @Override
  public boolean isSet(_Fields field) {
    if (field == null) {
      throw new java.lang.IllegalArgumentException();
    }

    switch (field) {
    case EXPERIMENT_ID:
      return isSetExperimentId();
    case GATEWAY_ID:
      return isSetGatewayId();
    case OUTPUT_NAMES:
      return isSetOutputNames();
    }
    throw new java.lang.IllegalStateException();
  }

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

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

    boolean this_present_experimentId = true && this.isSetExperimentId();
    boolean that_present_experimentId = true && that.isSetExperimentId();
    if (this_present_experimentId || that_present_experimentId) {
      if (!(this_present_experimentId && that_present_experimentId))
        return false;
      if (!this.experimentId.equals(that.experimentId))
        return false;
    }

    boolean this_present_gatewayId = true && this.isSetGatewayId();
    boolean that_present_gatewayId = true && that.isSetGatewayId();
    if (this_present_gatewayId || that_present_gatewayId) {
      if (!(this_present_gatewayId && that_present_gatewayId))
        return false;
      if (!this.gatewayId.equals(that.gatewayId))
        return false;
    }

    boolean this_present_outputNames = true && this.isSetOutputNames();
    boolean that_present_outputNames = true && that.isSetOutputNames();
    if (this_present_outputNames || that_present_outputNames) {
      if (!(this_present_outputNames && that_present_outputNames))
        return false;
      if (!this.outputNames.equals(that.outputNames))
        return false;
    }

    return true;
  }

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

    hashCode = hashCode * 8191 + ((isSetExperimentId()) ? 131071 : 524287);
    if (isSetExperimentId())
      hashCode = hashCode * 8191 + experimentId.hashCode();

    hashCode = hashCode * 8191 + ((isSetGatewayId()) ? 131071 : 524287);
    if (isSetGatewayId())
      hashCode = hashCode * 8191 + gatewayId.hashCode();

    hashCode = hashCode * 8191 + ((isSetOutputNames()) ? 131071 : 524287);
    if (isSetOutputNames())
      hashCode = hashCode * 8191 + outputNames.hashCode();

    return hashCode;
  }

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

    int lastComparison = 0;

    lastComparison = java.lang.Boolean.compare(isSetExperimentId(), other.isSetExperimentId());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetExperimentId()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.experimentId, other.experimentId);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.compare(isSetGatewayId(), other.isSetGatewayId());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetGatewayId()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.gatewayId, other.gatewayId);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.compare(isSetOutputNames(), other.isSetOutputNames());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetOutputNames()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.outputNames, other.outputNames);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    return 0;
  }

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

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

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

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

    sb.append("experimentId:");
    if (this.experimentId == null) {
      sb.append("null");
    } else {
      sb.append(this.experimentId);
    }
    first = false;
    if (!first) sb.append(", ");
    sb.append("gatewayId:");
    if (this.gatewayId == null) {
      sb.append("null");
    } else {
      sb.append(this.gatewayId);
    }
    first = false;
    if (!first) sb.append(", ");
    sb.append("outputNames:");
    if (this.outputNames == null) {
      sb.append("null");
    } else {
      sb.append(this.outputNames);
    }
    first = false;
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws org.apache.thrift.TException {
    // check for required fields
    if (!isSetExperimentId()) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'experimentId' is unset! Struct:" + toString());
    }

    if (!isSetGatewayId()) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'gatewayId' is unset! Struct:" + toString());
    }

    if (!isSetOutputNames()) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'outputNames' 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 (org.apache.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.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
    } catch (org.apache.thrift.TException te) {
      throw new java.io.IOException(te);
    }
  }

  private static class ExperimentIntermediateOutputsEventStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
    @Override
    public ExperimentIntermediateOutputsEventStandardScheme getScheme() {
      return new ExperimentIntermediateOutputsEventStandardScheme();
    }
  }

  private static class ExperimentIntermediateOutputsEventStandardScheme extends org.apache.thrift.scheme.StandardScheme<ExperimentIntermediateOutputsEvent> {

    @Override
    public void read(org.apache.thrift.protocol.TProtocol iprot, ExperimentIntermediateOutputsEvent struct) throws org.apache.thrift.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: // EXPERIMENT_ID
            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
              struct.experimentId = iprot.readString();
              struct.setExperimentIdIsSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 2: // GATEWAY_ID
            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
              struct.gatewayId = iprot.readString();
              struct.setGatewayIdIsSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 3: // OUTPUT_NAMES
            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
              {
                org.apache.thrift.protocol.TList _list8 = iprot.readListBegin();
                struct.outputNames = new java.util.ArrayList<java.lang.String>(_list8.size);
                @org.apache.thrift.annotation.Nullable java.lang.String _elem9;
                for (int _i10 = 0; _i10 < _list8.size; ++_i10)
                {
                  _elem9 = iprot.readString();
                  struct.outputNames.add(_elem9);
                }
                iprot.readListEnd();
              }
              struct.setOutputNamesIsSet(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();
    }

    @Override
    public void write(org.apache.thrift.protocol.TProtocol oprot, ExperimentIntermediateOutputsEvent struct) throws org.apache.thrift.TException {
      struct.validate();

      oprot.writeStructBegin(STRUCT_DESC);
      if (struct.experimentId != null) {
        oprot.writeFieldBegin(EXPERIMENT_ID_FIELD_DESC);
        oprot.writeString(struct.experimentId);
        oprot.writeFieldEnd();
      }
      if (struct.gatewayId != null) {
        oprot.writeFieldBegin(GATEWAY_ID_FIELD_DESC);
        oprot.writeString(struct.gatewayId);
        oprot.writeFieldEnd();
      }
      if (struct.outputNames != null) {
        oprot.writeFieldBegin(OUTPUT_NAMES_FIELD_DESC);
        {
          oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.outputNames.size()));
          for (java.lang.String _iter11 : struct.outputNames)
          {
            oprot.writeString(_iter11);
          }
          oprot.writeListEnd();
        }
        oprot.writeFieldEnd();
      }
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }

  private static class ExperimentIntermediateOutputsEventTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
    @Override
    public ExperimentIntermediateOutputsEventTupleScheme getScheme() {
      return new ExperimentIntermediateOutputsEventTupleScheme();
    }
  }

  private static class ExperimentIntermediateOutputsEventTupleScheme extends org.apache.thrift.scheme.TupleScheme<ExperimentIntermediateOutputsEvent> {

    @Override
    public void write(org.apache.thrift.protocol.TProtocol prot, ExperimentIntermediateOutputsEvent struct) throws org.apache.thrift.TException {
      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
      oprot.writeString(struct.experimentId);
      oprot.writeString(struct.gatewayId);
      {
        oprot.writeI32(struct.outputNames.size());
        for (java.lang.String _iter12 : struct.outputNames)
        {
          oprot.writeString(_iter12);
        }
      }
    }

    @Override
    public void read(org.apache.thrift.protocol.TProtocol prot, ExperimentIntermediateOutputsEvent struct) throws org.apache.thrift.TException {
      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
      struct.experimentId = iprot.readString();
      struct.setExperimentIdIsSet(true);
      struct.gatewayId = iprot.readString();
      struct.setGatewayIdIsSet(true);
      {
        org.apache.thrift.protocol.TList _list13 = iprot.readListBegin(org.apache.thrift.protocol.TType.STRING);
        struct.outputNames = new java.util.ArrayList<java.lang.String>(_list13.size);
        @org.apache.thrift.annotation.Nullable java.lang.String _elem14;
        for (int _i15 = 0; _i15 < _list13.size; ++_i15)
        {
          _elem14 = iprot.readString();
          struct.outputNames.add(_elem14);
        }
      }
      struct.setOutputNamesIsSet(true);
    }
  }

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

