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

@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
/**
 * Gateway Resource Profile
 * 
 * gatewayID:
 *  Unique identifier for the gateway assigned by Airavata. Corelate this to Airavata Admin API Gateway Registration.
 * 
 * credentialStoreToken:
 *  Gateway's defualt credential store token.
 * 
 * computeResourcePreferences:
 *  List of resource preferences for each of the registered compute resources.
 * 
 *  identityServerTenant:
 * 
 *  identityServerPwdCredToken:
 * 
 */
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
public class GatewayResourceProfile implements org.apache.thrift.TBase<GatewayResourceProfile, GatewayResourceProfile._Fields>, java.io.Serializable, Cloneable, Comparable<GatewayResourceProfile> {
  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("GatewayResourceProfile");

  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)1);
  private static final org.apache.thrift.protocol.TField CREDENTIAL_STORE_TOKEN_FIELD_DESC = new org.apache.thrift.protocol.TField("credentialStoreToken", org.apache.thrift.protocol.TType.STRING, (short)2);
  private static final org.apache.thrift.protocol.TField COMPUTE_RESOURCE_PREFERENCES_FIELD_DESC = new org.apache.thrift.protocol.TField("computeResourcePreferences", org.apache.thrift.protocol.TType.LIST, (short)3);
  private static final org.apache.thrift.protocol.TField STORAGE_PREFERENCES_FIELD_DESC = new org.apache.thrift.protocol.TField("storagePreferences", org.apache.thrift.protocol.TType.LIST, (short)4);
  private static final org.apache.thrift.protocol.TField IDENTITY_SERVER_TENANT_FIELD_DESC = new org.apache.thrift.protocol.TField("identityServerTenant", org.apache.thrift.protocol.TType.STRING, (short)5);
  private static final org.apache.thrift.protocol.TField IDENTITY_SERVER_PWD_CRED_TOKEN_FIELD_DESC = new org.apache.thrift.protocol.TField("identityServerPwdCredToken", org.apache.thrift.protocol.TType.STRING, (short)6);

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

  private java.lang.String gatewayID; // required
  private java.lang.String credentialStoreToken; // optional
  private java.util.List<ComputeResourcePreference> computeResourcePreferences; // optional
  private java.util.List<StoragePreference> storagePreferences; // optional
  private java.lang.String identityServerTenant; // optional
  private java.lang.String identityServerPwdCredToken; // optional

  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
    GATEWAY_ID((short)1, "gatewayID"),
    CREDENTIAL_STORE_TOKEN((short)2, "credentialStoreToken"),
    COMPUTE_RESOURCE_PREFERENCES((short)3, "computeResourcePreferences"),
    STORAGE_PREFERENCES((short)4, "storagePreferences"),
    IDENTITY_SERVER_TENANT((short)5, "identityServerTenant"),
    IDENTITY_SERVER_PWD_CRED_TOKEN((short)6, "identityServerPwdCredToken");

    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.
     */
    public static _Fields findByThriftId(int fieldId) {
      switch(fieldId) {
        case 1: // GATEWAY_ID
          return GATEWAY_ID;
        case 2: // CREDENTIAL_STORE_TOKEN
          return CREDENTIAL_STORE_TOKEN;
        case 3: // COMPUTE_RESOURCE_PREFERENCES
          return COMPUTE_RESOURCE_PREFERENCES;
        case 4: // STORAGE_PREFERENCES
          return STORAGE_PREFERENCES;
        case 5: // IDENTITY_SERVER_TENANT
          return IDENTITY_SERVER_TENANT;
        case 6: // IDENTITY_SERVER_PWD_CRED_TOKEN
          return IDENTITY_SERVER_PWD_CRED_TOKEN;
        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.
     */
    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.CREDENTIAL_STORE_TOKEN,_Fields.COMPUTE_RESOURCE_PREFERENCES,_Fields.STORAGE_PREFERENCES,_Fields.IDENTITY_SERVER_TENANT,_Fields.IDENTITY_SERVER_PWD_CRED_TOKEN};
  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.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.CREDENTIAL_STORE_TOKEN, new org.apache.thrift.meta_data.FieldMetaData("credentialStoreToken", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
    tmpMap.put(_Fields.COMPUTE_RESOURCE_PREFERENCES, new org.apache.thrift.meta_data.FieldMetaData("computeResourcePreferences", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
            new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, ComputeResourcePreference.class))));
    tmpMap.put(_Fields.STORAGE_PREFERENCES, new org.apache.thrift.meta_data.FieldMetaData("storagePreferences", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
            new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, StoragePreference.class))));
    tmpMap.put(_Fields.IDENTITY_SERVER_TENANT, new org.apache.thrift.meta_data.FieldMetaData("identityServerTenant", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
    tmpMap.put(_Fields.IDENTITY_SERVER_PWD_CRED_TOKEN, new org.apache.thrift.meta_data.FieldMetaData("identityServerPwdCredToken", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
        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(GatewayResourceProfile.class, metaDataMap);
  }

  public GatewayResourceProfile() {
  }

  public GatewayResourceProfile(
    java.lang.String gatewayID)
  {
    this();
    this.gatewayID = gatewayID;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public GatewayResourceProfile(GatewayResourceProfile other) {
    if (other.isSetGatewayID()) {
      this.gatewayID = other.gatewayID;
    }
    if (other.isSetCredentialStoreToken()) {
      this.credentialStoreToken = other.credentialStoreToken;
    }
    if (other.isSetComputeResourcePreferences()) {
      java.util.List<ComputeResourcePreference> __this__computeResourcePreferences = new java.util.ArrayList<ComputeResourcePreference>(other.computeResourcePreferences.size());
      for (ComputeResourcePreference other_element : other.computeResourcePreferences) {
        __this__computeResourcePreferences.add(new ComputeResourcePreference(other_element));
      }
      this.computeResourcePreferences = __this__computeResourcePreferences;
    }
    if (other.isSetStoragePreferences()) {
      java.util.List<StoragePreference> __this__storagePreferences = new java.util.ArrayList<StoragePreference>(other.storagePreferences.size());
      for (StoragePreference other_element : other.storagePreferences) {
        __this__storagePreferences.add(new StoragePreference(other_element));
      }
      this.storagePreferences = __this__storagePreferences;
    }
    if (other.isSetIdentityServerTenant()) {
      this.identityServerTenant = other.identityServerTenant;
    }
    if (other.isSetIdentityServerPwdCredToken()) {
      this.identityServerPwdCredToken = other.identityServerPwdCredToken;
    }
  }

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

  @Override
  public void clear() {
    this.gatewayID = null;
    this.credentialStoreToken = null;
    this.computeResourcePreferences = null;
    this.storagePreferences = null;
    this.identityServerTenant = null;
    this.identityServerPwdCredToken = null;
  }

  public java.lang.String getGatewayID() {
    return this.gatewayID;
  }

  public void setGatewayID(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 java.lang.String getCredentialStoreToken() {
    return this.credentialStoreToken;
  }

  public void setCredentialStoreToken(java.lang.String credentialStoreToken) {
    this.credentialStoreToken = credentialStoreToken;
  }

  public void unsetCredentialStoreToken() {
    this.credentialStoreToken = null;
  }

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

  public void setCredentialStoreTokenIsSet(boolean value) {
    if (!value) {
      this.credentialStoreToken = null;
    }
  }

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

  public java.util.Iterator<ComputeResourcePreference> getComputeResourcePreferencesIterator() {
    return (this.computeResourcePreferences == null) ? null : this.computeResourcePreferences.iterator();
  }

  public void addToComputeResourcePreferences(ComputeResourcePreference elem) {
    if (this.computeResourcePreferences == null) {
      this.computeResourcePreferences = new java.util.ArrayList<ComputeResourcePreference>();
    }
    this.computeResourcePreferences.add(elem);
  }

  public java.util.List<ComputeResourcePreference> getComputeResourcePreferences() {
    return this.computeResourcePreferences;
  }

  public void setComputeResourcePreferences(java.util.List<ComputeResourcePreference> computeResourcePreferences) {
    this.computeResourcePreferences = computeResourcePreferences;
  }

  public void unsetComputeResourcePreferences() {
    this.computeResourcePreferences = null;
  }

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

  public void setComputeResourcePreferencesIsSet(boolean value) {
    if (!value) {
      this.computeResourcePreferences = null;
    }
  }

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

  public java.util.Iterator<StoragePreference> getStoragePreferencesIterator() {
    return (this.storagePreferences == null) ? null : this.storagePreferences.iterator();
  }

  public void addToStoragePreferences(StoragePreference elem) {
    if (this.storagePreferences == null) {
      this.storagePreferences = new java.util.ArrayList<StoragePreference>();
    }
    this.storagePreferences.add(elem);
  }

  public java.util.List<StoragePreference> getStoragePreferences() {
    return this.storagePreferences;
  }

  public void setStoragePreferences(java.util.List<StoragePreference> storagePreferences) {
    this.storagePreferences = storagePreferences;
  }

  public void unsetStoragePreferences() {
    this.storagePreferences = null;
  }

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

  public void setStoragePreferencesIsSet(boolean value) {
    if (!value) {
      this.storagePreferences = null;
    }
  }

  public java.lang.String getIdentityServerTenant() {
    return this.identityServerTenant;
  }

  public void setIdentityServerTenant(java.lang.String identityServerTenant) {
    this.identityServerTenant = identityServerTenant;
  }

  public void unsetIdentityServerTenant() {
    this.identityServerTenant = null;
  }

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

  public void setIdentityServerTenantIsSet(boolean value) {
    if (!value) {
      this.identityServerTenant = null;
    }
  }

  public java.lang.String getIdentityServerPwdCredToken() {
    return this.identityServerPwdCredToken;
  }

  public void setIdentityServerPwdCredToken(java.lang.String identityServerPwdCredToken) {
    this.identityServerPwdCredToken = identityServerPwdCredToken;
  }

  public void unsetIdentityServerPwdCredToken() {
    this.identityServerPwdCredToken = null;
  }

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

  public void setIdentityServerPwdCredTokenIsSet(boolean value) {
    if (!value) {
      this.identityServerPwdCredToken = null;
    }
  }

  public void setFieldValue(_Fields field, java.lang.Object value) {
    switch (field) {
    case GATEWAY_ID:
      if (value == null) {
        unsetGatewayID();
      } else {
        setGatewayID((java.lang.String)value);
      }
      break;

    case CREDENTIAL_STORE_TOKEN:
      if (value == null) {
        unsetCredentialStoreToken();
      } else {
        setCredentialStoreToken((java.lang.String)value);
      }
      break;

    case COMPUTE_RESOURCE_PREFERENCES:
      if (value == null) {
        unsetComputeResourcePreferences();
      } else {
        setComputeResourcePreferences((java.util.List<ComputeResourcePreference>)value);
      }
      break;

    case STORAGE_PREFERENCES:
      if (value == null) {
        unsetStoragePreferences();
      } else {
        setStoragePreferences((java.util.List<StoragePreference>)value);
      }
      break;

    case IDENTITY_SERVER_TENANT:
      if (value == null) {
        unsetIdentityServerTenant();
      } else {
        setIdentityServerTenant((java.lang.String)value);
      }
      break;

    case IDENTITY_SERVER_PWD_CRED_TOKEN:
      if (value == null) {
        unsetIdentityServerPwdCredToken();
      } else {
        setIdentityServerPwdCredToken((java.lang.String)value);
      }
      break;

    }
  }

  public java.lang.Object getFieldValue(_Fields field) {
    switch (field) {
    case GATEWAY_ID:
      return getGatewayID();

    case CREDENTIAL_STORE_TOKEN:
      return getCredentialStoreToken();

    case COMPUTE_RESOURCE_PREFERENCES:
      return getComputeResourcePreferences();

    case STORAGE_PREFERENCES:
      return getStoragePreferences();

    case IDENTITY_SERVER_TENANT:
      return getIdentityServerTenant();

    case IDENTITY_SERVER_PWD_CRED_TOKEN:
      return getIdentityServerPwdCredToken();

    }
    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 GATEWAY_ID:
      return isSetGatewayID();
    case CREDENTIAL_STORE_TOKEN:
      return isSetCredentialStoreToken();
    case COMPUTE_RESOURCE_PREFERENCES:
      return isSetComputeResourcePreferences();
    case STORAGE_PREFERENCES:
      return isSetStoragePreferences();
    case IDENTITY_SERVER_TENANT:
      return isSetIdentityServerTenant();
    case IDENTITY_SERVER_PWD_CRED_TOKEN:
      return isSetIdentityServerPwdCredToken();
    }
    throw new java.lang.IllegalStateException();
  }

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

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

    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_credentialStoreToken = true && this.isSetCredentialStoreToken();
    boolean that_present_credentialStoreToken = true && that.isSetCredentialStoreToken();
    if (this_present_credentialStoreToken || that_present_credentialStoreToken) {
      if (!(this_present_credentialStoreToken && that_present_credentialStoreToken))
        return false;
      if (!this.credentialStoreToken.equals(that.credentialStoreToken))
        return false;
    }

    boolean this_present_computeResourcePreferences = true && this.isSetComputeResourcePreferences();
    boolean that_present_computeResourcePreferences = true && that.isSetComputeResourcePreferences();
    if (this_present_computeResourcePreferences || that_present_computeResourcePreferences) {
      if (!(this_present_computeResourcePreferences && that_present_computeResourcePreferences))
        return false;
      if (!this.computeResourcePreferences.equals(that.computeResourcePreferences))
        return false;
    }

    boolean this_present_storagePreferences = true && this.isSetStoragePreferences();
    boolean that_present_storagePreferences = true && that.isSetStoragePreferences();
    if (this_present_storagePreferences || that_present_storagePreferences) {
      if (!(this_present_storagePreferences && that_present_storagePreferences))
        return false;
      if (!this.storagePreferences.equals(that.storagePreferences))
        return false;
    }

    boolean this_present_identityServerTenant = true && this.isSetIdentityServerTenant();
    boolean that_present_identityServerTenant = true && that.isSetIdentityServerTenant();
    if (this_present_identityServerTenant || that_present_identityServerTenant) {
      if (!(this_present_identityServerTenant && that_present_identityServerTenant))
        return false;
      if (!this.identityServerTenant.equals(that.identityServerTenant))
        return false;
    }

    boolean this_present_identityServerPwdCredToken = true && this.isSetIdentityServerPwdCredToken();
    boolean that_present_identityServerPwdCredToken = true && that.isSetIdentityServerPwdCredToken();
    if (this_present_identityServerPwdCredToken || that_present_identityServerPwdCredToken) {
      if (!(this_present_identityServerPwdCredToken && that_present_identityServerPwdCredToken))
        return false;
      if (!this.identityServerPwdCredToken.equals(that.identityServerPwdCredToken))
        return false;
    }

    return true;
  }

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

    hashCode = hashCode * 8191 + ((isSetGatewayID()) ? 131071 : 524287);
    if (isSetGatewayID())
      hashCode = hashCode * 8191 + gatewayID.hashCode();

    hashCode = hashCode * 8191 + ((isSetCredentialStoreToken()) ? 131071 : 524287);
    if (isSetCredentialStoreToken())
      hashCode = hashCode * 8191 + credentialStoreToken.hashCode();

    hashCode = hashCode * 8191 + ((isSetComputeResourcePreferences()) ? 131071 : 524287);
    if (isSetComputeResourcePreferences())
      hashCode = hashCode * 8191 + computeResourcePreferences.hashCode();

    hashCode = hashCode * 8191 + ((isSetStoragePreferences()) ? 131071 : 524287);
    if (isSetStoragePreferences())
      hashCode = hashCode * 8191 + storagePreferences.hashCode();

    hashCode = hashCode * 8191 + ((isSetIdentityServerTenant()) ? 131071 : 524287);
    if (isSetIdentityServerTenant())
      hashCode = hashCode * 8191 + identityServerTenant.hashCode();

    hashCode = hashCode * 8191 + ((isSetIdentityServerPwdCredToken()) ? 131071 : 524287);
    if (isSetIdentityServerPwdCredToken())
      hashCode = hashCode * 8191 + identityServerPwdCredToken.hashCode();

    return hashCode;
  }

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

    int lastComparison = 0;

    lastComparison = java.lang.Boolean.valueOf(isSetGatewayID()).compareTo(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.valueOf(isSetCredentialStoreToken()).compareTo(other.isSetCredentialStoreToken());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetCredentialStoreToken()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.credentialStoreToken, other.credentialStoreToken);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(isSetComputeResourcePreferences()).compareTo(other.isSetComputeResourcePreferences());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetComputeResourcePreferences()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.computeResourcePreferences, other.computeResourcePreferences);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(isSetStoragePreferences()).compareTo(other.isSetStoragePreferences());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetStoragePreferences()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.storagePreferences, other.storagePreferences);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(isSetIdentityServerTenant()).compareTo(other.isSetIdentityServerTenant());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetIdentityServerTenant()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.identityServerTenant, other.identityServerTenant);
      if (lastComparison != 0) {
        return lastComparison;
      }
    }
    lastComparison = java.lang.Boolean.valueOf(isSetIdentityServerPwdCredToken()).compareTo(other.isSetIdentityServerPwdCredToken());
    if (lastComparison != 0) {
      return lastComparison;
    }
    if (isSetIdentityServerPwdCredToken()) {
      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.identityServerPwdCredToken, other.identityServerPwdCredToken);
      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 org.apache.thrift.TException {
    scheme(iprot).read(iprot, this);
  }

  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("GatewayResourceProfile(");
    boolean first = true;

    sb.append("gatewayID:");
    if (this.gatewayID == null) {
      sb.append("null");
    } else {
      sb.append(this.gatewayID);
    }
    first = false;
    if (isSetCredentialStoreToken()) {
      if (!first) sb.append(", ");
      sb.append("credentialStoreToken:");
      if (this.credentialStoreToken == null) {
        sb.append("null");
      } else {
        sb.append(this.credentialStoreToken);
      }
      first = false;
    }
    if (isSetComputeResourcePreferences()) {
      if (!first) sb.append(", ");
      sb.append("computeResourcePreferences:");
      if (this.computeResourcePreferences == null) {
        sb.append("null");
      } else {
        sb.append(this.computeResourcePreferences);
      }
      first = false;
    }
    if (isSetStoragePreferences()) {
      if (!first) sb.append(", ");
      sb.append("storagePreferences:");
      if (this.storagePreferences == null) {
        sb.append("null");
      } else {
        sb.append(this.storagePreferences);
      }
      first = false;
    }
    if (isSetIdentityServerTenant()) {
      if (!first) sb.append(", ");
      sb.append("identityServerTenant:");
      if (this.identityServerTenant == null) {
        sb.append("null");
      } else {
        sb.append(this.identityServerTenant);
      }
      first = false;
    }
    if (isSetIdentityServerPwdCredToken()) {
      if (!first) sb.append(", ");
      sb.append("identityServerPwdCredToken:");
      if (this.identityServerPwdCredToken == null) {
        sb.append("null");
      } else {
        sb.append(this.identityServerPwdCredToken);
      }
      first = false;
    }
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws org.apache.thrift.TException {
    // check for required fields
    if (!isSetGatewayID()) {
      throw new org.apache.thrift.protocol.TProtocolException("Required field 'gatewayID' 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 GatewayResourceProfileStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
    public GatewayResourceProfileStandardScheme getScheme() {
      return new GatewayResourceProfileStandardScheme();
    }
  }

  private static class GatewayResourceProfileStandardScheme extends org.apache.thrift.scheme.StandardScheme<GatewayResourceProfile> {

    public void read(org.apache.thrift.protocol.TProtocol iprot, GatewayResourceProfile 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: // 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 2: // CREDENTIAL_STORE_TOKEN
            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
              struct.credentialStoreToken = iprot.readString();
              struct.setCredentialStoreTokenIsSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 3: // COMPUTE_RESOURCE_PREFERENCES
            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
              {
                org.apache.thrift.protocol.TList _list10 = iprot.readListBegin();
                struct.computeResourcePreferences = new java.util.ArrayList<ComputeResourcePreference>(_list10.size);
                ComputeResourcePreference _elem11;
                for (int _i12 = 0; _i12 < _list10.size; ++_i12)
                {
                  _elem11 = new ComputeResourcePreference();
                  _elem11.read(iprot);
                  struct.computeResourcePreferences.add(_elem11);
                }
                iprot.readListEnd();
              }
              struct.setComputeResourcePreferencesIsSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 4: // STORAGE_PREFERENCES
            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
              {
                org.apache.thrift.protocol.TList _list13 = iprot.readListBegin();
                struct.storagePreferences = new java.util.ArrayList<StoragePreference>(_list13.size);
                StoragePreference _elem14;
                for (int _i15 = 0; _i15 < _list13.size; ++_i15)
                {
                  _elem14 = new StoragePreference();
                  _elem14.read(iprot);
                  struct.storagePreferences.add(_elem14);
                }
                iprot.readListEnd();
              }
              struct.setStoragePreferencesIsSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 5: // IDENTITY_SERVER_TENANT
            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
              struct.identityServerTenant = iprot.readString();
              struct.setIdentityServerTenantIsSet(true);
            } else { 
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
            }
            break;
          case 6: // IDENTITY_SERVER_PWD_CRED_TOKEN
            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
              struct.identityServerPwdCredToken = iprot.readString();
              struct.setIdentityServerPwdCredTokenIsSet(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, GatewayResourceProfile struct) throws org.apache.thrift.TException {
      struct.validate();

      oprot.writeStructBegin(STRUCT_DESC);
      if (struct.gatewayID != null) {
        oprot.writeFieldBegin(GATEWAY_ID_FIELD_DESC);
        oprot.writeString(struct.gatewayID);
        oprot.writeFieldEnd();
      }
      if (struct.credentialStoreToken != null) {
        if (struct.isSetCredentialStoreToken()) {
          oprot.writeFieldBegin(CREDENTIAL_STORE_TOKEN_FIELD_DESC);
          oprot.writeString(struct.credentialStoreToken);
          oprot.writeFieldEnd();
        }
      }
      if (struct.computeResourcePreferences != null) {
        if (struct.isSetComputeResourcePreferences()) {
          oprot.writeFieldBegin(COMPUTE_RESOURCE_PREFERENCES_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.computeResourcePreferences.size()));
            for (ComputeResourcePreference _iter16 : struct.computeResourcePreferences)
            {
              _iter16.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      if (struct.storagePreferences != null) {
        if (struct.isSetStoragePreferences()) {
          oprot.writeFieldBegin(STORAGE_PREFERENCES_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.storagePreferences.size()));
            for (StoragePreference _iter17 : struct.storagePreferences)
            {
              _iter17.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
      }
      if (struct.identityServerTenant != null) {
        if (struct.isSetIdentityServerTenant()) {
          oprot.writeFieldBegin(IDENTITY_SERVER_TENANT_FIELD_DESC);
          oprot.writeString(struct.identityServerTenant);
          oprot.writeFieldEnd();
        }
      }
      if (struct.identityServerPwdCredToken != null) {
        if (struct.isSetIdentityServerPwdCredToken()) {
          oprot.writeFieldBegin(IDENTITY_SERVER_PWD_CRED_TOKEN_FIELD_DESC);
          oprot.writeString(struct.identityServerPwdCredToken);
          oprot.writeFieldEnd();
        }
      }
      oprot.writeFieldStop();
      oprot.writeStructEnd();
    }

  }

  private static class GatewayResourceProfileTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
    public GatewayResourceProfileTupleScheme getScheme() {
      return new GatewayResourceProfileTupleScheme();
    }
  }

  private static class GatewayResourceProfileTupleScheme extends org.apache.thrift.scheme.TupleScheme<GatewayResourceProfile> {

    @Override
    public void write(org.apache.thrift.protocol.TProtocol prot, GatewayResourceProfile struct) throws org.apache.thrift.TException {
      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
      oprot.writeString(struct.gatewayID);
      java.util.BitSet optionals = new java.util.BitSet();
      if (struct.isSetCredentialStoreToken()) {
        optionals.set(0);
      }
      if (struct.isSetComputeResourcePreferences()) {
        optionals.set(1);
      }
      if (struct.isSetStoragePreferences()) {
        optionals.set(2);
      }
      if (struct.isSetIdentityServerTenant()) {
        optionals.set(3);
      }
      if (struct.isSetIdentityServerPwdCredToken()) {
        optionals.set(4);
      }
      oprot.writeBitSet(optionals, 5);
      if (struct.isSetCredentialStoreToken()) {
        oprot.writeString(struct.credentialStoreToken);
      }
      if (struct.isSetComputeResourcePreferences()) {
        {
          oprot.writeI32(struct.computeResourcePreferences.size());
          for (ComputeResourcePreference _iter18 : struct.computeResourcePreferences)
          {
            _iter18.write(oprot);
          }
        }
      }
      if (struct.isSetStoragePreferences()) {
        {
          oprot.writeI32(struct.storagePreferences.size());
          for (StoragePreference _iter19 : struct.storagePreferences)
          {
            _iter19.write(oprot);
          }
        }
      }
      if (struct.isSetIdentityServerTenant()) {
        oprot.writeString(struct.identityServerTenant);
      }
      if (struct.isSetIdentityServerPwdCredToken()) {
        oprot.writeString(struct.identityServerPwdCredToken);
      }
    }

    @Override
    public void read(org.apache.thrift.protocol.TProtocol prot, GatewayResourceProfile struct) throws org.apache.thrift.TException {
      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
      struct.gatewayID = iprot.readString();
      struct.setGatewayIDIsSet(true);
      java.util.BitSet incoming = iprot.readBitSet(5);
      if (incoming.get(0)) {
        struct.credentialStoreToken = iprot.readString();
        struct.setCredentialStoreTokenIsSet(true);
      }
      if (incoming.get(1)) {
        {
          org.apache.thrift.protocol.TList _list20 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
          struct.computeResourcePreferences = new java.util.ArrayList<ComputeResourcePreference>(_list20.size);
          ComputeResourcePreference _elem21;
          for (int _i22 = 0; _i22 < _list20.size; ++_i22)
          {
            _elem21 = new ComputeResourcePreference();
            _elem21.read(iprot);
            struct.computeResourcePreferences.add(_elem21);
          }
        }
        struct.setComputeResourcePreferencesIsSet(true);
      }
      if (incoming.get(2)) {
        {
          org.apache.thrift.protocol.TList _list23 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
          struct.storagePreferences = new java.util.ArrayList<StoragePreference>(_list23.size);
          StoragePreference _elem24;
          for (int _i25 = 0; _i25 < _list23.size; ++_i25)
          {
            _elem24 = new StoragePreference();
            _elem24.read(iprot);
            struct.storagePreferences.add(_elem24);
          }
        }
        struct.setStoragePreferencesIsSet(true);
      }
      if (incoming.get(3)) {
        struct.identityServerTenant = iprot.readString();
        struct.setIdentityServerTenantIsSet(true);
      }
      if (incoming.get(4)) {
        struct.identityServerPwdCredToken = iprot.readString();
        struct.setIdentityServerPwdCredTokenIsSet(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();
  }
}

