diff --git a/VectoCommon/VectoHashing/VectoComponents.cs b/VectoCommon/VectoHashing/VectoComponents.cs index 08f873020f5144e198a9f18c8c4b7783bfc7f4af..81665bc0e7f19511112365273f643a9e5f949907 100644 --- a/VectoCommon/VectoHashing/VectoComponents.cs +++ b/VectoCommon/VectoHashing/VectoComponents.cs @@ -29,84 +29,84 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using TUGraz.VectoCommon.Resources; - -namespace TUGraz.VectoHashing -{ - public enum VectoComponents - { - Engine, - Gearbox, - Axlegear, - Retarder, - TorqueConverter, - Angledrive, - Airdrag, - Tyre, - Vehicle, - VectoOutput, - VectoCustomerInformation - } - - public static class VectoComponentsExtensionMethods - { - public static string XMLElementName(this VectoComponents component) - { - switch (component) { - case VectoComponents.Engine: - return XMLNames.Component_Engine; - case VectoComponents.Gearbox: - return XMLNames.Component_Gearbox; - case VectoComponents.Axlegear: - return XMLNames.Component_Axlegear; - case VectoComponents.Retarder: - return XMLNames.Component_Retarder; - case VectoComponents.TorqueConverter: - return XMLNames.Component_TorqueConverter; - case VectoComponents.Angledrive: - return XMLNames.Component_Angledrive; - case VectoComponents.Airdrag: - return XMLNames.Component_AirDrag; - case VectoComponents.Tyre: - return XMLNames.AxleWheels_Axles_Axle_Tyre; - case VectoComponents.Vehicle: - return XMLNames.Component_Vehicle; - case VectoComponents.VectoOutput: - return "VectoOutput"; - case VectoComponents.VectoCustomerInformation: - return "VectoCustomerInformation"; - default: - throw new ArgumentOutOfRangeException("VectoComponents", component, null); - } - } - - public static string HashIdPrefix(this VectoComponents component) - { - switch (component) { - case VectoComponents.Engine: - return "ENG-"; - case VectoComponents.Gearbox: - return "GBX-"; - case VectoComponents.Axlegear: - return "AXL-"; - case VectoComponents.Retarder: - return "RET-"; - case VectoComponents.TorqueConverter: - return "TC-"; - case VectoComponents.Angledrive: - return "ANGL-"; - case VectoComponents.Airdrag: - return "AD-"; - case VectoComponents.Tyre: - return "TYRE-"; - case VectoComponents.VectoOutput: - return "RESULT-"; - case VectoComponents.VectoCustomerInformation: - return "COC-"; - default: - throw new ArgumentOutOfRangeException("VectoComponents", component, null); - } - } - } +using System; +using TUGraz.VectoCommon.Resources; + +namespace TUGraz.VectoHashing +{ + public enum VectoComponents + { + Engine, + Gearbox, + Axlegear, + Retarder, + TorqueConverter, + Angledrive, + Airdrag, + Tyre, + Vehicle, + VectoOutput, + VectoCustomerInformation + } + + public static class VectoComponentsExtensionMethods + { + public static string XMLElementName(this VectoComponents component) + { + switch (component) { + case VectoComponents.Engine: + return XMLNames.Component_Engine; + case VectoComponents.Gearbox: + return XMLNames.Component_Gearbox; + case VectoComponents.Axlegear: + return XMLNames.Component_Axlegear; + case VectoComponents.Retarder: + return XMLNames.Component_Retarder; + case VectoComponents.TorqueConverter: + return XMLNames.Component_TorqueConverter; + case VectoComponents.Angledrive: + return XMLNames.Component_Angledrive; + case VectoComponents.Airdrag: + return XMLNames.Component_AirDrag; + case VectoComponents.Tyre: + return XMLNames.AxleWheels_Axles_Axle_Tyre; + case VectoComponents.Vehicle: + return XMLNames.Component_Vehicle; + case VectoComponents.VectoOutput: + return "VectoOutput"; + case VectoComponents.VectoCustomerInformation: + return "VectoCustomerInformation"; + default: + throw new ArgumentOutOfRangeException("VectoComponents", component, null); + } + } + + public static string HashIdPrefix(this VectoComponents component) + { + switch (component) { + case VectoComponents.Engine: + return "ENG-"; + case VectoComponents.Gearbox: + return "GBX-"; + case VectoComponents.Axlegear: + return "AXL-"; + case VectoComponents.Retarder: + return "RET-"; + case VectoComponents.TorqueConverter: + return "TC-"; + case VectoComponents.Angledrive: + return "ANGL-"; + case VectoComponents.Airdrag: + return "AD-"; + case VectoComponents.Tyre: + return "TYRE-"; + case VectoComponents.VectoOutput: + return "RESULT-"; + case VectoComponents.VectoCustomerInformation: + return "COC-"; + default: + throw new ArgumentOutOfRangeException("VectoComponents", component, null); + } + } + } } \ No newline at end of file diff --git a/VectoCommon/VectoHashing/VectoHash.cs b/VectoCommon/VectoHashing/VectoHash.cs index 67a8b759a69f2e1adf5d90bbc735f4e789e139a7..22a0d468df16149266d70a1a0ad9008ca45826d6 100644 --- a/VectoCommon/VectoHashing/VectoHash.cs +++ b/VectoCommon/VectoHashing/VectoHash.cs @@ -155,44 +155,27 @@ namespace TUGraz.VectoHashing public XDocument AddHash() { - if (Document.DocumentElement == null) { - throw new Exception("invalid input document"); - } - IList<VectoComponents> components; - if (Document.DocumentElement.LocalName.Equals(XMLNames.VectoInputDeclaration)) { - components = GetContainigComponents(); - if (components.Contains(VectoComponents.Vehicle)) { - throw new Exception("adding hash for Vehicle is not supported"); - } - if (components.Count > 1) { - throw new Exception("input must not contain multiple components!"); - } - if (components.Count == 0) { - throw new Exception("input does not contain a known component!"); - } - } else if (Document.DocumentElement.LocalName.Equals("VectoOutput")) { - components = new List<VectoComponents>() { VectoComponents.VectoOutput }; - } else if (Document.DocumentElement.LocalName.Equals("VectoCustomerInformation")) { - components = new List<VectoComponents>() { VectoComponents.VectoCustomerInformation }; - } else { - throw new Exception("unknown document structure! neither input data nor output data format"); - } - var query = string.Format("//*[local-name()='{0}']/*[local-name()='Data']", components[0].XMLElementName()); + var component = GetComponentToHash(); + var query = string.Format("//*[local-name()='{0}']/*[local-name()='Data']", component.XMLElementName()); var node = Document.SelectSingleNode(query); if (node == null) { - throw new Exception(string.Format("'Data' element for component '{0}' not found!", components[0].XMLElementName())); + throw new Exception(string.Format("'Data' element for component '{0}' not found!", component.XMLElementName())); } - query = string.Format("//*[local-name()='{0}']/*[local-name()='Signature']", components[0].XMLElementName()); + query = string.Format("//*[local-name()='{0}']/*[local-name()='Signature']", component.XMLElementName()); var sigNodes = Document.SelectNodes(query); if (sigNodes != null && sigNodes.Count > 0) { throw new Exception("input data already contains a signature element"); } var attributes = node.Attributes; - var id = components[0].HashIdPrefix() + Guid.NewGuid().ToString("n").Substring(0, 20); + var id = component.HashIdPrefix() + Guid.NewGuid().ToString("n").Substring(0, 20); var idSet = false; if (attributes != null && attributes[XMLNames.Component_ID_Attr] != null) { - attributes[XMLNames.Component_ID_Attr].Value = id; + if (attributes[XMLNames.Component_ID_Attr].Value.Length < 5) { + attributes[XMLNames.Component_ID_Attr].Value = id; + } else { + id = attributes[XMLNames.Component_ID_Attr].Value; + } idSet = true; } if (!idSet) { @@ -204,6 +187,16 @@ namespace TUGraz.VectoHashing node.Attributes.Append(attr); } + query = component == VectoComponents.VectoCustomerInformation || component == VectoComponents.VectoOutput + ? string.Format("*/*[local-name()='Data']/*[local-name()='ApplicationInformation']/*[local-name()='Date']") + : string.Format("*/*[local-name()='{0}']/*/*[local-name()='Date']", component); + var dateNode = Document.SelectSingleNode(query); + if (dateNode == null) { + throw new Exception("Date-Element not found in input!"); + } + dateNode.FirstChild.Value = XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.Utc); + + var hash = XMLHashProvider.ComputeHash(Document, id); var sig = Document.CreateElement(XMLNames.DI_Signature, node.NamespaceURI); @@ -215,6 +208,33 @@ namespace TUGraz.VectoHashing return Document.ToXDocument(); } + private VectoComponents GetComponentToHash() + { + if (Document.DocumentElement == null) { + throw new Exception("invalid input document"); + } + if (Document.DocumentElement.LocalName.Equals(XMLNames.VectoInputDeclaration)) { + var components = GetContainigComponents(); + if (components.Contains(VectoComponents.Vehicle)) { + throw new Exception("adding hash for Vehicle is not supported"); + } + if (components.Count > 1) { + throw new Exception("input must not contain multiple components!"); + } + if (components.Count == 0) { + throw new Exception("input does not contain a known component!"); + } + return components.First(); + } + if (Document.DocumentElement.LocalName.Equals("VectoOutput")) { + return VectoComponents.VectoOutput; + } + if (Document.DocumentElement.LocalName.Equals("VectoCustomerInformation")) { + return VectoComponents.VectoCustomerInformation; + } + throw new Exception("unknown document structure! neither input data nor output data format"); + } + public string ReadHash() { var nodes = Document.SelectNodes(GetComponentQueryString()); diff --git a/VectoCommon/VectoHashingTest/VectoHashTest.cs b/VectoCommon/VectoHashingTest/VectoHashTest.cs index a38bbeacaa4f12c341bbeb90019ade3c44ff749a..8075dc91655b067f4993c1552c13226721c937ed 100644 --- a/VectoCommon/VectoHashingTest/VectoHashTest.cs +++ b/VectoCommon/VectoHashingTest/VectoHashTest.cs @@ -36,6 +36,7 @@ using System.Text; using System.Xml; using System.Xml.Linq; using System.Xml.Schema; +using System.Xml.XPath; using NUnit.Framework; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; @@ -276,6 +277,67 @@ namespace VectoHashingTest Assert.IsTrue(h2.ValidateHash()); } + [TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 5), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 10), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 15), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 20), + ] + public void TestAddHashoDoNotOverwriteID(string file, int idLength) + { + var newid = "x" + Guid.NewGuid().ToString("n").Substring(0, idLength - 1); + var input = new XmlDocument(); + input.Load(file); + var data = input.SelectSingleNode("//*[local-name()='Data']"); + data.Attributes["id"].Value = newid; + + var h = VectoHash.Load(input); + var r = h.AddHash(); + + var id = r.XPathSelectElement("//*[local-name()='Data']"); + Assert.IsNotNull(id.Attribute("id")); + Assert.AreEqual(newid, id.Attribute("id").Value); + } + + [TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 2), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 3), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml", 4)] + public void TestAddHashoDoOverwriteID(string file, int idLength) + { + var newid = "x" + Guid.NewGuid().ToString("n").Substring(0, idLength - 1); + var input = new XmlDocument(); + input.Load(file); + var data = input.SelectSingleNode("//*[local-name()='Data']"); + data.Attributes["id"].Value = newid; + + var h = VectoHash.Load(input); + var r = h.AddHash(); + + var id = r.XPathSelectElement("//*[local-name()='Data']"); + Assert.IsNotNull(id.Attribute("id")); + Assert.AreNotEqual(newid, id.Attribute("id").Value); + } + + [TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml")] + public void TestReplaceDate(string file) + { + var input = new XmlDocument(); + input.Load(file); + var dateNode = input.SelectSingleNode("//*[local-name()='Date']"); + var date = XmlConvert.ToDateTime(dateNode.FirstChild.Value); + + var h = VectoHash.Load(input); + var r = h.AddHash(); + + var newDateNode = r.XPathSelectElement("//*[local-name()='Date']"); + var newDate = XmlConvert.ToDateTime(newDateNode.Value); + + var now = DateTime.Now; + + Assert.AreNotEqual(date.ToString(), newDate.ToString()); + Assert.IsTrue(now - date > new TimeSpan(0, 0, 0, 1)); + Assert.IsTrue(now - newDate < new TimeSpan(0, 0, 0, 1)); + } + [TestCase(@"Testdata\XML\ToHash\vecto_engine_withhash-input.xml", "input data already contains a signature element"), TestCase(@"Testdata\XML\ToHash\vecto_vehicle-sample.xml", "adding hash for Vehicle is not supported"), TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input_nodata.xml", "'Data' element for component 'Gearbox' not found!"),