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:
@@ -1,102 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Exceptionless;
|
||||
using iTextSharp.text.pdf;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.AttachmentBI
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
|
||||
public static bool GenerateThumbnail(Stream Source, string SourceMimeType, Stream OutStream)
|
||||
{
|
||||
if (Source != null)
|
||||
{
|
||||
// GDI+ (jpg, png, gif, bmp)
|
||||
if (SourceMimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("jpg") ||
|
||||
SourceMimeType.Equals("image/png", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("png") ||
|
||||
SourceMimeType.Equals("image/gif", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("gif") ||
|
||||
SourceMimeType.Equals("image/bmp", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("bmp"))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Image sourceImage = Image.FromStream(Source))
|
||||
{
|
||||
using (Image thumbImage = sourceImage.ResizeImage(48, 48))
|
||||
{
|
||||
using (Image mimeTypeIcon = Disco.Properties.Resources.MimeType_img16)
|
||||
thumbImage.EmbedIconOverlay(mimeTypeIcon);
|
||||
thumbImage.SaveJpg(90, OutStream);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.ToExceptionless().Submit();
|
||||
|
||||
// Ignore Thumbnail Generation exceptions for images
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// PDF
|
||||
if (SourceMimeType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("pdf"))
|
||||
{
|
||||
PdfReader pdfReader = new PdfReader(Source);
|
||||
try
|
||||
{
|
||||
using (DisposableImageCollection pdfPageImages = pdfReader.PdfPageImages(1))
|
||||
{
|
||||
if (pdfPageImages.Count() > 0)
|
||||
{
|
||||
// Find Biggest Image on Page
|
||||
Image biggestImage = pdfPageImages.OrderByDescending(i => i.Height * i.Width).First();
|
||||
using (Image thumbImage = biggestImage.ResizeImage(48, 48, Brushes.White))
|
||||
{
|
||||
using (Image mimeTypeIcon = Disco.Properties.Resources.MimeType_pdf16)
|
||||
thumbImage.EmbedIconOverlay(mimeTypeIcon);
|
||||
thumbImage.SaveJpg(90, OutStream);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.ToExceptionless().Submit();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pdfReader != null)
|
||||
pdfReader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static bool GenerateThumbnail(string SourceFilename, string SourceMimeType, string DestinationFilename)
|
||||
{
|
||||
using (FileStream sourceStream = new FileStream(SourceFilename, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
return GenerateThumbnail(sourceStream, SourceMimeType, DestinationFilename);
|
||||
}
|
||||
}
|
||||
public static bool GenerateThumbnail(Stream Source, string SourceMimeType, string DestinationFilename)
|
||||
{
|
||||
bool result;
|
||||
using (FileStream destinationStream = new FileStream(DestinationFilename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
result = GenerateThumbnail(Source, SourceMimeType, destinationStream);
|
||||
}
|
||||
if (!result && File.Exists(DestinationFilename))
|
||||
File.Delete(DestinationFilename);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Data.Configuration;
|
||||
|
||||
namespace Disco.BI
|
||||
{
|
||||
public static class DataStore
|
||||
{
|
||||
|
||||
public static string CreateLocation(DiscoDataContext Database, string SubLocation, DateTime? SubSubLocationTimestamp = null)
|
||||
{
|
||||
return CreateLocation(Database.DiscoConfiguration, SubLocation, SubSubLocationTimestamp);
|
||||
}
|
||||
public static string CreateLocation(SystemConfiguration DiscoConfiguration, string SubLocation, DateTime? SubSubLocationTimestamp = null)
|
||||
{
|
||||
string SubSubLocation = string.Empty;
|
||||
if (SubSubLocationTimestamp.HasValue)
|
||||
SubSubLocation = SubSubLocationTimestamp.Value.ToString(@"yyyy\\MM");
|
||||
|
||||
string storeDirectory = System.IO.Path.Combine(DiscoConfiguration.DataStoreLocation, SubLocation, SubSubLocation);
|
||||
if (!System.IO.Directory.Exists(storeDirectory))
|
||||
System.IO.Directory.CreateDirectory(storeDirectory);
|
||||
|
||||
return storeDirectory;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Concurrent;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.BI.Extensions;
|
||||
using System.Web;
|
||||
using System.Drawing;
|
||||
using iTextSharp.text.pdf;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
{
|
||||
class DocumentTemplateQRCodeLocationCache
|
||||
{
|
||||
private static ConcurrentDictionary<string, List<RectangleF>> _Cache = new ConcurrentDictionary<string, List<RectangleF>>();
|
||||
|
||||
public static List<RectangleF> GetLocations(DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
// Check Cache
|
||||
List<RectangleF> locations;
|
||||
if (_Cache.TryGetValue(dt.Id, out locations))
|
||||
{
|
||||
return locations;
|
||||
}
|
||||
// Generate Cache
|
||||
return GenerateLocations(dt, Database);
|
||||
}
|
||||
|
||||
public static bool InvalidateLocations(DocumentTemplate dt)
|
||||
{
|
||||
List<RectangleF> locations;
|
||||
return _Cache.TryRemove(dt.Id, out locations);
|
||||
}
|
||||
|
||||
private static bool SetValue(string DocumentTemplateId, List<RectangleF> Locations)
|
||||
{
|
||||
if (_Cache.ContainsKey(DocumentTemplateId))
|
||||
{
|
||||
List<RectangleF> oldLocations;
|
||||
if (_Cache.TryGetValue(DocumentTemplateId, out oldLocations))
|
||||
{
|
||||
return _Cache.TryUpdate(DocumentTemplateId, Locations, oldLocations);
|
||||
}
|
||||
}
|
||||
return _Cache.TryAdd(DocumentTemplateId, Locations);
|
||||
}
|
||||
|
||||
internal static List<RectangleF> GenerateLocations(DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
string templateFilename = dt.RepositoryFilename(Database);
|
||||
PdfReader pdfReader = new PdfReader(templateFilename);
|
||||
List<RectangleF> locations = new List<RectangleF>();
|
||||
|
||||
if (pdfReader.AcroFields.Fields.ContainsKey("DiscoAttachmentId"))
|
||||
{
|
||||
foreach (var pdfFieldPosition in pdfReader.AcroFields.GetFieldPositions("DiscoAttachmentId"))
|
||||
{
|
||||
var pdfPageSize = pdfReader.GetPageSize(pdfFieldPosition.page);
|
||||
// Original Position
|
||||
locations.Add(new RectangleF(
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(pdfFieldPosition.position.Left / pdfPageSize.Width) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)((pdfPageSize.Height - pdfFieldPosition.position.Top) / pdfPageSize.Height) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(pdfFieldPosition.position.Width / pdfPageSize.Width) + 0.1)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(pdfFieldPosition.position.Height / pdfPageSize.Height) + 0.1))
|
||||
));
|
||||
}
|
||||
}
|
||||
pdfReader.Close();
|
||||
|
||||
// Update Cache
|
||||
SetValue(dt.Id, locations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using System;
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
{
|
||||
public class DocumentUniqueIdentifier
|
||||
{
|
||||
private bool? _loadedComponentsOk;
|
||||
private DocumentTemplate _documentTemplate;
|
||||
private object _data;
|
||||
private string _dataDescription;
|
||||
public string TemplateTypeId { get; private set; }
|
||||
public string DataId { get; private set; }
|
||||
public string DocumentUniqueId
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("{0}|{1}", this.TemplateTypeId, this.DataId);
|
||||
}
|
||||
}
|
||||
public string CreatorId { get; private set; }
|
||||
public System.DateTime TimeStamp { get; private set; }
|
||||
public int Page { get; private set; }
|
||||
public string Tag { get; private set; }
|
||||
public DocumentTemplate DocumentTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this._loadedComponentsOk.HasValue && this._loadedComponentsOk.Value;
|
||||
if (flag)
|
||||
{
|
||||
return this._documentTemplate;
|
||||
}
|
||||
throw new System.Exception("Document Unique Identifier Components not loaded or invalid");
|
||||
}
|
||||
}
|
||||
public object Data
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this._loadedComponentsOk.HasValue && this._loadedComponentsOk.Value;
|
||||
if (flag)
|
||||
{
|
||||
return this._data;
|
||||
}
|
||||
throw new System.Exception("Document Unique Identifier Components not loaded or invalid");
|
||||
}
|
||||
}
|
||||
public string DataDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
bool flag = this._loadedComponentsOk.HasValue && this._loadedComponentsOk.Value;
|
||||
if (flag)
|
||||
{
|
||||
return this._dataDescription;
|
||||
}
|
||||
throw new System.Exception("Document Unique Identifier Components not loaded or invalid");
|
||||
}
|
||||
}
|
||||
public string DataScope { get; private set; }
|
||||
public static bool IsDocumentUniqueIdentifier(string UniqueIdentifier)
|
||||
{
|
||||
return UniqueIdentifier.StartsWith("Disco|", System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public DocumentUniqueIdentifier(string TemplateTypeId, string DataId, string CreatorId, DateTime TimeStamp, int? Page = null, string Tag = null)
|
||||
{
|
||||
this.Tag = Tag;
|
||||
this.TemplateTypeId = TemplateTypeId;
|
||||
this.DataId = DataId;
|
||||
this.CreatorId = ActiveDirectory.ParseDomainAccountId(CreatorId);
|
||||
this.TimeStamp = TimeStamp;
|
||||
this.Page = Page ?? 0;
|
||||
}
|
||||
public DocumentUniqueIdentifier(string UniqueIdentifier, string Tag)
|
||||
{
|
||||
if (!DocumentUniqueIdentifier.IsDocumentUniqueIdentifier(UniqueIdentifier))
|
||||
{
|
||||
throw new System.ArgumentException("Invalid Document Unique Identifier", "UniqueIdentifier");
|
||||
}
|
||||
this.Tag = Tag;
|
||||
string[] s = UniqueIdentifier.Split(new char[] { '|' });
|
||||
string left = s[1].ToUpper();
|
||||
if (left == "AT" || left == "1")
|
||||
{
|
||||
if (s.Length >= 3)
|
||||
{
|
||||
this.TemplateTypeId = s[2];
|
||||
}
|
||||
if (s.Length >= 4)
|
||||
{
|
||||
this.DataId = s[3];
|
||||
}
|
||||
if (s.Length >= 5)
|
||||
{
|
||||
this.CreatorId = ActiveDirectory.ParseDomainAccountId(s[4]);
|
||||
}
|
||||
if (s.Length >= 6)
|
||||
{
|
||||
System.DateTime timeStamp;
|
||||
if (System.DateTime.TryParse(s[5], out timeStamp))
|
||||
{
|
||||
this.TimeStamp = timeStamp;
|
||||
}
|
||||
}
|
||||
if (s.Length >= 7)
|
||||
{
|
||||
int page = 0;
|
||||
if (int.TryParse(s[6], out page))
|
||||
{
|
||||
this.Page = page;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw new System.ArgumentException(string.Format("Invalid Document Unique Identifier Version ({0})", s[1]), "UniqueIdentifier");
|
||||
}
|
||||
public bool LoadComponents(DiscoDataContext Database)
|
||||
{
|
||||
bool LoadComponents;
|
||||
if (!this._loadedComponentsOk.HasValue)
|
||||
{
|
||||
string scopeType;
|
||||
if (this.TemplateTypeId.StartsWith("--"))
|
||||
{
|
||||
string templateTypeId = this.TemplateTypeId;
|
||||
switch (this.TemplateTypeId)
|
||||
{
|
||||
case "--DEVICE":
|
||||
scopeType = DocumentTemplate.DocumentTemplateScopes.Device;
|
||||
break;
|
||||
case "--JOB":
|
||||
scopeType = DocumentTemplate.DocumentTemplateScopes.Job;
|
||||
break;
|
||||
case "--USER":
|
||||
scopeType = DocumentTemplate.DocumentTemplateScopes.User;
|
||||
break;
|
||||
default:
|
||||
scopeType = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._documentTemplate = Database.DocumentTemplates.Find(this.TemplateTypeId);
|
||||
if (this._documentTemplate != null)
|
||||
{
|
||||
scopeType = this._documentTemplate.Scope;
|
||||
}
|
||||
else
|
||||
{
|
||||
scopeType = null;
|
||||
}
|
||||
}
|
||||
if (scopeType != null)
|
||||
{
|
||||
this.DataScope = scopeType;
|
||||
switch (scopeType)
|
||||
{
|
||||
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
Device d = Database.Devices.Find(this.DataId);
|
||||
if (d != null)
|
||||
{
|
||||
this._data = d;
|
||||
this._dataDescription = d.SerialNumber;
|
||||
this._loadedComponentsOk = true;
|
||||
LoadComponents = true;
|
||||
return LoadComponents;
|
||||
}
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
Job i = Database.Jobs.Find(int.Parse(this.DataId));
|
||||
if (i != null)
|
||||
{
|
||||
this._data = i;
|
||||
this._dataDescription = i.Id.ToString();
|
||||
this._loadedComponentsOk = true;
|
||||
LoadComponents = true;
|
||||
return LoadComponents;
|
||||
}
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
User u = Database.Users.Find(ActiveDirectory.ParseDomainAccountId(this.DataId));
|
||||
if (u != null)
|
||||
{
|
||||
this._data = u;
|
||||
this._dataDescription = u.DisplayName;
|
||||
this._loadedComponentsOk = true;
|
||||
LoadComponents = true;
|
||||
return LoadComponents;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._loadedComponentsOk = false;
|
||||
}
|
||||
LoadComponents = this._loadedComponentsOk.Value;
|
||||
return LoadComponents;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,478 +0,0 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Logging.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
namespace Disco.BI.DocumentTemplateBI
|
||||
{
|
||||
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, Device device, DeviceAttachment attachment, string Result)
|
||||
{
|
||||
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
|
||||
{
|
||||
template.Id,
|
||||
device.SerialNumber,
|
||||
attachment.Id,
|
||||
Result
|
||||
});
|
||||
}
|
||||
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate template, Job job, JobAttachment attachment, string Result)
|
||||
{
|
||||
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
|
||||
{
|
||||
template.Id,
|
||||
job.Id,
|
||||
attachment.Id,
|
||||
Result
|
||||
});
|
||||
}
|
||||
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate template, User user, UserAttachment attachment, string Result)
|
||||
{
|
||||
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
|
||||
{
|
||||
template.Id,
|
||||
user.UserId,
|
||||
attachment.Id,
|
||||
Result
|
||||
});
|
||||
}
|
||||
public static void LogImportAttachmentExpressionEvaluated(DocumentTemplate Template, object Data, object Attachment, string Result)
|
||||
{
|
||||
if (Data is Job)
|
||||
LogImportAttachmentExpressionEvaluated(Template, (Job)Data, (JobAttachment)Attachment, Result);
|
||||
else if (Data is User)
|
||||
LogImportAttachmentExpressionEvaluated(Template, (User)Data, (UserAttachment)Attachment, Result);
|
||||
else if (Data is Device)
|
||||
LogImportAttachmentExpressionEvaluated(Template, (Device)Data, (DeviceAttachment)Attachment, Result);
|
||||
else
|
||||
DocumentsLog.Log(DocumentsLog.EventTypeIds.ImportAttachmentExpressionEvaluated, new object[]
|
||||
{
|
||||
Template.Id,
|
||||
Data.ToString(),
|
||||
Attachment.ToString(),
|
||||
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, object 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
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web.Caching;
|
||||
using Disco.Data.Repository;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Quartz.Impl.Triggers;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI.Importer
|
||||
{
|
||||
public class DocumentDropBoxMonitor : System.IDisposable
|
||||
{
|
||||
private IScheduler _scheduler;
|
||||
private FileSystemWatcher _fsw;
|
||||
private Cache _httpCache;
|
||||
|
||||
public const string WatcherFilter = "*.pdf";
|
||||
public string DropBoxLocation { get; private set; }
|
||||
|
||||
public DocumentDropBoxMonitor(DiscoDataContext Database, ISchedulerFactory SchedulerFactory, Cache HttpCache)
|
||||
{
|
||||
if (Database == null)
|
||||
throw new System.ArgumentNullException("Context");
|
||||
|
||||
this._httpCache = HttpCache;
|
||||
|
||||
var location = DataStore.CreateLocation(Database, "DocumentDropBox");
|
||||
this.DropBoxLocation = location.EndsWith(@"\") ? location : string.Concat(location, @"\");
|
||||
|
||||
this._scheduler = SchedulerFactory.GetScheduler();
|
||||
this._scheduler.Start();
|
||||
}
|
||||
public void ScheduleCurrentFiles(int Delay)
|
||||
{
|
||||
foreach (var filename in System.IO.Directory.GetFiles(this.DropBoxLocation, "*.pdf"))
|
||||
{
|
||||
this.ScheduleFile(filename, Delay);
|
||||
}
|
||||
}
|
||||
public void StartWatching()
|
||||
{
|
||||
if (this._fsw == null)
|
||||
{
|
||||
this._fsw = new FileSystemWatcher(this.DropBoxLocation, "*.pdf");
|
||||
this._fsw.Created += new FileSystemEventHandler(this.FSW_Created);
|
||||
}
|
||||
this._fsw.EnableRaisingEvents = true;
|
||||
}
|
||||
public void StopWatching()
|
||||
{
|
||||
if (this._fsw != null)
|
||||
{
|
||||
this._fsw.EnableRaisingEvents = false;
|
||||
}
|
||||
}
|
||||
public void ScheduleFile(string Filename, int Delay)
|
||||
{
|
||||
System.Guid guid = System.Guid.NewGuid();
|
||||
JobDetailImpl jd = new JobDetailImpl(guid.ToString(), typeof(DocumentImporterJob));
|
||||
jd.JobDataMap.Add("Filename", Filename);
|
||||
jd.JobDataMap.Add("RetryCount", 0);
|
||||
jd.JobDataMap.Add("HttpCache", this._httpCache);
|
||||
guid = System.Guid.NewGuid();
|
||||
|
||||
System.DateTimeOffset startTimeUtc = new System.DateTimeOffset(DateTime.Now.AddSeconds((double)Delay));
|
||||
SimpleTriggerImpl trig = new SimpleTriggerImpl(guid.ToString(), startTimeUtc);
|
||||
|
||||
this._scheduler.ScheduleJob(jd, trig);
|
||||
}
|
||||
private void FSW_Created(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if ((e.ChangeType & WatcherChangeTypes.Deleted) != WatcherChangeTypes.Deleted)
|
||||
this.ScheduleFile(e.FullPath, 5);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.StopWatching();
|
||||
if (this._fsw != null)
|
||||
this._fsw.Dispose();
|
||||
if (this._scheduler != null)
|
||||
this._scheduler.Shutdown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Logging;
|
||||
using Quartz;
|
||||
using Quartz.Impl;
|
||||
using Disco.Services.Tasks;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI.Importer
|
||||
{
|
||||
public class DocumentImporterCleanCacheJob : 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;
|
||||
|
||||
System.IO.DirectoryInfo dataStoreInfo = new System.IO.DirectoryInfo(dataStoreLocation);
|
||||
|
||||
System.DateTime today = System.DateTime.Today;
|
||||
|
||||
foreach (System.IO.FileInfo file in dataStoreInfo.GetFiles())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (file.CreationTime < today)
|
||||
{
|
||||
file.Delete();
|
||||
deleteCount++;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
SystemLog.LogInformation(
|
||||
string.Format("Cleared DocumentDropBox_SessionPages Cache, Deleted {0} File/s, with {1} Error/s", deleteCount, errorCount),
|
||||
deleteCount,
|
||||
errorCount
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Exceptionless;
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Disco.BI.DocumentTemplateBI.Importer
|
||||
{
|
||||
[PersistJobDataAfterExecution]
|
||||
public class DocumentImporterJob : IJob
|
||||
{
|
||||
|
||||
void IJob.Execute(IJobExecutionContext context)
|
||||
{
|
||||
string sessionId = context.JobDetail.JobDataMap["SessionId"] as string;
|
||||
if (string.IsNullOrEmpty(sessionId))
|
||||
{
|
||||
sessionId = Guid.NewGuid().ToString();
|
||||
context.JobDetail.JobDataMap["SessionId"] = sessionId;
|
||||
}
|
||||
|
||||
string filename = context.JobDetail.JobDataMap["Filename"] as string;
|
||||
int retryCount = (int)context.JobDetail.JobDataMap["RetryCount"];
|
||||
Cache httpCache = context.JobDetail.JobDataMap["HttpCache"] as Cache;
|
||||
|
||||
var friendlyFilename = filename;
|
||||
if (!string.IsNullOrEmpty(friendlyFilename))
|
||||
friendlyFilename = System.IO.Path.GetFileName(friendlyFilename);
|
||||
|
||||
DocumentsLog.LogImportStarting(sessionId, friendlyFilename);
|
||||
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
DocumentsLog.LogImportWarning(sessionId, string.Format("File not found: {0}", filename));
|
||||
DocumentsLog.LogImportFinished(sessionId);
|
||||
context.Scheduler.DeleteJob(context.JobDetail.Key);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
if (retryCount < 18)
|
||||
{
|
||||
context.JobDetail.JobDataMap["RetryCount"] = (++retryCount);
|
||||
bool processResult = Interop.Pdf.PdfImporter.ProcessPdfAttachment(filename, database, sessionId, httpCache);
|
||||
|
||||
if (processResult)
|
||||
{
|
||||
// Import Successful - Delete
|
||||
if (File.Exists(filename))
|
||||
File.Delete(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Import Failed - Move to Errors Folder
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
try
|
||||
{
|
||||
string folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
|
||||
string filenameError = Path.Combine(folderError, Path.GetFileName(filename));
|
||||
int filenameErrorCount = 0;
|
||||
while (File.Exists(filenameError))
|
||||
{
|
||||
filenameError = Path.Combine(folderError, string.Format("{0} ({1}){2}", Path.GetFileNameWithoutExtension(filename), ++filenameErrorCount, Path.GetExtension(filename)));
|
||||
}
|
||||
File.Move(filename, filenameError);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.ToExceptionless().Submit();
|
||||
// Ignore Errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// To Many Errors
|
||||
DocumentsLog.LogImportError(sessionId, string.Format("To many errors occurred trying to import '{1}' (SessionId: {0})", sessionId, friendlyFilename));
|
||||
// Move to Errors Folder
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
try
|
||||
{
|
||||
string folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
|
||||
string filenameError = Path.Combine(folderError, Path.GetFileName(filename));
|
||||
int filenameErrorCount = 0;
|
||||
while (File.Exists(filenameError))
|
||||
{
|
||||
filenameError = Path.Combine(folderError, string.Format("{0} ({1}){2}", Path.GetFileNameWithoutExtension(filename), ++filenameErrorCount, Path.GetExtension(filename)));
|
||||
}
|
||||
File.Move(filename, filenameError);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore Errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DocumentsLog.LogImportFinished(sessionId);
|
||||
|
||||
// All Done
|
||||
context.Scheduler.DeleteJob(context.JobDetail.Key);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.ToExceptionless().Submit();
|
||||
DocumentsLog.LogImportWarning(sessionId, string.Format("{0}; Will try again in 10 Seconds", ex.Message));
|
||||
// Reschedule Job for 10 seconds
|
||||
SimpleTriggerImpl trig = new SimpleTriggerImpl(Guid.NewGuid().ToString(), new DateTimeOffset(DateTime.Now.AddSeconds(10)));
|
||||
context.Scheduler.RescheduleJob(context.Trigger.Key, trig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Spring.Expressions.Parser.antlr;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class EvaluateExpressionParseException
|
||||
{
|
||||
public string Expression { get; set; }
|
||||
public int PositionRow { get; set; }
|
||||
public int PositionColumn { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
internal static EvaluateExpressionParseException FromRecognitionException(RecognitionException e, string Expression)
|
||||
{
|
||||
return new EvaluateExpressionParseException()
|
||||
{
|
||||
Expression = Expression,
|
||||
Message = e.Message,
|
||||
PositionRow = e.getLine(),
|
||||
PositionColumn = e.getColumn()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Spring.Expressions.Parser.antlr;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class EvaluateExpressionPart : IExpressionPart
|
||||
{
|
||||
private Spring.Expressions.IExpression _Expression;
|
||||
private RecognitionException _ExpressionParseException;
|
||||
private EvaluateExpressionParseException _EvaluateParseException;
|
||||
|
||||
public string RawSource { get; set; }
|
||||
public string Source { get; set; }
|
||||
public bool ErrorsAllowed { get; set; }
|
||||
public bool IsDynamic { get { return true; } set { return; } }
|
||||
|
||||
public EvaluateExpressionParseException ParseException
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_ExpressionParseException == null)
|
||||
return null;
|
||||
else
|
||||
if (_EvaluateParseException == null)
|
||||
_EvaluateParseException = EvaluateExpressionParseException.FromRecognitionException(_ExpressionParseException, this.Source);
|
||||
return _EvaluateParseException;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ParseError
|
||||
{
|
||||
get { return (_ExpressionParseException != null); }
|
||||
}
|
||||
public string ParseErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ParseError)
|
||||
return ParseException.Message;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public EvaluateExpressionPart(string Source)
|
||||
{
|
||||
this.RawSource = Source;
|
||||
|
||||
if (Source.StartsWith("{") && Source.EndsWith("}"))
|
||||
Source = Source.Substring(1, Source.Length - 2);
|
||||
|
||||
if (Source[0] == '~')
|
||||
{
|
||||
this.ErrorsAllowed = true;
|
||||
this.Source = Source.Substring(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ErrorsAllowed = false;
|
||||
this.Source = Source;
|
||||
}
|
||||
try
|
||||
{
|
||||
this._Expression = Spring.Expressions.Expression.Parse(this.Source);
|
||||
|
||||
}
|
||||
catch (RecognitionException ex)
|
||||
{
|
||||
this._ExpressionParseException = ex;
|
||||
}
|
||||
}
|
||||
object IExpressionPart.Evaluate(object ExpressionContext, System.Collections.IDictionary Variables)
|
||||
{
|
||||
if (this._ExpressionParseException == null)
|
||||
{
|
||||
return this._Expression.GetValue(ExpressionContext, Variables);
|
||||
}
|
||||
throw this._ExpressionParseException;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public sealed class Expression : System.Collections.Generic.List<IExpressionPart>
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public string Source { get; private set; }
|
||||
public bool IsDynamic { get; private set; }
|
||||
public int Ordinal { get; private set; }
|
||||
|
||||
private Expression(string Name, string Source, int Ordinal)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Source = Source;
|
||||
this.Ordinal = Ordinal;
|
||||
}
|
||||
|
||||
public static void InitializeExpressions()
|
||||
{
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("DataExt", typeof(Extensions.DataExt));
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("UserExt", typeof(Extensions.UserExt));
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("DeviceExt", typeof(Extensions.DeviceExt));
|
||||
Spring.Core.TypeResolution.TypeRegistry.RegisterType("ImageExt", typeof(Extensions.ImageExt));
|
||||
}
|
||||
|
||||
public T EvaluateFirst<T>(object ExpressionContext, System.Collections.IDictionary Variables)
|
||||
{
|
||||
T result = default(T);
|
||||
if (this.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
object expressionResult = this[0].Evaluate(ExpressionContext, Variables);
|
||||
if (expressionResult != null)
|
||||
{
|
||||
if (expressionResult is T)
|
||||
{
|
||||
result = (T)expressionResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Expression returned an invalid type");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Expression evaluation resulted in an error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Tuple<string, bool, object> Evaluate(object ExpressionContext, System.Collections.IDictionary Variables)
|
||||
{
|
||||
System.Text.StringBuilder resultValue = new System.Text.StringBuilder();
|
||||
object resultObject = null;
|
||||
bool resultError = false;
|
||||
foreach (var expressionPart in this)
|
||||
{
|
||||
try
|
||||
{
|
||||
object partValue = expressionPart.Evaluate(ExpressionContext, Variables);
|
||||
if (partValue != null)
|
||||
{
|
||||
// Check for Result Objects
|
||||
if (partValue is IImageExpressionResult)
|
||||
resultObject = partValue;
|
||||
else
|
||||
resultValue.Append(partValue.ToString());
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (!expressionPart.ErrorsAllowed)
|
||||
{
|
||||
resultValue.Append("## ERROR # ");
|
||||
resultValue.Append(ex.Message);
|
||||
resultValue.Append(" ##");
|
||||
resultError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Tuple<string, bool, object>(resultValue.ToString(), resultError, resultObject);
|
||||
}
|
||||
public static Expression TokenizeSingleDynamic(string Name, string ExpressionSource, int Ordinal)
|
||||
{
|
||||
Expression e = new Expression(Name, ExpressionSource, Ordinal);
|
||||
if (ExpressionSource != null && !string.IsNullOrWhiteSpace(ExpressionSource))
|
||||
e.Add(new EvaluateExpressionPart(ExpressionSource));
|
||||
e.IsDynamic = true;
|
||||
return e;
|
||||
}
|
||||
public static Expression Tokenize(string Name, string ExpressionSource, int Ordinal)
|
||||
{
|
||||
Expression e = new Expression(Name, ExpressionSource, Ordinal);
|
||||
if (!ExpressionSource.Contains("{") || !ExpressionSource.Contains("}"))
|
||||
{
|
||||
e.Add(new TextExpressionPart(ExpressionSource));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Text.StringBuilder token = new System.Text.StringBuilder();
|
||||
bool tokenEval = false;
|
||||
int tokenEvalDepth = 0;
|
||||
foreach (char c in ExpressionSource)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '{':
|
||||
{
|
||||
if (!tokenEval)
|
||||
{
|
||||
if (token.Length > 0)
|
||||
{
|
||||
e.Add(new TextExpressionPart(token.ToString()));
|
||||
token = new System.Text.StringBuilder();
|
||||
}
|
||||
tokenEval = true;
|
||||
tokenEvalDepth = 0;
|
||||
}
|
||||
tokenEvalDepth++;
|
||||
token.Append(c);
|
||||
break;
|
||||
}
|
||||
case '}':
|
||||
{
|
||||
token.Append(c);
|
||||
if (tokenEval)
|
||||
{
|
||||
tokenEvalDepth--;
|
||||
if (tokenEvalDepth <= 0)
|
||||
{
|
||||
if (token.Length != 2 && (token.Length != 3 || token[1] != '@'))
|
||||
{
|
||||
e.Add(new EvaluateExpressionPart(token.ToString()));
|
||||
e.IsDynamic = true;
|
||||
token = new System.Text.StringBuilder();
|
||||
}
|
||||
tokenEval = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
token.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (token.Length > 0)
|
||||
{
|
||||
e.Add(new TextExpressionPart(token.ToString()));
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public static IDictionary StandardVariables(DocumentTemplate AttachmentType, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState DocumentState)
|
||||
{
|
||||
return new Hashtable
|
||||
{
|
||||
|
||||
{
|
||||
"DataContext",
|
||||
Database
|
||||
},
|
||||
|
||||
{
|
||||
"User",
|
||||
User
|
||||
},
|
||||
|
||||
{
|
||||
"TimeStamp",
|
||||
TimeStamp
|
||||
},
|
||||
|
||||
{
|
||||
"AttachmentType",
|
||||
AttachmentType
|
||||
},
|
||||
|
||||
{
|
||||
"State",
|
||||
DocumentState
|
||||
}
|
||||
};
|
||||
}
|
||||
public static Dictionary<string, string> StandardVariableTypes()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
|
||||
{
|
||||
"#DataContext",
|
||||
typeof(DiscoDataContext).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#User",
|
||||
typeof(User).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#TimeStamp",
|
||||
typeof(System.DateTime).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#AttachmentType",
|
||||
typeof(DocumentTemplate).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"#State",
|
||||
typeof(DocumentState).AssemblyQualifiedName
|
||||
}
|
||||
};
|
||||
}
|
||||
public static Dictionary<string, string> ExtensionLibraryTypes()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
{
|
||||
"DataExt",
|
||||
typeof(Extensions.DataExt).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"DeviceExt",
|
||||
typeof(Extensions.DeviceExt).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"ImageExt",
|
||||
typeof(Extensions.ImageExt).AssemblyQualifiedName
|
||||
},
|
||||
|
||||
{
|
||||
"UserExt",
|
||||
typeof(Extensions.UserExt).AssemblyQualifiedName
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public static class ExpressionCache
|
||||
{
|
||||
private static ConcurrentDictionary<string, ConcurrentDictionary<string, Expression>> _Cache = new ConcurrentDictionary<string, ConcurrentDictionary<string, Expression>>();
|
||||
|
||||
public delegate Expression CreateValueDelegate();
|
||||
|
||||
public static ConcurrentDictionary<string, Expression> GetModule(string Module, bool Create = false)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache;
|
||||
if (_Cache.TryGetValue(Module, out moduleCache))
|
||||
return moduleCache;
|
||||
else
|
||||
{
|
||||
if (Create)
|
||||
{
|
||||
moduleCache = new ConcurrentDictionary<string, Expression>();
|
||||
_Cache.TryAdd(Module, moduleCache);
|
||||
return moduleCache;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static Expression GetModuleValue(string Module, string Key, CreateValueDelegate CreateValue)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache = GetModule(Module, (CreateValue != null));
|
||||
if (moduleCache != null)
|
||||
{
|
||||
Expression expression;
|
||||
if (moduleCache.TryGetValue(Key, out expression))
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
if (CreateValue != null)
|
||||
{
|
||||
expression = CreateValue();
|
||||
Expression oldExpression;
|
||||
if (moduleCache.TryGetValue(Key, out oldExpression))
|
||||
moduleCache.TryUpdate(Key, expression, oldExpression);
|
||||
else
|
||||
moduleCache.TryAdd(Key, expression);
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Expression GetValue(string Module, string Key, CreateValueDelegate CreateValue)
|
||||
{
|
||||
return GetModuleValue(Module, Key, CreateValue);
|
||||
}
|
||||
|
||||
public static Expression GetValue(string Module, string Key)
|
||||
{
|
||||
return GetModuleValue(Module, Key, null);
|
||||
}
|
||||
|
||||
public static bool InvalidModule(string Module)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache;
|
||||
return _Cache.TryRemove(Module, out moduleCache);
|
||||
}
|
||||
|
||||
public static bool InvalidateKey(string Module, string Key)
|
||||
{
|
||||
Expression expression;
|
||||
ConcurrentDictionary<string, Expression> moduleCache = GetModule(Module, false);
|
||||
if (moduleCache != null)
|
||||
{
|
||||
bool removeResult = moduleCache.TryRemove(Key, out expression);
|
||||
if (moduleCache.Count == 0)
|
||||
InvalidModule(Module);
|
||||
return removeResult;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetValue(string Module, string Key, Expression Expression)
|
||||
{
|
||||
ConcurrentDictionary<string, Expression> moduleCache = GetModule(Module, true);
|
||||
|
||||
if (moduleCache.ContainsKey(Key))
|
||||
{
|
||||
Expression oldExpression;
|
||||
if (moduleCache.TryGetValue(Key, out oldExpression))
|
||||
{
|
||||
return moduleCache.TryUpdate(Key, Expression, oldExpression);
|
||||
}
|
||||
}
|
||||
return moduleCache.TryAdd(Key, Expression);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class ExpressionCachePreloadTask : ScheduledTask
|
||||
{
|
||||
|
||||
public override string TaskName { get { return "Expression Cache - Preload 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)
|
||||
{
|
||||
// Run in Background 5 Second after Scheduled (on App Startup)
|
||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(new DateTimeOffset(DateTime.Now).AddSeconds(5));
|
||||
|
||||
this.ScheduleTask(triggerBuilder);
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
// Cache Document Template Filter Expressions
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
foreach (var documentTemplate in database.DocumentTemplates.Where(dt => dt.FilterExpression != null && dt.FilterExpression != string.Empty))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(documentTemplate.FilterExpression))
|
||||
documentTemplate.FilterExpressionFromCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class ExpressionTypeDescriptor
|
||||
{
|
||||
public string ExpressionType { get; set; }
|
||||
public string Name { get; set; }
|
||||
public List<ExpressionTypeMemberDescriptor> Members { get; set; }
|
||||
|
||||
public static ExpressionTypeDescriptor Build(System.Type t, bool StaticDeclaredMembersOnly = true)
|
||||
{
|
||||
ExpressionTypeDescriptor i = new ExpressionTypeDescriptor
|
||||
{
|
||||
ExpressionType = t.AssemblyQualifiedName,
|
||||
Name = t.Name
|
||||
};
|
||||
i.Members = new System.Collections.Generic.List<ExpressionTypeMemberDescriptor>();
|
||||
|
||||
System.Reflection.MemberInfo[] members;
|
||||
if (StaticDeclaredMembersOnly)
|
||||
members = t.GetMembers(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
|
||||
else
|
||||
members = t.GetMembers(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
for (int j = 0; j < members.Length; j++)
|
||||
{
|
||||
System.Reflection.MemberInfo member = members[j];
|
||||
if (member is System.Reflection.PropertyInfo)
|
||||
{
|
||||
System.Reflection.PropertyInfo pi = (System.Reflection.PropertyInfo)member;
|
||||
if (!pi.IsSpecialName && pi.CanRead)
|
||||
{
|
||||
i.Members.Add(ExpressionTypeMemberDescriptor.Build(pi));
|
||||
}
|
||||
}
|
||||
if (member is System.Reflection.MethodInfo)
|
||||
{
|
||||
System.Reflection.MethodInfo mi2 = (System.Reflection.MethodInfo)member;
|
||||
if (!mi2.IsSpecialName)
|
||||
{
|
||||
i.Members.Add(ExpressionTypeMemberDescriptor.Build(mi2));
|
||||
}
|
||||
}
|
||||
}
|
||||
i.Members = (
|
||||
from mi in i.Members
|
||||
orderby mi.Name
|
||||
select mi).ToList();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class ExpressionTypeMemberDescriptor
|
||||
{
|
||||
public const string FunctionKind = "function";
|
||||
public const string PropertyKind = "property";
|
||||
public const string ParameterKind = "parameter";
|
||||
|
||||
public string Kind {get;set;}
|
||||
public string Name {get;set;}
|
||||
public string ReturnType {get;set;}
|
||||
public string ReturnExpressionType{get;set;}
|
||||
public List<ExpressionTypeMemberDescriptor> Parameters{get;set;}
|
||||
|
||||
public static ExpressionTypeMemberDescriptor Build(System.Reflection.MethodInfo m)
|
||||
{
|
||||
ExpressionTypeMemberDescriptor md = new ExpressionTypeMemberDescriptor
|
||||
{
|
||||
Kind = "function",
|
||||
Name = m.Name,
|
||||
ReturnType = m.ReturnType.Name,
|
||||
ReturnExpressionType = m.ReturnType.AssemblyQualifiedName
|
||||
};
|
||||
md.Parameters = (
|
||||
from mdp in m.GetParameters()
|
||||
select ExpressionTypeMemberDescriptor.Build(mdp)).ToList<ExpressionTypeMemberDescriptor>();
|
||||
return md;
|
||||
}
|
||||
public static ExpressionTypeMemberDescriptor Build(System.Reflection.PropertyInfo p)
|
||||
{
|
||||
ExpressionTypeMemberDescriptor md = new ExpressionTypeMemberDescriptor
|
||||
{
|
||||
Kind = "property",
|
||||
Name = p.Name,
|
||||
ReturnType = p.PropertyType.Name,
|
||||
ReturnExpressionType = p.PropertyType.AssemblyQualifiedName
|
||||
};
|
||||
md.Parameters = (
|
||||
from mdp in p.GetIndexParameters()
|
||||
select ExpressionTypeMemberDescriptor.Build(mdp)).ToList<ExpressionTypeMemberDescriptor>();
|
||||
return md;
|
||||
}
|
||||
public static ExpressionTypeMemberDescriptor Build(System.Reflection.ParameterInfo pi)
|
||||
{
|
||||
return new ExpressionTypeMemberDescriptor
|
||||
{
|
||||
Kind = "parameter",
|
||||
Name = pi.Name,
|
||||
ReturnType = pi.ParameterType.Name,
|
||||
ReturnExpressionType = pi.ParameterType.AssemblyQualifiedName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Collections;
|
||||
using System.Data.Odbc;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions
|
||||
{
|
||||
public static class DataExt
|
||||
{
|
||||
#region SqlClient
|
||||
|
||||
private static SqlConnection BuildSqlConnection(string Server, string Database, string Username, string Password)
|
||||
{
|
||||
SqlConnectionStringBuilder dbConnectionStringBuilder = new SqlConnectionStringBuilder();
|
||||
dbConnectionStringBuilder.ApplicationName = "Disco";
|
||||
dbConnectionStringBuilder.DataSource = Server;
|
||||
dbConnectionStringBuilder.InitialCatalog = Database;
|
||||
dbConnectionStringBuilder.MultipleActiveResultSets = true;
|
||||
dbConnectionStringBuilder.PersistSecurityInfo = true;
|
||||
if (Username == null || Password == null)
|
||||
dbConnectionStringBuilder.IntegratedSecurity = true;
|
||||
else
|
||||
{
|
||||
dbConnectionStringBuilder.UserID = Username;
|
||||
dbConnectionStringBuilder.Password = Password;
|
||||
}
|
||||
|
||||
return new SqlConnection(dbConnectionStringBuilder.ConnectionString);
|
||||
}
|
||||
private static void BuildSqlParameters(SqlCommand dbCommand, Hashtable SqlParameters)
|
||||
{
|
||||
if (SqlParameters != null)
|
||||
{
|
||||
foreach (var sqlParameterKey in SqlParameters.Keys)
|
||||
{
|
||||
string key = sqlParameterKey.ToString();
|
||||
if (!key.StartsWith("@"))
|
||||
key = string.Concat("@", key);
|
||||
dbCommand.Parameters.AddWithValue(key, SqlParameters[sqlParameterKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static DataTable QuerySqlDatabase(string Server, string Database, string Username, string Password, string SqlQuery, Hashtable SqlParameters)
|
||||
{
|
||||
using (SqlConnection dbConnection = BuildSqlConnection(Server, Database, Username, Password))
|
||||
{
|
||||
using (SqlCommand dbCommand = new SqlCommand(SqlQuery, dbConnection))
|
||||
{
|
||||
BuildSqlParameters(dbCommand, SqlParameters);
|
||||
using (SqlDataAdapter dbAdapter = new SqlDataAdapter(dbCommand))
|
||||
{
|
||||
var dbTable = new DataTable();
|
||||
dbAdapter.Fill(dbTable);
|
||||
return dbTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static DataTable QuerySqlDatabase(string Server, string Database, string SqlQuery, Hashtable SqlParameters)
|
||||
{
|
||||
return QuerySqlDatabase(Server, Database, null, null, SqlQuery, SqlParameters);
|
||||
}
|
||||
public static DataTable QuerySqlDatabase(string Server, string Database, string SqlQuery)
|
||||
{
|
||||
return QuerySqlDatabase(Server, Database, null, null, SqlQuery, null);
|
||||
}
|
||||
|
||||
public static object QuerySqlDatabaseScalar(string Server, string Database, string Username, string Password, string SqlQuery, Hashtable SqlParameters)
|
||||
{
|
||||
using (SqlConnection dbConnection = BuildSqlConnection(Server, Database, Username, Password))
|
||||
{
|
||||
using (SqlCommand dbCommand = new SqlCommand(SqlQuery, dbConnection))
|
||||
{
|
||||
BuildSqlParameters(dbCommand, SqlParameters);
|
||||
try
|
||||
{
|
||||
dbConnection.Open();
|
||||
return dbCommand.ExecuteScalar();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
dbConnection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static object QuerySqlDatabaseScalar(string Server, string Database, string SqlQuery, Hashtable SqlParameters)
|
||||
{
|
||||
return QuerySqlDatabaseScalar(Server, Database, null, null, SqlQuery, SqlParameters);
|
||||
}
|
||||
public static object QuerySqlDatabaseScalar(string Server, string Database, string SqlQuery)
|
||||
{
|
||||
return QuerySqlDatabaseScalar(Server, Database, null, null, SqlQuery, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ODBC
|
||||
|
||||
private static OdbcConnection BuildOdbcConnection(string ConnectionString)
|
||||
{
|
||||
return new OdbcConnection(ConnectionString);
|
||||
}
|
||||
private static void BuildOdbcParameters(OdbcCommand dbCommand, Hashtable OdbcParameters)
|
||||
{
|
||||
if (OdbcParameters != null)
|
||||
{
|
||||
foreach (var odbcParameterKey in OdbcParameters.Keys)
|
||||
{
|
||||
string key = odbcParameterKey.ToString();
|
||||
dbCommand.Parameters.AddWithValue(key, OdbcParameters[odbcParameterKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static DataTable QueryOdbcDatabase(string ConnectionString, string OdbcQuery, Hashtable OdbcParameters)
|
||||
{
|
||||
using (OdbcConnection dbConnection = BuildOdbcConnection(ConnectionString))
|
||||
{
|
||||
using (OdbcCommand dbCommand = new OdbcCommand(OdbcQuery, dbConnection))
|
||||
{
|
||||
BuildOdbcParameters(dbCommand, OdbcParameters);
|
||||
using (OdbcDataAdapter dbAdapter = new OdbcDataAdapter(dbCommand))
|
||||
{
|
||||
var dbTable = new DataTable();
|
||||
dbAdapter.Fill(dbTable);
|
||||
return dbTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static DataTable QueryOdbcDatabase(string ConnectionString, string OdbcQuery)
|
||||
{
|
||||
return QueryOdbcDatabase(ConnectionString, OdbcQuery, null);
|
||||
}
|
||||
|
||||
public static object QueryOdbcDatabaseScalar(string ConnectionString, string OdbcQuery, Hashtable OdbcParameters)
|
||||
{
|
||||
using (OdbcConnection dbConnection = BuildOdbcConnection(ConnectionString))
|
||||
{
|
||||
using (OdbcCommand dbCommand = new OdbcCommand(OdbcQuery, dbConnection))
|
||||
{
|
||||
BuildOdbcParameters(dbCommand, OdbcParameters);
|
||||
try
|
||||
{
|
||||
dbConnection.Open();
|
||||
return dbCommand.ExecuteScalar();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
dbConnection.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static object QueryOdbcDatabaseScalar(string ConnectionString, string OdbcQuery)
|
||||
{
|
||||
return QueryOdbcDatabaseScalar(ConnectionString, OdbcQuery, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions
|
||||
{
|
||||
public static class DeviceExt
|
||||
{
|
||||
public static object GetActiveDirectoryObjectValue(Device Device, string PropertyName, int Index = 0)
|
||||
{
|
||||
var adMachineAccount = Device.ActiveDirectoryAccount(PropertyName);
|
||||
if (adMachineAccount != null)
|
||||
return adMachineAccount.GetPropertyValues<object>(PropertyName).Skip(Index).FirstOrDefault();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetActiveDirectoryStringValue(Device Device, string PropertyName, int Index = 0)
|
||||
{
|
||||
var objectValue = GetActiveDirectoryObjectValue(Device, PropertyName, Index);
|
||||
string stringValue = objectValue as string;
|
||||
if (stringValue == null && objectValue != null)
|
||||
stringValue = objectValue.ToString();
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
public static int GetActiveDirectoryIntegerValue(Device Device, string PropertyName, int Index = 0)
|
||||
{
|
||||
var objectValue = GetActiveDirectoryObjectValue(Device, PropertyName, Index);
|
||||
if (objectValue == null)
|
||||
return default(int);
|
||||
else
|
||||
{
|
||||
int intValue;
|
||||
try
|
||||
{
|
||||
intValue = (int)Convert.ChangeType(objectValue, typeof(int));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using Disco.BI.Expressions.Extensions.ImageResultImplementations;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions
|
||||
{
|
||||
public static class ImageExt
|
||||
{
|
||||
public static FileImageExpressionResult ImageFromFile(string AbsoluteFilePath)
|
||||
{
|
||||
return new FileImageExpressionResult(AbsoluteFilePath);
|
||||
}
|
||||
public static FileImageExpressionResult ImageFromDataStoreFile(string RelativeFilePath)
|
||||
{
|
||||
var configCache = new Disco.Data.Configuration.SystemConfiguration(null);
|
||||
string DataStoreLocation = configCache.DataStoreLocation;
|
||||
string AbsoluteFilePath = System.IO.Path.Combine(DataStoreLocation, RelativeFilePath);
|
||||
return new FileImageExpressionResult(AbsoluteFilePath);
|
||||
}
|
||||
public static FileImageExpressionResult JobAttachmentFirstImage(Job Job, DiscoDataContext Database)
|
||||
{
|
||||
var attachment = Job.JobAttachments.FirstOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase));
|
||||
if (attachment != null)
|
||||
{
|
||||
var filename = attachment.RepositoryFilename(Database);
|
||||
return new FileImageExpressionResult(filename);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public static FileImageExpressionResult JobAttachmentLastImage(Job Job, DiscoDataContext Database)
|
||||
{
|
||||
var attachment = Job.JobAttachments.LastOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase));
|
||||
if (attachment != null)
|
||||
{
|
||||
var filename = attachment.RepositoryFilename(Database);
|
||||
return new FileImageExpressionResult(filename);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public static FileImageExpressionResult JobAttachmentImage(JobAttachment JobAttachment, DiscoDataContext Database)
|
||||
{
|
||||
if (JobAttachment == null)
|
||||
throw new ArgumentNullException("JobAttachment");
|
||||
if (!JobAttachment.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
|
||||
throw new ArgumentException("Invalid Image MimeType for Attachment");
|
||||
|
||||
var filename = JobAttachment.RepositoryFilename(Database);
|
||||
return new FileImageExpressionResult(filename);
|
||||
}
|
||||
public static FileMontageImageExpressionResult JobAttachmentImageMontage(Job Job, DiscoDataContext Database)
|
||||
{
|
||||
if (Job == null)
|
||||
throw new ArgumentNullException("Job");
|
||||
if (Job.JobAttachments == null)
|
||||
throw new ArgumentException("Job.JobAttachments is null", "Job");
|
||||
|
||||
var attachments = Job.JobAttachments.Where(a => a.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
if (attachments.Count > 0)
|
||||
{
|
||||
var attachmentFilepaths = attachments.Select(a => a.RepositoryFilename(Database)).ToList();
|
||||
|
||||
return new FileMontageImageExpressionResult(attachmentFilepaths);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public static FileMontageImageExpressionResult JobAttachmentsImageMontage(ArrayList JobAttachments, DiscoDataContext Database)
|
||||
{
|
||||
if (JobAttachments == null)
|
||||
throw new ArgumentNullException("JobAttachments");
|
||||
|
||||
var attachments = JobAttachments.Cast<JobAttachment>().Where(a => a.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
if (attachments.Count > 0)
|
||||
{
|
||||
var attachmentFilepaths = attachments.Select(a => a.RepositoryFilename(Database)).ToList();
|
||||
|
||||
return new FileMontageImageExpressionResult(attachmentFilepaths);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BitmapImageExpressionResult ImageFromStream(Stream ImageStream)
|
||||
{
|
||||
if (ImageStream == null)
|
||||
throw new ArgumentNullException("ImageStream");
|
||||
|
||||
return new BitmapImageExpressionResult(Bitmap.FromStream(ImageStream));
|
||||
}
|
||||
public static BitmapImageExpressionResult ImageFromByteArray(byte[] ImageByteArray)
|
||||
{
|
||||
if (ImageByteArray == null)
|
||||
throw new ArgumentNullException("ImageByteArray");
|
||||
|
||||
return new BitmapImageExpressionResult(Bitmap.FromStream(new MemoryStream(ImageByteArray)));
|
||||
}
|
||||
public static BitmapImageExpressionResult DeviceModelImage(DeviceModel DeviceModel)
|
||||
{
|
||||
if (DeviceModel == null)
|
||||
throw new ArgumentNullException("DeviceModel");
|
||||
|
||||
using (Stream deviceModelImage = DeviceModel.Image())
|
||||
{
|
||||
if (deviceModelImage == null)
|
||||
return null;
|
||||
else
|
||||
return ImageFromStream(deviceModelImage);
|
||||
}
|
||||
//if (DeviceModel.Image == null || DeviceModel.Image.Length == 0)
|
||||
// return null;
|
||||
|
||||
//return ImageFromByteArray(DeviceModel.Image);
|
||||
}
|
||||
public static BitmapImageExpressionResult OrganisationLogo()
|
||||
{
|
||||
var configCache = new Disco.Data.Configuration.SystemConfiguration(null);
|
||||
BitmapImageExpressionResult result;
|
||||
using (var orgLogo = configCache.OrganisationLogo)
|
||||
{
|
||||
result = ImageFromStream(orgLogo);
|
||||
}
|
||||
result.LosslessFormat = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public abstract class BaseImageExpressionResult : IImageExpressionResult
|
||||
{
|
||||
public byte Quality { get; set; }
|
||||
public bool LosslessFormat { get; set; }
|
||||
public bool ShowField { get; set; }
|
||||
public string BackgroundColour { get; set; }
|
||||
public bool BackgroundPreferTransparent { get; set; }
|
||||
|
||||
public BaseImageExpressionResult()
|
||||
{
|
||||
this.LosslessFormat = false;
|
||||
this.Quality = 90;
|
||||
this.ShowField = false;
|
||||
this.BackgroundPreferTransparent = true;
|
||||
}
|
||||
|
||||
public abstract Stream GetImage(int Width, int Height);
|
||||
|
||||
protected Stream RenderImage(Image SourceImage, int Width, int Height)
|
||||
{
|
||||
if (SourceImage == null)
|
||||
throw new ArgumentNullException("SourceImage");
|
||||
if (Width <= 0)
|
||||
throw new ArgumentOutOfRangeException("Width", "Width must be > 0");
|
||||
if (Height <= 0)
|
||||
throw new ArgumentOutOfRangeException("Height", "Height must be > 0");
|
||||
|
||||
Brush backgroundBrush = null;
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = Brushes.White;
|
||||
else
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
}
|
||||
|
||||
using (Image resizedImage = SourceImage.ResizeImage(Width, Height, backgroundBrush))
|
||||
{
|
||||
return OutputImage(resizedImage);
|
||||
}
|
||||
}
|
||||
|
||||
protected Stream OutputImage(Image SourceImage)
|
||||
{
|
||||
MemoryStream imageStream = new MemoryStream();
|
||||
if (LosslessFormat)
|
||||
{ // Lossless Format - PNG
|
||||
SourceImage.SavePng(imageStream);
|
||||
}
|
||||
else
|
||||
{ // Lossy Format - JPG
|
||||
byte quality = Math.Min((byte)100, Math.Max((byte)1, this.Quality));
|
||||
SourceImage.SaveJpg(quality, imageStream);
|
||||
}
|
||||
imageStream.Position = 0;
|
||||
return imageStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class BitmapImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public Image Image { get; set; }
|
||||
|
||||
public BitmapImageExpressionResult(Image Image)
|
||||
{
|
||||
if (Image == null)
|
||||
throw new ArgumentNullException("Image");
|
||||
|
||||
this.Image = Image;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
return this.RenderImage(this.Image, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public string AbsoluteFilePath { get; set; }
|
||||
|
||||
public FileImageExpressionResult(string AbsoluteFilePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AbsoluteFilePath))
|
||||
throw new ArgumentNullException("AbsoluteFilePath");
|
||||
if (!File.Exists(AbsoluteFilePath))
|
||||
throw new FileNotFoundException("Image not found", AbsoluteFilePath);
|
||||
|
||||
this.AbsoluteFilePath = AbsoluteFilePath;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
using (Image SourceImage = Bitmap.FromFile(this.AbsoluteFilePath))
|
||||
{
|
||||
return this.RenderImage(SourceImage, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-181
@@ -1,181 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using Disco.BI.Extensions;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions.ImageResultImplementations
|
||||
{
|
||||
public class FileMontageImageExpressionResult : BaseImageExpressionResult
|
||||
{
|
||||
public List<string> AbsoluteFilePaths { get; set; }
|
||||
public bool MontageHorizontalLayout { get; set; }
|
||||
public bool MontageVerticalLayout { get; set; }
|
||||
public bool MontageTableLayout { get; set; }
|
||||
public int Padding { get; set; }
|
||||
|
||||
public FileMontageImageExpressionResult(List<string> AbsoluteFilePaths)
|
||||
{
|
||||
if (AbsoluteFilePaths == null)
|
||||
throw new ArgumentNullException("AbsoluteFilePaths");
|
||||
if (AbsoluteFilePaths.Count == 0)
|
||||
throw new ArgumentException("AbsoluteFilePaths is empty", "AbsoluteFilePaths");
|
||||
|
||||
this.AbsoluteFilePaths = AbsoluteFilePaths;
|
||||
this.MontageTableLayout = true;
|
||||
this.Padding = 4;
|
||||
}
|
||||
|
||||
public override Stream GetImage(int Width, int Height)
|
||||
{
|
||||
List<Image> Images = new List<Image>();
|
||||
try
|
||||
{
|
||||
// Load Images
|
||||
foreach (string imageFilePath in this.AbsoluteFilePaths)
|
||||
Images.Add(Bitmap.FromFile(imageFilePath));
|
||||
|
||||
// Build Montage
|
||||
using (Bitmap montageImage = new Bitmap(Width, Height))
|
||||
{
|
||||
using (Graphics montageGraphics = Graphics.FromImage(montageImage))
|
||||
{
|
||||
montageGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
montageGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
montageGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
// Draw Background
|
||||
if (!LosslessFormat || !BackgroundPreferTransparent)
|
||||
{
|
||||
Brush backgroundBrush = Brushes.White;
|
||||
if (!string.IsNullOrEmpty(this.BackgroundColour))
|
||||
backgroundBrush = new SolidBrush(ColorTranslator.FromHtml(this.BackgroundColour));
|
||||
montageGraphics.FillRectangle(backgroundBrush, montageGraphics.VisibleClipBounds);
|
||||
}
|
||||
|
||||
if (this.MontageHorizontalLayout)
|
||||
DoHorizontalLayout(Images, montageGraphics);
|
||||
else
|
||||
if (this.MontageVerticalLayout)
|
||||
DoVirticalLayout(Images, montageGraphics);
|
||||
else
|
||||
DoTableLayout(Images, montageGraphics);
|
||||
}
|
||||
|
||||
return this.OutputImage(montageImage);
|
||||
}
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
finally
|
||||
{
|
||||
// Dispose of any Images
|
||||
if (Images != null)
|
||||
foreach (Image i in Images)
|
||||
i.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void DoHorizontalLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
|
||||
float imageScale;
|
||||
float imagePosition = 0;
|
||||
int imagesWidthTotal = Images.Sum(i => i.Width);
|
||||
int imagesHeightMax = Images.Max(i => i.Height);
|
||||
int imagesPadding = ((Images.Count - 1) * this.Padding);
|
||||
|
||||
imageScale = (float)(MontageGraphics.VisibleClipBounds.Width - imagesPadding) / (float)imagesWidthTotal;
|
||||
if ((MontageGraphics.VisibleClipBounds.Height / (float)imagesHeightMax) < imageScale)
|
||||
imageScale = (float)MontageGraphics.VisibleClipBounds.Height / (float)imagesHeightMax;
|
||||
foreach (Image image in Images)
|
||||
{
|
||||
MontageGraphics.DrawImageResized(image, imageScale, imagePosition, 0);
|
||||
imagePosition += (imageScale * image.Width) + this.Padding;
|
||||
}
|
||||
}
|
||||
private void DoVirticalLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
float imageScale;
|
||||
float imagePosition = 0;
|
||||
int imagesWidthMax = Images.Max(i => i.Width);
|
||||
int imagesHeightTotal = Images.Sum(i => i.Height);
|
||||
int imagesPadding = ((Images.Count - 1) * this.Padding);
|
||||
|
||||
imageScale = (float)(MontageGraphics.VisibleClipBounds.Height - imagesPadding) / (float)imagesHeightTotal;
|
||||
if ((MontageGraphics.VisibleClipBounds.Width / (float)imagesWidthMax) < imageScale)
|
||||
imageScale = (float)MontageGraphics.VisibleClipBounds.Width / (float)imagesWidthMax;
|
||||
foreach (Image image in Images)
|
||||
{
|
||||
MontageGraphics.DrawImageResized(image, imageScale, 0, imagePosition);
|
||||
imagePosition += (imageScale * image.Height) + this.Padding;
|
||||
}
|
||||
}
|
||||
private void DoTableLayout(List<Image> Images, Graphics MontageGraphics)
|
||||
{
|
||||
var stageSize = MontageGraphics.VisibleClipBounds.Size.ToSize();
|
||||
var itemAverageSize = new SizeF(Images.Average(i => (float)i.Size.Width), Images.Average(i => (float)i.Size.Height));
|
||||
|
||||
var calculatedLayout = CalculateColumnCount(stageSize, itemAverageSize, Images.Count);
|
||||
|
||||
SizeF cellSize = new SizeF((MontageGraphics.VisibleClipBounds.Width - ((calculatedLayout.Item1 - 1) * this.Padding)) / calculatedLayout.Item1,
|
||||
(MontageGraphics.VisibleClipBounds.Height - ((calculatedLayout.Item2 - 1) * this.Padding)) / calculatedLayout.Item2);
|
||||
|
||||
int imageIndex = 0;
|
||||
for (int rowIndex = 0; rowIndex < calculatedLayout.Item2; rowIndex++)
|
||||
{
|
||||
for (int columnIndex = 0; columnIndex < calculatedLayout.Item1; columnIndex++)
|
||||
{
|
||||
if (imageIndex < Images.Count)
|
||||
{
|
||||
var image = Images[imageIndex];
|
||||
var cellPoint = new PointF((cellSize.Width * columnIndex) + (this.Padding * columnIndex), (cellSize.Height * rowIndex) + (this.Padding * rowIndex));
|
||||
MontageGraphics.Clip = new Region(new RectangleF(cellPoint, cellSize));
|
||||
MontageGraphics.DrawImageResized(image);
|
||||
imageIndex++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Tuple<int, int, double> CalculateColumnCount(Size StageSize, SizeF ItemAverageSize, int ItemCount)
|
||||
{
|
||||
double? bestUsedSpace = null;
|
||||
int bestColumnCount = 1;
|
||||
int bestRowCount = 1;
|
||||
double bestItemRatio = 1;
|
||||
|
||||
for (int columnCount = 1; columnCount <= ItemCount; columnCount++)
|
||||
{
|
||||
int rowCount = (int)Math.Ceiling((double)ItemCount / (double)columnCount);
|
||||
|
||||
int requiredWidthPadding = (columnCount - 1) * this.Padding;
|
||||
int requiredHeightPadding = (rowCount - 1) * this.Padding;
|
||||
Size usableStageSize = new Size(StageSize.Width - requiredWidthPadding, StageSize.Height - requiredHeightPadding);
|
||||
double stageWidthRatio = (float)usableStageSize.Width / (float)usableStageSize.Height;
|
||||
double stageHeightRatio = (float)usableStageSize.Height / (float)usableStageSize.Width;
|
||||
|
||||
int requiredWidth = (int)Math.Ceiling(ItemAverageSize.Width * columnCount);
|
||||
int requiredHeight = (int)Math.Ceiling(ItemAverageSize.Height * rowCount);
|
||||
|
||||
int usedSpace = requiredWidth * requiredHeight;
|
||||
int stageArea = Math.Max((requiredWidth * (int)Math.Ceiling(requiredWidth * stageHeightRatio)),
|
||||
(requiredHeight * (int)Math.Ceiling(requiredHeight * stageWidthRatio)));
|
||||
double usedStageSpace = (double)usedSpace / stageArea;
|
||||
if (bestUsedSpace == null || bestUsedSpace < usedStageSpace)
|
||||
{
|
||||
bestUsedSpace = usedStageSpace;
|
||||
bestColumnCount = columnCount;
|
||||
bestRowCount = rowCount;
|
||||
bestItemRatio = Math.Min((double)usableStageSize.Width / (double)requiredWidth, (double)usableStageSize.Height / (double)requiredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return new Tuple<int, int, double>(bestColumnCount, bestRowCount, bestItemRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Expressions.Extensions
|
||||
{
|
||||
public static class UserExt
|
||||
{
|
||||
#region Active Directory Extensions
|
||||
public static object GetActiveDirectoryObjectValue(User User, string PropertyName, int Index = 0)
|
||||
{
|
||||
var adUserAccount = User.ActiveDirectoryAccount(PropertyName);
|
||||
if (adUserAccount != null)
|
||||
return adUserAccount.GetPropertyValues<object>(PropertyName).Skip(Index).FirstOrDefault();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetActiveDirectoryStringValue(User User, string PropertyName, int Index = 0)
|
||||
{
|
||||
var objectValue = GetActiveDirectoryObjectValue(User, PropertyName, Index);
|
||||
string stringValue = objectValue as string;
|
||||
if (stringValue == null && objectValue != null)
|
||||
stringValue = objectValue.ToString();
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
public static int GetActiveDirectoryIntegerValue(User User, string PropertyName, int Index = 0)
|
||||
{
|
||||
var objectValue = GetActiveDirectoryObjectValue(User, PropertyName, Index);
|
||||
if (objectValue == null)
|
||||
return default(int);
|
||||
else
|
||||
{
|
||||
int intValue;
|
||||
try
|
||||
{
|
||||
intValue = (int)Convert.ChangeType(objectValue, typeof(int));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Authorization Testing Extensions
|
||||
public static bool HasAuthorization(User User, string Claim)
|
||||
{
|
||||
var authorization = UserService.GetAuthorization(User.UserId);
|
||||
|
||||
return authorization.Has(Claim);
|
||||
}
|
||||
|
||||
public static bool HasAuthorizationAll(User User, params string[] Claims)
|
||||
{
|
||||
var authorization = UserService.GetAuthorization(User.UserId);
|
||||
|
||||
return authorization.HasAll(Claims);
|
||||
}
|
||||
|
||||
public static bool HasAuthorizationAny(User User, params string[] Claims)
|
||||
{
|
||||
var authorization = UserService.GetAuthorization(User.UserId);
|
||||
|
||||
return authorization.HasAny(Claims);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public interface IExpressionPart
|
||||
{
|
||||
string RawSource { get; set; }
|
||||
string Source { get; set; }
|
||||
bool ErrorsAllowed { get; set; }
|
||||
bool ParseError { get; }
|
||||
string ParseErrorMessage { get; }
|
||||
bool IsDynamic { get; set; }
|
||||
object Evaluate(object ExpressionContext, System.Collections.IDictionary Variables);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Disco.BI.Expressions
|
||||
{
|
||||
public class TextExpressionPart : IExpressionPart
|
||||
{
|
||||
private string _Source;
|
||||
|
||||
bool IExpressionPart.ErrorsAllowed
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
string IExpressionPart.Source
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._Source;
|
||||
}
|
||||
set
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
string IExpressionPart.RawSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._Source;
|
||||
}
|
||||
set
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
bool IExpressionPart.IsDynamic
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
public bool ParseError
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public string ParseErrorMessage
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public TextExpressionPart(string Source)
|
||||
{
|
||||
this._Source = Source;
|
||||
}
|
||||
object IExpressionPart.Evaluate(object ExpressionContext, System.Collections.IDictionary Variables)
|
||||
{
|
||||
return this._Source;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Disco.Data.Repository;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
using Disco.Services;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Logging;
|
||||
using Disco.Services.Users;
|
||||
using Exceptionless;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class AttachmentExtensions
|
||||
{
|
||||
|
||||
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier UniqueIdentifier, DiscoDataContext Database, System.IO.Stream PdfContent, byte[] PdfThumbnail)
|
||||
{
|
||||
UniqueIdentifier.LoadComponents(Database);
|
||||
DocumentTemplate documentTemplate = UniqueIdentifier.DocumentTemplate;
|
||||
string filename;
|
||||
string comments;
|
||||
object attachment;
|
||||
|
||||
if (documentTemplate == null)
|
||||
{
|
||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId.Replace('\\', '_'), UniqueIdentifier.TimeStamp);
|
||||
comments = string.Format("Uploaded: {0:s}", UniqueIdentifier.TimeStamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.TemplateTypeId, UniqueIdentifier.TimeStamp);
|
||||
comments = string.Format("Generated: {0:s}", UniqueIdentifier.TimeStamp);
|
||||
}
|
||||
|
||||
User creatorUser = UserService.GetUser(UniqueIdentifier.CreatorId, Database);
|
||||
if (creatorUser == null)
|
||||
{
|
||||
// No Creator User (or Username invalid)
|
||||
creatorUser = UserService.CurrentUser;
|
||||
}
|
||||
switch (UniqueIdentifier.DataScope)
|
||||
{
|
||||
case DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
Device d = (Device)UniqueIdentifier.Data;
|
||||
attachment = d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
Job j = (Job)UniqueIdentifier.Data;
|
||||
attachment = j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
User u = (User)UniqueIdentifier.Data;
|
||||
attachment = u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (documentTemplate != null && !string.IsNullOrWhiteSpace(documentTemplate.OnImportAttachmentExpression))
|
||||
{
|
||||
try
|
||||
{
|
||||
var expressionResult = documentTemplate.EvaluateOnAttachmentImportExpression(attachment, Database, creatorUser, UniqueIdentifier.TimeStamp);
|
||||
DocumentsLog.LogImportAttachmentExpressionEvaluated(documentTemplate, UniqueIdentifier.Data, attachment, expressionResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogException("Document Importer - OnImportAttachmentExpression", ex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string RepositoryFilename(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_file", da.DeviceSerialNumber, da.Id));
|
||||
}
|
||||
public static string RepositoryFilename(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_file", ja.JobId, ja.Id));
|
||||
}
|
||||
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||
}
|
||||
|
||||
private static string RepositoryThumbnailFilenameInternal(string DirectoryPath, string Filename)
|
||||
{
|
||||
return Path.Combine(DirectoryPath, Filename);
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_thumb.jpg", da.DeviceSerialNumber, da.Id));
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_thumb.jpg", ja.JobId, ja.Id));
|
||||
}
|
||||
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId.Replace('\\', '_'), ua.Id));
|
||||
}
|
||||
|
||||
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(da.RepositoryFilename(Database), da.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
public static void RepositoryDelete(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(ja.RepositoryFilename(Database), ja.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
public static void RepositoryDelete(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
RepositoryDelete(ua.RepositoryFilename(Database), ua.RepositoryThumbnailFilename(Database));
|
||||
}
|
||||
private static void RepositoryDelete(params string[] filePaths)
|
||||
{
|
||||
foreach (string filePath in filePaths)
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SaveAttachment(this DeviceAttachment da, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = da.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveAttachment(this JobAttachment ja, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = ja.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveAttachment(this UserAttachment ua, DiscoDataContext Database, Stream FileContent)
|
||||
{
|
||||
string filePath = ua.RepositoryFilename(Database);
|
||||
SaveAttachment(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this DeviceAttachment da, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this JobAttachment ja, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
public static string SaveThumbnailAttachment(this UserAttachment ua, DiscoDataContext Database, byte[] FileContent)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
File.WriteAllBytes(filePath, FileContent);
|
||||
return filePath;
|
||||
}
|
||||
private static void SaveAttachment(string FilePath, Stream FileContent)
|
||||
{
|
||||
using (FileStream sw = new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
FileContent.CopyTo(sw);
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(da.RepositoryFilename(Database), da.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(ja.RepositoryFilename(Database), ja.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(ua.RepositoryFilename(Database), ua.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = da.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, da.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = ja.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ja.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database, Stream SourceFile)
|
||||
{
|
||||
string filePath = ua.RepositoryThumbnailFilename(Database);
|
||||
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ua.MimeType, filePath);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
using System.Linq;
|
||||
using Disco.Data.Configuration;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using Exceptionless;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
@@ -21,15 +22,15 @@ namespace Disco.BI.Extensions
|
||||
if (Domain == null)
|
||||
throw new ArgumentNullException("Domain");
|
||||
|
||||
DeviceProfile deviceProfile = device.DeviceProfile;
|
||||
Expressions.Expression computerNameTemplateExpression = null;
|
||||
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||
var deviceProfile = device.DeviceProfile;
|
||||
Expression computerNameTemplateExpression = null;
|
||||
computerNameTemplateExpression = ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
|
||||
{
|
||||
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
|
||||
//return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.Configuration(context).ComputerNameTemplate, 0);
|
||||
return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.ComputerNameTemplate, 0);
|
||||
return Expression.TokenizeSingleDynamic(null, deviceProfile.ComputerNameTemplate, 0);
|
||||
});
|
||||
System.Collections.IDictionary evaluatorVariables = Expressions.Expression.StandardVariables(null, Database, UserService.CurrentUser, System.DateTime.Now, null);
|
||||
var evaluatorVariables = Expression.StandardVariables(null, Database, UserService.CurrentUser, DateTime.Now, null);
|
||||
string rendered;
|
||||
try
|
||||
{
|
||||
@@ -42,53 +43,22 @@ namespace Disco.BI.Extensions
|
||||
}
|
||||
if (rendered == null || rendered.Length > 24)
|
||||
{
|
||||
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||
throw new InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
|
||||
}
|
||||
|
||||
return string.Format(@"{0}\{1}", Domain.NetBiosName, rendered);
|
||||
}
|
||||
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
List<DocumentTemplate> ats = Database.DocumentTemplates
|
||||
.Where(at => at.Scope == Disco.Models.Repository.DocumentTemplate.DocumentTemplateScopes.Device).ToList();
|
||||
.Where(at => at.Scope == DocumentTemplate.DocumentTemplateScopes.Device).ToList();
|
||||
|
||||
return ats.Where(at => at.FilterExpressionMatches(d, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
|
||||
}
|
||||
|
||||
public static bool UpdateLastNetworkLogonDate(this Device Device)
|
||||
{
|
||||
return Disco.Services.Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
|
||||
}
|
||||
|
||||
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
DeviceAttachment da = new DeviceAttachment()
|
||||
{
|
||||
DeviceSerialNumber = Device.SerialNumber,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
da.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.DeviceAttachments.Add(da);
|
||||
Database.SaveChanges();
|
||||
|
||||
da.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
da.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
da.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return da;
|
||||
return ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
|
||||
}
|
||||
|
||||
public static Device AddOffline(this Device d, DiscoDataContext Database)
|
||||
@@ -189,15 +159,7 @@ namespace Disco.BI.Extensions
|
||||
return newDua;
|
||||
}
|
||||
|
||||
public static ADMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
|
||||
{
|
||||
if (ActiveDirectory.IsValidDomainAccountId(Device.DeviceDomainId))
|
||||
return ActiveDirectory.RetrieveADMachineAccount(Device.DeviceDomainId, AdditionalProperties: AdditionalProperties);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons r)
|
||||
public static string ReasonMessage(this DecommissionReasons r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
@@ -220,7 +182,7 @@ namespace Disco.BI.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons? r)
|
||||
public static string ReasonMessage(this DecommissionReasons? r)
|
||||
{
|
||||
if (!r.HasValue)
|
||||
return "Not Decommissioned";
|
||||
|
||||
@@ -1,79 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Users;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DeviceModelExtensions
|
||||
{
|
||||
public static bool ImageImport(this DeviceModel deviceModel, Stream ImageStream)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Bitmap inputBitmap = new Bitmap(ImageStream))
|
||||
{
|
||||
using (Image outputBitmap = inputBitmap.ResizeImage(256, 256))
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
outputBitmap.SavePng(ms);
|
||||
ms.Position = 0;
|
||||
|
||||
var deviceModelImagePath = deviceModel.ImageFilePath();
|
||||
|
||||
|
||||
using (var storeStream = new FileStream(deviceModelImagePath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
ms.CopyTo(storeStream);
|
||||
}
|
||||
//deviceModel.Image = ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static FileStream Image(this DeviceModel deviceModel)
|
||||
{
|
||||
var deviceModelImagePath = deviceModel.ImageFilePath();
|
||||
|
||||
if (File.Exists(deviceModelImagePath))
|
||||
return new FileStream(deviceModelImagePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string ImageFilePath(this DeviceModel deviceModel)
|
||||
{
|
||||
var configCache = new Disco.Data.Configuration.SystemConfiguration(null);
|
||||
|
||||
var deviceModelImagesDataStore = DataStore.CreateLocation(configCache, "DeviceModelImages");
|
||||
|
||||
return Path.Combine(deviceModelImagesDataStore, string.Format("{0}.png", deviceModel.Id));
|
||||
}
|
||||
|
||||
public static string ImageHash(this DeviceModel deviceModel)
|
||||
{
|
||||
var deviceModelImagePath = deviceModel.ImageFilePath();
|
||||
|
||||
if (File.Exists(deviceModelImagePath))
|
||||
return File.GetLastWriteTimeUtc(deviceModelImagePath).ToBinary().ToString();
|
||||
else
|
||||
return "-1";
|
||||
}
|
||||
|
||||
#region Actions
|
||||
public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Disco.Models.BI.Config;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Devices.ManagedGroups;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
@@ -16,7 +17,7 @@ namespace Disco.BI.Extensions
|
||||
|
||||
public static void ComputerNameInvalidateCache(this DeviceProfile deviceProfile)
|
||||
{
|
||||
Expressions.ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
|
||||
ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
|
||||
}
|
||||
|
||||
public static OrganisationAddress DefaultOrganisationAddressDetails(this DeviceProfile deviceProfile, DiscoDataContext Database)
|
||||
|
||||
@@ -1,48 +1,27 @@
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using Disco.BI.DocumentTemplateBI.ManagedGroups;
|
||||
using Disco.BI.Expressions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Documents;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using iTextSharp.text.pdf;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class DocumentTemplateExtensions
|
||||
{
|
||||
private const string DocumentTemplateExpressionCacheTemplate = "DocumentTemplate_{0}";
|
||||
|
||||
public static string RepositoryFilename(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return System.IO.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(DocumentTemplateExpressionCacheTemplate, dt.Id));
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static DisposableImageCollection PdfPageImages(this PdfReader pdfReader, int PageNumber)
|
||||
{
|
||||
return Interop.Pdf.PdfImporter.GetPageImages(pdfReader, PageNumber);
|
||||
}
|
||||
internal const string CacheTemplate = "DocumentTemplate_{0}";
|
||||
|
||||
public static ConcurrentDictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
string cacheModuleKey = string.Format(DocumentTemplateExpressionCacheTemplate, dt.Id);
|
||||
var module = Expressions.ExpressionCache.GetModule(cacheModuleKey);
|
||||
string cacheModuleKey = string.Format(CacheTemplate, dt.Id);
|
||||
var module = ExpressionCache.GetModule(cacheModuleKey);
|
||||
if (module == null)
|
||||
{
|
||||
// Cache
|
||||
@@ -52,199 +31,46 @@ namespace Disco.BI.Extensions
|
||||
foreach (string pdfFieldKey in pdfReader.AcroFields.Fields.Keys)
|
||||
{
|
||||
var pdfFieldValue = pdfReader.AcroFields.GetField(pdfFieldKey);
|
||||
Expressions.ExpressionCache.SetValue(cacheModuleKey, pdfFieldKey, Expressions.Expression.Tokenize(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal));
|
||||
ExpressionCache.SetValue(cacheModuleKey, pdfFieldKey, Expression.Tokenize(pdfFieldKey, pdfFieldValue, pdfFieldOrdinal));
|
||||
pdfFieldOrdinal++;
|
||||
}
|
||||
pdfReader.Close();
|
||||
module = Expressions.ExpressionCache.GetModule(cacheModuleKey, true);
|
||||
module = ExpressionCache.GetModule(cacheModuleKey, true);
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
public static List<BI.Expressions.Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
public static List<Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return dt.PdfExpressionsFromCache(Database).Values.OrderBy(e => e.Ordinal).ToList();
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
|
||||
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params string[] DataObjectsIds)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjectsIds);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
|
||||
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params IAttachmentTarget[] DataObjects)
|
||||
{
|
||||
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
}
|
||||
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
{
|
||||
bool generateExpression = !string.IsNullOrEmpty(dt.OnGenerateExpression);
|
||||
string generateExpressionResult = null;
|
||||
|
||||
if (generateExpression)
|
||||
generateExpressionResult = dt.EvaluateOnGenerateExpression(Data, Database, CreatorUser, TimeStamp, State);
|
||||
generateExpressionResult = dt.EvaluateOnGenerateExpression(Target, Database, CreatorUser, TimeStamp, State);
|
||||
|
||||
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Data, CreatorUser, TimeStamp, State, FlattenFields);
|
||||
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Target, CreatorUser, TimeStamp, State, FlattenFields);
|
||||
|
||||
if (generateExpression)
|
||||
DocumentsLog.LogDocumentGenerated(dt, Data, CreatorUser, generateExpressionResult);
|
||||
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser, generateExpressionResult);
|
||||
else
|
||||
DocumentsLog.LogDocumentGenerated(dt, Data, CreatorUser);
|
||||
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser);
|
||||
|
||||
return pdfStream;
|
||||
}
|
||||
|
||||
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, System.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, System.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;
|
||||
}
|
||||
|
||||
public static string GetDataId(this DocumentTemplate dt, object Data)
|
||||
{
|
||||
if (Data is string)
|
||||
{
|
||||
return (string)Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dt.Scope)
|
||||
{
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.Device:
|
||||
if (!(Data is Device))
|
||||
throw new ArgumentException("This Document Template is configured for Devices only", "Data");
|
||||
Device d = (Device)Data;
|
||||
return d.SerialNumber;
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.Job:
|
||||
if (!(Data is Job))
|
||||
throw new ArgumentException("This Document Template is configured for Jobs only", "Data");
|
||||
Job d2 = (Job)Data;
|
||||
return d2.Id.ToString();
|
||||
case Models.Repository.DocumentTemplate.DocumentTemplateScopes.User:
|
||||
if (!(Data is User))
|
||||
throw new ArgumentException("This Document Template is configured for Users only", "Data");
|
||||
User d3 = (User)Data;
|
||||
return d3.UserId;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid Document Template Scope");
|
||||
}
|
||||
}
|
||||
}
|
||||
public static string UniqueIdentifier(string DocumentTemplateId, string DataId, string CreatorId, System.DateTime Timestamp)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}",
|
||||
DocumentTemplateId,
|
||||
DataId,
|
||||
CreatorId,
|
||||
Timestamp
|
||||
);
|
||||
}
|
||||
public static string UniqueIdentifier(this DocumentTemplate dt, object Data, string CreatorId, System.DateTime Timestamp)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}",
|
||||
dt.Id,
|
||||
dt.GetDataId(System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Data)),
|
||||
CreatorId,
|
||||
Timestamp
|
||||
);
|
||||
}
|
||||
public static string UniquePageIdentifier(this DocumentTemplate dt, object Data, string CreatorId, System.DateTime Timestamp, int Page)
|
||||
{
|
||||
return string.Format("Disco|1|{0}|{1}|{2}|{3:s}|{4}",
|
||||
dt.Id,
|
||||
dt.GetDataId(System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Data)),
|
||||
CreatorId,
|
||||
Timestamp,
|
||||
Page
|
||||
);
|
||||
}
|
||||
public static List<RectangleF> QRCodeLocations(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
return DocumentTemplateBI.DocumentTemplateQRCodeLocationCache.GetLocations(dt, Database);
|
||||
}
|
||||
|
||||
public static void Delete(this DocumentTemplate dt, DiscoDataContext Database)
|
||||
{
|
||||
// Find & Rename all references
|
||||
|
||||
@@ -13,6 +13,7 @@ using Disco.Services.Plugins.Features.RepairProvider;
|
||||
|
||||
using PublishJobResult = Disco.Models.Services.Interop.DiscoServices.PublishJobResult;
|
||||
using DiscoServicesJobs = Disco.Services.Interop.DiscoServices.Jobs;
|
||||
using Disco.Services;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
@@ -176,7 +177,7 @@ namespace Disco.BI.Extensions
|
||||
null,
|
||||
FaultDescription,
|
||||
SendAttachments,
|
||||
Disco.BI.Extensions.AttachmentExtensions.RepositoryFilename);
|
||||
AttachmentDataStoreExtensions.RepositoryFilename);
|
||||
|
||||
if (!publishJobResult.Success)
|
||||
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
|
||||
@@ -398,7 +399,7 @@ namespace Disco.BI.Extensions
|
||||
null,
|
||||
RepairDescription,
|
||||
SendAttachments,
|
||||
Disco.BI.Extensions.AttachmentExtensions.RepositoryFilename);
|
||||
AttachmentDataStoreExtensions.RepositoryFilename);
|
||||
|
||||
if (!publishJobResult.Success)
|
||||
throw new Exception(string.Format("Disco ICT Online Services failed with the following message: ", publishJobResult.ErrorMessage));
|
||||
|
||||
@@ -1,50 +1,18 @@
|
||||
using System;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Plugins;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Services.Plugins;
|
||||
using Disco.Models.BI.Job;
|
||||
using Disco.Services.Authorization;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class JobExtensions
|
||||
{
|
||||
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
JobAttachment ja = new JobAttachment()
|
||||
{
|
||||
JobId = Job.Id,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
ja.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.JobAttachments.Add(ja);
|
||||
Database.SaveChanges();
|
||||
|
||||
ja.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
ja.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
ja.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return ja;
|
||||
}
|
||||
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
|
||||
@@ -1,48 +1,15 @@
|
||||
using System;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Data.Repository;
|
||||
using System.IO;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
|
||||
namespace Disco.BI.Extensions
|
||||
{
|
||||
public static class UserExtensions
|
||||
{
|
||||
public static UserAttachment CreateAttachment(this User User, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
|
||||
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
|
||||
|
||||
UserAttachment ua = new UserAttachment()
|
||||
{
|
||||
UserId = User.UserId,
|
||||
TechUserId = CreatorUser.UserId,
|
||||
Filename = Filename,
|
||||
MimeType = MimeType,
|
||||
Timestamp = DateTime.Now,
|
||||
Comments = Comments
|
||||
};
|
||||
|
||||
if (DocumentTemplate != null)
|
||||
ua.DocumentTemplateId = DocumentTemplate.Id;
|
||||
|
||||
Database.UserAttachments.Add(ua);
|
||||
Database.SaveChanges();
|
||||
|
||||
ua.SaveAttachment(Database, Content);
|
||||
Content.Position = 0;
|
||||
if (PdfThumbnail == null)
|
||||
ua.GenerateThumbnail(Database, Content);
|
||||
else
|
||||
ua.SaveThumbnailAttachment(Database, PdfThumbnail);
|
||||
|
||||
return ua;
|
||||
}
|
||||
|
||||
public static List<DocumentTemplate> AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp)
|
||||
{
|
||||
var dts = Database.DocumentTemplates.Include("JobSubTypes")
|
||||
@@ -57,10 +24,6 @@ namespace Disco.BI.Extensions
|
||||
{
|
||||
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
|
||||
}
|
||||
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
|
||||
{
|
||||
return ActiveDirectory.RetrieveADUserAccount(User.UserId, AdditionalProperties);
|
||||
}
|
||||
|
||||
public static bool CanCreateJob(this User u)
|
||||
{
|
||||
|
||||
@@ -22,240 +22,6 @@ namespace Disco.BI.Extensions
|
||||
return sr.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
#region Image Extensions
|
||||
|
||||
public static Bitmap RotateImage(this Image Source, float Angle, Brush BackgroundColor = null, bool ResizeIfOver45Deg = true)
|
||||
{
|
||||
int destWidth = Source.Width;
|
||||
int destHeight = Source.Height;
|
||||
bool resizedDest = false;
|
||||
|
||||
if (ResizeIfOver45Deg && ((Angle > 45 && Angle < 135) || (Angle < -45 && Angle > -135)))
|
||||
{
|
||||
destWidth = Source.Height;
|
||||
destHeight = Source.Width;
|
||||
resizedDest = true;
|
||||
}
|
||||
|
||||
Bitmap destination = new Bitmap(destWidth, destHeight);
|
||||
destination.SetResolution(Source.HorizontalResolution, Source.VerticalResolution);
|
||||
|
||||
using (Graphics destinationGraphics = Graphics.FromImage(destination))
|
||||
{
|
||||
destinationGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
destinationGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
destinationGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
if (BackgroundColor != null)
|
||||
destinationGraphics.FillRectangle(BackgroundColor, destinationGraphics.VisibleClipBounds);
|
||||
|
||||
float offsetWidth = destWidth / 2;
|
||||
float offsetHeight = destHeight / 2;
|
||||
|
||||
destinationGraphics.TranslateTransform(offsetWidth, offsetHeight);
|
||||
destinationGraphics.RotateTransform(Angle);
|
||||
|
||||
RectangleF destinationLocation;
|
||||
|
||||
if (resizedDest)
|
||||
destinationLocation = new RectangleF(
|
||||
offsetHeight * -1, offsetWidth * -1,
|
||||
destHeight, destWidth);
|
||||
else
|
||||
destinationLocation = new RectangleF(
|
||||
offsetWidth * -1, offsetHeight * -1,
|
||||
destWidth, destHeight);
|
||||
|
||||
destinationGraphics.DrawImage(Source, destinationLocation, new RectangleF(0, 0, Source.Width, Source.Height), GraphicsUnit.Pixel);
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static Bitmap ResizeImage(this Image Source, int Width, int Height, Brush BackgroundColor = null)
|
||||
{
|
||||
Bitmap destination = new Bitmap(Width, Height);
|
||||
destination.SetResolution(72, 72);
|
||||
using (Graphics destinationGraphics = Graphics.FromImage(destination))
|
||||
{
|
||||
destinationGraphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
destinationGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
destinationGraphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
|
||||
if (BackgroundColor != null)
|
||||
destinationGraphics.FillRectangle(BackgroundColor, destinationGraphics.VisibleClipBounds);
|
||||
|
||||
float ratio = Math.Min((float)(destination.Width) / (float)(Source.Width), (float)(destination.Height) / (float)(Source.Height));
|
||||
|
||||
destinationGraphics.DrawImageResized(Source, ratio);
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
public static void DrawImageResized(this Graphics graphics, Image SourceImage, float? Scale = null, float LocationX = -1, float LocationY = -1)
|
||||
{
|
||||
RectangleF clipBounds = graphics.VisibleClipBounds;
|
||||
if (Scale == null) // Calculate Scale
|
||||
Scale = Math.Min(clipBounds.Width / SourceImage.Width, clipBounds.Height / SourceImage.Height);
|
||||
float newWidth = SourceImage.Width * Scale.Value;
|
||||
float newHeight = SourceImage.Height * Scale.Value;
|
||||
float newLeft = LocationX;
|
||||
float newTop = LocationY;
|
||||
|
||||
if (newLeft < 0 || newTop < 0)
|
||||
{
|
||||
if (newWidth < clipBounds.Width)
|
||||
newLeft = (clipBounds.Width - newWidth) / 2;
|
||||
else
|
||||
newLeft = 0;
|
||||
if (newHeight < clipBounds.Height)
|
||||
newTop = (clipBounds.Height - newHeight) / 2;
|
||||
else
|
||||
newTop = 0;
|
||||
}
|
||||
newLeft += clipBounds.Left;
|
||||
newTop += clipBounds.Top;
|
||||
|
||||
graphics.DrawImage(SourceImage, new RectangleF(newLeft, newTop, newWidth, newHeight), new RectangleF(0, 0, SourceImage.Width, SourceImage.Height), GraphicsUnit.Pixel);
|
||||
}
|
||||
public static void EmbedIconOverlay(this Image Source, Image Icon)
|
||||
{
|
||||
int top = Math.Max(0, Source.Height - Icon.Height);
|
||||
int left = Math.Max(0, Source.Width - Icon.Width);
|
||||
|
||||
using (Graphics sourceGraphics = Graphics.FromImage(Source))
|
||||
{
|
||||
sourceGraphics.DrawImage(Icon, left, top);
|
||||
}
|
||||
}
|
||||
public static void SavePng(this Image Source, string Filename)
|
||||
{
|
||||
using (FileStream outStream = new FileStream(Filename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
SavePng(Source, outStream);
|
||||
outStream.Flush();
|
||||
outStream.Close();
|
||||
}
|
||||
}
|
||||
public static void SavePng(this Image Source, Stream OutStream)
|
||||
{
|
||||
Source.Save(OutStream, ImageFormat.Png);
|
||||
}
|
||||
public static Stream SavePng(this Image Source)
|
||||
{
|
||||
MemoryStream outStream = new MemoryStream();
|
||||
Source.SavePng(outStream);
|
||||
outStream.Position = 0;
|
||||
return outStream;
|
||||
}
|
||||
public static Stream SaveJpg(this Image Source, int Quality)
|
||||
{
|
||||
MemoryStream outStream = new MemoryStream();
|
||||
Source.SaveJpg(Quality, outStream);
|
||||
outStream.Position = 0;
|
||||
return outStream;
|
||||
}
|
||||
public static void SaveJpg(this Image Source, int Quality, string Filename)
|
||||
{
|
||||
using (FileStream outStream = new FileStream(Filename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
SaveJpg(Source, Quality, outStream);
|
||||
outStream.Flush();
|
||||
outStream.Close();
|
||||
}
|
||||
}
|
||||
public static void SaveJpg(this Image Source, int Quality, Stream OutStream)
|
||||
{
|
||||
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
|
||||
if (jpgCodec != null)
|
||||
{
|
||||
if (Quality < 0 || Quality > 100)
|
||||
throw new ArgumentOutOfRangeException("Quality", "Quality must be a positive integer <= 100");
|
||||
using (EncoderParameters ep = new EncoderParameters(1))
|
||||
{
|
||||
ep.Param[0] = new EncoderParameter(Encoder.Quality, Quality);
|
||||
Source.Save(OutStream, jpgCodec, ep);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback
|
||||
Source.Save(OutStream, ImageFormat.Jpeg);
|
||||
}
|
||||
}
|
||||
public static ImageMontage BuildImageMontage(this IEnumerable<Image> Images, int MaxHeight = -1, int MaxWidth = -1, bool EnforceDimensions = false)
|
||||
{
|
||||
if (EnforceDimensions && (MaxHeight < 0 || MaxWidth < 0))
|
||||
throw new ArgumentOutOfRangeException("EnforceDimensions", "Dimensions can only be enforced when a MaxHeight and MaxWidth is supplied");
|
||||
|
||||
Dictionary<Image, int> imageLocations = new Dictionary<Image, int>();
|
||||
double imageScale = 1.0;
|
||||
int totalHeight = Images.Max(i => i.Height);
|
||||
int totalWidth = Images.Sum(i => i.Width);
|
||||
if (MaxHeight > 0 && totalHeight > MaxHeight)
|
||||
{
|
||||
imageScale = (double)MaxHeight / (double)totalHeight;
|
||||
}
|
||||
if (MaxWidth > 0 && totalWidth > MaxWidth)
|
||||
{
|
||||
imageScale = System.Math.Min(imageScale, (double)MaxWidth / (double)totalWidth);
|
||||
}
|
||||
int scaledHeight = EnforceDimensions ? MaxHeight : (int)System.Math.Round((double)totalHeight * imageScale);
|
||||
int scaledWidth = EnforceDimensions ? MaxWidth : (int)System.Math.Round((double)totalWidth * imageScale);
|
||||
System.Drawing.Bitmap imageResult = new System.Drawing.Bitmap(scaledWidth, scaledHeight);
|
||||
imageResult.SetResolution(72f, 72f);
|
||||
|
||||
using (Graphics g = Graphics.FromImage(imageResult))
|
||||
{
|
||||
g.FillRectangle(Brushes.White, new Rectangle(Point.Empty, imageResult.Size));
|
||||
|
||||
int imageResultNextOffset = 0;
|
||||
foreach (Image i in Images)
|
||||
{
|
||||
Rectangle imagePosition = new Rectangle(imageResultNextOffset, 0, (int)System.Math.Round((double)i.Width * imageScale), (int)System.Math.Round((double)i.Height * imageScale));
|
||||
System.Drawing.Rectangle imageSize = new System.Drawing.Rectangle(0, 0, i.Width, i.Height);
|
||||
g.DrawImage(i, imagePosition, imageSize, System.Drawing.GraphicsUnit.Pixel);
|
||||
imageLocations[i] = imageResultNextOffset;
|
||||
imageResultNextOffset += imagePosition.Width;
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageMontage() { Montage = imageResult, MontageScale = imageScale, MontageSourceImageOffsets = imageLocations };
|
||||
}
|
||||
public class ImageMontage : IDisposable
|
||||
{
|
||||
|
||||
public Image Montage { get; set; }
|
||||
public double MontageScale { get; set; }
|
||||
public Dictionary<Image, int> MontageSourceImageOffsets { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Montage != null)
|
||||
{
|
||||
Montage.Dispose();
|
||||
Montage = null;
|
||||
}
|
||||
if (MontageSourceImageOffsets != null)
|
||||
{
|
||||
MontageSourceImageOffsets.Clear();
|
||||
MontageSourceImageOffsets = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Color InterpolateColours(this Color Start, Color End, double Progress)
|
||||
{
|
||||
if (Progress > 1 || Progress < 0)
|
||||
throw new ArgumentOutOfRangeException("Progress", "Progress must be >= 0 && <= 1");
|
||||
|
||||
return Color.FromArgb(
|
||||
(byte)(Start.A * (1 - Progress) + (End.A * Progress)),
|
||||
(byte)(Start.R * (1 - Progress) + (End.R * Progress)),
|
||||
(byte)(Start.G * (1 - Progress) + (End.G * Progress)),
|
||||
(byte)(Start.B * (1 - Progress) + (End.B * Progress))
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Disco.BI.Interop
|
||||
{
|
||||
public static class MimeTypes
|
||||
{
|
||||
public static string ResolveMimeType(string Filename)
|
||||
{
|
||||
string fileExtension;
|
||||
if (Filename.Contains("."))
|
||||
fileExtension = Filename.Substring(Filename.LastIndexOf(".") + 1).ToLower();
|
||||
else
|
||||
fileExtension = Filename.ToLower();
|
||||
|
||||
// Try Known Mime Types
|
||||
switch (fileExtension)
|
||||
{
|
||||
case "pdf":
|
||||
return "application/pdf";
|
||||
case "doc":
|
||||
return "application/msword";
|
||||
case "docx":
|
||||
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
case "docm":
|
||||
return "application/vnd.ms-word.document.macroEnabled.12";
|
||||
case "xml":
|
||||
return "text/xml";
|
||||
case "xls":
|
||||
return "application/vnd.ms-excel";
|
||||
case "xlsx":
|
||||
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
case "xlsm":
|
||||
return "application/vnd.ms-excel.sheet.macroEnabled.12";
|
||||
case "csv":
|
||||
return "application/vnd.ms-excel";
|
||||
case "jpg":
|
||||
return "image/jpeg";
|
||||
case "gif":
|
||||
return "image/gif";
|
||||
case "png":
|
||||
return "image/png";
|
||||
case "bmp":
|
||||
return "image/bmp";
|
||||
case "avi":
|
||||
return "video/avi";
|
||||
case "mpeg":
|
||||
case "mpg":
|
||||
return "video/mpeg";
|
||||
case "mp3":
|
||||
return "audio/mpeg";
|
||||
case "mp4":
|
||||
return "video/mp4";
|
||||
case "wmv":
|
||||
return "video/x-ms-wmv";
|
||||
case "mov":
|
||||
return "video/quicktime";
|
||||
}
|
||||
|
||||
// Check System Registry
|
||||
try
|
||||
{
|
||||
RegistryKey regExtensionKey = Registry.ClassesRoot.OpenSubKey("." + fileExtension);
|
||||
if (regExtensionKey != null)
|
||||
{
|
||||
string regExtensionContentType = regExtensionKey.GetValue("Content Type") as string;
|
||||
if (regExtensionContentType != null)
|
||||
{
|
||||
return regExtensionContentType;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore Errors
|
||||
}
|
||||
|
||||
// Return Default
|
||||
return "unknown/unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using Disco.BI.Expressions;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.BI.DocumentTemplates;
|
||||
using Disco.Models.BI.Expressions;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Models.Services.Documents;
|
||||
using Disco.Services;
|
||||
using Disco.Services.Expressions;
|
||||
using Disco.Services.Interop.ActiveDirectory;
|
||||
using Disco.Services.Users;
|
||||
using iTextSharp.text.pdf;
|
||||
@@ -19,14 +20,14 @@ namespace Disco.BI.Interop.Pdf
|
||||
public static class PdfGenerator
|
||||
{
|
||||
|
||||
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params IAttachmentTarget[] DataObjects)
|
||||
{
|
||||
if (DataObjects.Length > 0)
|
||||
{
|
||||
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Length);
|
||||
using (Models.BI.DocumentTemplates.DocumentState state = Models.BI.DocumentTemplates.DocumentState.DefaultState())
|
||||
using (var state = DocumentState.DefaultState())
|
||||
{
|
||||
foreach (object d in DataObjects)
|
||||
foreach (var d in DataObjects)
|
||||
{
|
||||
generatedPdfs.Add(dt.GeneratePdf(Database, d, CreatorUser, Timestamp, state, true));
|
||||
state.SequenceNumber++;
|
||||
@@ -48,9 +49,9 @@ namespace Disco.BI.Interop.Pdf
|
||||
return null;
|
||||
}
|
||||
|
||||
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
|
||||
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, params string[] DataObjectsIds)
|
||||
{
|
||||
object[] DataObjects;
|
||||
IAttachmentTarget[] DataObjects;
|
||||
|
||||
switch (dt.Scope)
|
||||
{
|
||||
@@ -62,7 +63,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
DataObjects = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToArray();
|
||||
break;
|
||||
case DocumentTemplate.DocumentTemplateScopes.User:
|
||||
DataObjects = new object[DataObjectsIds.Length];
|
||||
DataObjects = new IAttachmentTarget[DataObjectsIds.Length];
|
||||
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
|
||||
{
|
||||
string dataObjectId = DataObjectsIds[idIndex];
|
||||
@@ -79,7 +80,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
|
||||
}
|
||||
|
||||
public static System.IO.Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
public static Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
|
||||
{
|
||||
// Validate Data
|
||||
switch (dt.Scope)
|
||||
@@ -124,7 +125,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
|
||||
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.UserId, TimeStamp);
|
||||
string fieldValue = dt.CreateUniqueIdentifier(Database, Data, CreatorUser, TimeStamp, 0).ToJson();
|
||||
if (FlattenFields)
|
||||
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
|
||||
else
|
||||
@@ -134,7 +135,7 @@ namespace Disco.BI.Interop.Pdf
|
||||
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
|
||||
{
|
||||
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
|
||||
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.UserId, TimeStamp, pdfFieldPosition.page);
|
||||
string pdfBarcodeContent = dt.CreateUniqueIdentifier(Database, Data, CreatorUser, TimeStamp, pdfFieldPosition.page).ToQRCodeString();
|
||||
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
|
||||
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
|
||||
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
|
||||
|
||||
@@ -1,977 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using iTextSharp.text.pdf;
|
||||
using System.IO;
|
||||
using System.Drawing;
|
||||
using Disco.BI.DocumentTemplateBI.Importer;
|
||||
using Disco.BI.DocumentTemplateBI;
|
||||
using System.Drawing.Drawing2D;
|
||||
using com.google.zxing;
|
||||
using com.google.zxing.multi.qrcode;
|
||||
using Disco.Data.Repository;
|
||||
using System.Web.Caching;
|
||||
using Disco.BI.Extensions;
|
||||
using Disco.Models.Repository;
|
||||
using System.Collections;
|
||||
using com.google.zxing.common;
|
||||
using BitMiracle.LibTiff.Classic;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Disco.BI.Interop.Pdf
|
||||
{
|
||||
public static class PdfImporter
|
||||
{
|
||||
public static RectangleF CalculateLocationRatio(this Result zxingResult, int ImageWidth, int ImageHeight)
|
||||
{
|
||||
var orderedPoints = zxingResult.ResultPoints.OrderBy(p => p.X * p.Y).ToArray();
|
||||
var topLeftPoint = orderedPoints.First();
|
||||
var bottomRightPoint = orderedPoints.Last();
|
||||
|
||||
var x = topLeftPoint.X;
|
||||
var y = topLeftPoint.Y;
|
||||
var width = bottomRightPoint.X - x;
|
||||
var height = bottomRightPoint.Y - y;
|
||||
|
||||
return new RectangleF(
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(x / ImageWidth) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(y / ImageHeight) - 0.05)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(width / ImageWidth) + 0.1)),
|
||||
(float)System.Math.Min(1.0, System.Math.Max(0.0, (double)(height / ImageHeight) + 0.1))
|
||||
);
|
||||
}
|
||||
|
||||
private class DetectImageResult : IDisposable
|
||||
{
|
||||
public Result Result { get; set; }
|
||||
public Point ResultOffset { get; set; }
|
||||
public double ResultScale { get; set; }
|
||||
|
||||
public float CalculateRotation()
|
||||
{
|
||||
var p1 = this.Result.ResultPoints[0];
|
||||
var p2 = this.Result.ResultPoints[1];
|
||||
double rotOpposite = p1.X - p2.X;
|
||||
double rotAdjacent = p1.Y - p2.Y;
|
||||
float rotation = 0;
|
||||
|
||||
if (rotOpposite != 0 || rotAdjacent != 0)
|
||||
{
|
||||
rotation = (float)(Math.Atan2(rotOpposite, rotAdjacent) * (180 / Math.PI)); // Degrees
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do Nothing; yet...
|
||||
}
|
||||
}
|
||||
|
||||
private class DetectStateHints
|
||||
{
|
||||
public List<Tuple<RectangleF, Rotation>> PriorDetections { get; set; }
|
||||
|
||||
public DetectStateHints()
|
||||
{
|
||||
this.PriorDetections = new List<Tuple<RectangleF, Rotation>>();
|
||||
}
|
||||
}
|
||||
|
||||
private enum Rotation
|
||||
{
|
||||
None = 0,
|
||||
Degrees90 = 1,
|
||||
DegreesNeg90 = 2,
|
||||
Degrees180 = 3
|
||||
}
|
||||
|
||||
private class DetectPageResult : IDisposable
|
||||
{
|
||||
public int PageNumber { get; set; }
|
||||
public DocumentUniqueIdentifier DetectedIdentifier { get; set; }
|
||||
public Disco.BI.Extensions.UtilityExtensions.ImageMontage ThumbnailImage { get; set; }
|
||||
public MemoryStream AttachmentThumbnailImage { get; set; }
|
||||
public Disco.BI.Extensions.UtilityExtensions.ImageMontage UndetectedPageImage { get; set; }
|
||||
|
||||
public void DrawThumbnailImageResult(DetectImageResult Result, Image DetectedImage)
|
||||
{
|
||||
if (Result.Result.ResultPoints.Length == 4)
|
||||
{ // Draw Square on Thumbnail
|
||||
using (Graphics thumbnailGraphics = Graphics.FromImage(ThumbnailImage.Montage))
|
||||
{
|
||||
var thumbnailOffset = ThumbnailImage.MontageSourceImageOffsets[DetectedImage];
|
||||
|
||||
var linePoints = Result.Result.ResultPoints.Select(p => new Point((int)(thumbnailOffset + ((Result.ResultOffset.X + p.X) * Result.ResultScale * ThumbnailImage.MontageScale)), (int)((p.Y + Result.ResultOffset.Y) * Result.ResultScale * ThumbnailImage.MontageScale))).ToArray();
|
||||
using (GraphicsPath graphicsPath = new GraphicsPath())
|
||||
{
|
||||
for (int linePointIndex = 0; linePointIndex < (linePoints.Length - 1); linePointIndex++)
|
||||
graphicsPath.AddLine(linePoints[linePointIndex], linePoints[linePointIndex + 1]);
|
||||
graphicsPath.AddLine(linePoints[linePoints.Length - 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ThumbnailImage != null)
|
||||
{
|
||||
ThumbnailImage.Dispose();
|
||||
ThumbnailImage = null;
|
||||
}
|
||||
if (AttachmentThumbnailImage != null)
|
||||
{
|
||||
AttachmentThumbnailImage.Dispose();
|
||||
AttachmentThumbnailImage = null;
|
||||
}
|
||||
if (UndetectedPageImage != null)
|
||||
{
|
||||
UndetectedPageImage.Dispose();
|
||||
UndetectedPageImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Tuple<Result, Rectangle, Rotation> DetectImageFromSegment(Bitmap pageImage, QRCodeMultiReader zxingReader, Hashtable zxingReaderHints, RectangleF LocationPercentage, Rotation Rotation)
|
||||
{
|
||||
System.Drawing.Rectangle region;
|
||||
|
||||
switch (Rotation)
|
||||
{
|
||||
case Rotation.None: // Original Position
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width * LocationPercentage.Left),
|
||||
(int)(pageImage.Height * LocationPercentage.Top),
|
||||
(int)(pageImage.Width * LocationPercentage.Width),
|
||||
(int)(pageImage.Height * LocationPercentage.Height));
|
||||
break;
|
||||
case Rotation.Degrees90: // Clockwise 90 degrees
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width - (pageImage.Width * (LocationPercentage.Top + LocationPercentage.Height))),
|
||||
(int)(pageImage.Height * LocationPercentage.Left),
|
||||
(int)(pageImage.Width * LocationPercentage.Height),
|
||||
(int)(pageImage.Height * LocationPercentage.Width));
|
||||
break;
|
||||
case Rotation.DegreesNeg90: // Anti-clockwise 90 degrees
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width * LocationPercentage.Top),
|
||||
(int)(pageImage.Height - (pageImage.Height * (LocationPercentage.Left + LocationPercentage.Width))),
|
||||
(int)(pageImage.Width * LocationPercentage.Height),
|
||||
(int)(pageImage.Height * LocationPercentage.Width));
|
||||
break;
|
||||
case Rotation.Degrees180: // 180 degrees
|
||||
region = new Rectangle(
|
||||
(int)(pageImage.Width - (pageImage.Width * (LocationPercentage.Left + LocationPercentage.Width))),
|
||||
(int)(pageImage.Height - (pageImage.Height * (LocationPercentage.Top + LocationPercentage.Height))),
|
||||
(int)(pageImage.Width * LocationPercentage.Width),
|
||||
(int)(pageImage.Height * LocationPercentage.Height));
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown Rotation");
|
||||
}
|
||||
|
||||
LuminanceSource zxingSource;
|
||||
using (Bitmap pageImageRegion = new Bitmap(region.Width, region.Height))
|
||||
{
|
||||
pageImageRegion.SetResolution(pageImage.HorizontalResolution, pageImage.VerticalResolution);
|
||||
|
||||
using (Graphics pageImageRegionGraphics = Graphics.FromImage(pageImageRegion))
|
||||
{
|
||||
pageImageRegionGraphics.DrawImage(pageImage, 0, 0, region, GraphicsUnit.Pixel);
|
||||
}
|
||||
|
||||
zxingSource = new BitmapLuminanceSource(pageImageRegion);
|
||||
}
|
||||
var zxingHB = new HybridBinarizer(zxingSource);
|
||||
var zxingBB = new BinaryBitmap(zxingHB);
|
||||
try
|
||||
{
|
||||
var zxingResult = zxingReader.decode(zxingBB, zxingReaderHints);
|
||||
if (zxingResult != null)
|
||||
return new Tuple<Result, Rectangle, Rotation>(zxingResult, region, Rotation);
|
||||
}
|
||||
catch (ReaderException)
|
||||
{
|
||||
// Ignore Location Errors
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DetectImageResult DetectImage(DiscoDataContext Database, Bitmap pageImageOriginal, string SessionId, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
|
||||
{
|
||||
Bitmap pageImage = pageImageOriginal;
|
||||
double pageImageModifiedScale = 1;
|
||||
|
||||
try
|
||||
{
|
||||
// Resize if Resolution > 80; Set to 72 Dpi
|
||||
if (pageImage.HorizontalResolution > 80 || pageImage.VerticalResolution > 80)
|
||||
{
|
||||
pageImageModifiedScale = pageImage.HorizontalResolution / 72;
|
||||
int newWidth = (int)((72 / pageImage.HorizontalResolution) * pageImage.Width);
|
||||
int newHeight = (int)((72 / pageImage.VerticalResolution) * pageImage.Height);
|
||||
|
||||
pageImage = pageImage.ResizeImage(newWidth, newHeight);
|
||||
}
|
||||
|
||||
Tuple<Result, Rectangle, Rotation> result = default(Tuple<Result, Rectangle, Rotation>);
|
||||
QRCodeMultiReader zxingMfr = new QRCodeMultiReader();
|
||||
Hashtable zxingMfrHints = new Hashtable();
|
||||
zxingMfrHints.Add(DecodeHintType.TRY_HARDER, true);
|
||||
|
||||
|
||||
// Look in previously found locations
|
||||
if (StateHints.PriorDetections.Count > 0)
|
||||
{
|
||||
foreach (var previousLocation in StateHints.PriorDetections)
|
||||
{
|
||||
result = DetectImageFromSegment(pageImage, zxingMfr, zxingMfrHints,
|
||||
previousLocation.Item1, previousLocation.Item2);
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// Try the whole image
|
||||
var zxingSource = new BitmapLuminanceSource(pageImage);
|
||||
var zxingHB = new HybridBinarizer(zxingSource);
|
||||
var zxingBB = new BinaryBitmap(zxingHB);
|
||||
try
|
||||
{
|
||||
var zxingResult = zxingMfr.decode(zxingBB, zxingMfrHints);
|
||||
if (zxingResult != null)
|
||||
{
|
||||
result = new Tuple<Result, Rectangle, Rotation>(zxingResult, new Rectangle(0, 0, pageImage.Width, pageImage.Height), Rotation.None);
|
||||
|
||||
StateHints.PriorDetections.Insert(0, new Tuple<RectangleF, Rotation>(
|
||||
result.Item1.CalculateLocationRatio(pageImage.Width, pageImage.Height)
|
||||
, Rotation.None));
|
||||
|
||||
}
|
||||
}
|
||||
catch (ReaderException)
|
||||
{
|
||||
// Ignore Errors
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// Look in 'Known' locations
|
||||
for (int rotationIndex = 0; rotationIndex < 4; rotationIndex++)
|
||||
{
|
||||
foreach (DocumentTemplate dt in detectDocumentTemplates)
|
||||
{
|
||||
var locationBag = dt.QRCodeLocations(Database);
|
||||
foreach (var location in locationBag)
|
||||
{
|
||||
result = DetectImageFromSegment(pageImage, zxingMfr, zxingMfrHints,
|
||||
location, (Rotation)rotationIndex);
|
||||
|
||||
StateHints.PriorDetections.Insert(0, new Tuple<RectangleF, Rotation>(location, (Rotation)rotationIndex));
|
||||
}
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
if (result != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
|
||||
return new DetectImageResult() { Result = result.Item1, ResultOffset = result.Item2.Location, ResultScale = pageImageModifiedScale };
|
||||
else
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pageImageOriginal != pageImage)
|
||||
pageImage.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static DetectPageResult DetectPage(DiscoDataContext Database, PdfReader pdfReader, int PageNumber, string SessionId, string DataStoreSessionCacheLocation, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
|
||||
{
|
||||
DetectPageResult result = new DetectPageResult() { PageNumber = PageNumber };
|
||||
|
||||
DocumentsLog.LogImportPageProgress(SessionId, PageNumber, 10, "Loading Page Images");
|
||||
|
||||
using (DisposableImageCollection pageImages = pdfReader.PdfPageImages(PageNumber))
|
||||
{
|
||||
if (pageImages.Count > 0)
|
||||
{
|
||||
result.ThumbnailImage = pageImages.BuildImageMontage(256, 256);
|
||||
var pageThumbnailFilename = Path.Combine(DataStoreSessionCacheLocation, string.Format("{0}-{1}", SessionId, PageNumber));
|
||||
|
||||
result.ThumbnailImage.Montage.SavePng(pageThumbnailFilename);
|
||||
DocumentsLog.LogImportPageImageUpdate(SessionId, PageNumber);
|
||||
|
||||
double pageProgressInterval = 90 / pageImages.Count;
|
||||
|
||||
foreach (var pageImageOriginal in pageImages)
|
||||
{
|
||||
DocumentsLog.LogImportPageProgress(SessionId, PageNumber, (int)(10 + (pageProgressInterval * pageImages.IndexOf(pageImageOriginal))), String.Format("Processing Page Image {0} of {1}", pageImages.IndexOf(pageImageOriginal) + 1, pageImages.Count));
|
||||
|
||||
using (var zxingResult = DetectImage(Database, pageImageOriginal, SessionId, detectDocumentTemplates, StateHints))
|
||||
{
|
||||
if (zxingResult != null)
|
||||
{
|
||||
if (DocumentUniqueIdentifier.IsDocumentUniqueIdentifier(zxingResult.Result.Text))
|
||||
{
|
||||
float imageRotation = zxingResult.CalculateRotation();
|
||||
|
||||
result.DrawThumbnailImageResult(zxingResult, pageImageOriginal);
|
||||
|
||||
if (imageRotation != 0)
|
||||
{
|
||||
var preImageRotation = result.ThumbnailImage.Montage;
|
||||
result.ThumbnailImage.Montage = result.ThumbnailImage.Montage.RotateImage(imageRotation);
|
||||
preImageRotation.Dispose();
|
||||
}
|
||||
|
||||
result.ThumbnailImage.Montage.SavePng(pageThumbnailFilename);
|
||||
DocumentsLog.LogImportPageImageUpdate(SessionId, PageNumber);
|
||||
|
||||
result.AttachmentThumbnailImage = new MemoryStream();
|
||||
using (var attachmentThumbImage = pageImages.BuildImageMontage(48, 48, true))
|
||||
{
|
||||
using (Image mimeTypeIcon = Disco.Properties.Resources.MimeType_pdf16)
|
||||
attachmentThumbImage.Montage.EmbedIconOverlay(mimeTypeIcon);
|
||||
|
||||
if (imageRotation != 0)
|
||||
{
|
||||
var preImageRotation = attachmentThumbImage.Montage;
|
||||
attachmentThumbImage.Montage = attachmentThumbImage.Montage.RotateImage(imageRotation, Brushes.White);
|
||||
preImageRotation.Dispose();
|
||||
}
|
||||
|
||||
attachmentThumbImage.Montage.SaveJpg(95, result.AttachmentThumbnailImage);
|
||||
}
|
||||
|
||||
result.DetectedIdentifier = new DocumentUniqueIdentifier(zxingResult.Result.Text, PageNumber.ToString());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Page Unassigned
|
||||
result.UndetectedPageImage = pageImages.BuildImageMontage(700, 700);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext Database, string SessionId, Cache HttpCache)
|
||||
{
|
||||
var dataStoreUnassignedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
|
||||
|
||||
DocumentsLog.LogImportProgress(SessionId, 0, "Reading File");
|
||||
|
||||
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
var pdfReader = new PdfReader(fs);
|
||||
|
||||
var pdfPagesAssigned = new Dictionary<int, Tuple<DocumentUniqueIdentifier, byte[]>>();
|
||||
|
||||
var dataStoreSessionPagesCacheLocation = DataStore.CreateLocation(Database, "Cache\\DocumentDropBox_SessionPages");
|
||||
var detectDocumentTemplates = Database.DocumentTemplates.ToArray();
|
||||
|
||||
double progressInterval = 70 / pdfReader.NumberOfPages;
|
||||
|
||||
DetectStateHints detectStateHints = new DetectStateHints();
|
||||
|
||||
for (int PageNumber = 1; PageNumber <= pdfReader.NumberOfPages; PageNumber++)
|
||||
{
|
||||
DocumentsLog.LogImportProgress(SessionId, (int)(PageNumber * progressInterval), string.Format("Processing Page {0} of {1}", PageNumber, pdfReader.NumberOfPages));
|
||||
DocumentsLog.LogImportPageStarting(SessionId, PageNumber);
|
||||
|
||||
using (var pageResult = DetectPage(Database, pdfReader, PageNumber, SessionId, dataStoreSessionPagesCacheLocation, detectDocumentTemplates, detectStateHints))
|
||||
{
|
||||
if (pageResult.DetectedIdentifier != null)
|
||||
{
|
||||
var docId = pageResult.DetectedIdentifier;
|
||||
pdfPagesAssigned.Add(PageNumber, new Tuple<DocumentUniqueIdentifier, byte[]>(docId, pageResult.AttachmentThumbnailImage.ToArray()));
|
||||
|
||||
docId.LoadComponents(Database);
|
||||
DocumentsLog.LogImportPageDetected(SessionId, PageNumber, docId.TemplateTypeId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undetected Page - Write Preview-Images while still in Memory
|
||||
DocumentsLog.LogImportPageUndetected(SessionId, PageNumber);
|
||||
|
||||
// Thumbnail:
|
||||
string unassignedImageThumbnailFilename = Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}_thumbnail.png", SessionId, PageNumber));
|
||||
if (pageResult.ThumbnailImage != null)
|
||||
pageResult.ThumbnailImage.Montage.SavePng(unassignedImageThumbnailFilename);
|
||||
else
|
||||
Disco.Properties.Resources.MimeType_pdf48.SavePng(unassignedImageThumbnailFilename);
|
||||
// Large Preview
|
||||
string unassignedImageFilename = Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}.jpg", SessionId, PageNumber));
|
||||
if (pageResult.UndetectedPageImage != null)
|
||||
pageResult.UndetectedPageImage.Montage.SaveJpg(90, unassignedImageFilename);
|
||||
else
|
||||
Disco.Properties.Resources.MimeType_pdf48.SaveJpg(90, unassignedImageFilename);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Write out Assigned Documents
|
||||
var assignedDocuments = pdfPagesAssigned.GroupBy(u => u.Value.Item1.DocumentUniqueId).ToList();
|
||||
if (assignedDocuments.Count > 0)
|
||||
{
|
||||
progressInterval = 20 / assignedDocuments.Count;
|
||||
|
||||
foreach (var documentPortion in assignedDocuments)
|
||||
{
|
||||
DocumentsLog.LogImportProgress(SessionId, (int)(70 + (assignedDocuments.IndexOf(documentPortion) * progressInterval)), string.Format("Importing Documents {0} of {1}", assignedDocuments.IndexOf(documentPortion) + 1, assignedDocuments.Count));
|
||||
|
||||
var documentPortionInfo = documentPortion.First().Value;
|
||||
var documentPortionIdentifier = documentPortionInfo.Item1;
|
||||
var documentPortionThumbnail = documentPortionInfo.Item2;
|
||||
|
||||
if (!documentPortionIdentifier.LoadComponents(Database))
|
||||
{
|
||||
// Unknown Document Unique Id
|
||||
foreach (var dp in documentPortion)
|
||||
{
|
||||
var tag = int.Parse(dp.Value.Item1.Tag);
|
||||
if (pdfPagesAssigned.ContainsKey(tag))
|
||||
pdfPagesAssigned.Remove(tag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (MemoryStream msBuilder = new MemoryStream())
|
||||
{
|
||||
var pdfDoc = new iTextSharp.text.Document();
|
||||
var pdfCopy = new PdfCopy(pdfDoc, msBuilder);
|
||||
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
foreach (var dp in documentPortion.OrderBy(dg => dg.Value.Item1.Page))
|
||||
{
|
||||
var pageSize = pdfReader.GetPageSizeWithRotation(dp.Key);
|
||||
var page = pdfCopy.GetImportedPage(pdfReader, dp.Key);
|
||||
|
||||
pdfDoc.SetPageSize(pageSize);
|
||||
pdfDoc.NewPage();
|
||||
|
||||
pdfCopy.AddPage(page);
|
||||
}
|
||||
|
||||
pdfDoc.Close();
|
||||
pdfCopy.Close();
|
||||
|
||||
msBuilder.Position = 0;
|
||||
|
||||
var attachmentSuccess = documentPortionIdentifier.ImportPdfAttachment(Database, msBuilder, documentPortionThumbnail);
|
||||
|
||||
if (!attachmentSuccess)
|
||||
{ // Unable to add Attachment
|
||||
foreach (var dp in documentPortion)
|
||||
{
|
||||
var tag = int.Parse(dp.Value.Item1.Tag);
|
||||
if (pdfPagesAssigned.ContainsKey(tag))
|
||||
pdfPagesAssigned.Remove(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Write out Unassigned Pages
|
||||
List<int> pdfPagesUnassigned = new List<int>();
|
||||
for (int PageNumber = 1; PageNumber <= pdfReader.NumberOfPages; PageNumber++)
|
||||
if (!pdfPagesAssigned.ContainsKey(PageNumber))
|
||||
pdfPagesUnassigned.Add(PageNumber);
|
||||
if (pdfPagesUnassigned.Count > 0)
|
||||
{
|
||||
progressInterval = 10 / pdfPagesUnassigned.Count;
|
||||
//dataStoreUnassignedLocation
|
||||
foreach (var PageNumber in pdfPagesUnassigned)
|
||||
{
|
||||
DocumentsLog.LogImportProgress(SessionId, (int)(90 + (pdfPagesUnassigned.IndexOf(PageNumber) * progressInterval)), string.Format("Processing Undetected Documents {0} of {1}", pdfPagesUnassigned.IndexOf(PageNumber) + 1, pdfPagesUnassigned.Count));
|
||||
|
||||
using (MemoryStream msBuilder = new MemoryStream())
|
||||
{
|
||||
var pdfDoc = new iTextSharp.text.Document();
|
||||
var pdfCopy = new PdfCopy(pdfDoc, msBuilder);
|
||||
|
||||
pdfDoc.Open();
|
||||
pdfCopy.CloseStream = false;
|
||||
|
||||
var pageSize = pdfReader.GetPageSizeWithRotation(PageNumber);
|
||||
var page = pdfCopy.GetImportedPage(pdfReader, PageNumber);
|
||||
pdfDoc.SetPageSize(pageSize);
|
||||
pdfDoc.NewPage();
|
||||
|
||||
pdfCopy.AddPage(page);
|
||||
pdfDoc.Close();
|
||||
pdfCopy.Close();
|
||||
|
||||
File.WriteAllBytes(Path.Combine(dataStoreUnassignedLocation, string.Format("{0}_{1}.pdf", SessionId, PageNumber)), msBuilder.ToArray());
|
||||
|
||||
DocumentsLog.LogImportPageUndetectedStored(SessionId, PageNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DocumentsLog.LogImportProgress(SessionId, 100, "Finished Importing Document");
|
||||
|
||||
return true;
|
||||
}
|
||||
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext Database, string DocumentTemplateId, string DataId, string UserId, DateTime Timestamp)
|
||||
{
|
||||
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
DocumentUniqueIdentifier identifier = new DocumentUniqueIdentifier(DocumentTemplateId, DataId, UserId, Timestamp);
|
||||
identifier.LoadComponents(Database);
|
||||
return identifier.ImportPdfAttachment(Database, fs, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static DisposableImageCollection GetPageImages(PdfReader pdfReader, int PageNumber)
|
||||
{
|
||||
var pageImages = new DisposableImageCollection();
|
||||
|
||||
var pdfPage = pdfReader.GetPageN(PageNumber);
|
||||
PdfDictionary pdfPageResouces = (PdfDictionary)((PdfDictionary)pdfPage.GetDirectObject(PdfName.RESOURCES)).GetDirectObject(PdfName.XOBJECT);
|
||||
|
||||
foreach (var pdfResKey in pdfPageResouces.Keys)
|
||||
{
|
||||
var pdfRes = pdfPageResouces.GetDirectObject(pdfResKey);
|
||||
if (pdfRes.IsStream())
|
||||
{
|
||||
var pdfResStream = (PdfStream)pdfRes;
|
||||
var pdfResSubType = pdfResStream.Get(PdfName.SUBTYPE);
|
||||
if (pdfResSubType != null && pdfResSubType == PdfName.IMAGE)
|
||||
{
|
||||
if (pdfResStream.Get(PdfName.FILTER) == PdfName.CCITTFAXDECODE)
|
||||
{ // TIFF
|
||||
// Try Using GDI+ for TIFF...
|
||||
var width = ((PdfNumber)(pdfResStream.Get(PdfName.WIDTH))).IntValue;
|
||||
var height = ((PdfNumber)(pdfResStream.Get(PdfName.HEIGHT))).IntValue;
|
||||
var bpc = ((PdfNumber)(pdfResStream.Get(PdfName.BITSPERCOMPONENT))).IntValue;
|
||||
|
||||
var compressionMethod = Compression.CCITTFAX3;
|
||||
|
||||
var decodeParams = pdfResStream.GetAsDict(PdfName.DECODEPARMS);
|
||||
if (decodeParams != null && decodeParams.Contains(PdfName.K) && decodeParams.GetAsNumber(PdfName.K).IntValue < 0)
|
||||
compressionMethod = Compression.CCITTFAX4;
|
||||
|
||||
using (MemoryStream tiffStream = PdfToTiffStream(PdfReader.GetStreamBytesRaw((PRStream)pdfResStream), width, height, bpc, compressionMethod))
|
||||
{
|
||||
pageImages.Add((Bitmap)Bitmap.FromStream(tiffStream));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (pdfResStream.Get(PdfName.FILTER) == PdfName.DCTDECODE)
|
||||
{ // JPG
|
||||
using (MemoryStream jpgStream = new MemoryStream(PdfReader.GetStreamBytesRaw((PRStream)pdfResStream)))
|
||||
{
|
||||
pageImages.Add((Bitmap)Bitmap.FromStream(jpgStream, true, true));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pageImages;
|
||||
}
|
||||
|
||||
private static MemoryStream PdfToTiffStream(byte[] PdfStream, int Width, int Height, int BitsPerComponent, Compression CompressionMethod)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
|
||||
Tiff tif = Tiff.ClientOpen("in-memory", "w", ms, new TiffStream());
|
||||
tif.SetField(TiffTag.IMAGEWIDTH, Width);
|
||||
tif.SetField(TiffTag.IMAGELENGTH, Height);
|
||||
tif.SetField(TiffTag.COMPRESSION, CompressionMethod);
|
||||
tif.SetField(TiffTag.BITSPERSAMPLE, BitsPerComponent);
|
||||
tif.SetField(TiffTag.SAMPLESPERPIXEL, 1);
|
||||
tif.WriteRawStrip(0, PdfStream, PdfStream.Length);
|
||||
tif.Flush();
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2012 ZXing.Net authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/// <summary>
|
||||
/// The base class for luminance sources which supports
|
||||
/// cropping and rotating based upon the luminance values.
|
||||
/// </summary>
|
||||
public abstract class BaseLuminanceSource : LuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected sbyte[] luminances;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BaseLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
luminances = new sbyte[width * height];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="luminanceArray">The luminance array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BaseLuminanceSource(sbyte[] luminanceArray, int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
luminances = luminanceArray;
|
||||
//Buffer.BlockCopy(luminanceArray, 0, luminances, 0, width * height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
/// 0 (black) to 255 (white). It is preferable for implementations of this method
|
||||
/// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
/// getMatrix() may never be called.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, 0 <= y < Height.</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// Always use the returned object, and ignore the .length of the array.</param>
|
||||
/// <returns>
|
||||
/// An array containing the luminance data.
|
||||
/// </returns>
|
||||
override public sbyte[] getRow(int y, sbyte[] row)
|
||||
{
|
||||
int width = Width;
|
||||
if (row == null || row.Length < width)
|
||||
{
|
||||
row = new sbyte[width];
|
||||
}
|
||||
//for (int i = 0; i < width; i++)
|
||||
// row[i] = luminances[y * width + i];
|
||||
Buffer.BlockCopy(luminances, y * width, row, 0, width);
|
||||
return row;
|
||||
}
|
||||
|
||||
public override sbyte[] Matrix
|
||||
{
|
||||
get { return luminances; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
/// Only callable if {@link #isRotateSupported()} is true.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A rotated version of this object.
|
||||
/// </returns>
|
||||
public override LuminanceSource rotateCounterClockwise()
|
||||
{
|
||||
var rotatedLuminances = new sbyte[Width * Height];
|
||||
var newWidth = Height;
|
||||
var newHeight = Width;
|
||||
var localLuminances = Matrix;
|
||||
for (var yold = 0; yold < Height; yold++)
|
||||
{
|
||||
for (var xold = 0; xold < Width; xold++)
|
||||
{
|
||||
var ynew = xold;
|
||||
var xnew = newWidth - yold - 1;
|
||||
rotatedLuminances[ynew * newWidth + xnew] = localLuminances[yold * Width + xold];
|
||||
}
|
||||
}
|
||||
return CreateLuminanceSource(rotatedLuminances, newWidth, newHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports counter-clockwise rotation.</returns>
|
||||
public override bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if CropSupported is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, 0 <= left < Width.</param>
|
||||
/// <param name="top">The top coordinate, 0 <= top <= Height.</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns>
|
||||
/// A cropped version of this object.
|
||||
/// </returns>
|
||||
public override LuminanceSource crop(int left, int top, int width, int height)
|
||||
{
|
||||
if (left + width > Width || top + height > Height)
|
||||
{
|
||||
throw new ArgumentException("Crop rectangle does not fit within image data.");
|
||||
}
|
||||
var croppedLuminances = new sbyte[width * height];
|
||||
for (int yold = top, ynew = 0; yold < height; yold++, ynew++)
|
||||
{
|
||||
for (int xold = left, xnew = 0; xold < width; xold++, xnew++)
|
||||
{
|
||||
croppedLuminances[ynew * width + xnew] = luminances[yold * Width + xold];
|
||||
}
|
||||
}
|
||||
return CreateLuminanceSource(croppedLuminances, width, height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports cropping.</returns>
|
||||
public override bool CropSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected abstract LuminanceSource CreateLuminanceSource(sbyte[] newLuminances, int width, int height);
|
||||
}
|
||||
public partial class BitmapLuminanceSource : BaseLuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BitmapLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapLuminanceSource"/> class
|
||||
/// with the image of a Bitmap instance
|
||||
/// </summary>
|
||||
/// <param name="bitmap">The bitmap.</param>
|
||||
public BitmapLuminanceSource(Bitmap bitmap)
|
||||
: base(bitmap.Width, bitmap.Height)
|
||||
{
|
||||
var height = bitmap.Height;
|
||||
var width = bitmap.Width;
|
||||
|
||||
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
|
||||
luminances = new sbyte[width * height];
|
||||
|
||||
// The underlying raster of image consists of bytes with the luminance values
|
||||
#if WindowsCE
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
|
||||
#else
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
|
||||
if (pixelWidth > 4)
|
||||
{
|
||||
// old slow way for unsupported bit depth
|
||||
Color c;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
c = bitmap.GetPixel(x, y);
|
||||
luminances[offset + x] = (sbyte)(0.3 * c.R + 0.59 * c.G + 0.11 * c.B + 0.01);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
|
||||
#if !WindowsCE
|
||||
// prepare palette for 1 and 8 bit indexed bitmaps
|
||||
var luminancePalette = new sbyte[bitmap.Palette.Entries.Length];
|
||||
for (var index = 0; index < bitmap.Palette.Entries.Length; index++)
|
||||
{
|
||||
var color = bitmap.Palette.Entries[index];
|
||||
luminancePalette[index] = (sbyte)(0.3 * color.R +
|
||||
0.59 * color.G +
|
||||
0.11 * color.B + 0.01);
|
||||
}
|
||||
if (bitmap.PixelFormat == PixelFormat.Format32bppArgb ||
|
||||
bitmap.PixelFormat == PixelFormat.Format32bppPArgb)
|
||||
{
|
||||
pixelWidth = 40;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
switch (pixelWidth)
|
||||
{
|
||||
#if !WindowsCE
|
||||
case 0:
|
||||
for (int x = 0; x * 8 < width; x++)
|
||||
{
|
||||
for (int subX = 0; subX < 8 && 8 * x + subX < width; subX++)
|
||||
{
|
||||
var index = (buffer[x] >> (7 - subX)) & 1;
|
||||
luminances[offset + 8 * x + subX] = luminancePalette[index];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
luminances[offset + x] = luminancePalette[buffer[x]];
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 2:
|
||||
// should be RGB565 or RGB555, assume RGB565
|
||||
{
|
||||
for (int index = 0, x = 0; index < 2 * width; index += 2, x++)
|
||||
{
|
||||
var byte1 = buffer[index];
|
||||
var byte2 = buffer[index + 1];
|
||||
|
||||
var b5 = byte1 & 0x1F;
|
||||
var g5 = (((byte1 & 0xE0) >> 5) | ((byte2 & 0x03) << 3)) & 0x1F;
|
||||
var r5 = (byte2 >> 2) & 0x1F;
|
||||
var r8 = (r5 * 527 + 23) >> 6;
|
||||
var g8 = (g5 * 527 + 23) >> 6;
|
||||
var b8 = (b5 * 527 + 23) >> 6;
|
||||
|
||||
luminances[offset + x] = (sbyte)(0.3 * r8 + 0.59 * g8 + 0.11 * b8 + 0.01);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var luminance = (sbyte)(0.3 * buffer[x * 3] +
|
||||
0.59 * buffer[x * 3 + 1] +
|
||||
0.11 * buffer[x * 3 + 2] + 0.01);
|
||||
luminances[offset + x] = luminance;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// 4 bytes without alpha channel value
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var luminance = (sbyte)(0.30 * buffer[x * 4] +
|
||||
0.59 * buffer[x * 4 + 1] +
|
||||
0.11 * buffer[x * 4 + 2] + 0.01);
|
||||
|
||||
luminances[offset + x] = luminance;
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
// with alpha channel; some barcodes are completely black if you
|
||||
// only look at the r, g and b channel but the alpha channel controls
|
||||
// the view
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var luminance = (sbyte)(0.30 * buffer[x * 4] +
|
||||
0.59 * buffer[x * 4 + 1] +
|
||||
0.11 * buffer[x * 4 + 2] + 0.01);
|
||||
|
||||
// calculating the resulting luminance based upon a white background
|
||||
// var alpha = buffer[x * pixelWidth + 3] / 255.0;
|
||||
// luminance = (byte)(luminance * alpha + 255 * (1 - alpha));
|
||||
var alpha = buffer[x * 4 + 3];
|
||||
luminance = (sbyte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8));
|
||||
luminances[offset + x] = luminance;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected override LuminanceSource CreateLuminanceSource(sbyte[] newLuminances, int width, int height)
|
||||
{
|
||||
return new BitmapLuminanceSource(width, height) { luminances = newLuminances };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user