diff --git a/GUIs.Common/DocumentResultList/Watcher.vb b/GUIs.Common/DocumentResultList/Watcher.vb index 96984de9..63c01204 100644 --- a/GUIs.Common/DocumentResultList/Watcher.vb +++ b/GUIs.Common/DocumentResultList/Watcher.vb @@ -119,26 +119,36 @@ Namespace DocumentResultList Private Sub FileOpenTimer_Elapsed() Handles FileOpenTimer.Elapsed Try For Each oOpenFile In OpenFiles + ' All files that are currently processe/updated on the outside, + ' will not be checked again. If oOpenFile.CurrentlyProcessing = False Then Continue For End If + ' Check if the file is currently in use, and skip if it is. Dim oIsLocked = FileEx.TestFileIsLocked(oOpenFile.FilePath) - If oIsLocked Then Continue For End If + ' If this point is reached, we assume the file was closed again after opening it. + ' ------ + + ' Compute the current hash of the file and compare it with the one + ' in the database. Dim oOldHash = oOpenFile.Document.FileHash Dim oNewHash = FileEx.GetChecksum(oOpenFile.FilePath) - If oNewHash.Equals(oOldHash) = False Then - ' File changed - RaiseEvent FileChanged(Me, New FileChangedArgs() With {.File = oOpenFile}) - oOpenFile.CurrentlyProcessing = True - Else + ' If the the file did not change, remove it from the watch list + If oNewHash.Equals(oOldHash) Then OpenFiles.Remove(oOpenFile) + Continue For End If + + ' The File changed, so mark the file as being processed/updated + ' and notify any listeners of the FileChanged event + oOpenFile.CurrentlyProcessing = True + RaiseEvent FileChanged(Me, New FileChangedArgs() With {.File = oOpenFile}) Next Catch ex As Exception Logger.Error(ex) diff --git a/GUIs.Common/frmDocumentResultList.vb b/GUIs.Common/frmDocumentResultList.vb index c48d7b1b..9e85bd97 100644 --- a/GUIs.Common/frmDocumentResultList.vb +++ b/GUIs.Common/frmDocumentResultList.vb @@ -236,7 +236,13 @@ Public Class frmDocumentResultList End Sub Public Sub Watcher_FileChanged(sender As Object, e As DocumentResultList.Watcher.FileChangedArgs) Handles Watcher.FileChanged + Try + Catch ex As Exception + + Finally + e.File.CurrentlyProcessing = False + End Try End Sub diff --git a/Modules.EDMIAPI/Client.vb b/Modules.EDMIAPI/Client.vb index c2bad5be..8f9e8ffd 100644 --- a/Modules.EDMIAPI/Client.vb +++ b/Modules.EDMIAPI/Client.vb @@ -9,7 +9,7 @@ Imports DigitalData.Modules.Logging Public Class Client ' Constants Private Const UPDATE_INTERVAL_IN_MINUTES As Integer = 1 - Public Const INVALID_OBEJCT_ID As Long = 0 + Private Const KIND_TYPE_DOC = "DOC" ' Helper Classes @@ -188,58 +188,11 @@ Public Class Client ''' The ObjectId of the newly generated filesystem object Public Async Function NewFileAsync(pFilePath As String, pObjectStoreName As String, pObjectKind As String, pBusinessEntity As String, Optional pImportOptions As Options.NewFileOptions = Nothing) As Task(Of Long) Try - ' Set default options - If pImportOptions Is Nothing Then - pImportOptions = New Options.NewFileOptions() - End If - - ' Check if file exists - If File.Exists(pFilePath) = False Then - Throw New FileNotFoundException("Path does not exist") - End If - - Dim oFileInfo As New FileInfo(pFilePath) - Dim oExtension As String = oFileInfo.Extension - - Dim oFileName As String = oFileInfo.Name - Dim oFileCreatedAt As Date = oFileInfo?.CreationTime - Dim oFileModifiedAt As Date = oFileInfo?.LastWriteTime - Dim oFileHash As String = FileEx.GetChecksum(oFileInfo.FullName) - - ' Importing the file now - 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.NewFileAsync(New NewFileRequest With { - .BusinessEntity = pBusinessEntity, - .File = New FileProperties With { - .FileName = oFileInfo.Name, - .FileCreatedAt = oFileCreatedAt, - .FileChangedAt = oFileModifiedAt, - .FileContents = oContents, - .FileImportedAt = pImportOptions.DateImported, - .FileChecksum = oFileHash - }, - .KindType = pObjectKind, - .StoreName = pObjectStoreName, - .User = New UserState With { - .Language = pImportOptions.Language, - .UserName = pImportOptions.Username - } - }) - - If oFileImportResponse.OK = False Then - Throw New ApplicationException("Could not Import File Contents!") - End If - - Return oFileImportResponse.ObjectId - End Using - End Using + Dim oNewFile As New Modules.IDB.NewFile(LogConfig, Channel) + Return Await oNewFile.RunAsync(pFilePath, pObjectStoreName, pObjectKind, pBusinessEntity, pImportOptions) Catch ex As Exception Logger.Error(ex) - Return INVALID_OBEJCT_ID + Return Nothing End Try End Function diff --git a/Modules.EDMIAPI/Client/Options.vb b/Modules.EDMIAPI/Client/Options.vb index df869eb9..dbb241ce 100644 --- a/Modules.EDMIAPI/Client/Options.vb +++ b/Modules.EDMIAPI/Client/Options.vb @@ -25,6 +25,15 @@ Public Property DateImported As Date = Date.Now End Class + Public Class UpdateFileOptions + Inherits BaseOptions + + ''' + ''' Should the changes in the file result in a new version? Otherwise the old file will be overridden. + ''' + Public Property CreateNewFileVersion As Boolean = False + End Class + Public Class ImportFileOptions Inherits BaseOptions diff --git a/Modules.EDMIAPI/Constants.vb b/Modules.EDMIAPI/Constants.vb index cc2dcacb..0b18fb91 100644 --- a/Modules.EDMIAPI/Constants.vb +++ b/Modules.EDMIAPI/Constants.vb @@ -1,5 +1,6 @@ Public Class Constants Public Const DEFAULT_SERVICE_PORT = 9000 + Public Const INVALID_OBEJCT_ID As Long = 0 Public Enum DatabaseType ECM diff --git a/Modules.EDMIAPI/EDMI.API.vbproj b/Modules.EDMIAPI/EDMI.API.vbproj index d9595048..04daf047 100644 --- a/Modules.EDMIAPI/EDMI.API.vbproj +++ b/Modules.EDMIAPI/EDMI.API.vbproj @@ -78,6 +78,9 @@ + + + True diff --git a/Modules.EDMIAPI/Helpers.vb b/Modules.EDMIAPI/Helpers.vb new file mode 100644 index 00000000..53872b2d --- /dev/null +++ b/Modules.EDMIAPI/Helpers.vb @@ -0,0 +1,41 @@ +Imports DigitalData.Modules.EDMI.API.EDMIServiceReference +Imports DigitalData.Modules.Logging + + +Public Class Helpers + Private ReadOnly LogConfig As LogConfig + Private ReadOnly Logger As Logger + Private ReadOnly FileEx As Filesystem.File + + Public Sub New(pLogConfig As LogConfig) + LogConfig = pLogConfig + Logger = pLogConfig.GetLogger() + FileEx = New Filesystem.File(pLogConfig) + End Sub + + Public Function GetFileProperties(pFilePath As String, pDateImportedAt As Date) As FileProperties + Using oFileStream As New IO.FileStream(pFilePath, IO.FileMode.Open, IO.FileAccess.Read) + Using oMemoryStream As New IO.MemoryStream() + oFileStream.CopyTo(oMemoryStream) + Dim oContents = oMemoryStream.ToArray() + + Dim oFileInfo As New IO.FileInfo(pFilePath) + Dim oExtension As String = oFileInfo.Extension + + Dim oFileName As String = oFileInfo.Name + Dim oFileCreatedAt As Date = oFileInfo?.CreationTime + Dim oFileModifiedAt As Date = oFileInfo?.LastWriteTime + Dim oFileHash As String = FileEx.GetChecksum(oFileInfo.FullName) + + Return New FileProperties With { + .FileName = oFileInfo.Name, + .FileCreatedAt = oFileCreatedAt, + .FileChangedAt = oFileModifiedAt, + .FileContents = oContents, + .FileImportedAt = pDateImportedAt, + .FileChecksum = oFileHash + } + End Using + End Using + End Function + End Class diff --git a/Modules.EDMIAPI/Modules/BaseMethod.vb b/Modules.EDMIAPI/Modules/BaseMethod.vb index 24c01c5d..09893e6f 100644 --- a/Modules.EDMIAPI/Modules/BaseMethod.vb +++ b/Modules.EDMIAPI/Modules/BaseMethod.vb @@ -6,11 +6,15 @@ Namespace Modules Friend ReadOnly LogConfig As LogConfig Friend ReadOnly Logger As Logger Friend ReadOnly Channel As IEDMIServiceChannel + Friend ReadOnly FileEx As Filesystem.File + Friend ReadOnly Helpers As Helpers Public Sub New(pLogConfig As LogConfig, pChannel As IEDMIServiceChannel) LogConfig = pLogConfig Logger = pLogConfig.GetLogger() Channel = pChannel + FileEx = New Filesystem.File(pLogConfig) + Helpers = New Helpers(pLogConfig) End Sub End Class diff --git a/Modules.EDMIAPI/Modules/IDB/NewFile.vb b/Modules.EDMIAPI/Modules/IDB/NewFile.vb new file mode 100644 index 00000000..f938f46c --- /dev/null +++ b/Modules.EDMIAPI/Modules/IDB/NewFile.vb @@ -0,0 +1,49 @@ +Imports DigitalData.Modules.EDMI.API.EDMIServiceReference +Imports DigitalData.Modules.Logging +Imports DigitalData.Modules.Filesystem + +Namespace Modules.IDB + Public Class NewFile + Inherits BaseMethod + + Public Sub New(pLogConfig As LogConfig, pChannel As IEDMIServiceChannel) + MyBase.New(pLogConfig, pChannel) + End Sub + + Public Async Function RunAsync(pFilePath As String, pObjectStoreName As String, pObjectKind As String, pBusinessEntity As String, Optional pOptions As Options.NewFileOptions = Nothing) As Task(Of Long) + Try + ' Set default options + If pOptions Is Nothing Then + pOptions = New Options.NewFileOptions() + End If + + ' Check if file exists + If IO.File.Exists(pFilePath) = False Then + Throw New IO.FileNotFoundException("Path does not exist") + End If + + ' Importing the file now + Dim oFileProperties = Helpers.GetFileProperties(pFilePath, pOptions.DateImported) + Dim oFileImportResponse = Await Channel.NewFileAsync(New NewFileRequest With { + .BusinessEntity = pBusinessEntity, + .File = oFileProperties, + .KindType = pObjectKind, + .StoreName = pObjectStoreName, + .User = New UserState With { + .Language = pOptions.Language, + .UserName = pOptions.Username + } + }) + + If oFileImportResponse.OK = False Then + Throw New ApplicationException("Could not Import File Contents!") + End If + + Return oFileImportResponse.ObjectId + Catch ex As Exception + Logger.Error(ex) + Return Constants.INVALID_OBEJCT_ID + End Try + End Function + End Class +End Namespace \ No newline at end of file diff --git a/Modules.EDMIAPI/Modules/IDB/UpdateFile.vb b/Modules.EDMIAPI/Modules/IDB/UpdateFile.vb new file mode 100644 index 00000000..8ec2f014 --- /dev/null +++ b/Modules.EDMIAPI/Modules/IDB/UpdateFile.vb @@ -0,0 +1,39 @@ +Imports DigitalData.Modules.EDMI.API.EDMIServiceReference +Imports DigitalData.Modules.EDMI.API.Options +Imports DigitalData.Modules.Logging + +Namespace Modules.IDB + Public Class UpdateFile + Inherits BaseMethod + + Public Sub New(pLogConfig As LogConfig, pChannel As IEDMIServiceChannel) + MyBase.New(pLogConfig, pChannel) + End Sub + + Public Async Function RunAsync(pFilePath As String, pObjectId As Long, Optional pOptions As UpdateFileOptions = Nothing) As Task + ' Set default options + If pOptions Is Nothing Then + pOptions = New UpdateFileOptions() + End If + + ' Check if file exists + If IO.File.Exists(pFilePath) = False Then + Throw New IO.FileNotFoundException("Path does not exist") + End If + + ' Importing the file now + Dim oFileProperties = Helpers.GetFileProperties(pFilePath, Date.Now) + 'Dim oFileImportResponse = Await Channel.(New NewFileRequest With { + ' .BusinessEntity = pBusinessEntity, + ' .File = oFileProperties, + ' .KindType = pObjectKind, + ' .StoreName = pObjectStoreName, + ' .User = New UserState With { + ' .Language = pOptions.Language, + ' .UserName = pOptions.Username + ' } + '}) + End Function + End Class + +End Namespace \ No newline at end of file diff --git a/Service.EDMIService/EDMIService.vb b/Service.EDMIService/EDMIService.vb index f90123ff..665540c6 100644 --- a/Service.EDMIService/EDMIService.vb +++ b/Service.EDMIService/EDMIService.vb @@ -80,9 +80,9 @@ Public Class EDMIService Return oNewFile.Run(Data) End Function - Public Function VersionFile(Data As VersionFile.VersionFileRequest) As VersionFile.VersionFileResponse Implements IEDMIService.VersionFile + Public Function UpdateFile(Data As UpdateFile.UpdateFileRequest) As UpdateFile.UpdateFileResponse Implements IEDMIService.UpdateFile _Logger.Debug("Start of Method [VersionFile]") - Dim oVersionFile As New VersionFile.VersionFileMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) + Dim oVersionFile As New UpdateFile.UpdateFileMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) Return oVersionFile.Run(Data) End Function diff --git a/Service.EDMIService/EDMIService.vbproj b/Service.EDMIService/EDMIService.vbproj index 4adf00e9..e6bb97f9 100644 --- a/Service.EDMIService/EDMIService.vbproj +++ b/Service.EDMIService/EDMIService.vbproj @@ -181,9 +181,9 @@ - - - + + + diff --git a/Service.EDMIService/IEDMIService.vb b/Service.EDMIService/IEDMIService.vb index 98b65762..03476a69 100644 --- a/Service.EDMIService/IEDMIService.vb +++ b/Service.EDMIService/IEDMIService.vb @@ -84,7 +84,7 @@ Interface IEDMIService Function NewFile(Data As NewFile.NewFileRequest) As NewFile.NewFileResponse - Function VersionFile(Data As VersionFile.VersionFileRequest) As VersionFile.VersionFileResponse + Function UpdateFile(Data As UpdateFile.UpdateFileRequest) As UpdateFile.UpdateFileResponse Function SetAttributeValue(Data As SetAttributeValue.SetAttributeValueRequest) As SetAttributeValue.SetAttributeValueResponse diff --git a/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileMethod.vb b/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileMethod.vb new file mode 100644 index 00000000..d06584fc --- /dev/null +++ b/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileMethod.vb @@ -0,0 +1,254 @@ +Imports System.Data.SqlClient +Imports DigitalData.Modules.Database +Imports DigitalData.Modules.Database.MSSQLServer.TransactionMode +Imports DigitalData.Modules.Logging +Imports DigitalData.Services.EDMIService.Methods +Imports DigitalData.Services.EDMIService.GlobalState + +Namespace Methods.IDB.UpdateFile + Public Class UpdateFileMethod + Inherits BaseMethod + + Private ReadOnly Connection As SqlConnection + Private ReadOnly Transaction As SqlTransaction + + Public Sub New(pLogConfig As LogConfig, pDatabaseIDB As MSSQLServer, pDatabaseECM As MSSQLServer, pGlobalState As GlobalState) + MyBase.New(pLogConfig, pDatabaseIDB, pDatabaseECM, pGlobalState) + + Connection = DatabaseIDB.GetConnection() + Transaction = Connection.BeginTransaction() + End Sub + + Public Function Run(pData As UpdateFileRequest) As UpdateFileResponse + + ' TODO: Update file object + If Helpers.TestObjectIdExists(pData.ObjectId) = False Then + LogAndThrow("ObjectId does not exist!") + End If + + 'TODO: Create a view that collects all information about an idb object + + If pData.CreateNewVersion = False Then + + + Else + + End If + + + + + Return New UpdateFileResponse(pData.ObjectId) + + 'Dim oFilePath As String = Nothing + ' + 'Dim oExistingObjectId = TestFileChecksumExists(pData.File.FileChecksum) + 'If oExistingObjectId > 0 Then + ' Return New UpdateFileResponse(oExistingObjectId) + 'End If + 'Try + + ' Dim oObjectId = NewObjectId(pData.KindType, pData.BusinessEntity, pData.User.UserName) + ' If oObjectId = 0 Then + ' LogAndThrow("Could not create new ObjectId!") + ' End If + + ' ' Find ObjectStore by Title + ' Logger.Debug("Checking for DataStore [{0}].", pData.StoreName) + ' Dim oStore = GlobalState.ObjectStores. + ' Where(Function(store) store.Title.Equals(pData.StoreName, StringComparison.OrdinalIgnoreCase)). + 'SingleOrDefault() + + ' If oStore Is Nothing Then + ' LogAndThrow($"DataStore [{pData.StoreName}] does not exist. Exiting.") + ' End If + + ' ' Get Store base path + ' Dim oBasePath As String = oStore.Path + ' Logger.Debug("Store BasePath is [{0}]", oBasePath) + + ' ' Get directory by DateImported or, if not supplied, by current date + ' Dim oSubDirectory As String + ' If IsNothing(pData.File.FileImportedAt) Then + ' oSubDirectory = GetDateSubDirectory(Now) + ' Else + ' oSubDirectory = GetDateSubDirectory(pData.File.FileImportedAt) + ' End If + ' Logger.Debug("Subdirectory is [{0}]", oSubDirectory) + + ' ' Check and create final path, if necessary + ' Dim oFinalPath = IO.Path.Combine(oBasePath, oSubDirectory) + ' If Not IO.Directory.Exists(oFinalPath) Then + ' Try + ' Logger.Debug("Path does not exist, creating: [{0}]", oFinalPath) + ' IO.Directory.CreateDirectory(oFinalPath) + ' Logger.Debug("Created folder [{0}]", oFinalPath) + ' Catch ex As Exception + ' LogAndThrow(ex, $"Store Directory [{oFinalPath}] could not be created!") + ' End Try + ' End If + ' Logger.Debug("Final Directory is [{0}]", oFinalPath) + + ' ' Get filename + ' Dim oKeepFileName As Boolean = False + ' If oStore.IsArchive Then + ' Logger.Debug("Object Store is an archive: [{0}]", oStore.IsArchive) + ' oKeepFileName = True + ' End If + + ' Dim oFileName As String = GetFileObjectFileName(oObjectId, pData.File.FileName, oKeepFileName) + ' Logger.Debug("Filename is [{0}]", oFileName) + + ' oFilePath = IO.Path.Combine(oFinalPath, oFileName) + ' Dim oFileObjectInfo As IO.FileInfo = New IO.FileInfo(oFilePath) + + ' Dim oFileObjectSize As Long = pData.File.FileContents.Length + ' Dim oFileObjectName As String = oFileObjectInfo.Name + ' Dim oOriginalExtension As String = pData.File.FileInfoRaw.Extension.Substring(1) + + ' Logger.Debug("File Information for [{0}]:", oFileObjectName) + ' Logger.Debug("Size: [{0}]", oFileObjectSize) + ' Logger.Debug("Original Extension: [{0}]", oOriginalExtension) + ' Logger.Debug("Checksum: [{0}]", pData.File.FileChecksum) + + ' Try + ' Using oStream = New IO.FileStream(oFilePath, IO.FileMode.Create, IO.FileAccess.Write) + ' Logger.Info("Saving file to path [{0}]", oFilePath) + ' oStream.Write(pData.File.FileContents, 0, oFileObjectSize) + ' oStream.Flush(True) + ' oStream.Close() + ' End Using + ' Catch ex As Exception + ' LogAndThrow(ex, $"Could not write file [{oFilePath}] to disk!") + ' End Try + + ' '--------------------------------------------------------------------------- + + ' Logger.Info("Creating IDB FileObject for ObjectId [{0}].", oObjectId) + + ' ' Insert into DB + ' Dim oSQL As String = $"EXEC PRIDB_NEW_IDBFO + ' '{oFinalPath}', + ' '{oFileObjectName}', + ' '{oOriginalExtension}', + ' {oFileObjectSize}, + ' '{pData.File.FileChecksum}' , + ' '{pData.User.UserName}', + ' '{oObjectId}', + ' {oStore.Id}" + + ' Dim oResult As Boolean = DatabaseIDB.ExecuteNonQueryWithConnectionObject(oSQL, Connection, ExternalTransaction, Transaction) + + ' If oResult = False Then + ' LogAndThrow("IDB FileObject could not be created!") + ' End If + + ' '--------------------------------------------------------------------------- + + ' 'TODO: File dates in try catch + + ' Dim oSystemAttributes As New Dictionary(Of String, Object) From { + ' {"OriginFileName", pData.File.FileName}, + ' {"OriginCreationDatetime", pData.File.FileCreatedAt}, + ' {"OriginChangedDatetime", pData.File.FileChangedAt} + '} + + ' For Each oAttribute As KeyValuePair(Of String, Object) In oSystemAttributes + ' Try + ' ' Dont write empty attributes + ' If oAttribute.Value Is Nothing Then + ' Continue For + ' End If + + ' Dim oSuccess = Helpers.SetAttributeValue(Connection, Transaction, oObjectId, oAttribute.Key, oAttribute.Value, pData.User.Language, pData.User.UserName) + ' If oSuccess Then + ' Logger.Debug("System Attribute [{0}] written with value [{1}]", oAttribute.Key, oAttribute.Value) + ' Else + ' Logger.Warn("System attribute value could not be written") + ' End If + ' Catch ex As Exception + ' LogAndThrow(ex, $"System attribute [{oAttribute.Key}] could not be written!") + ' End Try + ' Next + + ' '--------------------------------------------------------------------------- + + ' ' Finally, commit the transaction + ' Transaction?.Commit() + + ' Return New UpdateFileResponse(oObjectId) + 'Catch ex As Exception + ' Logger.Warn("Error occurred while creating file!") + ' Logger.Error(ex) + + ' Logger.Info("Cleaning up files.") + ' If Not IsNothing(oFilePath) AndAlso IO.File.Exists(oFilePath) Then + ' Try + ' IO.File.Delete(oFilePath) + ' Catch exInner As Exception + ' Logger.Warn("Error while cleaning up files.") + ' Logger.Error(exInner) + ' End Try + ' End If + + ' Logger.Info("Rolling back transaction.") + ' Transaction?.Rollback() + + ' Return New UpdateFileResponse(ex) + + 'End Try + End Function + + Private Function TestFileChecksumExists(pChecksum As String) As Long + Try + Dim oChecksumSQL = $"SELECT IDB_OBJ_ID FROM TBIDB_FILE_OBJECT WHERE FILE_HASH = '{pChecksum}'" + Dim oExistingObjectId As Long = DatabaseIDB.GetScalarValue(oChecksumSQL) + + If oExistingObjectId > 0 Then + Logger.Info("Returning early with ObjectId [{0}] because Checksum [{1}] already exists.", oExistingObjectId, pChecksum) + Return oExistingObjectId + End If + + Return Nothing + + Catch ex As Exception + Logger.Error(ex) + Return Nothing + + End Try + End Function + + Private Function NewObjectId(pKindType As String, pBusinessEntity As String, pWho As String) As Long + Try + Dim oNewObjectIdSQL = $"DECLARE @NEW_IDB_OBJ_ID BIGINT + EXEC PRIDB_NEW_OBJECT '{pKindType}','{pWho}','{pBusinessEntity}',0, @IDB_OBJ_ID = @NEW_IDB_OBJ_ID OUTPUT; + SELECT @NEW_IDB_OBJ_ID" + Dim oObjectId As Long = DatabaseIDB.GetScalarValueWithConnectionObject(oNewObjectIdSQL, Connection, ExternalTransaction, Transaction) + Logger.Info("New Object with Id [{0}] created!", oObjectId) + + If IsNothing(oObjectId) Then + LogAndThrow("Could not create new ObjectId!") + End If + + Return oObjectId + Catch ex As Exception + Logger.Error(ex) + Return Nothing + End Try + End Function + + Private Function GetFileObjectFileName(IDB_OBJ_ID As Long, pFilename As String, pKeepFilename As Boolean) As String + ' TODO: save actual extensions + If pKeepFilename Then + Return pFilename + Else + Return $"{IDB_OBJ_ID}.ddfo" + End If + End Function + + Private Function GetDateSubDirectory(pDate As Date) As String + Return IO.Path.Combine(pDate.ToString("yyyy"), pDate.ToString("MM"), pDate.ToString("dd")) + End Function + End Class + +End Namespace \ No newline at end of file diff --git a/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileRequest.vb b/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileRequest.vb new file mode 100644 index 00000000..ed155734 --- /dev/null +++ b/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileRequest.vb @@ -0,0 +1,26 @@ +Imports System.Runtime.Serialization +Imports DigitalData.Modules.ZooFlow.State + +Namespace Methods.IDB.UpdateFile + + + Public Class UpdateFileRequest + + Public Property ObjectId As Long + + + Public Property File As FileProperties + + + Public Property CreateNewVersion As Boolean + + ''' + ''' User Importing the file + ''' + ''' + + Public Property User As UserState + End Class + +End Namespace + diff --git a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileResponse.vb b/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileResponse.vb similarity index 86% rename from Service.EDMIService/Methods/IDB/VersionFile/VersionFileResponse.vb rename to Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileResponse.vb index c19a4969..002632df 100644 --- a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileResponse.vb +++ b/Service.EDMIService/Methods/IDB/UpdateFile/UpdateFileResponse.vb @@ -1,9 +1,9 @@ Imports System.Runtime.Serialization -Namespace Methods.IDB.VersionFile +Namespace Methods.IDB.UpdateFile - Public Class VersionFileResponse + Public Class UpdateFileResponse Inherits Messages.BaseResponse diff --git a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileMethod.vb b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileMethod.vb deleted file mode 100644 index 6f027b74..00000000 --- a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileMethod.vb +++ /dev/null @@ -1,235 +0,0 @@ -Imports System.Data.SqlClient -Imports DigitalData.Modules.Database -Imports DigitalData.Modules.Database.MSSQLServer.TransactionMode -Imports DigitalData.Modules.Logging -Imports DigitalData.Services.EDMIService.Methods -Imports DigitalData.Services.EDMIService.GlobalState - -Namespace Methods.IDB.VersionFile - Public Class VersionFileMethod - Inherits BaseMethod - - Private ReadOnly Connection As SqlConnection - Private ReadOnly Transaction As SqlTransaction - - Public Sub New(pLogConfig As LogConfig, pDatabaseIDB As MSSQLServer, pDatabaseECM As MSSQLServer, pGlobalState As GlobalState) - MyBase.New(pLogConfig, pDatabaseIDB, pDatabaseECM, pGlobalState) - - Connection = DatabaseIDB.GetConnection() - Transaction = Connection.BeginTransaction() - End Sub - - Public Function Run(pData As VersionFileRequest) As VersionFileResponse - Dim oFilePath As String = Nothing - - Dim oExistingObjectId = TestFileChecksumExists(pData.File.FileChecksum) - If oExistingObjectId > 0 Then - Return New VersionFileResponse(oExistingObjectId) - End If - - Try - - Dim oObjectId = NewObjectId(pData.KindType, pData.BusinessEntity, pData.User.UserName) - If oObjectId = 0 Then - LogAndThrow("Could not create new ObjectId!") - End If - - ' Find ObjectStore by Title - Logger.Debug("Checking for DataStore [{0}].", pData.StoreName) - Dim oStore = GlobalState.ObjectStores. - Where(Function(store) store.Title.Equals(pData.StoreName, StringComparison.OrdinalIgnoreCase)). - SingleOrDefault() - - If oStore Is Nothing Then - LogAndThrow($"DataStore [{pData.StoreName}] does not exist. Exiting.") - End If - - ' Get Store base path - Dim oBasePath As String = oStore.Path - Logger.Debug("Store BasePath is [{0}]", oBasePath) - - ' Get directory by DateImported or, if not supplied, by current date - Dim oSubDirectory As String - If IsNothing(pData.File.FileImportedAt) Then - oSubDirectory = GetDateSubDirectory(Now) - Else - oSubDirectory = GetDateSubDirectory(pData.File.FileImportedAt) - End If - Logger.Debug("Subdirectory is [{0}]", oSubDirectory) - - ' Check and create final path, if necessary - Dim oFinalPath = IO.Path.Combine(oBasePath, oSubDirectory) - If Not IO.Directory.Exists(oFinalPath) Then - Try - Logger.Debug("Path does not exist, creating: [{0}]", oFinalPath) - IO.Directory.CreateDirectory(oFinalPath) - Logger.Debug("Created folder [{0}]", oFinalPath) - Catch ex As Exception - LogAndThrow(ex, $"Store Directory [{oFinalPath}] could not be created!") - End Try - End If - Logger.Debug("Final Directory is [{0}]", oFinalPath) - - ' Get filename - Dim oKeepFileName As Boolean = False - If oStore.IsArchive Then - Logger.Debug("Object Store is an archive: [{0}]", oStore.IsArchive) - oKeepFileName = True - End If - - Dim oFileName As String = GetFileObjectFileName(oObjectId, pData.File.FileName, oKeepFileName) - Logger.Debug("Filename is [{0}]", oFileName) - - oFilePath = IO.Path.Combine(oFinalPath, oFileName) - Dim oFileObjectInfo As IO.FileInfo = New IO.FileInfo(oFilePath) - - Dim oFileObjectSize As Long = pData.File.FileContents.Length - Dim oFileObjectName As String = oFileObjectInfo.Name - Dim oOriginalExtension As String = pData.File.FileInfoRaw.Extension.Substring(1) - - Logger.Debug("File Information for [{0}]:", oFileObjectName) - Logger.Debug("Size: [{0}]", oFileObjectSize) - Logger.Debug("Original Extension: [{0}]", oOriginalExtension) - Logger.Debug("Checksum: [{0}]", pData.File.FileChecksum) - - Try - Using oStream = New IO.FileStream(oFilePath, IO.FileMode.Create, IO.FileAccess.Write) - Logger.Info("Saving file to path [{0}]", oFilePath) - oStream.Write(pData.File.FileContents, 0, oFileObjectSize) - oStream.Flush(True) - oStream.Close() - End Using - Catch ex As Exception - LogAndThrow(ex, $"Could not write file [{oFilePath}] to disk!") - End Try - - '--------------------------------------------------------------------------- - - Logger.Info("Creating IDB FileObject for ObjectId [{0}].", oObjectId) - - ' Insert into DB - Dim oSQL As String = $"EXEC PRIDB_NEW_IDBFO - '{oFinalPath}', - '{oFileObjectName}', - '{oOriginalExtension}', - {oFileObjectSize}, - '{pData.File.FileChecksum}' , - '{pData.User.UserName}', - '{oObjectId}', - {oStore.Id}" - - Dim oResult As Boolean = DatabaseIDB.ExecuteNonQueryWithConnectionObject(oSQL, Connection, ExternalTransaction, Transaction) - - If oResult = False Then - LogAndThrow("IDB FileObject could not be created!") - End If - - '--------------------------------------------------------------------------- - - 'TODO: File dates in try catch - - Dim oSystemAttributes As New Dictionary(Of String, Object) From { - {"OriginFileName", pData.File.FileName}, - {"OriginCreationDatetime", pData.File.FileCreatedAt}, - {"OriginChangedDatetime", pData.File.FileChangedAt} - } - - For Each oAttribute As KeyValuePair(Of String, Object) In oSystemAttributes - Try - ' Dont write empty attributes - If oAttribute.Value Is Nothing Then - Continue For - End If - - Dim oSuccess = Helpers.SetAttributeValue(Connection, Transaction, oObjectId, oAttribute.Key, oAttribute.Value, pData.User.Language, pData.User.UserName) - If oSuccess Then - Logger.Debug("System Attribute [{0}] written with value [{1}]", oAttribute.Key, oAttribute.Value) - Else - Logger.Warn("System attribute value could not be written") - End If - Catch ex As Exception - LogAndThrow(ex, $"System attribute [{oAttribute.Key}] could not be written!") - End Try - Next - - '--------------------------------------------------------------------------- - - ' Finally, commit the transaction - Transaction?.Commit() - - Return New VersionFileResponse(oObjectId) - Catch ex As Exception - Logger.Warn("Error occurred while creating file!") - Logger.Error(ex) - - Logger.Info("Cleaning up files.") - If Not IsNothing(oFilePath) AndAlso IO.File.Exists(oFilePath) Then - Try - IO.File.Delete(oFilePath) - Catch exInner As Exception - Logger.Warn("Error while cleaning up files.") - Logger.Error(exInner) - End Try - End If - - Logger.Info("Rolling back transaction.") - Transaction?.Rollback() - - Return New VersionFileResponse(ex) - - End Try - End Function - - Private Function TestFileChecksumExists(pChecksum As String) As Long - Try - Dim oChecksumSQL = $"SELECT IDB_OBJ_ID FROM TBIDB_FILE_OBJECT WHERE FILE_HASH = '{pChecksum}'" - Dim oExistingObjectId As Long = DatabaseIDB.GetScalarValue(oChecksumSQL) - - If oExistingObjectId > 0 Then - Logger.Info("Returning early with ObjectId [{0}] because Checksum [{1}] already exists.", oExistingObjectId, pChecksum) - Return oExistingObjectId - End If - - Return Nothing - - Catch ex As Exception - Logger.Error(ex) - Return Nothing - - End Try - End Function - - Private Function NewObjectId(pKindType As String, pBusinessEntity As String, pWho As String) As Long - Try - Dim oNewObjectIdSQL = $"DECLARE @NEW_IDB_OBJ_ID BIGINT - EXEC PRIDB_NEW_OBJECT '{pKindType}','{pWho}','{pBusinessEntity}',0, @IDB_OBJ_ID = @NEW_IDB_OBJ_ID OUTPUT; - SELECT @NEW_IDB_OBJ_ID" - Dim oObjectId As Long = DatabaseIDB.GetScalarValueWithConnectionObject(oNewObjectIdSQL, Connection, ExternalTransaction, Transaction) - Logger.Info("New Object with Id [{0}] created!", oObjectId) - - If IsNothing(oObjectId) Then - LogAndThrow("Could not create new ObjectId!") - End If - - Return oObjectId - Catch ex As Exception - Logger.Error(ex) - Return Nothing - End Try - End Function - - Private Function GetFileObjectFileName(IDB_OBJ_ID As Long, pFilename As String, pKeepFilename As Boolean) As String - ' TODO: save actual extensions - If pKeepFilename Then - Return pFilename - Else - Return $"{IDB_OBJ_ID}.ddfo" - End If - End Function - - Private Function GetDateSubDirectory(pDate As Date) As String - Return IO.Path.Combine(pDate.ToString("yyyy"), pDate.ToString("MM"), pDate.ToString("dd")) - End Function - End Class - -End Namespace \ No newline at end of file diff --git a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileRequest.vb b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileRequest.vb deleted file mode 100644 index 68a1e1b8..00000000 --- a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileRequest.vb +++ /dev/null @@ -1,38 +0,0 @@ -Imports System.Runtime.Serialization -Imports DigitalData.Modules.ZooFlow.State - -Namespace Methods.IDB.VersionFile - - - Public Class VersionFileRequest - - Public Property File As FileProperties - - ''' - ''' Name/title of the ObjectStore to save the file to, ex. Work - ''' - - Public Property StoreName As String - - ''' - ''' The business entity of the file, ex DEFAULT - ''' - - Public Property BusinessEntity As String - - ''' - ''' The kind of object to be created, ex. DOC - ''' - - Public Property KindType As String - - ''' - ''' User Importing the file - ''' - ''' - - Public Property User As UserState - End Class - -End Namespace -