Pdf Import Rewrite

Pdf Import rewritten to greatly improve QR Code detection, reduce
reliance on iTextSharp and improve thumbnails. Fixes #50
This commit is contained in:
Gary Sharp
2016-08-26 09:46:35 +10:00
parent 44f6d325db
commit 5ea9a814d6
98 changed files with 3168 additions and 3202 deletions
@@ -0,0 +1,92 @@
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using System;
using System.IO;
namespace Disco.Services.Documents.AttachmentImport
{
public class ImportDirectoryMonitor : IDisposable
{
private FileSystemWatcher watcher;
public const string WatcherFilter = "*.pdf";
public string MonitorLocation { get; private set; }
public IScheduler Scheduler { get; private set; }
public int ImportDelay { get; private set; }
public ImportDirectoryMonitor(string MonitorLocation, IScheduler Scheduler, int ImportDelay)
{
if (MonitorLocation == null)
throw new ArgumentNullException(nameof(MonitorLocation));
if (Scheduler == null)
throw new ArgumentNullException(nameof(Scheduler));
this.MonitorLocation = MonitorLocation.EndsWith(@"\") ? MonitorLocation : $@"{MonitorLocation}\";
this.Scheduler = Scheduler;
this.ImportDelay = Math.Max(0, ImportDelay);
}
public void Start()
{
if (watcher == null)
{
if (!Directory.Exists(MonitorLocation))
{
Directory.CreateDirectory(MonitorLocation);
}
watcher = new FileSystemWatcher(MonitorLocation, WatcherFilter);
watcher.Created += OnFileCreated;
}
watcher.EnableRaisingEvents = true;
}
public void Stop()
{
if (watcher != null)
{
watcher.EnableRaisingEvents = false;
}
}
private void OnFileCreated(object sender, FileSystemEventArgs e)
{
if (!e.ChangeType.HasFlag(WatcherChangeTypes.Deleted))
{
ScheduleImport(e.FullPath, ImportDelay);
}
}
private void ScheduleImport(string Filename, int ImportDelay)
{
var startTime = new DateTimeOffset(DateTime.Now.AddMilliseconds(ImportDelay));
var jobTrigger = new SimpleTriggerImpl(Guid.NewGuid().ToString(), startTime);
var jobDetails = new JobDetailImpl(Guid.NewGuid().ToString(), typeof(ImporterJob));
jobDetails.JobDataMap.Add("Filename", Filename);
jobDetails.JobDataMap.Add("RetryCount", 0);
Scheduler.ScheduleJob(jobDetails, jobTrigger);
}
public void ScheduleCurrentFiles(int ImportDelay)
{
foreach (var filename in Directory.GetFiles(this.MonitorLocation, "*.pdf"))
{
ScheduleImport(filename, ImportDelay);
}
}
public void Dispose()
{
if (watcher != null)
{
watcher.EnableRaisingEvents = false;
watcher.Dispose();
watcher = null;
}
}
}
}
@@ -0,0 +1,317 @@
using Disco.Data.Repository;
using PdfiumViewer;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using ZXing;
using ZXing.Common;
using ZXing.Multi.QrCode;
namespace Disco.Services.Documents.AttachmentImport
{
internal class ImportPage : IDisposable
{
public DiscoDataContext Database { get; private set; }
public string SessionId { get; private set; }
public PdfDocument PdfiumDocument { get; private set; }
public int PageIndex { get; private set; }
public DocumentUniqueIdentifier Identifier { get; private set; }
private Result qrCodeResult;
private float qrCodeResultScale;
private Image renderedImage;
private Bitmap renderedThumbnail;
private RotateFlipType detectedRotation;
public ImportPage(DiscoDataContext Database, string SessionId, PdfDocument PdfiumDocument, int PageIndex)
{
this.Database = Database;
this.SessionId = SessionId;
this.PdfiumDocument = PdfiumDocument;
this.PageIndex = PageIndex;
}
public bool IsDetected
{
get
{
return Identifier != null;
}
}
public Image Image
{
get
{
return GetRenderedImage();
}
}
public Bitmap Thumbnail
{
get
{
return GetRenderedThumbnail();
}
}
public bool IsValidAttachment
{
get
{
return Identifier != null &&
Identifier.Creator != null &&
Identifier.Target != null &&
(Identifier.DocumentTemplate != null || Identifier.AttachmentType.HasValue);
}
}
public int Rotation
{
get
{
switch (detectedRotation)
{
case RotateFlipType.Rotate90FlipNone:
return 90;
case RotateFlipType.Rotate180FlipNone:
return 180;
case RotateFlipType.Rotate270FlipNone:
return 270;
default:
return 0;
}
}
}
public void WriteThumbnailSessionCache()
{
var sessionCacheLocation = DataStore.CreateLocation(Database, "Cache\\DocumentDropBox_SessionPages");
var filename = Path.Combine(sessionCacheLocation, $"{SessionId}-{PageIndex + 1}");
Thumbnail.SavePng(filename);
}
public void WriteUndetectedImages()
{
var undetectedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
var filename = Path.Combine(undetectedLocation, $"{SessionId}_{PageIndex + 1}_thumbnail.png");
Thumbnail.SavePng(filename);
using (var largePreview = Image.ResizeImage(700, 700))
{
filename = Path.Combine(undetectedLocation, $"{SessionId}_{PageIndex + 1}.jpg");
largePreview.SaveJpg(90, filename);
}
}
public bool DetectQRCode()
{
var qrReader = new QRCodeMultiReader();
var qrReaderHints = new Dictionary<DecodeHintType, object>() {
{ DecodeHintType.TRY_HARDER, true }
};
var qrImageSource = new BitmapLuminanceSource((Bitmap)Image);
var qrBinarizer = new HybridBinarizer(qrImageSource);
var qrBinaryBitmap = new BinaryBitmap(qrBinarizer);
try
{
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault();
qrCodeResultScale = 1F;
}
catch (ReaderException)
{
// QR Detection Failed
qrCodeResult = null;
}
if (qrCodeResult == null)
{
var sizePoints = PdfiumDocument.PageSizes[PageIndex];
// Try at 175%
using (var image = PdfiumDocument.Render(PageIndex, (int)(sizePoints.Width * 1.75), (int)(sizePoints.Height * 1.75), 72F, 72F, false))
{
qrImageSource = new BitmapLuminanceSource((Bitmap)image);
// Try Entire Image
qrBinarizer = new HybridBinarizer(qrImageSource);
qrBinaryBitmap = new BinaryBitmap(qrBinarizer);
try
{
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault();
qrCodeResultScale = 1.75F;
}
catch (ReaderException)
{
// QR Detection Failed
qrCodeResult = null;
}
}
if (qrCodeResult == null)
{
// Try at 200%
using (var image = PdfiumDocument.Render(PageIndex, (int)(sizePoints.Width * 2), (int)(sizePoints.Height * 2), 72F, 72F, false))
{
qrImageSource = new BitmapLuminanceSource((Bitmap)image);
// Try Entire Image
qrBinarizer = new HybridBinarizer(qrImageSource);
qrBinaryBitmap = new BinaryBitmap(qrBinarizer);
try
{
qrCodeResult = qrReader.decodeMultiple(qrBinaryBitmap, qrReaderHints)?.FirstOrDefault();
qrCodeResultScale = 2F;
}
catch (ReaderException)
{
// QR Detection Failed
qrCodeResult = null;
}
}
}
}
if (qrCodeResult != null)
{
// Detect Rotation
var rotationAngle = Math.Atan2(
qrCodeResult.ResultPoints[2].Y - qrCodeResult.ResultPoints[1].Y,
qrCodeResult.ResultPoints[2].X - qrCodeResult.ResultPoints[1].X) * 180 / Math.PI;
if (rotationAngle <= 45 || rotationAngle > 315)
{
detectedRotation = RotateFlipType.RotateNoneFlipNone;
}
else if (rotationAngle <= 135)
{
detectedRotation = RotateFlipType.Rotate270FlipNone;
}
else if (rotationAngle <= 225)
{
detectedRotation = RotateFlipType.Rotate180FlipNone;
}
else
{
detectedRotation = RotateFlipType.Rotate90FlipNone;
}
// Reset Thumbnail
if (renderedThumbnail != null)
{
renderedThumbnail.Dispose();
renderedThumbnail = null;
}
// Try binary encoding (from v2)
if (qrCodeResult.ResultMetadata.ContainsKey(ResultMetadataType.BYTE_SEGMENTS))
{
var byteSegments = (List<byte[]>)qrCodeResult.ResultMetadata[ResultMetadataType.BYTE_SEGMENTS];
var qrBytes = byteSegments[0];
if (DocumentUniqueIdentifier.IsDocumentUniqueIdentifier(qrBytes))
{
Identifier = DocumentUniqueIdentifier.Parse(Database, qrBytes);
}
}
// Fall back to v1
if (Identifier == null)
{
Identifier = DocumentUniqueIdentifier.Parse(Database, qrCodeResult.Text);
}
return true;
}
return false;
}
public Bitmap GetAttachmentThumbnail()
{
var thumbnail = renderedImage.ResizeImage(48, 48, Brushes.White);
// Draw Rotation
if (detectedRotation != RotateFlipType.RotateNoneFlipNone)
{
thumbnail.RotateFlip(detectedRotation);
}
// Add PDF Icon overlay
using (Image mimeTypeIcon = Disco.Services.Properties.Resources.MimeType_pdf16)
{
thumbnail.EmbedIconOverlay(mimeTypeIcon);
}
return thumbnail;
}
private Image GetRenderedImage()
{
if (renderedImage == null)
{
var pageSize = PdfiumDocument.PageSizes[PageIndex];
renderedImage = PdfiumDocument.Render(PageIndex, (int)pageSize.Width, (int)pageSize.Height, 72F, 72F, true);
}
return renderedImage;
}
private Bitmap GetRenderedThumbnail()
{
if (renderedThumbnail == null)
{
renderedThumbnail = GetRenderedImage().ResizeImage(256, 256, Brushes.White);
if (qrCodeResult != null && qrCodeResult.ResultPoints.Length == 4)
{
float thumbnailScale;
var thumbnailOffset = renderedImage.CalculateResize(renderedThumbnail.Width, renderedThumbnail.Height, out thumbnailScale);
thumbnailScale = thumbnailScale / qrCodeResultScale;
using (Graphics thumbnailGraphics = Graphics.FromImage(renderedThumbnail))
{
// Draw Square on QR Code
var linePoints = qrCodeResult.ResultPoints.Select(p => new Point((int)(thumbnailOffset.X + (p.X * thumbnailScale)), (int)(thumbnailOffset.Y + (p.Y * thumbnailScale)))).ToList();
using (GraphicsPath graphicsPath = new GraphicsPath())
{
for (int linePointIndex = 0; linePointIndex < (linePoints.Count - 1); linePointIndex++)
graphicsPath.AddLine(linePoints[linePointIndex], linePoints[linePointIndex + 1]);
graphicsPath.AddLine(linePoints[linePoints.Count - 1], linePoints[0]);
using (SolidBrush graphicsBrush = new SolidBrush(Color.FromArgb(128, 255, 0, 0)))
thumbnailGraphics.FillPath(graphicsBrush, graphicsPath);
using (Pen graphicsPen = new Pen(Color.FromArgb(200, 255, 0, 0), 2))
thumbnailGraphics.DrawPath(graphicsPen, graphicsPath);
}
// Draw Rotation
if (detectedRotation != RotateFlipType.RotateNoneFlipNone)
{
renderedThumbnail.RotateFlip(detectedRotation);
}
}
}
}
return renderedThumbnail;
}
public void Dispose()
{
if (renderedImage != null)
renderedImage.Dispose();
if (renderedThumbnail != null)
renderedThumbnail.Dispose();
}
}
}
@@ -0,0 +1,244 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Logging;
using Disco.Services.Users;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
namespace Disco.Services.Documents.AttachmentImport
{
public static class Importer
{
public static void Import(DiscoDataContext Database, string SessionId, string Filename)
{
var dataStoreUnassignedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
var dataStoreSessionPagesCacheLocation = DataStore.CreateLocation(Database, "Cache\\DocumentDropBox_SessionPages");
var documentTemplates = Database.DocumentTemplates.ToArray();
if (!File.Exists(Filename))
{
DocumentsLog.LogImportWarning(SessionId, string.Format("File not found: {0}", Filename));
throw new FileNotFoundException("Document Not Found", Filename);
}
DocumentsLog.LogImportProgress(SessionId, 0, "Reading File");
List<ImportPage> pages = null;
List<ImportPage> assignedPages;
double progressInterval;
try
{
// Use Pdfium to Rasterize and Detect Pages
using (var importFileStream = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
using (var pdfiumDocument = PdfiumViewer.PdfDocument.Load(importFileStream))
{
progressInterval = 70D / pdfiumDocument.PageCount;
pages = new List<ImportPage>(pdfiumDocument.PageCount);
assignedPages = new List<ImportPage>(pdfiumDocument.PageCount);
// Rasterize and Detect Pages
for (int pageIndex = 0; pageIndex < pdfiumDocument.PageCount; pageIndex++)
{
var pageNumber = pageIndex + 1;
DocumentsLog.LogImportProgress(SessionId, (int)(pageIndex * progressInterval), $"Processing Page {pageNumber} of {pdfiumDocument.PageCount}");
DocumentsLog.LogImportPageStarting(SessionId, pageNumber);
var page = new ImportPage(Database, SessionId, pdfiumDocument, pageIndex);
pages.Add(page);
// Write Session Thumbnail
page.WriteThumbnailSessionCache();
DocumentsLog.LogImportPageImageUpdate(SessionId, pageNumber);
// Detect Image
if (page.DetectQRCode())
{
// Write updated session thumbnail
page.WriteThumbnailSessionCache();
DocumentsLog.LogImportPageImageUpdate(SessionId, pageNumber);
var identifier = page.Identifier;
DocumentsLog.LogImportPageDetected(SessionId, pageNumber, identifier.DocumentTemplateId, identifier.DocumentTemplate.Description, identifier.DocumentTemplate.Scope, identifier.TargetId, identifier.Target.ToString());
}
else
{
page.WriteUndetectedImages();
DocumentsLog.LogImportPageUndetected(SessionId, pageNumber);
}
}
}
}
// Use PdfSharp to Import and Build Documents
using (var importFileStream = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
using (var pdfSharpDocument = PdfReader.Open(importFileStream, PdfDocumentOpenMode.Import))
{
// Assign Pages
var documents = pages
.Where(p => p.IsValidAttachment)
.GroupBy(p => p.Identifier.DocumentGroupingId)
.ToList();
if (documents.Count > 0)
{
progressInterval = 20D / documents.Count;
foreach (var document in documents)
{
var documentPages = document.OrderBy(p => p.Identifier.PageIndex).ToList();
var documentPageFirst = documentPages.First();
DocumentsLog.LogImportProgress(SessionId, (int)(70D + (documents.IndexOf(document) * progressInterval)), $"Importing Documents {documents.IndexOf(document) + 1} of {documents.Count}");
using (MemoryStream msBuilder = new MemoryStream())
{
using (var pdfSharpDocumentOutput = new PdfDocument())
{
foreach (var documentPage in documentPages)
{
var pdfSharpImportPage = pdfSharpDocument.Pages[documentPage.PageIndex];
var importedPage = pdfSharpDocumentOutput.AddPage(pdfSharpImportPage);
importedPage.Rotate = documentPage.Rotation;
}
pdfSharpDocumentOutput.Save(msBuilder, false);
}
msBuilder.Position = 0;
using (var attachmentThumbnail = documentPageFirst.GetAttachmentThumbnail())
{
documentPageFirst.Identifier.ImportPdfAttachment(Database, msBuilder, attachmentThumbnail);
}
}
}
}
// Write Unassigned Pages
var unassignedPages = pages
.Where(p => !p.IsValidAttachment)
.ToList();
if (unassignedPages.Count > 0)
{
progressInterval = 10D / unassignedPages.Count;
foreach (var documentPage in unassignedPages)
{
DocumentsLog.LogImportProgress(SessionId, (int)(90 + (unassignedPages.IndexOf(documentPage) * progressInterval)), string.Format("Processing Undetected Pages {0} of {1}", unassignedPages.IndexOf(documentPage) + 1, unassignedPages.Count));
using (var pdfSharpDocumentOutput = new PdfDocument())
{
var pdfSharpImportPage = pdfSharpDocument.Pages[documentPage.PageIndex];
pdfSharpDocumentOutput.AddPage(pdfSharpImportPage);
var filename = Path.Combine(dataStoreUnassignedLocation, $"{SessionId}_{documentPage.PageIndex + 1}.pdf");
pdfSharpDocumentOutput.Save(filename);
DocumentsLog.LogImportPageUndetectedStored(SessionId, documentPage.PageIndex + 1);
}
}
}
}
}
}
finally
{
// Dispose of pages
if (pages != null && pages.Count != 0)
{
for (int i = 0; i < pages.Count; i++)
{
pages[i].Dispose();
}
}
}
}
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, string PdfFilename)
{
return ImportPdfAttachment(Identifier, Database, PdfFilename, null);
}
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, string PdfFilename, Image Thumbnail)
{
using (var pdfStream = File.OpenRead(PdfFilename))
{
return ImportPdfAttachment(Identifier, Database, pdfStream, Thumbnail);
}
}
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, Stream PdfContent)
{
return ImportPdfAttachment(Identifier, Database, PdfContent, null);
}
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, Stream PdfContent, Image Thumbnail)
{
string filename;
string comments;
IAttachment attachment;
if (Identifier.DocumentTemplate == null)
{
filename = $"{Identifier.Target.AttachmentReferenceId.Replace('\\', '_')}_{Identifier.TimeStamp:yyyyMMdd-HHmmss}.pdf";
comments = $"Uploaded: {Identifier.TimeStamp:s}";
}
else
{
filename = $"{Identifier.DocumentTemplateId}_{Identifier.TimeStamp:yyyyMMdd-HHmmss}.pdf";
comments = string.Format("Generated: {0:s}", Identifier.TimeStamp);
}
User creatorUser = UserService.GetUser(Identifier.CreatorId, Database);
if (creatorUser == null)
{
// No Creator User (or Username invalid)
creatorUser = UserService.CurrentUser;
}
switch (Identifier.AttachmentType)
{
case AttachmentTypes.Device:
Device d = (Device)Identifier.Target;
attachment = d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, Identifier.DocumentTemplate, Thumbnail);
break;
case AttachmentTypes.Job:
Job j = (Job)Identifier.Target;
attachment = j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, Identifier.DocumentTemplate, Thumbnail);
break;
case AttachmentTypes.User:
User u = (User)Identifier.Target;
attachment = u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, Identifier.DocumentTemplate, Thumbnail);
break;
default:
return false;
}
if (Identifier.DocumentTemplate != null && !string.IsNullOrWhiteSpace(Identifier.DocumentTemplate.OnImportAttachmentExpression))
{
try
{
var expressionResult = Identifier.DocumentTemplate.EvaluateOnAttachmentImportExpression(attachment, Database, creatorUser, Identifier.TimeStamp);
DocumentsLog.LogImportAttachmentExpressionEvaluated(Identifier.DocumentTemplate, Identifier.Target, attachment, expressionResult);
}
catch (Exception ex)
{
SystemLog.LogException("Document Importer - OnImportAttachmentExpression", ex);
}
}
return true;
}
}
}
@@ -0,0 +1,62 @@
using Disco.Data.Repository;
using Disco.Services.Logging;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.IO;
namespace Disco.Services.Documents.AttachmentImport
{
public class ImporterCleanCacheJob : ScheduledTask
{
public override string TaskName { get { return "Document Importer - Clean Cache Task"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override bool LogExceptionsOnly { get { return true; } }
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Trigger Daily @ 12:30am
TriggerBuilder triggerBuilder = TriggerBuilder.Create().WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 30));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
string dataStoreLocation;
using (DiscoDataContext database = new DiscoDataContext())
{
dataStoreLocation = DataStore.CreateLocation(database, @"Cache\DocumentDropBox_SessionPages");
}
int deleteCount = 0;
int errorCount = 0;
var dataStoreInfo = new DirectoryInfo(dataStoreLocation);
foreach (var file in dataStoreInfo.GetFiles())
{
try
{
if (file.CreationTime < DateTime.Today)
{
file.Delete();
deleteCount++;
}
}
catch
{
errorCount++;
}
}
SystemLog.LogInformation(
$"Cleared DocumentDropBox_SessionPages Cache, Deleted {deleteCount} File/s, with {errorCount} Error/s",
deleteCount,
errorCount
);
}
}
}
@@ -0,0 +1,92 @@
using Disco.Data.Repository;
using Exceptionless;
using Quartz;
using Quartz.Impl.Triggers;
using System;
using System.IO;
namespace Disco.Services.Documents.AttachmentImport
{
[PersistJobDataAfterExecution]
public class ImporterJob : IJob
{
public void Execute(IJobExecutionContext context)
{
var sessionId = context.JobDetail.JobDataMap["SessionId"] as string;
if (sessionId == null)
{
sessionId = Guid.NewGuid().ToString();
context.JobDetail.JobDataMap["SessionId"] = sessionId;
}
var filename = context.JobDetail.JobDataMap["Filename"] as string;
var retryCount = (int)context.JobDetail.JobDataMap["RetryCount"];
using (DiscoDataContext database = new DiscoDataContext())
{
try
{
DocumentsLog.LogImportStarting(sessionId, Path.GetFileName(filename));
// Returns null if unrecoverable error (eg. Not matched document)
Importer.Import(database, sessionId, filename);
// Success - Delete File
if (File.Exists(filename))
File.Delete(filename);
DocumentsLog.LogImportFinished(sessionId);
// All Done - Delete job
context.Scheduler.DeleteJob(context.JobDetail.Key);
}
catch (FileNotFoundException)
{
// File not found - Delete job and don't reschedule
context.Scheduler.DeleteJob(context.JobDetail.Key);
DocumentsLog.LogImportFinished(sessionId);
return;
}
catch (Exception ex)
{
ex.ToExceptionless().Submit();
// Retry 18 times (for 3 minutes)
if (retryCount < 18)
{
context.JobDetail.JobDataMap["RetryCount"] = ++retryCount;
DocumentsLog.LogImportWarning(sessionId, string.Format("{0}; Will try again in 10 Seconds", ex.Message));
// Reschedule Job for 10 seconds
var trig = new SimpleTriggerImpl(Guid.NewGuid().ToString(), new DateTimeOffset(DateTime.Now.AddSeconds(10)));
context.Scheduler.RescheduleJob(context.Trigger.Key, trig);
}
else
{
// To Many Errors
DocumentsLog.LogImportError(sessionId, $"To many errors occurred trying to import (SessionId: {sessionId})");
// Move to Errors Folder
if (File.Exists(filename))
{
try
{
var folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
var filenameError = Path.Combine(folderError, Path.GetFileName(filename));
var filenameErrorCount = 0;
while (File.Exists(filenameError))
{
filenameError = Path.Combine(folderError, $"{Path.GetFileNameWithoutExtension(filename)} ({++filenameErrorCount}){Path.GetExtension(filename)}");
}
File.Move(filename, filenameError);
}
catch
{
// Ignore Errors
}
}
DocumentsLog.LogImportFinished(sessionId);
}
}
}
}
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services
{
public static class DocumentTemplateActionExtensions
{
}
}
@@ -0,0 +1,24 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using System.IO;
namespace Disco.Services
{
public static class DocumentTemplateDataStoreExtensions
{
public static string RepositoryFilename(this DocumentTemplate dt, DiscoDataContext Database)
{
return Path.Combine(DataStore.CreateLocation(Database, "DocumentTemplates"), string.Format("{0}.pdf", dt.Id));
}
public static string SavePdfTemplate(this DocumentTemplate dt, DiscoDataContext Database, Stream TemplateFile)
{
string filePath = dt.RepositoryFilename(Database);
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
TemplateFile.CopyTo(fs);
}
Expressions.ExpressionCache.InvalidModule(string.Format(DocumentTemplateExpressionExtensions.CacheTemplate, dt.Id));
return filePath;
}
}
}
@@ -0,0 +1,111 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Models.Services.Documents;
using Disco.Services.Expressions;
using System;
namespace Disco.Services
{
public static class DocumentTemplateExpressionExtensions
{
internal const string CacheTemplate = "DocumentTemplate_{0}";
public static Expression FilterExpressionFromCache(this DocumentTemplate dt)
{
return ExpressionCache.GetValue("DocumentTemplate_FilterExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.FilterExpression, 0); });
}
public static void FilterExpressionInvalidateCache(this DocumentTemplate dt)
{
ExpressionCache.InvalidateKey("DocumentTemplate_FilterExpression", dt.Id);
}
public static bool FilterExpressionMatches(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
{
if (!string.IsNullOrEmpty(dt.FilterExpression))
{
Expression compiledExpression = dt.FilterExpressionFromCache();
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
try
{
object er = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
if (er is bool)
{
return (bool)er;
}
bool erBool;
if (bool.TryParse(er.ToString(), out erBool))
{
return erBool;
}
}
catch
{
return false;
}
}
return true;
}
public static Expression OnImportAttachmentExpressionFromCache(this DocumentTemplate dt)
{
return ExpressionCache.GetValue("DocumentTemplate_OnImportExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.OnImportAttachmentExpression, 0); });
}
public static void OnImportAttachmentExpressionInvalidateCache(this DocumentTemplate dt)
{
ExpressionCache.InvalidateKey("DocumentTemplate_OnImportExpression", dt.Id);
}
public static string EvaluateOnAttachmentImportExpression(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, DateTime TimeStamp)
{
if (!string.IsNullOrEmpty(dt.OnImportAttachmentExpression))
{
Expression compiledExpression = dt.OnImportAttachmentExpressionFromCache();
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, null);
try
{
object result = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
if (result == null)
return null;
else
return result.ToString();
}
catch
{
throw;
}
}
return null;
}
public static Expression OnGenerateExpressionFromCache(this DocumentTemplate dt)
{
return ExpressionCache.GetValue("DocumentTemplate_OnGenerateExpression", dt.Id, () => { return Expression.TokenizeSingleDynamic(null, dt.OnGenerateExpression, 0); });
}
public static void OnGenerateExpressionInvalidateCache(this DocumentTemplate dt)
{
ExpressionCache.InvalidateKey("DocumentTemplate_OnGenerateExpression", dt.Id);
}
public static string EvaluateOnGenerateExpression(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, DateTime TimeStamp, DocumentState State)
{
if (!string.IsNullOrEmpty(dt.OnGenerateExpression))
{
Expression compiledExpression = dt.OnGenerateExpressionFromCache();
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
try
{
object result = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
return result.ToString();
}
catch
{
throw;
}
}
return null;
}
}
}
@@ -0,0 +1,425 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Interop.ActiveDirectory;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
namespace Disco.Services.Documents
{
public class DocumentUniqueIdentifier
{
private const int CurrentVersion = 2;
private const byte MagicNumber = 0xC4;
private DiscoDataContext database;
public int Version { get; private set; }
public short DeploymentChecksum { get; private set; }
public string DocumentTemplateId { get; private set; }
public string TargetId { get; private set; }
public string CreatorId { get; private set; }
public DateTime TimeStamp { get; private set; }
public int PageIndex { get; private set; }
private DocumentTemplate documentTemplate;
private AttachmentTypes? attachmentType;
private IAttachmentTarget target;
private User creator;
public DocumentTemplate DocumentTemplate
{
get
{
if (documentTemplate == null && !string.IsNullOrWhiteSpace(DocumentTemplateId) && !DocumentTemplateId.StartsWith("--", StringComparison.Ordinal))
{
documentTemplate = database.DocumentTemplates.Find(DocumentTemplateId);
if (documentTemplate != null)
{
attachmentType = documentTemplate.AttachmentType;
}
}
return documentTemplate;
}
}
public string DocumentGroupingId
{
get
{
// Unique identifier to distinguish this document from others (but keep pages together)
return $"{TimeStamp.Ticks}|{TargetId}|{DocumentTemplateId}|{CreatorId}|{Version}|{DeploymentChecksum}";
}
}
public AttachmentTypes? AttachmentType
{
get
{
if (!attachmentType.HasValue)
{
if (DocumentTemplateId.StartsWith("--", StringComparison.Ordinal))
{
if (DocumentTemplateId.Equals("--DEVICE", StringComparison.Ordinal))
{
attachmentType = AttachmentTypes.Device;
}
else if (DocumentTemplateId.Equals("--JOB", StringComparison.Ordinal))
{
attachmentType = AttachmentTypes.Job;
}
else if (DocumentTemplateId.Equals("--USER", StringComparison.Ordinal))
{
attachmentType = AttachmentTypes.User;
}
}
else
{
var dt = DocumentTemplate;
if (dt != null)
{
attachmentType = dt.AttachmentType;
}
}
}
return attachmentType;
}
}
public IAttachmentTarget Target
{
get
{
if (target == null)
{
switch (AttachmentType)
{
case AttachmentTypes.Device:
target = database.Devices.Find(TargetId);
break;
case AttachmentTypes.Job:
target = database.Jobs.Find(int.Parse(TargetId));
break;
case AttachmentTypes.User:
target = database.Users.Find(ActiveDirectory.ParseDomainAccountId(TargetId));
break;
default:
throw new ArgumentException("Unexpected Attachment Type", nameof(AttachmentType));
}
}
return target;
}
}
public User Creator
{
get
{
if (creator == null)
{
creator = database.Users.Find(ActiveDirectory.ParseDomainAccountId(CreatorId));
}
return creator;
}
}
private DocumentUniqueIdentifier(DiscoDataContext Database, int Version, short DeploymentChecksum, string DocumentTemplateId, string TargetId, string CreatorId, DateTime TimeStamp, int PageIndex, AttachmentTypes? AttachmentType)
{
this.database = Database;
this.Version = Version;
this.DeploymentChecksum = DeploymentChecksum;
this.DocumentTemplateId = DocumentTemplateId;
this.attachmentType = AttachmentType;
this.TargetId = TargetId;
this.CreatorId = ActiveDirectory.ParseDomainAccountId(CreatorId);
this.TimeStamp = TimeStamp;
this.PageIndex = PageIndex;
}
public string ToQRCodeString()
{
return $"Disco|1|{DocumentTemplate.Id}|{TargetId}|{CreatorId}|{TimeStamp:s}|{PageIndex}";
}
public string ToJson()
{
var builder = new StringBuilder();
using (var stringWriter = new StringWriter(builder))
{
using (var writer = new JsonTextWriter(stringWriter))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartObject();
writer.WritePropertyName("version");
writer.WriteValue(CurrentVersion);
writer.WritePropertyName("attachmentType");
writer.WriteValue(AttachmentType.Value.ToString());
writer.WritePropertyName("documentTemplateId");
writer.WriteValue(DocumentTemplateId);
writer.WritePropertyName("targetId");
writer.WriteValue(TargetId);
writer.WritePropertyName("creatorId");
writer.WriteValue(CreatorId);
writer.WritePropertyName("timestamp");
writer.WriteValue(TimeStamp);
writer.WritePropertyName("pageIndex");
writer.WriteValue(PageIndex);
writer.WriteEndObject();
}
}
return builder.ToString();
}
public byte[] ToQRCodeBytes()
{
// Byte | Meaning
// 0 | magic number = 0x0D
// 1 | bits 0-3 = version; 4-7 = flags (1 = has document template id, 2 = device attachment,
// | 4 = job attachment, 8 = user attachment)
// 2-3 | deployment checksum (int16)
// 4-7 | timestamp (uint32 unix epoch)
// 8-9 | page index (uint16)
// 10 | creator id length
// 11-? | creator id (UTF8)
// ? | target id length
// ?-? | target id
// ? | document template id length (optional based on flag)
// ?-? | document template id (UTF8, optional based on flag)
var encoding = Encoding.UTF8;
byte flags = 0;
switch (AttachmentType)
{
case AttachmentTypes.Device:
flags = 2;
break;
case AttachmentTypes.Job:
flags = 4;
break;
case AttachmentTypes.User:
flags = 8;
break;
}
var deploymentChecksumBytes = BitConverter.GetBytes(DeploymentChecksum);
var timeStampEpochBytes = BitConverter.GetBytes((uint)(TimeStamp.ToUniversalTime().Subtract(DateTime.FromFileTimeUtc(116444736000000000L)).Ticks / TimeSpan.TicksPerSecond));
var pageIndexBytes = BitConverter.GetBytes((ushort)PageIndex);
// magic number (1) + version/flags (1) + deployment checksum (2) + timestamp (4) +
// page index (2) + creator id length (1) + target id length (1)
var requiredBytes = 12;
var creatorIdLength = encoding.GetByteCount(CreatorId);
var targetIdLength = encoding.GetByteCount(TargetId);
var documentTemplateIdLength = 0;
if (DocumentTemplateId != null)
{
flags |= 1;
requiredBytes++;
documentTemplateIdLength = encoding.GetByteCount(DocumentTemplateId);
}
int position = 0;
var result = new byte[requiredBytes];
// magic number
result[position++] = MagicNumber;
// version & flags
result[position++] = (byte)(2 | (flags << 4));
// deployment checksum
deploymentChecksumBytes.CopyTo(result, position);
position += 2;
// timestamp
timeStampEpochBytes.CopyTo(result, position);
position += 4;
// page index
pageIndexBytes.CopyTo(result, position);
position += 2;
// creator id length
result[position++] = (byte)creatorIdLength;
// creator id
position += encoding.GetBytes(CreatorId, 0, CreatorId.Length, result, position);
// target id length
result[position++] = (byte)targetIdLength;
// target id
position += encoding.GetBytes(TargetId, 0, TargetId.Length, result, position);
if (documentTemplateIdLength > 0)
{
// document template id length
result[position++] = (byte)documentTemplateIdLength;
// document template id
position += encoding.GetBytes(DocumentTemplateId, 0, DocumentTemplateId.Length, result, position);
}
return result;
}
public static DocumentUniqueIdentifier Create(DiscoDataContext Database, DocumentTemplate DocumentTemplate, IAttachmentTarget Target, User Creator, DateTime TimeStamp, int PageIndex)
{
var deploymentChecksum = Database.DiscoConfiguration.DeploymentChecksum;
var documentTemplateId = DocumentTemplate.Id;
var targetId = Target.AttachmentReferenceId;
var creatorId = Creator.UserId;
var attachmentType = DocumentTemplate.AttachmentType;
var identifier = new DocumentUniqueIdentifier(Database, CurrentVersion, deploymentChecksum, documentTemplateId, targetId, creatorId, TimeStamp, PageIndex, attachmentType);
identifier.documentTemplate = DocumentTemplate;
identifier.target = Target;
identifier.creator = Creator;
return identifier;
}
public static DocumentUniqueIdentifier Create(DiscoDataContext Database, string DocumentTemplateId, string TargetId, string CreatorId, DateTime TimeStamp, int PageIndex)
{
var deploymentChecksum = Database.DiscoConfiguration.DeploymentChecksum;
return new DocumentUniqueIdentifier(Database, CurrentVersion, deploymentChecksum, DocumentTemplateId, TargetId, CreatorId, TimeStamp, PageIndex, null);
}
public static DocumentUniqueIdentifier Parse(DiscoDataContext Database, byte[] UniqueIdentifier)
{
DocumentUniqueIdentifier identifier;
if (TryParse(Database, UniqueIdentifier, out identifier))
{
return identifier;
}
else
{
throw new FormatException("Invalid Document Unique Identifier");
}
}
public static DocumentUniqueIdentifier Parse(DiscoDataContext Database, string UniqueIdentifier)
{
DocumentUniqueIdentifier identifier;
if (TryParse(Database, UniqueIdentifier, out identifier))
{
return identifier;
}
else
{
throw new FormatException("Invalid Document Unique Identifier");
}
}
public static bool TryParse(DiscoDataContext Database, string UniqueIdentifier, out DocumentUniqueIdentifier Identifier)
{
if (IsDocumentUniqueIdentifier(UniqueIdentifier))
{
var components = UniqueIdentifier.Split('|');
// Version 0, Version 1 Handling
if ((components.Length == 7 || components.Length == 6) &&
(components[1].Equals("1", StringComparison.Ordinal) || components[1].Equals("AT", StringComparison.OrdinalIgnoreCase)))
{
var documentTemplateId = components[2];
var targetId = components[3];
var creatorId = components[4];
var timeStamp = DateTime.Parse(components[5]);
var page = 0;
if (components.Length == 7)
{
page = int.Parse(components[6]);
}
Identifier = new DocumentUniqueIdentifier(Database, 1, -1, documentTemplateId, targetId, creatorId, timeStamp, page, null);
return true;
}
}
Identifier = null;
return false;
}
public static bool TryParse(DiscoDataContext Database, byte[] UniqueIdentifier, out DocumentUniqueIdentifier Identifier)
{
if (IsDocumentUniqueIdentifier(UniqueIdentifier))
{
// first 4 bit indicate version
var version = UniqueIdentifier[2] & 0x0F;
// Version 2
if (version == 2)
{
// Byte | Meaning
// 0 | magic number = 0x0D
// 1 | bits 0-3 = version; 4-7 = flags (1 = has document template id, 2 = device attachment,
// | 4 = job attachment, 8 = user attachment)
// 2-3 | deployment checksum (int16)
// 4-7 | timestamp (uint32 unix epoch)
// 8-9 | page index (uint16)
// 10 | creator id length
// 11-? | creator id (UTF8)
// ? | target id length
// ?-? | target id
// ? | document template id length (optional based on flag)
// ?-? | document template id (UTF8, optional based on flag)
var encoding = Encoding.UTF8;
var position = 2;
// next 4 bits are flags
var flags = UniqueIdentifier[position++] >> 4;
var deploymentChecksum = BitConverter.ToInt16(UniqueIdentifier, position);
position += 2;
var timeStampEpoch = BitConverter.ToUInt32(UniqueIdentifier, position);
position += 4;
var pageIndex = BitConverter.ToUInt16(UniqueIdentifier, position);
position += 2;
var creatorIdLength = UniqueIdentifier[position++];
var creatorId = encoding.GetString(UniqueIdentifier, position, creatorIdLength);
position += creatorIdLength;
var targetIdLength = UniqueIdentifier[position++];
var targetId = encoding.GetString(UniqueIdentifier, position, targetIdLength);
position += targetIdLength;
string documentTemplateId = null;
// Has document template id flag
if ((flags & 1) == 1)
{
var documentTemplateIdLength = UniqueIdentifier[position++];
documentTemplateId = encoding.GetString(UniqueIdentifier, position, documentTemplateIdLength);
}
AttachmentTypes? attachmentType = null;
if ((flags & 2) == 2)
attachmentType = AttachmentTypes.Device;
else if ((flags & 4) == 4)
attachmentType = AttachmentTypes.Job;
else if ((flags & 8) == 8)
attachmentType = AttachmentTypes.User;
var timeStamp = DateTime.FromFileTimeUtc(116444736000000000L).AddTicks(TimeSpan.TicksPerSecond * timeStampEpoch).ToLocalTime();
Identifier = new DocumentUniqueIdentifier(Database, version, deploymentChecksum, documentTemplateId, targetId, creatorId, timeStamp, pageIndex, attachmentType);
}
}
Identifier = null;
return false;
}
public static bool IsDocumentUniqueIdentifier(string Identifier)
{
return Identifier != null && Identifier.StartsWith("Disco|", System.StringComparison.OrdinalIgnoreCase);
}
public static bool IsDocumentUniqueIdentifier(byte[] Identifier)
{
// Identifier[0] = 0xC4; Magic number to identify Disco ICT QR Codes
return Identifier != null && Identifier.Length > 2 && Identifier[0] == MagicNumber;
}
}
}
@@ -0,0 +1,21 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Documents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services
{
public static class DocumentUniqueIdentifierExtensions
{
public static DocumentUniqueIdentifier CreateUniqueIdentifier(this DocumentTemplate Template, DiscoDataContext Database, IAttachmentTarget Target, User Creator, DateTime Timestamp, int PageIndex)
{
return DocumentUniqueIdentifier.Create(Database, Template, Target, Creator, Timestamp, PageIndex);
}
}
}
+441
View File
@@ -0,0 +1,441 @@
using Disco.Models.Repository;
using Disco.Services.Logging;
using Disco.Services.Logging.Models;
namespace Disco.Services.Documents
{
public class DocumentsLog : LogBase
{
public enum EventTypeIds
{
ImportStarting = 10,
ImportProgress,
ImportFinished,
ImportWarning = 15,
ImportError,
ImportAttachmentExpressionEvaluated = 50,
ImportPageStarting = 100,
ImportPageImageUpdate = 104,
ImportPageProgress,
ImportPageDetected = 110,
ImportPageUndetected = 115,
ImportPageError = 120,
ImportPageUndetectedStored = 150,
DocumentGenerated = 500,
DocumentGeneratedWithExpression
}
private const int _ModuleId = 40;
public static DocumentsLog Current
{
get
{
return (DocumentsLog)LogContext.LogModules[_ModuleId];
}
}
public override string ModuleDescription
{
get
{
return "Documents";
}
}
public override int ModuleId
{
get
{
return _ModuleId;
}
}
public override string ModuleName
{
get
{
return "Documents";
}
}
private static void Log(DocumentsLog.EventTypeIds EventTypeId, params object[] Args)
{
DocumentsLog.Current.Log((int)EventTypeId, Args);
}
public static void LogImportStarting(string SessionId, string DocumentName)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportStarting, new object[]
{
SessionId,
DocumentName
});
}
public static void LogImportProgress(string SessionId, int? Progress, string Status)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportProgress, new object[]
{
SessionId,
Progress,
Status
});
}
public static void LogImportFinished(string SessionId)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportFinished, new object[]
{
SessionId
});
}
public static void LogImportWarning(string SessionId, string Message)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportWarning, new object[]
{
SessionId,
Message
});
}
public static void LogImportError(string SessionId, string Message)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportError, new object[]
{
SessionId,
Message
});
}
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate template, IAttachmentTarget target, IAttachment attachment, string Result)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
{
template.Id,
target.AttachmentReferenceId,
attachment.Id,
Result
});
}
public static void LogImportPageStarting(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageStarting, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageImageUpdate(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageImageUpdate, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageProgress(string SessionId, int PageNumber, int? Progress, string Status)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageProgress, new object[]
{
SessionId,
PageNumber,
Progress,
Status
});
}
public static void LogImportPageDetected(string SessionId, int PageNumber, string DocumentTypeId, string DocumentTypeName, string TargetType, string AssignedId, string AssignedName)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageDetected, new object[]
{
SessionId,
PageNumber,
DocumentTypeId,
DocumentTypeName,
TargetType,
AssignedId,
AssignedName
});
}
public static void LogImportPageUndetected(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageUndetected, new object[]
{
SessionId,
PageNumber
});
}
public static void LogImportPageError(string SessionId, int PageNumber, string Message)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageError, new object[]
{
SessionId,
PageNumber,
Message
});
}
public static void LogImportPageUndetectedStored(string SessionId, int PageNumber)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportPageUndetectedStored, new object[]
{
SessionId,
PageNumber
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Device Device, User Author, string ExpressionResult)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
Device.SerialNumber,
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Job Job, User Author, string ExpressionResult)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
Job.Id,
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, User User, User Author, string ExpressionResult)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
User.UserId,
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, IAttachmentTarget Data, User Author, string ExpressionResult)
{
if (Data is Job)
LogDocumentGenerated(Template, (Job)Data, Author, ExpressionResult);
else if (Data is User)
LogDocumentGenerated(Template, (User)Data, Author, ExpressionResult);
else if (Data is Device)
LogDocumentGenerated(Template, (Device)Data, Author, ExpressionResult);
else
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGeneratedWithExpression, new object[]
{
Template.Id,
"UNKNOWN",
Author.UserId,
ExpressionResult
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Device Device, User Author)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
Device.SerialNumber,
Author.UserId
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, Job Job, User Author)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
Job.Id,
Author.UserId
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, User User, User Author)
{
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
User.UserId,
Author.UserId
});
}
public static void LogDocumentGenerated(DocumentTemplate Template, object Data, User Author)
{
if (Data is Job)
LogDocumentGenerated(Template, (Job)Data, Author);
else if (Data is User)
LogDocumentGenerated(Template, (User)Data, Author);
else if (Data is Device)
LogDocumentGenerated(Template, (Device)Data, Author);
else
DocumentsLog.Log(DocumentsLog.EventTypeIds.DocumentGenerated, new object[]
{
Template.Id,
"UNKNOWN",
Author.UserId
});
}
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
{
return new System.Collections.Generic.List<LogEventType>
{
new LogEventType
{
Id = (int)EventTypeIds.ImportStarting,
ModuleId = _ModuleId,
Name = "Import Starting",
Format = "Starting import of document: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportProgress,
ModuleId = _ModuleId,
Name = "Import Progress",
Format = "Processing: {1}% Complete; Status: {2}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.ImportFinished,
ModuleId = _ModuleId,
Name = "Import Finished",
Format = "Import of document complete (SessionId: {0})",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportWarning,
ModuleId = _ModuleId,
Name = "Import Warning",
Format = "Import Warning: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Warning,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportError,
ModuleId = _ModuleId,
Name = "Import Error",
Format = "Import Error: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Error,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportAttachmentExpressionEvaluated,
ModuleId = _ModuleId,
Name = "Import Attachment Expression Evaluated",
Format = "The import attachment expression for '{0}' was evaluated for '{1}' (attachment id: {2}) with the result: {3}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageStarting,
ModuleId = _ModuleId,
Name = "Import Page Starting",
Format = "Starting import of page: {1} (SessionId: {0})",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageImageUpdate,
ModuleId = _ModuleId,
Name = "Import Page Image Update",
Format = null,
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageProgress,
ModuleId = _ModuleId,
Name = "Import Page Progress",
Format = "Processing: Page {1}; {2}% Complete; Status: {3}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageDetected,
ModuleId = _ModuleId,
Name = "Import Page Assigned",
Format = "Page {1} of type '{3}' assigned to {4}: '{6}'",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageUndetected,
ModuleId = _ModuleId,
Name = "Import Page Undetected",
Format = "Page {1} not detected",
Severity = (int)LogEventType.Severities.Warning,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageError,
ModuleId = _ModuleId,
Name = "Import Page Error",
Format = "Page {1}, Import Error: {2}",
Severity = (int)LogEventType.Severities.Error,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.ImportPageUndetectedStored,
ModuleId = _ModuleId,
Name = "Import Page Undetected Stored",
Format = null,
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = (int)EventTypeIds.DocumentGenerated,
ModuleId = _ModuleId,
Name = "Document Generated",
Format = "A '{0}' document was generated for '{1}' by '{2}'",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = (int)EventTypeIds.DocumentGeneratedWithExpression,
ModuleId = _ModuleId,
Name = "Document Generated with Expression",
Format = "A '{0}' document was generated for '{1}' by '{2}'. The expression returned: {3}",
Severity = (int)LogEventType.Severities.Information,
UseLive = true,
UsePersist = true,
UseDisplay = true
}
};
}
}
}