diff --git a/Service.EDMIService/EDMIService.vb b/Service.EDMIService/EDMIService.vb index 53e5b602..f8bc5b59 100644 --- a/Service.EDMIService/EDMIService.vb +++ b/Service.EDMIService/EDMIService.vb @@ -74,12 +74,18 @@ Public Class EDMIService End Function #End Region - Public Function NewFile(Data As NewFile.NewFileRequest) As NewFile.NewFileResponse Implements IEDMIService.NewFile + Public Function NewFile(Data As NewFile.VersionFileRequest) As NewFile.VersionFileResponse Implements IEDMIService.NewFile _Logger.Debug("Start of Method [NewFile]") Dim oNewFile As New NewFile.NewFileMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) Return oNewFile.Run(Data) End Function + Public Function VersionFile(Data As VersionFile.VersionFileRequest) As VersionFile.VersionFileResponse Implements IEDMIService.VersionFile + _Logger.Debug("Start of Method [VersionFile]") + Dim oVersionFile As New VersionFile.VersionFileMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) + Return oVersionFile.Run(Data) + End Function + Public Function SetAttributeValue(Data As SetAttributeValue.SetAttributeValueRequest) As SetAttributeValue.SetAttributeValueResponse Implements IEDMIService.SetAttributeValue _Logger.Debug("Start of Method [SetAttributeValue]") Dim oSetAttributeValue As New SetAttributeValue.SetAttributeValueMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState) diff --git a/Service.EDMIService/EDMIService.vbproj b/Service.EDMIService/EDMIService.vbproj index 4cb4a321..4adf00e9 100644 --- a/Service.EDMIService/EDMIService.vbproj +++ b/Service.EDMIService/EDMIService.vbproj @@ -181,6 +181,9 @@ + + + @@ -287,5 +290,6 @@ false + \ No newline at end of file diff --git a/Service.EDMIService/IEDMIService.vb b/Service.EDMIService/IEDMIService.vb index 042aadb0..e75c93b6 100644 --- a/Service.EDMIService/IEDMIService.vb +++ b/Service.EDMIService/IEDMIService.vb @@ -81,7 +81,10 @@ Interface IEDMIService #Region "Document (New)" - Function NewFile(Data As NewFile.NewFileRequest) As NewFile.NewFileResponse + Function NewFile(Data As NewFile.VersionFileRequest) As NewFile.VersionFileResponse + + + Function VersionFile(Data As VersionFile.VersionFileRequest) As VersionFile.VersionFileResponse Function SetAttributeValue(Data As SetAttributeValue.SetAttributeValueRequest) As SetAttributeValue.SetAttributeValueResponse diff --git a/Service.EDMIService/Methods/GlobalIndexer/ImportFile/ImportFileMethod.vb b/Service.EDMIService/Methods/GlobalIndexer/ImportFile/ImportFileMethod.vb index b3ea349a..9e3f485a 100644 --- a/Service.EDMIService/Methods/GlobalIndexer/ImportFile/ImportFileMethod.vb +++ b/Service.EDMIService/Methods/GlobalIndexer/ImportFile/ImportFileMethod.vb @@ -61,7 +61,7 @@ Namespace Methods.GlobalIndexer.ImportFile ' Import the file Dim oNewFile As New NewFile.NewFileMethod(LogConfig, DatabaseIDB, DatabaseECM, GlobalState) - Dim oResponse = oNewFile.Run(New NewFile.NewFileRequest With { + Dim oResponse = oNewFile.Run(New NewFile.VersionFileRequest With { .File = pData.File, .BusinessEntity = pData.BusinessEntity, .KindType = pData.KindType, diff --git a/Service.EDMIService/Methods/IDB/NewFile/NewFileMethod.vb b/Service.EDMIService/Methods/IDB/NewFile/NewFileMethod.vb index a300c989..dca37679 100644 --- a/Service.EDMIService/Methods/IDB/NewFile/NewFileMethod.vb +++ b/Service.EDMIService/Methods/IDB/NewFile/NewFileMethod.vb @@ -19,12 +19,12 @@ Namespace Methods.IDB.NewFile Transaction = Connection.BeginTransaction() End Sub - Public Function Run(pData As NewFile.NewFileRequest) As Methods.IDB.NewFile.NewFileResponse + Public Function Run(pData As NewFile.VersionFileRequest) As Methods.IDB.NewFile.VersionFileResponse Dim oFilePath As String = Nothing Dim oExistingObjectId = TestFileChecksumExists(pData.File.FileChecksum) If oExistingObjectId > 0 Then - Return New NewFile.NewFileResponse(oExistingObjectId) + Return New NewFile.VersionFileResponse(oExistingObjectId) End If Try @@ -157,7 +157,7 @@ Namespace Methods.IDB.NewFile ' Finally, commit the transaction Transaction?.Commit() - Return New NewFile.NewFileResponse(oObjectId) + Return New NewFile.VersionFileResponse(oObjectId) Catch ex As Exception Logger.Warn("Error occurred while creating file!") Logger.Error(ex) @@ -175,7 +175,7 @@ Namespace Methods.IDB.NewFile Logger.Info("Rolling back transaction.") Transaction?.Rollback() - Return New NewFile.NewFileResponse(ex) + Return New NewFile.VersionFileResponse(ex) End Try End Function diff --git a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileMethod.vb b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileMethod.vb new file mode 100644 index 00000000..6f027b74 --- /dev/null +++ b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileMethod.vb @@ -0,0 +1,235 @@ +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 new file mode 100644 index 00000000..68a1e1b8 --- /dev/null +++ b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileRequest.vb @@ -0,0 +1,38 @@ +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 + diff --git a/Service.EDMIService/Methods/IDB/VersionFile/VersionFileResponse.vb b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileResponse.vb new file mode 100644 index 00000000..c19a4969 --- /dev/null +++ b/Service.EDMIService/Methods/IDB/VersionFile/VersionFileResponse.vb @@ -0,0 +1,22 @@ +Imports System.Runtime.Serialization + +Namespace Methods.IDB.VersionFile + + + Public Class VersionFileResponse + Inherits Messages.BaseResponse + + + Public Property ObjectId As Long + + Public Sub New(pObjectId As Long) + MyBase.New() + ObjectId = pObjectId + End Sub + + Public Sub New(pException As Exception, Optional pDetails As String = "") + MyBase.New(pException, pDetails) + End Sub + End Class + +End Namespace