Imports DigitalData.Modules.Logging Imports DigitalData.Modules.EDMI.API.EDMIServiceReference Imports DigitalData.Modules.EDMI.API.Rights Imports System.ServiceModel Imports System.IO Public Class Client Private Const INVALID_OBEJCT_ID As Long = 0 Private Const KIND_TYPE_DOC = "DOC" Public Const DEFAULT_SERVICE_PORT = 9000 Private ReadOnly _logger As Logger Private ReadOnly _channelFactory As ChannelFactory(Of IEDMIServiceChannel) Private ReadOnly _IPAddressServer As String Private _channel As IEDMIServiceChannel Public Class StreamedFile Public Stream As MemoryStream Public FileName As String End Class Public Class FileList Public Datatable As DataTable End Class Public Class DocumentInfo Public FullPath As String Public AccessRight As AccessRight End Class Public Shared Function ParseServiceAddress(AddressWithOptionalPort As String) As Tuple(Of String, Integer) Dim oSplit() As String = AddressWithOptionalPort.Split(":"c) Dim oAppServerAddress As String = oSplit(0) Dim oAppServerPort As Integer If oSplit.Length = 2 Then If Integer.TryParse(oSplit(1), oAppServerPort) Then oAppServerPort = DEFAULT_SERVICE_PORT End If Else oAppServerPort = DEFAULT_SERVICE_PORT End If Return New Tuple(Of String, Integer)(oAppServerAddress, oAppServerPort) End Function ''' ''' Creates a new EDMI Client object ''' ''' LogConfig object ''' The full service url to connect to, for example: net.tcp://1.1.1.1:1111/some/path Public Sub New(LogConfig As LogConfig, ServiceAdress As String) _logger = LogConfig.GetLogger() Try Dim oBinding = Channel.GetBinding() Dim oAddress = New EndpointAddress(ServiceAdress) Dim oFactory = New ChannelFactory(Of IEDMIServiceChannel)(oBinding, oAddress) _channelFactory = oFactory Catch ex As Exception _logger.Error(ex) End Try End Sub ''' ''' Creates a new EDMI Client object ''' ''' LogConfig object ''' The IP address to connect to ''' The Port number to use for the connection Public Sub New(LogConfig As LogConfig, IPAddress As String, PortNumber As Integer) _logger = LogConfig.GetLogger() Try _IPAddressServer = IPAddress Dim oBinding = Channel.GetBinding() Dim oAddress = New EndpointAddress($"net.tcp://{IPAddress}:{PortNumber}/DigitalData/Services/Main") Dim oFactory = New ChannelFactory(Of IEDMIServiceChannel)(oBinding, oAddress) _channelFactory = oFactory Catch ex As Exception _logger.Error(ex) End Try End Sub ''' ''' Connect to the service ''' ''' True if connection was successful, false otherwise Public Function Connect() As Boolean Try _channel = GetChannel() _logger.Debug("Opening channel..") _channel.Open() _logger.Info($"Connection to AppService {_IPAddressServer} successfully established!") Return True Catch ex As Exception _logger.Error(ex) Return False End Try End Function ''' ''' Import options for NewFileAsync. Contains default values for all options ''' Public Class ImportFileOptions Public KeepExtension As Boolean = True End Class ''' ''' TODO: Creates a new object ''' ''' Public Async Function NewObjectAsync() As Task Throw New NotImplementedException() End Function ''' ''' Imports a file from a filepath, creating a IDB ObjectId and Filesystem Object ''' ''' Local filepath to a file. ''' Windows username of the user responsible for the import. ''' Date when the file was imported. Can be in the past. ''' Type of ObjectStore. Can be WORK or ARCHIVE. ''' Business entity that the new file object should belong to. ''' Other file import options ''' When local filepath was not found ''' When there was a error in the Service ''' The ObjectId of the newly generated filesystem object Public Async Function NewFileAsync(pFilePath As String, pAddedWho As String, pAddedWhen As Date, pObjectStoreType As String, pBusinessEntity As String, pImportOptions As ImportFileOptions) As Task(Of Long) Try If File.Exists(pFilePath) = False Then Throw New FileNotFoundException("ImportFileAsync: Path does not exist") End If Dim oFileInfo As New FileInfo(pFilePath) Dim oExtension As String = oFileInfo.Extension Dim oObjectIdResponse = Await _channel.NewObjectIdAsync(New NewObjectIdRequest With { .BusinessEntity = pBusinessEntity, .KindType = KIND_TYPE_DOC, .Who = pAddedWho }) If oObjectIdResponse.ObjectId = Nothing OrElse oObjectIdResponse.ObjectId = 0 Then Throw New ApplicationException("ImportFileAsync: Could not get ObjectId") End If Dim oFilePathResponse = Await _channel.NewFileObjectAsync(New NewFileObjectRequest With { .DateImported = pAddedWhen, .Extension = oExtension, .KeepExtension = pImportOptions.KeepExtension, .ObjectId = oObjectIdResponse.ObjectId, .StoreType = pObjectStoreType }) If oFilePathResponse.FileObjectPath = Nothing OrElse oFilePathResponse.FileObjectPath = "" Then Throw New ApplicationException("ImportFileAsync: Could not get FileObject Path") End If Using oFileStream As New FileStream(pFilePath, FileMode.Open, FileAccess.Read) Using oMemoryStream As New MemoryStream() oFileStream.CopyTo(oMemoryStream) Dim oContents = oMemoryStream.ToArray() Dim oFileImportResponse = Await _channel.ImportFileIntoFileObjectAsync(New ImportFileIntoFileObjectRequest With { .FilePath = oFilePathResponse.FileObjectPath, .ObjectId = oObjectIdResponse.ObjectId, .ObjectStoreType = pObjectStoreType, .Who = pAddedWho, .Contents = oContents }) If oFileImportResponse.Result = False Then Throw New ApplicationException("ImportFileAsync: Could not Import File Contents") End If End Using End Using Return oObjectIdResponse.ObjectId Catch ex As Exception _logger.Error(ex) Return INVALID_OBEJCT_ID End Try End Function Public Function CreateObjectId(pKindType As String, pWho As String, pBusinessEntity As String) As Long Try Dim oResponse = _channel.NewObjectId(New NewObjectIdRequest With { .KindType = pKindType, .BusinessEntity = pBusinessEntity, .Who = pWho }) Return oResponse.ObjectId Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Function CreateFileStoreObject(pObjectId As Long, pStoreType As String, pDate As String, pExtension As String, pKeepExtension As String) As String Try ' Remove dot in Extension If pExtension.StartsWith(".") Then pExtension = pExtension.Substring(1) End If Dim oArgs As New NewFileObjectRequest With { .ObjectId = pObjectId, .StoreType = pStoreType, .DateImported = pDate, .Extension = pExtension, .KeepExtension = pKeepExtension } Dim oResponse = _channel.NewFileObject(oArgs) Return oResponse.FileObjectPath Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Async Function ImportFileObjectAsync(pContent As Byte(), pWho As String, pObjectId As Long, pObjectStoreType As String, pFileObjectPath As String) As Task(Of Boolean) Try Dim oData As New ImportFileIntoFileObjectRequest() With { .Contents = pContent, .Who = pWho, .FilePath = pFileObjectPath, .ObjectId = pObjectId, .ObjectStoreType = pObjectStoreType } Dim oResponse = Await _channel.ImportFileIntoFileObjectAsync(oData) Return oResponse.Result Catch ex As Exception _logger.Error(ex) Return False End Try End Function Public Async Function GetFileByObjectIdAsync(ObjectId As Long) As Task(Of StreamedFile) Try Dim oData As New DocumentStreamRequest() With {.ObjectId = ObjectId} Dim oResponse As DocumentStreamResponse = Await _channel.GetFileByObjectIdAsync(oData) Dim oMemoryStream As New MemoryStream() oResponse.FileContents.CopyTo(oMemoryStream) oMemoryStream.Position = 0 Return New StreamedFile() With { .Stream = oMemoryStream, .FileName = oResponse.FileName } Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Async Function ListFilesForUserAsync() As Task(Of FileList) Try Dim oResponse As DocumentListResponse = Await _channel.ListFilesForUserAsync(New ListFilesForUserRequest()) Return New FileList() With { .Datatable = oResponse.Datatable } Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Function GetDatatableFromIDB(SQL As String) As TableResult Try Dim oResponse = _channel.ReturnDatatable_MSSQL_IDB(SQL) Return oResponse Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Async Function GetDatatableFromIDBAsync(SQL As String) As Task(Of TableResult) Try Dim oResponse = Await _channel.ReturnDatatable_MSSQL_IDBAsync(SQL) Return oResponse Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Function GetScalarValueFromIDB(SQL As String) As ScalarResult Try Dim oResponse = _channel.ReturnScalar_MSSQL_IDB(SQL) Return oResponse Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Async Function GetScalarValueFromIDBAsync(SQL As String) As Task(Of ScalarResult) Try Dim oResponse = Await _channel.ReturnScalar_MSSQL_IDBAsync(SQL) Return oResponse Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Function GetDatatableByName(DatatableName As String, Optional FilterExpression As String = "", Optional SortByColumn As String = "") As TableResult Try Dim oResponse = _channel.ReturnDatatableFromCache(DatatableName, FilterExpression, SortByColumn) Return oResponse Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Async Function GetDatatableByNameAsync(DatatableName As String, Optional FilterExpression As String = "", Optional SortByColumn As String = "") As Task(Of TableResult) Try Dim oResponse = Await _channel.ReturnDatatableFromCacheAsync(DatatableName, FilterExpression, SortByColumn) Return oResponse Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Function GetDocumentInfo(UserId As Long, ObjectId As Long) As DocumentInfo Try Dim oParams = New DocumentInfoRequest With { .ObjectId = ObjectId, .UserId = UserId } Dim oResponse As DocumentInfoResponse = _channel.GetFileInfoByObjectId(oParams) Return New DocumentInfo With { .AccessRight = oResponse.FileRight, .FullPath = oResponse.FullPath } Catch ex As FaultException(Of ObjectDoesNotExistFault) _logger.Error(ex) Throw ex Catch ex As FaultException _logger.Error(ex) Throw ex Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function Public Async Function GetDocumentInfoAsync(UserId As Long, ObjectId As Long) As Task(Of DocumentInfo) Try Dim oParams = New DocumentInfoRequest With { .ObjectId = ObjectId, .UserId = UserId } Dim oResponse As DocumentInfoResponse = Await _channel.GetFileInfoByObjectIdAsync(oParams) Return New DocumentInfo With { .AccessRight = oResponse.FileRight, .FullPath = oResponse.FullPath } Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function ''' ''' Aborts the channel and creates a new connection ''' Public Sub Reconnect() _logger.Warn("Connection faulted. Trying to reconnect..") Try _channel.Abort() _channel = GetChannel() _channel.Open() Catch ex As Exception _logger.Error(ex) End Try End Sub ''' ''' Creates a channel and adds a Faulted-Handler ''' ''' A channel object Private Function GetChannel() As IEDMIServiceChannel Try _logger.Debug("...Creating channel..") Dim oChannel = _channelFactory.CreateChannel() AddHandler oChannel.Faulted, AddressOf Reconnect Return oChannel Catch ex As Exception _logger.Error(ex) Throw ex End Try End Function End Class