#
# Autogenerated by Thrift Compiler (0.18.1)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
#  options string: py
#

from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
from thrift.protocol.TProtocol import TProtocolException
from thrift.TRecursive import fix_spec

import sys
import airavata.model.commons.ttypes
import airavata.model.data.movement.ttypes

from thrift.transport import TTransport
all_structs = []


class StorageResourceDescription(object):
    """
    Storage Resource Description

    storageResourceId: Airavata Internal Unique Identifier to distinguish Compute Resource.

    hostName:
      Fully Qualified Host Name.

    storageResourceDescription:
     A user friendly description of the resource.


    DataMovementProtocol:
     Option to specify a prefered data movement mechanism of the available options.



    Attributes:
     - storageResourceId
     - hostName
     - storageResourceDescription
     - enabled
     - dataMovementInterfaces
     - creationTime
     - updateTime

    """


    def __init__(self, storageResourceId="DO_NOT_SET_AT_CLIENTS", hostName=None, storageResourceDescription=None, enabled=None, dataMovementInterfaces=None, creationTime=None, updateTime=None,):
        self.storageResourceId = storageResourceId
        self.hostName = hostName
        self.storageResourceDescription = storageResourceDescription
        self.enabled = enabled
        self.dataMovementInterfaces = dataMovementInterfaces
        self.creationTime = creationTime
        self.updateTime = updateTime

    def read(self, iprot):
        if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
            iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
            return
        iprot.readStructBegin()
        while True:
            (fname, ftype, fid) = iprot.readFieldBegin()
            if ftype == TType.STOP:
                break
            if fid == 1:
                if ftype == TType.STRING:
                    self.storageResourceId = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 2:
                if ftype == TType.STRING:
                    self.hostName = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 3:
                if ftype == TType.STRING:
                    self.storageResourceDescription = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
                else:
                    iprot.skip(ftype)
            elif fid == 4:
                if ftype == TType.BOOL:
                    self.enabled = iprot.readBool()
                else:
                    iprot.skip(ftype)
            elif fid == 5:
                if ftype == TType.LIST:
                    self.dataMovementInterfaces = []
                    (_etype3, _size0) = iprot.readListBegin()
                    for _i4 in range(_size0):
                        _elem5 = airavata.model.data.movement.ttypes.DataMovementInterface()
                        _elem5.read(iprot)
                        self.dataMovementInterfaces.append(_elem5)
                    iprot.readListEnd()
                else:
                    iprot.skip(ftype)
            elif fid == 6:
                if ftype == TType.I64:
                    self.creationTime = iprot.readI64()
                else:
                    iprot.skip(ftype)
            elif fid == 7:
                if ftype == TType.I64:
                    self.updateTime = iprot.readI64()
                else:
                    iprot.skip(ftype)
            else:
                iprot.skip(ftype)
            iprot.readFieldEnd()
        iprot.readStructEnd()

    def write(self, oprot):
        if oprot._fast_encode is not None and self.thrift_spec is not None:
            oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
            return
        oprot.writeStructBegin('StorageResourceDescription')
        if self.storageResourceId is not None:
            oprot.writeFieldBegin('storageResourceId', TType.STRING, 1)
            oprot.writeString(self.storageResourceId.encode('utf-8') if sys.version_info[0] == 2 else self.storageResourceId)
            oprot.writeFieldEnd()
        if self.hostName is not None:
            oprot.writeFieldBegin('hostName', TType.STRING, 2)
            oprot.writeString(self.hostName.encode('utf-8') if sys.version_info[0] == 2 else self.hostName)
            oprot.writeFieldEnd()
        if self.storageResourceDescription is not None:
            oprot.writeFieldBegin('storageResourceDescription', TType.STRING, 3)
            oprot.writeString(self.storageResourceDescription.encode('utf-8') if sys.version_info[0] == 2 else self.storageResourceDescription)
            oprot.writeFieldEnd()
        if self.enabled is not None:
            oprot.writeFieldBegin('enabled', TType.BOOL, 4)
            oprot.writeBool(self.enabled)
            oprot.writeFieldEnd()
        if self.dataMovementInterfaces is not None:
            oprot.writeFieldBegin('dataMovementInterfaces', TType.LIST, 5)
            oprot.writeListBegin(TType.STRUCT, len(self.dataMovementInterfaces))
            for iter6 in self.dataMovementInterfaces:
                iter6.write(oprot)
            oprot.writeListEnd()
            oprot.writeFieldEnd()
        if self.creationTime is not None:
            oprot.writeFieldBegin('creationTime', TType.I64, 6)
            oprot.writeI64(self.creationTime)
            oprot.writeFieldEnd()
        if self.updateTime is not None:
            oprot.writeFieldBegin('updateTime', TType.I64, 7)
            oprot.writeI64(self.updateTime)
            oprot.writeFieldEnd()
        oprot.writeFieldStop()
        oprot.writeStructEnd()

    def validate(self):
        if self.storageResourceId is None:
            raise TProtocolException(message='Required field storageResourceId is unset!')
        if self.hostName is None:
            raise TProtocolException(message='Required field hostName is unset!')
        return

    def __repr__(self):
        L = ['%s=%r' % (key, value)
             for key, value in self.__dict__.items()]
        return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not (self == other)
all_structs.append(StorageResourceDescription)
StorageResourceDescription.thrift_spec = (
    None,  # 0
    (1, TType.STRING, 'storageResourceId', 'UTF8', "DO_NOT_SET_AT_CLIENTS", ),  # 1
    (2, TType.STRING, 'hostName', 'UTF8', None, ),  # 2
    (3, TType.STRING, 'storageResourceDescription', 'UTF8', None, ),  # 3
    (4, TType.BOOL, 'enabled', None, None, ),  # 4
    (5, TType.LIST, 'dataMovementInterfaces', (TType.STRUCT, [airavata.model.data.movement.ttypes.DataMovementInterface, None], False), None, ),  # 5
    (6, TType.I64, 'creationTime', None, None, ),  # 6
    (7, TType.I64, 'updateTime', None, None, ),  # 7
)
fix_spec(all_structs)
del all_structs
