From 63f0d770be42d9b0b8213e72c1f2acde1cf1874d Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Wed, 20 Sep 2017 16:13:28 +0200
Subject: [PATCH] add certification number and digest values output and check
 to verify results view, splitting up into multiple files

---
 HashingTool/HashingTool.csproj                |   9 +-
 HashingTool/Helper/HashingHelper.cs           |   1 +
 HashingTool/ViewModel/ComponentEntry.cs       |   4 +
 .../ViewModel/HashComponentDataViewModel.cs   |   2 +-
 HashingTool/ViewModel/HashedXMLFile.cs        | 381 ----------------
 .../ViewModel/UserControl/HashedXMLFile.cs    |  26 ++
 .../UserControl/ManufacturerReportXMLFile.cs  | 232 ++++++++++
 .../ViewModel/UserControl/ReportXMLFile.cs    | 140 ++++++
 .../ViewModel/UserControl/VectoJobFile.cs     | 170 ++++++++
 .../ViewModel/UserControl/VectoXMLFile.cs     | 155 +++++++
 .../{XMLFile.cs => XMLFileSelector.cs}        |   7 +-
 .../VerifyComponentInputDataViewModel.cs      |   3 +-
 .../ViewModel/VerifyJobInputDataViewModel.cs  |   2 +-
 .../ViewModel/VerifyResultDataViewModel.cs    |  41 +-
 .../UserControl/VectoXMLFileSelector.xaml.cs  |  10 +-
 HashingTool/Views/VerifyJobInputData.xaml     | 353 ++++++++-------
 HashingTool/Views/VerifyResults.xaml          | 409 +++++++++++++++++-
 HashingTool/Views/VerifyResults.xaml.cs       |   1 +
 .../VectoHashing/Properties/AssemblyInfo.cs   |  74 ++--
 VectoCommon/VectoHashing/VectoHash.cs         |  32 +-
 20 files changed, 1416 insertions(+), 636 deletions(-)
 delete mode 100644 HashingTool/ViewModel/HashedXMLFile.cs
 create mode 100644 HashingTool/ViewModel/UserControl/HashedXMLFile.cs
 create mode 100644 HashingTool/ViewModel/UserControl/ManufacturerReportXMLFile.cs
 create mode 100644 HashingTool/ViewModel/UserControl/ReportXMLFile.cs
 create mode 100644 HashingTool/ViewModel/UserControl/VectoJobFile.cs
 create mode 100644 HashingTool/ViewModel/UserControl/VectoXMLFile.cs
 rename HashingTool/ViewModel/UserControl/{XMLFile.cs => XMLFileSelector.cs} (97%)

diff --git a/HashingTool/HashingTool.csproj b/HashingTool/HashingTool.csproj
index 89e5566db3..043b5f7e02 100644
--- a/HashingTool/HashingTool.csproj
+++ b/HashingTool/HashingTool.csproj
@@ -67,6 +67,7 @@
       <SubType>Designer</SubType>
     </ApplicationDefinition>
     <Compile Include="Helper\CollectionConverter.cs" />
+    <Compile Include="Helper\CultureAwareBinding.cs" />
     <Compile Include="Helper\HashingHelper.cs" />
     <Compile Include="Helper\IOService.cs" />
     <Compile Include="Properties\Annotations.cs" />
@@ -76,16 +77,20 @@
       <DesignTime>True</DesignTime>
     </Compile>
     <Compile Include="ViewModel\ComponentEntry.cs" />
-    <Compile Include="ViewModel\HashedXMLFile.cs" />
     <Compile Include="ViewModel\HomeViewModel.cs" />
     <Compile Include="ViewModel\IMainView.cs" />
     <Compile Include="ViewModel\ApplicationViewModel.cs" />
     <Compile Include="ViewModel\ObservableObject.cs" />
     <Compile Include="ViewModel\RelayCommand.cs" />
     <Compile Include="ViewModel\HashComponentDataViewModel.cs" />
+    <Compile Include="ViewModel\UserControl\HashedXMLFile.cs" />
+    <Compile Include="ViewModel\UserControl\ManufacturerReportXMLFile.cs" />
+    <Compile Include="ViewModel\UserControl\ReportXMLFile.cs" />
+    <Compile Include="ViewModel\UserControl\VectoJobFile.cs" />
+    <Compile Include="ViewModel\UserControl\VectoXMLFile.cs" />
     <Compile Include="ViewModel\VerifyJobInputDataViewModel.cs" />
     <Compile Include="ViewModel\VerifyComponentInputDataViewModel.cs" />
-    <Compile Include="ViewModel\UserControl\XMLFile.cs" />
+    <Compile Include="ViewModel\UserControl\XMLFileSelector.cs" />
     <Compile Include="Util\XMLValidator.cs" />
     <Compile Include="ViewModel\VerifyResultDataViewModel.cs" />
     <Compile Include="Views\AboutDialog.xaml.cs">
diff --git a/HashingTool/Helper/HashingHelper.cs b/HashingTool/Helper/HashingHelper.cs
index c3bebafe4d..8ad87f1e91 100644
--- a/HashingTool/Helper/HashingHelper.cs
+++ b/HashingTool/Helper/HashingHelper.cs
@@ -3,6 +3,7 @@ using System.Collections.ObjectModel;
 using System.Linq;
 using System.Xml;
 using HashingTool.ViewModel;
+using HashingTool.ViewModel.UserControl;
 using TUGraz.VectoCommon.Resources;
 using TUGraz.VectoHashing;
 
diff --git a/HashingTool/ViewModel/ComponentEntry.cs b/HashingTool/ViewModel/ComponentEntry.cs
index 2a28208886..38a76fe9cd 100644
--- a/HashingTool/ViewModel/ComponentEntry.cs
+++ b/HashingTool/ViewModel/ComponentEntry.cs
@@ -1,3 +1,5 @@
+using System;
+
 namespace HashingTool.ViewModel
 {
 	public class ComponentEntry
@@ -8,5 +10,7 @@ namespace HashingTool.ViewModel
 		public string[] CanonicalizationMethod { get; set; }
 		public string DigestMethod { get; set; }
 		public bool Valid { get; set; }
+		public string CertificationNumber { get; set; }
+		public DateTime CertificationDate { get; set; }
 	}
 }
diff --git a/HashingTool/ViewModel/HashComponentDataViewModel.cs b/HashingTool/ViewModel/HashComponentDataViewModel.cs
index 7d9df0b825..af4409bec9 100644
--- a/HashingTool/ViewModel/HashComponentDataViewModel.cs
+++ b/HashingTool/ViewModel/HashComponentDataViewModel.cs
@@ -62,7 +62,7 @@ namespace HashingTool.ViewModel
 
 		private void SourceChanged(object sender, PropertyChangedEventArgs e)
 		{
-			if (e.PropertyName == "Document" || e.PropertyName == "IsValid") {
+			if (e.PropertyName == "UPDATED") {
 				DoComputeHash();
 			}
 		}
diff --git a/HashingTool/ViewModel/HashedXMLFile.cs b/HashingTool/ViewModel/HashedXMLFile.cs
deleted file mode 100644
index cd02b40d9d..0000000000
--- a/HashingTool/ViewModel/HashedXMLFile.cs
+++ /dev/null
@@ -1,381 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Linq;
-using System.Xml;
-using HashingTool.Helper;
-using HashingTool.ViewModel.UserControl;
-using TUGraz.VectoHashing;
-
-namespace HashingTool.ViewModel
-{
-	public class VectoXMLFile : ObservableObject
-	{
-		protected readonly XMLFile _xmlFile;
-
-		protected string _digestValueComputed;
-		protected bool? _valid;
-		protected string _name;
-		protected string _tooltip;
-		protected string _componentType;
-		protected readonly Action<XmlDocument, VectoXMLFile> _validateHashes;
-		private string _digestMethod;
-
-
-		public VectoXMLFile(string name, bool validate, Func<XmlDocument, Collection<string>, bool?> contentCheck,
-			Action<XmlDocument, VectoXMLFile> hashValidation = null)
-		{
-			_validateHashes = hashValidation;
-			_xmlFile = new XMLFile(IoService, validate, contentCheck);
-			_xmlFile.PropertyChanged += FileChanged;
-			Name = name;
-			CanonicalizationMethods = new ObservableCollection<string>();
-
-			Valid = null;
-			ValidTooltip = HashingHelper.ToolTipNone;
-		}
-
-		protected virtual void FileChanged(object sender, PropertyChangedEventArgs e)
-		{
-			if (_xmlFile.IsValid == XmlFileStatus.ValidXML) {
-				if (_xmlFile.HasContentValidation) {
-					Valid = _xmlFile.ContentValid;
-					if (Valid != null && Valid.Value) {
-						ValidTooltip = HashingHelper.ToolTipOk;
-					} else {
-						ValidTooltip = HashingHelper.ToolTipInvalidFileType;
-					}
-				} else {
-					ValidTooltip = HashingHelper.ToolTipOk;
-				}
-			} else {
-				Valid = false;
-				ValidTooltip = HashingHelper.ToolTipXMLValidationFailed;
-			}
-
-			if (Valid != null && Valid.Value && _validateHashes != null) {
-				_validateHashes(_xmlFile.Document, this);
-			}
-		}
-
-
-		public XMLFile XMLFile
-		{
-			get { return _xmlFile; }
-		}
-
-		public string Name
-		{
-			get { return _name; }
-			private set {
-				if (_name == value) {
-					return;
-				}
-				_name = value;
-				RaisePropertyChanged("Name");
-			}
-		}
-
-		public ObservableCollection<string> CanonicalizationMethods { get; private set; }
-
-		public void SetCanonicalizationMethod(IEnumerable<string> c14NMethods)
-		{
-			CanonicalizationMethods.Clear();
-			foreach (var c14N in c14NMethods) {
-				CanonicalizationMethods.Add(c14N);
-			}
-			RaisePropertyChanged("CanonicalizationMethods");
-		}
-
-		public string DigestMethod
-		{
-			get { return _digestMethod; }
-			set {
-				if (_digestMethod == value) {
-					return;
-				}
-				_digestMethod = value;
-				RaisePropertyChanged("DigestMethod");
-			}
-		}
-
-
-		public string DigestValueComputed
-		{
-			get { return _digestValueComputed; }
-			internal set {
-				if (_digestValueComputed == value) {
-					return;
-				}
-				_digestValueComputed = value;
-				RaisePropertyChanged("DigestValueComputed");
-			}
-		}
-
-
-		public bool? Valid
-		{
-			get { return _valid; }
-			internal set {
-				if (_valid == value) {
-					return;
-				}
-				_valid = value;
-				RaisePropertyChanged("Valid");
-			}
-		}
-
-		public string ValidTooltip
-		{
-			get { return _tooltip; }
-			set {
-				if (_tooltip == value) {
-					return;
-				}
-				_tooltip = value;
-				RaisePropertyChanged("ValidTooltip");
-			}
-		}
-
-		public string Component
-		{
-			get { return _componentType; }
-			set {
-				if (_componentType == value) {
-					return;
-				}
-				_componentType = value;
-				RaisePropertyChanged("Component");
-			}
-		}
-	}
-
-	public class HashedXMLFile : VectoXMLFile
-	{
-		protected string _digestValueRead;
-
-		public HashedXMLFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
-			Action<XmlDocument, VectoXMLFile> hashValidation = null) : base(name, true, contentCheck, hashValidation) {}
-
-		public string DigestValueRead
-		{
-			get { return _digestValueRead; }
-			internal set {
-				if (_digestValueRead == value) {
-					return;
-				}
-				_digestValueRead = value;
-				RaisePropertyChanged("DigestValueRead");
-			}
-		}
-	}
-
-	public class ReportXMLFile : HashedXMLFile
-	{
-		private string _jobDigestValueReadRead;
-		private string _jobDigestMethodRead;
-		private string[] _jobCanonicalizationMethodRead;
-		private string _jobDigestComputed;
-		private bool _jobDigestValid;
-
-		public ReportXMLFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
-			Action<XmlDocument, VectoXMLFile> hashValidation = null)
-			: base(name, contentCheck, hashValidation)
-		{
-			_xmlFile.PropertyChanged += ReadJobDigest;
-		}
-
-		private void ReadJobDigest(object sender, PropertyChangedEventArgs e)
-		{
-			var jobDigest = "";
-			var jobDigestMethod = "";
-			var jobc14NMethod = new string[] { };
-
-			if (e.PropertyName != "Document") {
-				return;
-			}
-			if (_xmlFile.Document != null && _xmlFile.Document.DocumentElement != null) {
-				var digestValueNode =
-					_xmlFile.Document.SelectSingleNode("//*[local-name()='InputDataSignature']//*[local-name()='DigestValue']");
-				if (digestValueNode != null) {
-					jobDigest = digestValueNode.InnerText;
-				}
-				var digestMethodNode =
-					_xmlFile.Document.SelectSingleNode(
-						"//*[local-name()='InputDataSignature']//*[local-name()='DigestMethod']/@Algorithm");
-				if (digestMethodNode != null) {
-					jobDigestMethod = digestMethodNode.InnerText;
-				}
-
-				var c14NtMethodNodes =
-					_xmlFile.Document.SelectNodes("//*[local-name()='InputDataSignature']//*[local-name()='Transform']/@Algorithm");
-				if (c14NtMethodNodes != null) {
-					jobc14NMethod = (from XmlNode node in c14NtMethodNodes select node.InnerText).ToArray();
-				}
-			}
-			JobCanonicalizationMethodRead = jobc14NMethod;
-			JobDigestMethodRead = jobDigestMethod;
-			JobDigestValueRead = jobDigest;
-		}
-
-		public string JobDigestMethodRead
-		{
-			get { return _jobDigestMethodRead; }
-			set {
-				if (_jobDigestMethodRead == value) {
-					return;
-				}
-				_jobDigestMethodRead = value;
-				RaisePropertyChanged("JobDigestMethodRead");
-			}
-		}
-
-		public string[] JobCanonicalizationMethodRead
-		{
-			get { return _jobCanonicalizationMethodRead; }
-			set {
-				if (_jobCanonicalizationMethodRead == value) {
-					return;
-				}
-				_jobCanonicalizationMethodRead = value;
-				RaisePropertyChanged("JobCanonicalizationMethodRead");
-			}
-		}
-
-		public string JobDigestValueRead
-		{
-			get { return _jobDigestValueReadRead; }
-			internal set {
-				if (_jobDigestValueReadRead == value) {
-					return;
-				}
-				_jobDigestValueReadRead = value;
-				RaisePropertyChanged("JobDigestValueRead");
-			}
-		}
-
-		public string JobDigestValueComputed
-		{
-			get { return _jobDigestComputed; }
-			set {
-				if (_jobDigestComputed == value) {
-					return;
-				}
-				_jobDigestComputed = value;
-				RaisePropertyChanged("JobDigestValueComputed");
-				JobDigestValid = JobDigestValueComputed == JobDigestValueRead;
-			}
-		}
-
-		public bool JobDigestValid
-		{
-			get { return _jobDigestValid; }
-			set {
-				if (_jobDigestValid == value) {
-					return;
-				}
-				_jobDigestValid = value;
-				RaisePropertyChanged("JobDigestValid");
-			}
-		}
-	}
-
-	public class VectoJobFile : VectoXMLFile
-	{
-		private bool _componentDataValid;
-		private string _jobValidToolTip;
-
-
-		public VectoJobFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
-			Action<XmlDocument, VectoXMLFile> hashValidation = null) : base(name, true, contentCheck, hashValidation)
-		{
-			_xmlFile.PropertyChanged += JobFilechanged;
-			Components = new ObservableCollection<ComponentEntry>();
-		}
-
-		public ObservableCollection<ComponentEntry> Components { get; private set; }
-
-		public bool JobDataValid
-		{
-			get { return _componentDataValid; }
-			set {
-				if (_componentDataValid == value) {
-					return;
-				}
-				_componentDataValid = value;
-				JobValidToolTip = value ? HashingHelper.ToolTipComponentHashInvalid : HashingHelper.ToolTipOk;
-				RaisePropertyChanged("JobDataValid");
-			}
-		}
-
-		public string JobValidToolTip
-		{
-			get { return _jobValidToolTip; }
-			set {
-				if (_jobValidToolTip == value) {
-					return;
-				}
-				_jobValidToolTip = value;
-				RaisePropertyChanged("JobValidToolTip");
-			}
-		}
-
-		private void JobFilechanged(object sender, PropertyChangedEventArgs e)
-		{
-			DoValidateHash();
-		}
-
-		private void DoValidateHash()
-		{
-			if (_xmlFile.Document == null || _xmlFile.IsValid != XmlFileStatus.ValidXML || _xmlFile.ContentValid == null ||
-				!_xmlFile.ContentValid.Value) {
-				Components.Clear();
-				DigestValueComputed = "";
-				DigestMethod = "";
-				SetCanonicalizationMethod(new string[] { });
-				JobDataValid = false;
-				return;
-			}
-			try {
-				Components.Clear();
-				_xmlFile.XMLValidationErrors.Clear();
-				var h = VectoHash.Load(_xmlFile.Document);
-				var allValid = true;
-				var components = h.GetContainigComponents().GroupBy(s => s)
-					.Select(g => new { Entry = g.Key, Count = g.Count() });
-				foreach (var component in components) {
-					if (component.Entry == VectoComponents.Vehicle) {
-						continue;
-					}
-					for (var i = 0; i < component.Count; i++) {
-						var entry = new ComponentEntry();
-						entry.Component = component.Count == 1
-							? component.Entry.XMLElementName()
-							: string.Format("{0} ({1})", component.Entry.XMLElementName(), i + 1);
-						entry.Valid = h.ValidateHash(component.Entry, i);
-						entry.CanonicalizationMethod = h.GetCanonicalizationMethods(component.Entry, i).ToArray();
-						entry.DigestMethod = h.GetDigestMethod(component.Entry, i);
-						entry.DigestValueRead = h.ReadHash(component.Entry, i);
-						entry.DigestValueComputed = h.ComputeHash(component.Entry, i);
-						if (!entry.Valid) {
-							_xmlFile.XMLValidationErrors.Add(
-								string.Format(
-									"Digest Value mismatch for component \"{0}\". Read digest value: \"{1}\", computed digest value \"{2}\"",
-									entry.Component, entry.DigestValueRead, entry.DigestValueComputed));
-						}
-						Components.Add(entry);
-						allValid &= entry.Valid;
-					}
-				}
-
-				DigestValueComputed = h.ComputeHash();
-				JobDataValid = allValid;
-			} catch (Exception e) {
-				DigestValueComputed = "";
-				JobDataValid = false;
-				_xmlFile.XMLValidationErrors.Add(e.Message);
-			}
-		}
-	}
-}
diff --git a/HashingTool/ViewModel/UserControl/HashedXMLFile.cs b/HashingTool/ViewModel/UserControl/HashedXMLFile.cs
new file mode 100644
index 0000000000..25a7fd9ae8
--- /dev/null
+++ b/HashingTool/ViewModel/UserControl/HashedXMLFile.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Xml;
+
+namespace HashingTool.ViewModel.UserControl
+{
+	public class HashedXMLFile : VectoXMLFile
+	{
+		protected string _digestValueRead;
+
+		public HashedXMLFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
+			Action<XmlDocument, VectoXMLFile> hashValidation = null) : base(name, true, contentCheck, hashValidation) {}
+
+		public string DigestValueRead
+		{
+			get { return _digestValueRead; }
+			internal set {
+				if (_digestValueRead == value) {
+					return;
+				}
+				_digestValueRead = value;
+				RaisePropertyChanged("DigestValueRead");
+			}
+		}
+	}
+}
diff --git a/HashingTool/ViewModel/UserControl/ManufacturerReportXMLFile.cs b/HashingTool/ViewModel/UserControl/ManufacturerReportXMLFile.cs
new file mode 100644
index 0000000000..da8afd23c4
--- /dev/null
+++ b/HashingTool/ViewModel/UserControl/ManufacturerReportXMLFile.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Xml;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Resources;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoHashing;
+
+namespace HashingTool.ViewModel.UserControl
+{
+	public class ManufacturerReportXMLFile : ReportXMLFile
+	{
+		private ViewModel.ComponentEntry[] _jobComponents;
+
+		public ManufacturerReportXMLFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
+			Action<XmlDocument, VectoXMLFile> hashValidation = null) : base(name, contentCheck, hashValidation)
+		{
+			_xmlFile.PropertyChanged += UpdateComponents;
+		}
+
+		public ViewModel.ComponentEntry[] JobComponents
+		{
+			set {
+				if (_jobComponents == value) {
+					return;
+				}
+				_jobComponents = value;
+				DoUpdateComponents();
+				RaisePropertyChanged("JobComponents");
+				RaisePropertyChanged("ManufacturerReportValid");
+			}
+			private get { return _jobComponents; }
+		}
+
+		private void UpdateComponents(object sender, PropertyChangedEventArgs e)
+		{
+			if (e.PropertyName != "UPDATED") {
+				return;
+			}
+			DoUpdateComponents();
+			RaisePropertyChanged("ManufacturerReportValid");
+			RaisePropertyChanged("UPDATED");
+		}
+
+		private void DoUpdateComponents()
+		{
+			if (_xmlFile.Document == null || _xmlFile.Document.DocumentElement == null) {
+				Components = new ComponentEntry[] { };
+				VehicleIdentificationNumber = "";
+				RaisePropertyChanged("Components");
+				RaisePropertyChanged("VehicleIdentificationNumber");
+				return;
+			}
+			var components = GetContainigComponents().GroupBy(s => s)
+				.Select(g => new { Entry = g.Key, Count = g.Count() });
+			var componentData = new List<ComponentEntry>();
+			foreach (var component in components) {
+				if (component.Entry == XMLNames.Component_Vehicle) {
+					continue;
+				}
+				for (var i = 0; i < component.Count; i++) {
+					var node = GetNodes(component.Entry, i);
+					var entry = new ComponentEntry {
+						Component = component.Count == 1
+							? component.Entry
+							: string.Format("{0} ({1})", component.Entry, i + 1),
+						DigestValue = ReadElementValue(node, XMLNames.DI_Signature_Reference_DigestValue),
+						CertificationMethod = ReadElementValue(node, XMLNames.Report_Component_CertificationMethod),
+					};
+					if (entry.Component.StartsWith("Axle ")) {
+						entry.Component = entry.Component.Replace("Axle", "Tyre");
+						entry.CertificationNumber = ReadElementValue(node, XMLNames.Report_Tyre_TyreCertificationNumber);
+						entry.DigestValue = "Not Available";
+					} else {
+						entry.CertificationNumber = ReadElementValue(node, XMLNames.Report_Component_CertificationNumber) ??
+													ReadElementValue(node, XMLNames.Report_Component_CertificationMethod);
+					}
+					if (JobComponents != null) {
+						var jobComponent = JobComponents.Where(
+							x => x.Component == entry.Component).ToArray();
+						if (jobComponent.Any()) {
+							entry.DigestValueMatchesJobComponent = entry.Component.StartsWith("Tyre ")
+								? (bool?)null
+								: (jobComponent.First().DigestValueRead == entry.DigestValue);
+							entry.DigestValueExpected = jobComponent.First().DigestValueRead;
+							if (entry.CertificationMethod != CertificationMethod.StandardValues.ToXMLFormat()) {
+								entry.CertificationNumberMatchesJobComponent = jobComponent.First().CertificationNumber ==
+																				entry.CertificationNumber;
+								entry.CertificationNumberExpected = jobComponent.First().CertificationNumber;
+							}
+						}
+					}
+					componentData.Add(entry);
+				}
+			}
+			Components = componentData.ToArray();
+			VehicleIdentificationNumber = GetVehicleIdentificationNumber();
+
+			RaisePropertyChanged("Components");
+			RaisePropertyChanged("VehicleIdentificationNumber");
+		}
+
+		private string GetVehicleIdentificationNumber()
+		{
+			if (_xmlFile.Document == null || _xmlFile.IsValid != XmlFileStatus.ValidXML || _xmlFile.ContentValid == null ||
+				!_xmlFile.ContentValid.Value) {
+				return "";
+			}
+			var node = _xmlFile.Document.SelectSingleNode(string.Format("//*[local-name()='{0}']", XMLNames.Vehicle_VIN));
+			if (node == null) {
+				return "";
+			}
+			return node.InnerText;
+		}
+
+		public bool ManufacturerReportValid
+		{
+			get {
+				var componentsValid = JobComponents != null && JobComponents.Length > 0;
+				if (Components == null || JobComponents == null || JobComponents.Length == 0) {
+					return false;
+				}
+
+				foreach (var entry in Components) {
+					// certification number is optional (iff standard values are used)
+					var entryCertificationNbr = entry.CertificationNumberMatchesJobComponent == null ||
+												entry.CertificationNumberMatchesJobComponent.Value;
+					if (!entryCertificationNbr) {
+						var msg = string.Format("Certification number for component {0} does not match! Job-File: {1}, Report: {2}",
+							entry.Component, entry.CertificationNumberExpected, entry.CertificationNumber);
+						if (!_xmlFile.XMLValidationErrors.Contains(msg)) {
+							_xmlFile.XMLValidationErrors.Add(msg);
+						}
+					}
+					componentsValid &= entryCertificationNbr;
+					// digest value is mandatory (except for tires)
+					if (entry.Component.StartsWith("Tyre ")) {
+						continue;
+					}
+
+					var entryDigest = entry.DigestValueMatchesJobComponent != null && entry.DigestValueMatchesJobComponent.Value;
+					if (!entryDigest) {
+						var msg = string.Format("Digest value for component {0} does not match! Job-File: {1}, Report: {2}",
+							entry.Component, entry.DigestValueExpected, entry.DigestValue);
+						if (!_xmlFile.XMLValidationErrors.Contains(msg)) {
+							_xmlFile.XMLValidationErrors.Add(msg);
+						}
+					}
+					componentsValid &= entryDigest;
+				}
+				return JobDigestValid && componentsValid;
+			}
+		}
+
+		private string ReadElementValue(XmlNode xmlNode, string elementName)
+		{
+			var node = xmlNode.SelectSingleNode(string.Format("./*[local-name()='{0}']", elementName));
+			if (node == null) {
+				return null;
+			}
+			return node.InnerText;
+		}
+
+		protected XmlNode GetNodes(string component, int index)
+		{
+			var nodes = _xmlFile.Document.SelectNodes(GetComponentQueryString(component));
+			if (nodes == null || nodes.Count == 0) {
+				throw new Exception(component == null
+					? "No component found"
+					: string.Format("Component {0} not found", component));
+			}
+			if (index >= nodes.Count) {
+				throw new Exception(string.Format("index exceeds number of components found! index: {0}, #components: {1}", index,
+					nodes.Count));
+			}
+			return nodes[index];
+		}
+
+		protected static string GetComponentQueryString(string component = null)
+		{
+			if (component == null) {
+				return "(//*[@id])[1]";
+			}
+			return string.Format("//*[local-name()='{0}']", component);
+		}
+
+		protected IList<string> GetContainigComponents()
+		{
+			var retVal = new List<string>();
+			foreach (var component in EnumHelper.GetValues<VectoComponents>()) {
+				var nodes = _xmlFile.Document.SelectNodes(string.Format("//*[local-name()='{0}']//*[local-name()='{1}']",
+					XMLNames.VectoManufacturerReport, component.XMLElementName()));
+				var count = nodes == null ? 0 : nodes.Count;
+				for (var i = 0; i < count; i++) {
+					retVal.Add(component.XMLElementName());
+				}
+			}
+			foreach (var component in new[] { XMLNames.AxleWheels_Axles_Axle }) {
+				var nodes = _xmlFile.Document.SelectNodes(string.Format("//*[local-name()='{0}']//*[local-name()='{1}']",
+					XMLNames.VectoManufacturerReport, component));
+				var count = nodes == null ? 0 : nodes.Count;
+				for (var i = 0; i < count; i++) {
+					retVal.Add(component);
+				}
+			}
+			return retVal;
+		}
+
+		public string VehicleIdentificationNumber { get; private set; }
+
+		public ComponentEntry[] Components { get; private set; }
+
+		public class ComponentEntry
+		{
+			public string Component { get; set; }
+
+			public string CertificationNumber { get; set; }
+
+			public string DigestValue { get; set; }
+
+			public string CertificationMethod { get; set; }
+
+			public bool? DigestValueMatchesJobComponent { get; set; }
+			public bool? CertificationNumberMatchesJobComponent { get; set; }
+			public string DigestValueExpected { get; set; }
+			public string CertificationNumberExpected { get; set; }
+		}
+	}
+}
\ No newline at end of file
diff --git a/HashingTool/ViewModel/UserControl/ReportXMLFile.cs b/HashingTool/ViewModel/UserControl/ReportXMLFile.cs
new file mode 100644
index 0000000000..3c830404cc
--- /dev/null
+++ b/HashingTool/ViewModel/UserControl/ReportXMLFile.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Xml;
+
+namespace HashingTool.ViewModel.UserControl
+{
+	public class ReportXMLFile : HashedXMLFile
+	{
+		private string _jobDigestValueReadRead;
+		private string _jobDigestMethodRead;
+		private string[] _jobCanonicalizationMethodRead;
+		private string _jobDigestComputed;
+		private bool _jobDigestValid;
+		private DateTime? _creationDate;
+
+		public ReportXMLFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
+			Action<XmlDocument, VectoXMLFile> hashValidation = null)
+			: base(name, contentCheck, hashValidation)
+		{
+			_xmlFile.PropertyChanged += ReadJobDigest;
+		}
+
+		private void ReadJobDigest(object sender, PropertyChangedEventArgs e)
+		{
+			var jobDigest = "";
+			var jobDigestMethod = "";
+			var jobc14NMethod = new string[] { };
+			DateTime? creationDate = null;
+
+			if (e.PropertyName != "UPDATED") {
+				return;
+			}
+			if (_xmlFile.Document != null && _xmlFile.Document.DocumentElement != null) {
+				var digestValueNode =
+					_xmlFile.Document.SelectSingleNode("//*[local-name()='InputDataSignature']//*[local-name()='DigestValue']");
+				if (digestValueNode != null) {
+					jobDigest = digestValueNode.InnerText;
+				}
+				var digestMethodNode =
+					_xmlFile.Document.SelectSingleNode(
+						"//*[local-name()='InputDataSignature']//*[local-name()='DigestMethod']/@Algorithm");
+				if (digestMethodNode != null) {
+					jobDigestMethod = digestMethodNode.InnerText;
+				}
+
+				var c14NtMethodNodes =
+					_xmlFile.Document.SelectNodes("//*[local-name()='InputDataSignature']//*[local-name()='Transform']/@Algorithm");
+				if (c14NtMethodNodes != null) {
+					jobc14NMethod = (from XmlNode node in c14NtMethodNodes select node.InnerText).ToArray();
+				}
+				var dateNode =
+					_xmlFile.Document.SelectSingleNode("//*[local-name()='ApplicationInformation']/*[local-name()='Date']");
+				creationDate = dateNode != null
+					? XmlConvert.ToDateTime(dateNode.InnerText, XmlDateTimeSerializationMode.RoundtripKind)
+					: (DateTime?)null;
+			}
+			JobCanonicalizationMethodRead = jobc14NMethod;
+			JobDigestMethodRead = jobDigestMethod;
+			JobDigestValueRead = jobDigest;
+			CreationDate = creationDate;
+			RaisePropertyChanged("UPDATED");
+		}
+
+		public string JobDigestMethodRead
+		{
+			get { return _jobDigestMethodRead; }
+			set {
+				if (_jobDigestMethodRead == value) {
+					return;
+				}
+				_jobDigestMethodRead = value;
+				RaisePropertyChanged("JobDigestMethodRead");
+			}
+		}
+
+		public string[] JobCanonicalizationMethodRead
+		{
+			get { return _jobCanonicalizationMethodRead; }
+			set {
+				if (_jobCanonicalizationMethodRead == value) {
+					return;
+				}
+				_jobCanonicalizationMethodRead = value;
+				RaisePropertyChanged("JobCanonicalizationMethodRead");
+			}
+		}
+
+		public string JobDigestValueRead
+		{
+			get { return _jobDigestValueReadRead; }
+			internal set {
+				if (_jobDigestValueReadRead == value) {
+					return;
+				}
+				_jobDigestValueReadRead = value;
+				RaisePropertyChanged("JobDigestValueRead");
+			}
+		}
+
+		public string JobDigestValueComputed
+		{
+			get { return _jobDigestComputed; }
+			set {
+				if (_jobDigestComputed == value) {
+					JobDigestValid = _jobDigestComputed == JobDigestValueRead;
+					return;
+				}
+				_jobDigestComputed = value;
+				RaisePropertyChanged("JobDigestValueComputed");
+				JobDigestValid = _jobDigestComputed == JobDigestValueRead;
+			}
+		}
+
+		public bool JobDigestValid
+		{
+			get { return _jobDigestValid; }
+			set {
+				if (_jobDigestValid == value) {
+					return;
+				}
+				_jobDigestValid = value;
+				RaisePropertyChanged("JobDigestValid");
+			}
+		}
+
+		public DateTime? CreationDate
+		{
+			get { return _creationDate; }
+			set {
+				if (_creationDate == value) {
+					return;
+				}
+				_creationDate = value;
+				RaisePropertyChanged("CreationDate");
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/HashingTool/ViewModel/UserControl/VectoJobFile.cs b/HashingTool/ViewModel/UserControl/VectoJobFile.cs
new file mode 100644
index 0000000000..a964950128
--- /dev/null
+++ b/HashingTool/ViewModel/UserControl/VectoJobFile.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Xml;
+using HashingTool.Helper;
+using TUGraz.VectoCommon.Resources;
+using TUGraz.VectoHashing;
+
+namespace HashingTool.ViewModel.UserControl
+{
+	public class VectoJobFile : VectoXMLFile
+	{
+		private bool _componentDataValid;
+		private string _jobValidToolTip;
+		private string _vin;
+		private DateTime? _jobDate;
+
+
+		public VectoJobFile(string name, Func<XmlDocument, Collection<string>, bool?> contentCheck,
+			Action<XmlDocument, VectoXMLFile> hashValidation = null) : base(name, true, contentCheck, hashValidation)
+		{
+			_xmlFile.PropertyChanged += JobFilechanged;
+			Components = new ObservableCollection<ComponentEntry>();
+		}
+
+		public ObservableCollection<ComponentEntry> Components { get; private set; }
+
+		public bool JobDataValid
+		{
+			get { return _componentDataValid; }
+			set {
+				if (_componentDataValid == value) {
+					return;
+				}
+				_componentDataValid = value;
+				JobValidToolTip = value ? HashingHelper.ToolTipComponentHashInvalid : HashingHelper.ToolTipOk;
+				RaisePropertyChanged("JobDataValid");
+			}
+		}
+
+		public string JobValidToolTip
+		{
+			get { return _jobValidToolTip; }
+			set {
+				if (_jobValidToolTip == value) {
+					return;
+				}
+				_jobValidToolTip = value;
+				RaisePropertyChanged("JobValidToolTip");
+			}
+		}
+
+		public string VehicleIdentificationNumber
+		{
+			get { return _vin; }
+			set {
+				if (_vin == value) {
+					return;
+				}
+				_vin = value;
+				RaisePropertyChanged("VehicleIdentificationNumber");
+			}
+		}
+
+		public DateTime? JobCreationDate
+		{
+			get { return _jobDate; }
+			set {
+				if (_jobDate == value) {
+					return;
+				}
+				_jobDate = value;
+				RaisePropertyChanged("JobCreationDate");
+			}
+		}
+
+		private void JobFilechanged(object sender, PropertyChangedEventArgs e)
+		{
+			if (e.PropertyName != "UPDATED") {
+				return;
+			}
+			DoValidateHash();
+			VehicleIdentificationNumber = DoReadVIN();
+			JobCreationDate = DoReadJobDate();
+
+			RaisePropertyChanged("UPDATED");
+		}
+
+		private DateTime? DoReadJobDate()
+		{
+			if (_xmlFile.Document == null || _xmlFile.IsValid != XmlFileStatus.ValidXML || _xmlFile.ContentValid == null ||
+				!_xmlFile.ContentValid.Value) {
+				return null;
+			}
+			var nodes = _xmlFile.Document.SelectNodes(string.Format("//*[local-name()='{0}']", XMLNames.Component_Date));
+			if (nodes == null || nodes.Count == 0) {
+				return null;
+			}
+			return XmlConvert.ToDateTime(nodes[0].InnerText, XmlDateTimeSerializationMode.RoundtripKind);
+		}
+
+		private string DoReadVIN()
+		{
+			if (_xmlFile.Document == null || _xmlFile.IsValid != XmlFileStatus.ValidXML || _xmlFile.ContentValid == null ||
+				!_xmlFile.ContentValid.Value) {
+				return "";
+			}
+			var node = _xmlFile.Document.SelectSingleNode(string.Format("//*[local-name()='{0}']", XMLNames.Vehicle_VIN));
+			if (node == null) {
+				return "";
+			}
+			return node.InnerText;
+		}
+
+		private void DoValidateHash()
+		{
+			if (_xmlFile.Document == null || _xmlFile.IsValid != XmlFileStatus.ValidXML || _xmlFile.ContentValid == null ||
+				!_xmlFile.ContentValid.Value) {
+				Components.Clear();
+				DigestValueComputed = "";
+				DigestMethod = "";
+				SetCanonicalizationMethod(new string[] { });
+				JobDataValid = false;
+				return;
+			}
+			try {
+				Components.Clear();
+				_xmlFile.XMLValidationErrors.Clear();
+				var h = VectoHash.Load(_xmlFile.Document);
+				var allValid = true;
+				var components = h.GetContainigComponents().GroupBy(s => s)
+					.Select(g => new { Entry = g.Key, Count = g.Count() });
+				foreach (var component in components) {
+					if (component.Entry == VectoComponents.Vehicle) {
+						continue;
+					}
+					for (var i = 0; i < component.Count; i++) {
+						var entry = new ComponentEntry();
+						entry.Component = component.Count == 1
+							? component.Entry.XMLElementName()
+							: string.Format("{0} ({1})", component.Entry.XMLElementName(), i + 1);
+						entry.Valid = h.ValidateHash(component.Entry, i);
+						entry.CanonicalizationMethod = h.GetCanonicalizationMethods(component.Entry, i).ToArray();
+						entry.DigestMethod = h.GetDigestMethod(component.Entry, i);
+						entry.DigestValueRead = h.ReadHash(component.Entry, i);
+						entry.DigestValueComputed = h.ComputeHash(component.Entry, i);
+						entry.CertificationNumber = h.GetCertificationNumber(component.Entry, i);
+						entry.CertificationDate = h.GetCertificationDate(component.Entry, i);
+						if (!entry.Valid) {
+							_xmlFile.XMLValidationErrors.Add(
+								string.Format(
+									"Digest Value mismatch for component \"{0}\". Read digest value: \"{1}\", computed digest value \"{2}\"",
+									entry.Component, entry.DigestValueRead, entry.DigestValueComputed));
+						}
+						Components.Add(entry);
+						allValid &= entry.Valid;
+					}
+				}
+
+				DigestValueComputed = h.ComputeHash();
+				JobDataValid = allValid;
+			} catch (Exception e) {
+				DigestValueComputed = "";
+				JobDataValid = false;
+				_xmlFile.XMLValidationErrors.Add(e.Message);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/HashingTool/ViewModel/UserControl/VectoXMLFile.cs b/HashingTool/ViewModel/UserControl/VectoXMLFile.cs
new file mode 100644
index 0000000000..e96209319d
--- /dev/null
+++ b/HashingTool/ViewModel/UserControl/VectoXMLFile.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Xml;
+using HashingTool.Helper;
+
+namespace HashingTool.ViewModel.UserControl
+{
+	public class VectoXMLFile : ObservableObject
+	{
+		protected readonly XMLFileSelector _xmlFile;
+
+		protected string _digestValueComputed;
+		protected bool? _valid;
+		protected string _name;
+		protected string _tooltip;
+		protected string _componentType;
+		protected readonly Action<XmlDocument, VectoXMLFile> _validateHashes;
+		private string _digestMethod;
+
+
+		public VectoXMLFile(string name, bool validate, Func<XmlDocument, Collection<string>, bool?> contentCheck,
+			Action<XmlDocument, VectoXMLFile> hashValidation = null)
+		{
+			_validateHashes = hashValidation;
+			_xmlFile = new XMLFileSelector(IoService, validate, contentCheck);
+			_xmlFile.PropertyChanged += FileChanged;
+			Name = name;
+			CanonicalizationMethods = new ObservableCollection<string>();
+
+			Valid = null;
+			ValidTooltip = HashingHelper.ToolTipNone;
+		}
+
+		protected virtual void FileChanged(object sender, PropertyChangedEventArgs e)
+		{
+			if (e.PropertyName != "UPDATED") {
+				return;
+			}
+
+			if (_xmlFile.IsValid == XmlFileStatus.ValidXML) {
+				if (_xmlFile.HasContentValidation) {
+					Valid = _xmlFile.ContentValid;
+					if (Valid != null && Valid.Value) {
+						ValidTooltip = HashingHelper.ToolTipOk;
+					} else {
+						ValidTooltip = HashingHelper.ToolTipInvalidFileType;
+					}
+				} else {
+					ValidTooltip = HashingHelper.ToolTipOk;
+				}
+			} else {
+				Valid = false;
+				ValidTooltip = HashingHelper.ToolTipXMLValidationFailed;
+			}
+
+			if (Valid != null && Valid.Value && _validateHashes != null) {
+				_validateHashes(_xmlFile.Document, this);
+			}
+			RaisePropertyChanged("UPDATED");
+		}
+
+
+		public XMLFileSelector XMLFile
+		{
+			get { return _xmlFile; }
+		}
+
+		public string Name
+		{
+			get { return _name; }
+			private set {
+				if (_name == value) {
+					return;
+				}
+				_name = value;
+				RaisePropertyChanged("Name");
+			}
+		}
+
+		public ObservableCollection<string> CanonicalizationMethods { get; private set; }
+
+		public void SetCanonicalizationMethod(IEnumerable<string> c14NMethods)
+		{
+			CanonicalizationMethods.Clear();
+			foreach (var c14N in c14NMethods) {
+				CanonicalizationMethods.Add(c14N);
+			}
+			RaisePropertyChanged("CanonicalizationMethods");
+		}
+
+		public string DigestMethod
+		{
+			get { return _digestMethod; }
+			set {
+				if (_digestMethod == value) {
+					return;
+				}
+				_digestMethod = value;
+				RaisePropertyChanged("DigestMethod");
+			}
+		}
+
+
+		public string DigestValueComputed
+		{
+			get { return _digestValueComputed; }
+			internal set {
+				if (_digestValueComputed == value) {
+					return;
+				}
+				_digestValueComputed = value;
+				RaisePropertyChanged("DigestValueComputed");
+			}
+		}
+
+
+		public bool? Valid
+		{
+			get { return _valid; }
+			internal set {
+				if (_valid == value) {
+					return;
+				}
+				_valid = value;
+				RaisePropertyChanged("Valid");
+			}
+		}
+
+		public string ValidTooltip
+		{
+			get { return _tooltip; }
+			set {
+				if (_tooltip == value) {
+					return;
+				}
+				_tooltip = value;
+				RaisePropertyChanged("ValidTooltip");
+			}
+		}
+
+		public string Component
+		{
+			get { return _componentType; }
+			set {
+				if (_componentType == value) {
+					return;
+				}
+				_componentType = value;
+				RaisePropertyChanged("Component");
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/HashingTool/ViewModel/UserControl/XMLFile.cs b/HashingTool/ViewModel/UserControl/XMLFileSelector.cs
similarity index 97%
rename from HashingTool/ViewModel/UserControl/XMLFile.cs
rename to HashingTool/ViewModel/UserControl/XMLFileSelector.cs
index 57096aba1e..3dec80d376 100644
--- a/HashingTool/ViewModel/UserControl/XMLFile.cs
+++ b/HashingTool/ViewModel/UserControl/XMLFileSelector.cs
@@ -21,7 +21,7 @@ namespace HashingTool.ViewModel.UserControl
 		ValidXML //									green
 	}
 
-	public class XMLFile : ObservableObject
+	public class XMLFileSelector : ObservableObject
 	{
 		private string _source;
 		private XmlFileStatus _isValid;
@@ -34,7 +34,7 @@ namespace HashingTool.ViewModel.UserControl
 		private bool? _contentValid;
 		private RelayCommand _browseFileCommand;
 
-		public XMLFile(IOService ioservice, bool validate = false,
+		public XMLFileSelector(IOService ioservice, bool validate = false,
 			Func<XmlDocument, Collection<string>, bool?> contentCheck = null)
 		{
 			IoService = ioservice;
@@ -199,11 +199,12 @@ namespace HashingTool.ViewModel.UserControl
 				XMLValidationErrors.Add(e.Message);
 				fileValid = XmlFileStatus.Invalid;
 			} finally {
-				
 				IsValid = fileValid;
 				ContentValid = contentValid;
 				_busy = false;
 				_browseFileCommand.RaiseCanExecuteChanged();
+
+				RaisePropertyChanged("UPDATED");
 			}
 		}
 
diff --git a/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs b/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs
index a2479bbc86..60a099abf1 100644
--- a/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs
+++ b/HashingTool/ViewModel/VerifyComponentInputDataViewModel.cs
@@ -6,6 +6,7 @@ using System.Linq;
 using System.Windows;
 using System.Windows.Input;
 using HashingTool.Helper;
+using HashingTool.ViewModel.UserControl;
 using TUGraz.VectoHashing;
 
 namespace HashingTool.ViewModel
@@ -40,7 +41,7 @@ namespace HashingTool.ViewModel
 
 		private void ComponentFilechanged(object sender, PropertyChangedEventArgs e)
 		{
-			if (e.PropertyName == "Document" || e.PropertyName == "ContentValid") {
+			if (e.PropertyName == "UPDATED") {
 				DoValidateHash();
 			}
 		}
diff --git a/HashingTool/ViewModel/VerifyJobInputDataViewModel.cs b/HashingTool/ViewModel/VerifyJobInputDataViewModel.cs
index a3b3cb8af7..03a69aadff 100644
--- a/HashingTool/ViewModel/VerifyJobInputDataViewModel.cs
+++ b/HashingTool/ViewModel/VerifyJobInputDataViewModel.cs
@@ -14,7 +14,7 @@ namespace HashingTool.ViewModel
 			get { return ApplicationViewModel.HomeView; }
 		}
 
-		public XMLFile JobFile
+		public XMLFileSelector JobFile
 		{
 			get { return _xmlFile; }
 		}
diff --git a/HashingTool/ViewModel/VerifyResultDataViewModel.cs b/HashingTool/ViewModel/VerifyResultDataViewModel.cs
index f0a1b843be..47c181900f 100644
--- a/HashingTool/ViewModel/VerifyResultDataViewModel.cs
+++ b/HashingTool/ViewModel/VerifyResultDataViewModel.cs
@@ -1,9 +1,10 @@
 using System;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
+using System.Linq;
 using System.Windows.Input;
-using System.Xml;
 using HashingTool.Helper;
+using HashingTool.ViewModel.UserControl;
 using TUGraz.VectoHashing;
 
 namespace HashingTool.ViewModel
@@ -12,13 +13,13 @@ namespace HashingTool.ViewModel
 	{
 		private readonly VectoJobFile _jobFile;
 		private readonly ReportXMLFile _customerReport;
-		private readonly ReportXMLFile _manufacturerReport;
+		private readonly ManufacturerReportXMLFile _manufacturerReport;
 
 
 		public VerifyResultDataViewModel()
 		{
 			_jobFile = new VectoJobFile("Job File", HashingHelper.IsJobFile, HashingHelper.HashJobFile);
-			_manufacturerReport = new ReportXMLFile("Manufacturer Report", HashingHelper.IsManufacturerReport,
+			_manufacturerReport = new ManufacturerReportXMLFile("Manufacturer Report", HashingHelper.IsManufacturerReport,
 				HashingHelper.ValidateDocumentHash);
 			_customerReport = new ReportXMLFile("Customer Report", HashingHelper.IsCustomerReport,
 				HashingHelper.ValidateDocumentHash);
@@ -32,10 +33,12 @@ namespace HashingTool.ViewModel
 
 		private void Update(object sender, PropertyChangedEventArgs e)
 		{
-			//RaisePropertyChanged("ManufacturerReportValid");
-			//RaisePropertyChanged("CustomerReportReportValid");
+			if (e.PropertyName != "UPDATED")
+				return;
 			UpdateReportJobDigest(_manufacturerReport);
 			UpdateReportJobDigest(_customerReport);
+
+			_manufacturerReport.JobComponents = _jobFile.Components.ToArray();
 		}
 
 
@@ -60,16 +63,14 @@ namespace HashingTool.ViewModel
 			get { return _customerReport; }
 		}
 
-		public ReportXMLFile ManufacturerReport
+		public ManufacturerReportXMLFile ManufacturerReport
 		{
 			get { return _manufacturerReport; }
 		}
 
 		public ObservableCollection<VectoXMLFile> Files { get; private set; }
 
-		//public bool ManufacturerReportValid
-		//{
-		//	get {
+		
 		private void UpdateReportJobDigest(ReportXMLFile reportXML)
 		{
 			if (reportXML.Valid == null || !reportXML.Valid.Value || _jobFile.XMLFile.Document == null) {
@@ -81,29 +82,9 @@ namespace HashingTool.ViewModel
 				var jobDigest = h.ComputeHash(reportXML.JobCanonicalizationMethodRead,
 					reportXML.JobDigestMethodRead);
 				reportXML.JobDigestValueComputed = jobDigest;
-			} catch (Exception e) {
+			} catch (Exception ) {
 				reportXML.JobDigestValueComputed = "";
 			}
 		}
-
-		//	}
-		//}
-
-		//public bool CustomerReportReportValid
-		//{
-		//	get {
-		//		if (_customerReport.Valid == null || !_customerReport.Valid.Value) {
-		//			return false;
-		//		}
-		//		try {
-		//			var h = VectoHash.Load(_jobFile.XMLFile.Document);
-		//			var jobDigest = h.ComputeHash(_customerReport.JobCanonicalizationMethodRead, _customerReport.JobDigestMethodRead);
-		//			_customerReport.JobDigestValueComputed = jobDigest;
-		//			return _customerReport.JobDigestValueRead == jobDigest;
-		//		} catch (Exception e) {
-		//			return false;
-		//		}
-		//	}
-		//}
 	}
 }
diff --git a/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs b/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs
index 6833ffc72f..3fa92323b3 100644
--- a/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs
+++ b/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs
@@ -7,9 +7,10 @@ namespace HashingTool.Views
 	/// <summary>
 	/// Interaction logic for VectoXMLFileSelector.xaml
 	/// </summary>	
-	public partial class VectoXMLFileSelector 
+	public partial class VectoXMLFileSelector
 	{
-		public static readonly DependencyProperty XMLFileProperty = DependencyProperty.Register("XMLFile", typeof(XMLFile),
+		public static readonly DependencyProperty XMLFileProperty = DependencyProperty.Register("XMLFile",
+			typeof(XMLFileSelector),
 			typeof(VectoXMLFileSelector));
 
 
@@ -19,9 +20,9 @@ namespace HashingTool.Views
 			(Content as FrameworkElement).DataContext = this;
 		}
 
-		public XMLFile XMLFile
+		public XMLFileSelector XMLFile
 		{
-			get { return (XMLFile)GetValue(XMLFileProperty); }
+			get { return (XMLFileSelector)GetValue(XMLFileProperty); }
 			set { SetValue(XMLFileProperty, value); }
 		}
 
@@ -32,6 +33,5 @@ namespace HashingTool.Views
 
 			dialog.ShowDialog();
 		}
-
 	}
 }
diff --git a/HashingTool/Views/VerifyJobInputData.xaml b/HashingTool/Views/VerifyJobInputData.xaml
index ff20b83691..66ce598d87 100644
--- a/HashingTool/Views/VerifyJobInputData.xaml
+++ b/HashingTool/Views/VerifyJobInputData.xaml
@@ -6,6 +6,7 @@
 	xmlns:viewModel="clr-namespace:HashingTool.ViewModel"
 	xmlns:views="clr-namespace:HashingTool.Views"
 	xmlns:helper="clr-namespace:HashingTool.Helper"
+	xmlns:globalization="clr-namespace:System.Globalization;assembly=mscorlib"
 	x:Class="HashingTool.Views.VerifyJobInputData"
 	mc:Ignorable="d"
 	d:DesignHeight="657" d:DesignWidth="534">
@@ -15,7 +16,7 @@
 	<UserControl.DataContext>
 		<viewModel:VerifyJobInputDataViewModel />
 	</UserControl.DataContext>
-	
+
 	<DockPanel>
 
 		<Label DockPanel.Dock="Top" Name="lblHeader" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Top"
@@ -26,164 +27,204 @@
 				Width="75" Height="22" VerticalAlignment="Bottom" />
 		<ScrollViewer>
 			<DockPanel>
-		<Label x:Name="lblFileSelect" DockPanel.Dock="Top" Content="Job data:" HorizontalAlignment="Left" Margin="10,0,0,0"
-				VerticalAlignment="Top" />
-		<views:VectoXMLFileSelector Margin="10,0,10,0" DockPanel.Dock="Top" VerticalAlignment="Top" XMLFile="{Binding JobFile}"
-									Height="80" />
-		<Grid DockPanel.Dock="Top" Margin="0,0,0,0">
-			<Grid.RowDefinitions>
-				<RowDefinition Height="*"/>
-				<RowDefinition Height="Auto" />
-				<RowDefinition Height="Auto" />
-				<RowDefinition Height="Auto" />
-				<RowDefinition Height="Auto" />
-			</Grid.RowDefinitions>
-			<Grid.ColumnDefinitions>
-				<ColumnDefinition Width="Auto" />
-				<ColumnDefinition Width="*" />
-			</Grid.ColumnDefinitions>
-
-			<Label Grid.Row="1" Grid.Column="0" Content="Canonicalization methods:" />
-			<TextBox Grid.Row="1" Grid.Column="1"
-					Text="{Binding CanonicalizationMethods , Converter={StaticResource CollectionConverter}, Mode=OneWay}"
-					Margin="10,2" IsReadOnly="True" />
+				<Label x:Name="lblFileSelect" DockPanel.Dock="Top" Content="Job data:" HorizontalAlignment="Left" Margin="10,0,0,0"
+						VerticalAlignment="Top" />
+				<views:VectoXMLFileSelector Margin="10,0,10,0" DockPanel.Dock="Top" VerticalAlignment="Top"
+											XMLFile="{Binding JobFile}"
+											Height="80" />
+				<Grid DockPanel.Dock="Top"  Margin="10,10,0,10">
+					<Grid.ColumnDefinitions>
+						<ColumnDefinition Width="Auto"/>
+						<ColumnDefinition Width="Auto"  />
+						<ColumnDefinition Width="*" />
+						<ColumnDefinition Width="Auto"  />
+						<ColumnDefinition Width="Auto" MinWidth="100" />
+					</Grid.ColumnDefinitions>
+					<Grid.RowDefinitions>
+						<RowDefinition />
+						<RowDefinition />
+					</Grid.RowDefinitions>
+					<Label Grid.Row="0" Grid.Column="0" Content="Vehicle" FontWeight="Bold" Margin="0,0,10,0" />
+					<Label Grid.Row="0" Grid.Column="1" Content="VIN:" />
+					<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding VehicleIdentificationNumber, Mode=OneWay}"
+							Margin="10,2" IsReadOnly="True" />
+
+					<Label Grid.Row="0" Grid.Column="3" Content="Date:" />
+					<TextBox Grid.Row="0" Grid.Column="4"
+							Text="{helper:CultureAwareBinding Path=JobCreationDate, Mode=OneWay, StringFormat='g'}"
+							Margin="10,2" IsReadOnly="True" />
+				</Grid>
+
+				<Grid DockPanel.Dock="Top" Margin="0,0,0,0">
+					<Grid.RowDefinitions>
+						<RowDefinition Height="*" />
+						<RowDefinition Height="Auto" />
+						<RowDefinition Height="Auto" />
+						<RowDefinition Height="Auto" />
+						<RowDefinition Height="Auto" />
+					</Grid.RowDefinitions>
+					<Grid.ColumnDefinitions>
+						<ColumnDefinition Width="Auto" />
+						<ColumnDefinition Width="*" />
+					</Grid.ColumnDefinitions>
+
+					<Label Grid.Row="1" Grid.Column="0" Content="Canonicalization methods:" />
+					<TextBox Grid.Row="1" Grid.Column="1"
+							Text="{Binding CanonicalizationMethods , Converter={StaticResource CollectionConverter}, Mode=OneWay}"
+							Margin="10,2" IsReadOnly="True" />
 
 					<Label Grid.Row="2" Grid.Column="0" Content="Digest method:" />
 					<TextBox Grid.Row="2" Grid.Column="1"
-					Text="{Binding DigestMethod, Mode=OneWay}"
-					Margin="10,2" IsReadOnly="True" />
-
-					<Label Grid.Row="3" Grid.Column="0" Content="Digest Value computed:" Style="{StaticResource DigestValueLabelStyle}" />
-			<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DigestValueComputed}" Margin="10,2"
-					IsReadOnly="True" Style="{StaticResource DigestValueTextboxStyle}" />
-			<ContentControl Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" Margin="0,10,0,0"
-							VerticalAlignment="Top" Width="50" Height="50">
-				<ContentControl.LayoutTransform>
-					<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
-				</ContentControl.LayoutTransform>
-				<ContentControl.Style>
-					<Style TargetType="ContentControl">
-						<Setter Property="Content" Value="" />
-						<Setter Property="ToolTip" Value="" />
-						<Style.Triggers>
-							<DataTrigger Binding="{Binding JobDataValid}" Value="True">
-								<Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" />
-								<Setter Property="ToolTip" Value="Component data validates against schema" />
-							</DataTrigger>
-							<DataTrigger Binding="{Binding JobDataValid}" Value="False">
-								<Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" />
-								<Setter Property="ToolTip" Value="Component data does NOT validat against schema" />
-							</DataTrigger>
-						</Style.Triggers>
-					</Style>
-				</ContentControl.Style>
-			</ContentControl>
-
-
-			<ScrollViewer Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto"
-						Background="{x:Static SystemColors.ControlLightBrush}"
-						Margin="10,0,10,10">
-				<ItemsControl Margin="3" x:Name="ComponentListing" ItemsSource="{Binding Components}" MinHeight="300">
-					<ItemsControl.ItemContainerStyle>
-						<Style>
-							<Setter Property="FrameworkElement.Margin" Value="0,2" />
-						</Style>
-					</ItemsControl.ItemContainerStyle>
-					<ItemsControl.ItemTemplate>
-						<DataTemplate>
-							<Border BorderBrush="White" BorderThickness="1" CornerRadius="2">
-								<Expander Margin="4" Header="{Binding}" Style="{DynamicResource HeaderStretchExpanderStyle}">
-									<Expander.HeaderTemplate>
-										<DataTemplate>
-											<DockPanel HorizontalAlignment="Stretch">
-												<ContentControl DockPanel.Dock="Right" Width="35" Height="35" Margin="0,0,10,0">
-													<ContentControl.LayoutTransform>
-														<ScaleTransform ScaleX=".4" ScaleY=".4" />
-													</ContentControl.LayoutTransform>
-													<ContentControl.Style>
-														<Style TargetType="ContentControl">
-															<Setter Property="Content" Value="" />
-															<Style.Triggers>
-																<DataTrigger Binding="{Binding Valid}" Value="True">
-																	<Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" />
-																</DataTrigger>
-																<DataTrigger Binding="{Binding Valid}" Value="False">
-																	<Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" />
-																</DataTrigger>
-															</Style.Triggers>
-														</Style>
-													</ContentControl.Style>
-												</ContentControl>
-												<TextBlock DockPanel.Dock="Left" Text="{Binding Component}" Margin="4,0" FontSize="16" FontWeight="Bold" />
-											</DockPanel>
-										</DataTemplate>
-									</Expander.HeaderTemplate>
-									<Expander.Content>
-										<Grid Margin="0,5,0,0">
-											<Grid.RowDefinitions>
-												<RowDefinition />
-												<RowDefinition />
-												<RowDefinition />
-												<RowDefinition/>
-											</Grid.RowDefinitions>
-											<Grid.ColumnDefinitions>
-												<ColumnDefinition Width="Auto"/>
-												<ColumnDefinition Width="*"/>
-											</Grid.ColumnDefinitions>
-											
-												<Label Grid.Row="0" Grid.Column="0" Content="Canonicalization methods:" />
-											<TextBox Grid.Row="0" Grid.Column="1"  Text="{Binding CanonicalizationMethod , Converter={StaticResource CollectionConverter}}"
-														Margin="10,2" IsReadOnly="True" />
-
-													<Label Grid.Row="1" Grid.Column="0" Content="Digest method:" />
-													<TextBox Grid.Row="1" Grid.Column="1"  Text="{Binding DigestMethod}"
-														Margin="10,2" IsReadOnly="True" />
-											
-													<Label Grid.Row="2" Grid.Column="0"  Content="Digest Value read:" Style="{StaticResource DigestValueLabelStyle}" />
-											<TextBox Grid.Row="2" Grid.Column="1"  Text="{Binding DigestValueRead}"
-														Margin="10,2" IsReadOnly="True">
-												<TextBox.Style>
-													<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
-														<Style.Triggers>
-															<DataTrigger Binding="{Binding Valid}" Value="True">
-																<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}"/>
-															</DataTrigger>
-															<DataTrigger Binding="{Binding Valid}" Value="False">
-																<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}"/>
-															</DataTrigger>
-														</Style.Triggers>
-													</Style>
-												</TextBox.Style>
-												</TextBox>
-
-												<Label Grid.Row="3" Grid.Column="0"  Content="Digest Value computed:" Style="{StaticResource DigestValueLabelStyle}" />
-											<TextBox Grid.Row="3" Grid.Column="1"  Text="{Binding DigestValueComputed}"
-														Margin="10,2" IsReadOnly="True" >
-												<TextBox.Style>
-													<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
-														<Style.Triggers>
-															<DataTrigger Binding="{Binding Valid}" Value="True">
-																<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}"/>
-															</DataTrigger>
-															<DataTrigger Binding="{Binding Valid}" Value="False">
-																<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}"/>
-															</DataTrigger>
-														</Style.Triggers>
-													</Style>
-												</TextBox.Style>
-												</TextBox>
-
-										</Grid>
-
-									</Expander.Content>
-								</Expander>
-							</Border>
-						</DataTemplate>
-					</ItemsControl.ItemTemplate>
-				</ItemsControl>
-			</ScrollViewer>
-
-		</Grid>
+							Text="{Binding DigestMethod, Mode=OneWay}"
+							Margin="10,2" IsReadOnly="True" />
+
+					<Label Grid.Row="3" Grid.Column="0" Content="Digest Value computed:"
+							Style="{StaticResource DigestValueLabelStyle}" />
+					<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DigestValueComputed}" Margin="10,2"
+							IsReadOnly="True" Style="{StaticResource DigestValueTextboxStyle}" />
+					<ContentControl Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" Margin="0,10,0,0"
+									VerticalAlignment="Top" Width="50" Height="50">
+						<ContentControl.LayoutTransform>
+							<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
+						</ContentControl.LayoutTransform>
+						<ContentControl.Style>
+							<Style TargetType="ContentControl">
+								<Setter Property="Content" Value="" />
+								<Setter Property="ToolTip" Value="" />
+								<Style.Triggers>
+									<DataTrigger Binding="{Binding JobDataValid}" Value="True">
+										<Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" />
+										<Setter Property="ToolTip" Value="Component data validates against schema" />
+									</DataTrigger>
+									<DataTrigger Binding="{Binding JobDataValid}" Value="False">
+										<Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" />
+										<Setter Property="ToolTip" Value="Component data does NOT validat against schema" />
+									</DataTrigger>
+								</Style.Triggers>
+							</Style>
+						</ContentControl.Style>
+					</ContentControl>
+
+
+					<ScrollViewer Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto"
+								Background="{x:Static SystemColors.ControlLightBrush}"
+								Margin="10,0,10,10">
+						<ItemsControl Margin="3" x:Name="ComponentListing" ItemsSource="{Binding Components}" MinHeight="300">
+							<ItemsControl.ItemContainerStyle>
+								<Style>
+									<Setter Property="FrameworkElement.Margin" Value="0,2" />
+								</Style>
+							</ItemsControl.ItemContainerStyle>
+							<ItemsControl.ItemTemplate>
+								<DataTemplate>
+									<Border BorderBrush="White" BorderThickness="1" CornerRadius="2">
+										<Expander Margin="4" Header="{Binding}" Style="{DynamicResource HeaderStretchExpanderStyle}">
+											<Expander.HeaderTemplate>
+												<DataTemplate>
+													<DockPanel HorizontalAlignment="Stretch">
+														<ContentControl DockPanel.Dock="Right" Width="35" Height="35" Margin="0,0,10,0">
+															<ContentControl.LayoutTransform>
+																<ScaleTransform ScaleX=".4" ScaleY=".4" />
+															</ContentControl.LayoutTransform>
+															<ContentControl.Style>
+																<Style TargetType="ContentControl">
+																	<Setter Property="Content" Value="" />
+																	<Style.Triggers>
+																		<DataTrigger Binding="{Binding Valid}" Value="True">
+																			<Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" />
+																		</DataTrigger>
+																		<DataTrigger Binding="{Binding Valid}" Value="False">
+																			<Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" />
+																		</DataTrigger>
+																	</Style.Triggers>
+																</Style>
+															</ContentControl.Style>
+														</ContentControl>
+														<TextBlock DockPanel.Dock="Left" Text="{Binding Component}" Margin="4,0" FontSize="16" FontWeight="Bold" />
+													</DockPanel>
+												</DataTemplate>
+											</Expander.HeaderTemplate>
+											<Expander.Content>
+												<Grid Margin="0,5,0,0">
+													<Grid.RowDefinitions>
+														<RowDefinition />
+														<RowDefinition />
+														<RowDefinition />
+														<RowDefinition />
+														<RowDefinition />
+													</Grid.RowDefinitions>
+													<Grid.ColumnDefinitions>
+														<ColumnDefinition Width="Auto" />
+														<ColumnDefinition Width="*" />
+														<ColumnDefinition Width="Auto" />
+														<ColumnDefinition Width="Auto" />
+													</Grid.ColumnDefinitions>
+
+													<Label Grid.Row="0" Grid.Column="0" Content="Certification Number:" />
+													<TextBox Grid.Row="0" Grid.Column="1"
+															Text="{Binding CertificationNumber}"
+															Margin="10,2" IsReadOnly="True" />
+													<Label Grid.Row="0" Grid.Column="2" Content="Date:" />
+													<TextBox Grid.Row="0" Grid.Column="3"
+															Text="{helper:CultureAwareBinding Path=CertificationDate, StringFormat='g'}"
+															Margin="10,2" IsReadOnly="True" />
+
+													<Label Grid.Row="1" Grid.Column="0"  Content="Canonicalization methods:" />
+													<TextBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3"
+															Text="{Binding CanonicalizationMethod , Converter={StaticResource CollectionConverter}}"
+															Margin="10,2" IsReadOnly="True" />
+
+													<Label Grid.Row="2" Grid.Column="0"  Content="Digest method:" />
+													<TextBox Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding DigestMethod}"
+															Margin="10,2" IsReadOnly="True" />
+
+													<Label Grid.Row="3" Grid.Column="0"  Content="Digest Value read:"
+															Style="{StaticResource DigestValueLabelStyle}" />
+													<TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding DigestValueRead}"
+															Margin="10,2" IsReadOnly="True">
+														<TextBox.Style>
+															<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+																<Style.Triggers>
+																	<DataTrigger Binding="{Binding Valid}" Value="True">
+																		<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+																	</DataTrigger>
+																	<DataTrigger Binding="{Binding Valid}" Value="False">
+																		<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+																	</DataTrigger>
+																</Style.Triggers>
+															</Style>
+														</TextBox.Style>
+													</TextBox>
+
+													<Label Grid.Row="4" Grid.Column="0" Content="Digest Value computed:"
+															Style="{StaticResource DigestValueLabelStyle}" />
+													<TextBox Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding DigestValueComputed}"
+															Margin="10,2" IsReadOnly="True">
+														<TextBox.Style>
+															<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+																<Style.Triggers>
+																	<DataTrigger Binding="{Binding Valid}" Value="True">
+																		<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+																	</DataTrigger>
+																	<DataTrigger Binding="{Binding Valid}" Value="False">
+																		<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+																	</DataTrigger>
+																</Style.Triggers>
+															</Style>
+														</TextBox.Style>
+													</TextBox>
+
+												</Grid>
+
+											</Expander.Content>
+										</Expander>
+									</Border>
+								</DataTemplate>
+							</ItemsControl.ItemTemplate>
+						</ItemsControl>
+					</ScrollViewer>
+
+				</Grid>
 			</DockPanel>
 		</ScrollViewer>
 	</DockPanel>
diff --git a/HashingTool/Views/VerifyResults.xaml b/HashingTool/Views/VerifyResults.xaml
index b42b13e957..455f9ec4df 100644
--- a/HashingTool/Views/VerifyResults.xaml
+++ b/HashingTool/Views/VerifyResults.xaml
@@ -6,6 +6,7 @@
 	xmlns:viewModel="clr-namespace:HashingTool.ViewModel"
 	xmlns:views="clr-namespace:HashingTool.Views"
 	xmlns:helper="clr-namespace:HashingTool.Helper"
+	xmlns:userControl="clr-namespace:HashingTool.ViewModel.UserControl"
 	x:Class="HashingTool.Views.VerifyResults"
 	mc:Ignorable="d">
 	<UserControl.DataContext>
@@ -14,11 +15,10 @@
 	<UserControl.Resources>
 		<helper:CollectionConverter x:Key="CollectionConverter" />
 
-		<DataTemplate x:Key="ExpanderHeader" DataType="viewModel:VectoXMLFile">
+		<DataTemplate x:Key="ExpanderHeader" DataType="userControl:VectoXMLFile">
 			<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="top" MinWidth="450">
 				<TextBlock DockPanel.Dock="Top" Text="{Binding Name}" FontWeight="Bold" />
-				<ContentControl DockPanel.Dock="Right" Width="35" Height="35" Margin="10,-10,10,0"
-								ToolTip="{Binding JobValidToolTip}">
+				<ContentControl DockPanel.Dock="Right" Width="35" Height="35" Margin="10,-10,10,0">
 					<ContentControl.LayoutTransform>
 						<ScaleTransform ScaleX=".4" ScaleY=".4" />
 					</ContentControl.LayoutTransform>
@@ -42,7 +42,7 @@
 			</DockPanel>
 		</DataTemplate>
 
-		<DataTemplate x:Key="ExpanderHeaderJobFile" DataType="viewModel:VectoJobFile">
+		<DataTemplate x:Key="ExpanderHeaderJobFile" DataType="userControl:VectoJobFile">
 			<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="top" MinWidth="450">
 				<TextBlock DockPanel.Dock="Top" Text="{Binding Name}" FontWeight="Bold" />
 
@@ -67,11 +67,38 @@
 				</ContentControl>
 				<views:VectoXMLFileSelector DockPanel.Dock="Left" Margin="0,0,0,0" VerticalAlignment="Top"
 											XMLFile="{Binding XMLFile}" Height="1" />
+			</DockPanel>
+		</DataTemplate>
+
+		<DataTemplate x:Key="ExpanderHeaderManufacturerReport" DataType="userControl:ManufacturerReportXMLFile">
+			<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="top" MinWidth="450">
+				<TextBlock DockPanel.Dock="Top" Text="{Binding Name}" FontWeight="Bold" />
+				<ContentControl DockPanel.Dock="Right" Width="35" Height="35" Margin="10,-10,10,0">
+					<ContentControl.LayoutTransform>
+						<ScaleTransform ScaleX=".4" ScaleY=".4" />
+					</ContentControl.LayoutTransform>
+					<ContentControl.Style>
+						<Style TargetType="ContentControl">
+							<Setter Property="Content" Value="" />
+							<Style.Triggers>
+								<DataTrigger Binding="{Binding ManufacturerReportValid}" Value="True">
+									<Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" />
+								</DataTrigger>
+								<DataTrigger Binding="{Binding ManufacturerReportValid}" Value="False">
+									<Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" />
+								</DataTrigger>
+							</Style.Triggers>
+						</Style>
+					</ContentControl.Style>
+				</ContentControl>
+				<views:VectoXMLFileSelector DockPanel.Dock="Left" Margin="0,0,0,0" VerticalAlignment="Top"
+											XMLFile="{Binding XMLFile}" Height="1" />
 
 			</DockPanel>
 		</DataTemplate>
 
-		<DataTemplate x:Key="ExpanderContentJobFile" DataType="viewModel:VectoXMLFile">
+
+		<DataTemplate x:Key="ExpanderContentJobFile" DataType="userControl:VectoJobFile">
 			<Grid Grid.IsSharedSizeScope="True">
 				<Grid.RowDefinitions>
 					<RowDefinition />
@@ -128,19 +155,104 @@
 				<Label Grid.Row="3" Grid.Column="0" Content="Digest Value computed:" Style="{StaticResource DigestValueLabelStyle}" />
 				<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DigestValueComputed}"
 						Margin="10,2" IsReadOnly="True" Style="{StaticResource DigestValueTextboxStyle}" />
+
+				<!--<Expander Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Margin="4" Header="Components">-->
+				<GroupBox Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="2" Header="Vehicle Components"
+						Style="{DynamicResource CustomGroupboxStyle}">
+					<Grid IsSharedSizeScope="True" Margin="10,10,0,0">
+						<Grid.ColumnDefinitions>
+							<ColumnDefinition Width="Auto" SharedSizeGroup="ComponentLabel" />
+							<ColumnDefinition Width="Auto" SharedSizeGroup="certificationNbrLabel" />
+							<ColumnDefinition Width="*" />
+							<ColumnDefinition Width="Auto" SharedSizeGroup="dateLabel" />
+							<ColumnDefinition Width="Auto" SharedSizeGroup="dateField" MinWidth="150" />
+						</Grid.ColumnDefinitions>
+						<Grid.RowDefinitions>
+							<RowDefinition />
+							<RowDefinition />
+						</Grid.RowDefinitions>
+
+						<Label Grid.Row="0" Grid.Column="0" Content="Vehicle" FontWeight="Bold" Margin="0,0,10,0" />
+						<Label Grid.Row="0" Grid.Column="1" Content="VIN:" />
+						<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding VehicleIdentificationNumber, Mode=OneWay}"
+								Margin="10,2" IsReadOnly="True" />
+
+						<Label Grid.Row="0" Grid.Column="3" Content="Date:" />
+						<TextBox Grid.Row="0" Grid.Column="4"
+								Text="{helper:CultureAwareBinding Path=JobCreationDate, StringFormat='g', Mode=OneWay}"
+								Margin="10,2" IsReadOnly="True" />
+
+
+						<ItemsControl Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" DockPanel.Dock="Bottom"
+									ItemsSource="{Binding Components}" Margin="0,5,0,0">
+							<ItemsControl.ItemTemplate>
+								<DataTemplate>
+									<Grid Margin="0, 5">
+										<Grid.ColumnDefinitions>
+											<ColumnDefinition Width="Auto" SharedSizeGroup="ComponentLabel" />
+											<ColumnDefinition Width="Auto" SharedSizeGroup="certificationNbrLabel" />
+											<ColumnDefinition Width="*" />
+											<ColumnDefinition Width="Auto" SharedSizeGroup="dateLabel" />
+											<ColumnDefinition Width="Auto" SharedSizeGroup="dateField" />
+										</Grid.ColumnDefinitions>
+										<Grid.RowDefinitions>
+											<RowDefinition />
+											<RowDefinition />
+										</Grid.RowDefinitions>
+
+										<Label Grid.Row="0" Grid.Column="0" Content="{Binding Component}" FontWeight="Bold" Margin="0,0,10,0" />
+										<Label Grid.Row="0" Grid.Column="1" Content="Certification Number:" />
+										<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding CertificationNumber}"
+												Margin="10,2" IsReadOnly="True" />
+										<Label Grid.Row="0" Grid.Column="3" Content="Date:" />
+										<TextBox Grid.Row="0" Grid.Column="4"
+												Text="{helper:CultureAwareBinding Path=CertificationDate, StringFormat='g'}"
+												Margin="10,2" IsReadOnly="True" />
+
+										<Label Grid.Row="1" Grid.Column="1" Content="Digest Value:" />
+										<TextBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="3" Text="{Binding DigestValueRead}"
+												 Margin="10,2" >
+											<TextBox.Style>
+												<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+													<Style.Triggers>
+														<DataTrigger Binding="{Binding Valid}" Value="True">
+															<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}"/>
+														</DataTrigger>
+														<DataTrigger Binding="{Binding Valid}" Value="False">
+															<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}"/>
+															<Setter Property="ToolTip">
+																<Setter.Value>
+																	<TextBlock Text="{Binding DigestValueComputed, StringFormat='{}Computed digest value: {0}'}"></TextBlock>
+																</Setter.Value>
+															</Setter>
+														</DataTrigger>
+													</Style.Triggers>
+												</Style>
+											</TextBox.Style>
+											</TextBox>
+									</Grid>
+								</DataTemplate>
+							</ItemsControl.ItemTemplate>
+
+						</ItemsControl>
+						<!--</Expander>-->
+					</Grid>
+				</GroupBox>
 			</Grid>
 		</DataTemplate>
 
-		<DataTemplate x:Key="ExpanderContentReport" DataType="viewModel:ReportXMLFile">
+		<DataTemplate x:Key="ExpanderContentReport" DataType="userControl:ReportXMLFile">
 			<Grid Grid.IsSharedSizeScope="True">
 				<Grid.RowDefinitions>
 					<RowDefinition />
 					<RowDefinition />
 					<RowDefinition />
+					<RowDefinition />
 				</Grid.RowDefinitions>
 
-				<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
-					<Label>
+				<DockPanel Grid.Row="0" Grid.Column="0">
+
+					<Label DockPanel.Dock="Left">
 						<Label.Content>
 							<TextBlock Text="{Binding XMLFile.XMLValidationErrors.Count, StringFormat='{}{0} Warnings/Errors'}" />
 						</Label.Content>
@@ -155,7 +267,8 @@
 							</Style>
 						</Label.Style>
 					</Label>
-					<Button Margin="10,0,0,0" Content="Details..." HorizontalAlignment="Left" Width="91" Click="Button_Click">
+					<Button DockPanel.Dock="Left" Margin="10,0,0,0" Content="Details..." HorizontalAlignment="Left" Width="91"
+							Click="Button_Click">
 						<Button.Style>
 							<Style TargetType="Button">
 								<Setter Property="IsEnabled" Value="True" />
@@ -167,9 +280,14 @@
 							</Style>
 						</Button.Style>
 					</Button>
-				</StackPanel>
 
-				<GroupBox Grid.Row="1" Header="Report Integrity" Margin="0,0,0,5" Style="{DynamicResource CustomGroupboxStyle}">
+					<TextBox DockPanel.Dock="Right" Text="{helper:CultureAwareBinding Path=CreationDate, StringFormat='g'}"
+							Margin="10,2,20,2" IsReadOnly="True" MinWidth="150" />
+					<Label DockPanel.Dock="Right" Content="Creation Date:" HorizontalAlignment="Right" />
+
+				</DockPanel>
+
+				<GroupBox Grid.Row="2" Header="Report Integrity" Margin="0,0,0,5" Style="{DynamicResource CustomGroupboxStyle}">
 					<Grid>
 						<Grid.ColumnDefinitions>
 							<ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" />
@@ -224,7 +342,8 @@
 						</TextBox>
 					</Grid>
 				</GroupBox>
-				<GroupBox Grid.Row="2" Header="Job Integrity" Style="{DynamicResource CustomGroupboxStyle}">
+
+				<GroupBox Grid.Row="3" Header="Job Integrity" Style="{DynamicResource CustomGroupboxStyle}">
 					<Grid>
 						<Grid.ColumnDefinitions>
 							<ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" />
@@ -281,6 +400,256 @@
 			</Grid>
 		</DataTemplate>
 
+		<DataTemplate x:Key="ExpanderContentManufacturerReport" DataType="userControl:ManufacturerReportXMLFile">
+			<Grid Grid.IsSharedSizeScope="True">
+				<Grid.RowDefinitions>
+					<RowDefinition />
+					<RowDefinition />
+					<RowDefinition />
+					<RowDefinition />
+					<RowDefinition />
+				</Grid.RowDefinitions>
+
+				<DockPanel Grid.Row="0" Grid.Column="0">
+
+					<Label DockPanel.Dock="Left">
+						<Label.Content>
+							<TextBlock Text="{Binding XMLFile.XMLValidationErrors.Count, StringFormat='{}{0} Warnings/Errors'}" />
+						</Label.Content>
+						<Label.Style>
+							<Style TargetType="Label">
+								<Setter Property="Foreground" Value="Red" />
+								<Style.Triggers>
+									<DataTrigger Binding="{Binding XMLFile.XMLValidationErrors.Count}" Value="0">
+										<Setter Property="Foreground" Value="Black" />
+									</DataTrigger>
+								</Style.Triggers>
+							</Style>
+						</Label.Style>
+					</Label>
+					<Button DockPanel.Dock="Left" Margin="10,0,0,0" Content="Details..." HorizontalAlignment="Left" Width="91"
+							Click="Button_Click">
+						<Button.Style>
+							<Style TargetType="Button">
+								<Setter Property="IsEnabled" Value="True" />
+								<Style.Triggers>
+									<DataTrigger Binding="{Binding XMLFile.XMLValidationErrors.Count}" Value="0">
+										<Setter Property="IsEnabled" Value="False" />
+									</DataTrigger>
+								</Style.Triggers>
+							</Style>
+						</Button.Style>
+					</Button>
+
+					<TextBox DockPanel.Dock="Right" Text="{helper:CultureAwareBinding Path=CreationDate, StringFormat='g'}"
+							Margin="10,2,20,2" MinWidth="150" />
+					<Label DockPanel.Dock="Right" Content="Creation Date:" HorizontalAlignment="Right" />
+
+				</DockPanel>
+				<GroupBox Grid.Row="2" Header="Report Integrity" Margin="0,0,0,5" Style="{DynamicResource CustomGroupboxStyle}">
+					<Grid>
+						<Grid.ColumnDefinitions>
+							<ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" />
+							<ColumnDefinition Width="*" />
+						</Grid.ColumnDefinitions>
+						<Grid.RowDefinitions>
+							<RowDefinition />
+							<RowDefinition />
+							<RowDefinition />
+							<RowDefinition />
+						</Grid.RowDefinitions>
+
+						<Label Grid.Row="0" Grid.Column="0" Content="Canonicalization methods:" />
+						<TextBox Grid.Row="0" Grid.Column="1"
+								Text="{Binding CanonicalizationMethods, Mode=OneWay , Converter={StaticResource CollectionConverter}}"
+								Margin="10,2" IsReadOnly="True" />
+
+						<Label Grid.Row="1" Grid.Column="0" Content="Digest method:" />
+						<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding DigestMethod, Mode=OneWay}" Margin="10,2" IsReadOnly="True" />
+
+						<Label Grid.Row="2" Grid.Column="0" Content="Digest Value read:" Style="{StaticResource DigestValueLabelStyle}" />
+						<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding DigestValueRead}" Margin="10,2" IsReadOnly="True">
+							<TextBox.Style>
+								<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+									<Style.Triggers>
+										<DataTrigger Binding="{Binding Valid}" Value="True">
+											<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+										</DataTrigger>
+										<DataTrigger Binding="{Binding Valid}" Value="False">
+											<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+										</DataTrigger>
+									</Style.Triggers>
+								</Style>
+							</TextBox.Style>
+						</TextBox>
+
+						<Label Grid.Row="3" Grid.Column="0" Content="Digest Value computed:"
+								Style="{StaticResource DigestValueLabelStyle}" />
+						<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DigestValueComputed}" Margin="10,2" IsReadOnly="True">
+							<TextBox.Style>
+								<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+									<Style.Triggers>
+										<DataTrigger Binding="{Binding Valid}" Value="True">
+											<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+										</DataTrigger>
+										<DataTrigger Binding="{Binding Valid}" Value="False">
+											<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+										</DataTrigger>
+									</Style.Triggers>
+								</Style>
+							</TextBox.Style>
+						</TextBox>
+					</Grid>
+				</GroupBox>
+
+				<GroupBox Grid.Row="3" Header="Job Integrity" Style="{DynamicResource CustomGroupboxStyle}">
+					<Grid>
+						<Grid.ColumnDefinitions>
+							<ColumnDefinition Width="Auto" SharedSizeGroup="LabelsShareGroup" />
+							<ColumnDefinition Width="*" />
+						</Grid.ColumnDefinitions>
+						<Grid.RowDefinitions>
+							<RowDefinition />
+							<RowDefinition />
+							<RowDefinition />
+							<RowDefinition />
+						</Grid.RowDefinitions>
+						<Label Grid.Row="0" Grid.Column="0" Content="Job CanonicalizationMethod:" />
+						<TextBox Grid.Row="0" Grid.Column="1"
+								Text="{Binding JobCanonicalizationMethodRead, Mode=OneWay, Converter={StaticResource CollectionConverter}}"
+								Margin="10,2" IsReadOnly="True" />
+
+						<Label Grid.Row="1" Grid.Column="0" Content="Job Digest Method:" />
+						<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding JobDigestMethodRead, Mode=OneWay}"
+								Margin="10,2" IsReadOnly="True" />
+
+						<Label Grid.Row="2" Grid.Column="0" Content="Job Digest Value Read:"
+								Style="{StaticResource DigestValueLabelStyle}" />
+						<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding JobDigestValueRead, Mode=OneWay}"
+								Margin="10,2" IsReadOnly="True">
+							<TextBox.Style>
+								<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+									<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+									<Style.Triggers>
+										<DataTrigger Binding="{Binding JobDigestValid}" Value="True">
+											<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+										</DataTrigger>
+									</Style.Triggers>
+								</Style>
+							</TextBox.Style>
+						</TextBox>
+
+						<Label Grid.Row="3" Grid.Column="0" Content="Job Digest Value Computed:"
+								Style="{StaticResource DigestValueLabelStyle}" />
+						<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding JobDigestValueComputed, Mode=OneWay}"
+								Margin="10,2" IsReadOnly="True">
+							<TextBox.Style>
+								<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+									<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+									<Style.Triggers>
+										<DataTrigger Binding="{Binding JobDigestValid}" Value="True">
+											<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+										</DataTrigger>
+									</Style.Triggers>
+								</Style>
+							</TextBox.Style>
+						</TextBox>
+					</Grid>
+				</GroupBox>
+
+				<GroupBox Grid.Row="4" Header="Vehicle Components" Style="{DynamicResource CustomGroupboxStyle}">
+					<Grid Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="2" IsSharedSizeScope="True" Margin="10,10,0,0">
+						<Grid.ColumnDefinitions>
+							<ColumnDefinition Width="Auto" SharedSizeGroup="ComponentLabel" />
+							<ColumnDefinition Width="Auto" SharedSizeGroup="certificationNbrLabel" />
+							<ColumnDefinition Width="*" />
+							<ColumnDefinition Width="Auto" SharedSizeGroup="dateLabel" />
+							<ColumnDefinition Width="Auto" SharedSizeGroup="dateField" />
+						</Grid.ColumnDefinitions>
+						<Grid.RowDefinitions>
+							<RowDefinition />
+							<RowDefinition />
+						</Grid.RowDefinitions>
+
+						<Label Grid.Row="0" Grid.Column="0" Content="Vehicle" FontWeight="Bold" Margin="0,0,10,0" />
+						<Label Grid.Row="0" Grid.Column="1" Content="VIN:" />
+						<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding VehicleIdentificationNumber, Mode=OneWay}"
+								Margin="10,2" IsReadOnly="True" />
+
+						<ItemsControl Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" DockPanel.Dock="Bottom"
+									ItemsSource="{Binding Components}" Margin="0,5,0,0">
+							<ItemsControl.ItemTemplate>
+								<DataTemplate>
+									<Grid Margin="0,5">
+										<Grid.ColumnDefinitions>
+											<ColumnDefinition Width="Auto" SharedSizeGroup="ComponentLabel" />
+											<ColumnDefinition Width="Auto" SharedSizeGroup="certificationNbrLabel" />
+											<ColumnDefinition Width="*" />
+										</Grid.ColumnDefinitions>
+										<Grid.RowDefinitions>
+											<RowDefinition />
+											<RowDefinition />
+										</Grid.RowDefinitions>
+
+										<Label Grid.Row="0" Grid.Column="0" Content="{Binding Component}" FontWeight="Bold" Margin="0,0,10,0" />
+										<Label Grid.Row="0" Grid.Column="1" Content="Certification Number:" />
+										<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding CertificationNumber}"
+												Margin="10,2" IsReadOnly="True">
+											<TextBox.Style>
+												<Style TargetType="TextBox">
+													<Setter Property="IsEnabled" Value="True" />
+													<Style.Triggers>
+														<DataTrigger Binding="{Binding CertificationMethod}" Value="Standard values">
+															<Setter Property="IsEnabled" Value="False" />
+														</DataTrigger>
+														<DataTrigger Binding="{Binding CertificationNumberMatchesJobComponent}" Value="False">
+															<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+															<Setter Property="ToolTip">
+																<Setter.Value>
+																	<TextBlock
+																		Text="{Binding CertificationNumberExpected, StringFormat='{}Expected Certification Number: {0}'}" />
+																</Setter.Value>
+															</Setter>
+														</DataTrigger>
+													</Style.Triggers>
+												</Style>
+											</TextBox.Style>
+										</TextBox>
+
+										<Label Grid.Row="1" Grid.Column="1" Content="Digest Value:" />
+										<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding DigestValue}"
+												Margin="10,2">
+											<TextBox.Style>
+												<Style TargetType="TextBox" BasedOn="{StaticResource DigestValueTextboxStyle}">
+													<Style.Triggers>
+														<DataTrigger Binding="{Binding DigestValueMatchesJobComponent}" Value="True">
+															<Setter Property="Foreground" Value="{StaticResource Color.SuccessGreen}" />
+														</DataTrigger>
+														<DataTrigger Binding="{Binding DigestValueMatchesJobComponent}" Value="False">
+															<Setter Property="Foreground" Value="{StaticResource Color.ErrorRed}" />
+															<Setter Property="ToolTip">
+																<Setter.Value>
+																	<TextBlock Text="{Binding DigestValueExpected, StringFormat='{}Expected Digest Value: {0}'}" />
+																</Setter.Value>
+															</Setter>
+														</DataTrigger>
+													</Style.Triggers>
+												</Style>
+											</TextBox.Style>
+										</TextBox>
+
+									</Grid>
+								</DataTemplate>
+							</ItemsControl.ItemTemplate>
+
+						</ItemsControl>
+						<!--</Expander>-->
+					</Grid>
+				</GroupBox>
+			</Grid>
+		</DataTemplate>
+
+
 		<BorderGapMaskConverter x:Key="BorderGapMaskConverter" />
 
 		<Style x:Key="CustomGroupboxStyle" TargetType="{x:Type GroupBox}">
@@ -353,7 +722,7 @@
 						</Style>
 					</ItemsControl.ItemContainerStyle>
 					<ItemsControl.Resources>
-						<DataTemplate DataType="{x:Type viewModel:VectoJobFile}">
+						<DataTemplate DataType="{x:Type userControl:VectoJobFile}">
 
 							<Border BorderBrush="White" BorderThickness="1" CornerRadius="2" Margin="0,0,3,0">
 								<Expander Margin="2" Header="{Binding}" HorizontalAlignment="Stretch"
@@ -364,7 +733,7 @@
 							</Border>
 
 						</DataTemplate>
-						<DataTemplate DataType="{x:Type viewModel:ReportXMLFile}">
+						<DataTemplate DataType="{x:Type userControl:ReportXMLFile}">
 							<Border BorderBrush="White" BorderThickness="1" CornerRadius="2" Margin="0,0,3,0">
 								<Expander Margin="2" Header="{Binding}" HorizontalAlignment="Stretch"
 										Style="{DynamicResource HeaderStretchExpanderStyle}"
@@ -373,6 +742,16 @@
 							</Border>
 
 						</DataTemplate>
+						<DataTemplate DataType="{x:Type userControl:ManufacturerReportXMLFile}">
+							<Border BorderBrush="White" BorderThickness="1" CornerRadius="2" Margin="0,0,3,0">
+								<Expander Margin="2" Header="{Binding}" HorizontalAlignment="Stretch"
+										Style="{DynamicResource HeaderStretchExpanderStyle}"
+										HeaderTemplate="{DynamicResource ExpanderHeaderManufacturerReport}"
+										ContentTemplate="{DynamicResource ExpanderContentManufacturerReport}"
+										Content="{Binding}" />
+							</Border>
+
+						</DataTemplate>
 					</ItemsControl.Resources>
 
 				</ItemsControl>
@@ -426,7 +805,7 @@
 						<Style TargetType="ContentControl">
 							<Setter Property="ContentTemplate" Value="{StaticResource Icon_NOK}" />
 							<Style.Triggers>
-								<DataTrigger Binding="{Binding ManufacturerReport.JobDigestValid}" Value="True">
+								<DataTrigger Binding="{Binding ManufacturerReport.ManufacturerReportValid}" Value="True">
 									<Setter Property="ContentTemplate" Value="{StaticResource Icon_OK}" />
 								</DataTrigger>
 							</Style.Triggers>
diff --git a/HashingTool/Views/VerifyResults.xaml.cs b/HashingTool/Views/VerifyResults.xaml.cs
index 557207dd44..005603e7cc 100644
--- a/HashingTool/Views/VerifyResults.xaml.cs
+++ b/HashingTool/Views/VerifyResults.xaml.cs
@@ -1,6 +1,7 @@
 using System.Windows;
 using System.Windows.Controls;
 using HashingTool.ViewModel;
+using HashingTool.ViewModel.UserControl;
 
 namespace HashingTool.Views
 {
diff --git a/VectoCommon/VectoHashing/Properties/AssemblyInfo.cs b/VectoCommon/VectoHashing/Properties/AssemblyInfo.cs
index 27c4ea3afa..b337fe1ec3 100644
--- a/VectoCommon/VectoHashing/Properties/AssemblyInfo.cs
+++ b/VectoCommon/VectoHashing/Properties/AssemblyInfo.cs
@@ -29,40 +29,40 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-
-[assembly: AssemblyTitle("VectoHashing")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("VectoHashing")]
-[assembly: AssemblyCopyright("Copyright ©  2017")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-
-[assembly: Guid("334248fa-331e-4255-97fe-617e1a497f6f")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
\ No newline at end of file
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("VectoHashing")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("VectoHashing")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("334248fa-331e-4255-97fe-617e1a497f6f")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
diff --git a/VectoCommon/VectoHashing/VectoHash.cs b/VectoCommon/VectoHashing/VectoHash.cs
index 1f1654c230..29cd8453e9 100644
--- a/VectoCommon/VectoHashing/VectoHash.cs
+++ b/VectoCommon/VectoHashing/VectoHash.cs
@@ -34,6 +34,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Security.Cryptography.X509Certificates;
 using System.Xml;
 using System.Xml.Linq;
 using TUGraz.VectoCommon.Resources;
@@ -89,9 +90,9 @@ namespace TUGraz.VectoHashing
 		{
 			var retVal = new List<VectoComponents>();
 			foreach (var component in EnumHelper.GetValues<VectoComponents>()) {
-				var count =
-					Document.SelectNodes(string.Format("//*[local-name()='{0}']//*[local-name()='{1}']",
-						XMLNames.VectoInputDeclaration, component.XMLElementName())).Count;
+				var nodes = Document.SelectNodes(string.Format("//*[local-name()='{0}']//*[local-name()='{1}']",
+						XMLNames.VectoInputDeclaration, component.XMLElementName()));
+				var count = nodes == null ? 0 : nodes.Count;
 				for (var i = 0; i < count; i++) {
 					retVal.Add(component);
 				}
@@ -318,6 +319,27 @@ namespace TUGraz.VectoHashing
 			return DoReadHash(component, index);
 		}
 
+		public string GetCertificationNumber(VectoComponents component, int idx)
+		{
+			var nodes = GetNodes(component, idx);
+			return ReadElementValue(nodes[idx], XMLNames.Component_CertificationNumber);
+		}
+
+		public DateTime GetCertificationDate(VectoComponents component, int idx)
+		{
+			var nodes = GetNodes(component, idx);
+			return XmlConvert.ToDateTime(ReadElementValue(nodes[idx], XMLNames.Component_Date), XmlDateTimeSerializationMode.RoundtripKind);
+		}
+
+		private string ReadElementValue(XmlNode xmlNode, string elementName)
+		{
+			var node = xmlNode.SelectSingleNode(string.Format("./*[local-name()='{0}']", elementName));
+			if (node == null) {
+				throw new Exception(string.Format("Node '{0}' not found!", elementName));
+			}
+			return node.InnerText;
+		}
+
 		private string DoReadHash(VectoComponents? component, int index)
 		{
 			var nodes = GetNodes(component, index);
@@ -352,7 +374,7 @@ namespace TUGraz.VectoHashing
 		}
 
 
-		private static string GetComponentQueryString(VectoComponents? component = null)
+		protected static string GetComponentQueryString(VectoComponents? component = null)
 		{
 			if (component == null) {
 				return "(//*[@id])[1]";
@@ -390,5 +412,7 @@ namespace TUGraz.VectoHashing
 			}
 			return nodes[0].InnerText;
 		}
+
+		
 	}
 }
-- 
GitLab