diff --git a/src/FasTnT.Domain/Constants.cs b/src/FasTnT.Domain/Constants.cs index e2b5f517..c8f80b02 100644 --- a/src/FasTnT.Domain/Constants.cs +++ b/src/FasTnT.Domain/Constants.cs @@ -6,5 +6,5 @@ public sealed class Constants public int MaxEventsCapturePerCall { get; init; } = 500; public int MaxEventsReturnedInQuery { get; init; } = 20_000; - public Version VendorVersion { get; init; } = Version.Parse("2.4.2"); + public Version VendorVersion { get; init; } = Version.Parse("2.4.3"); } diff --git a/src/FasTnT.Host/Features/v1_2/Communication/Parsers/XmlEventParser.cs b/src/FasTnT.Host/Features/v1_2/Communication/Parsers/XmlEventParser.cs index bad27fd1..f9a0364c 100644 --- a/src/FasTnT.Host/Features/v1_2/Communication/Parsers/XmlEventParser.cs +++ b/src/FasTnT.Host/Features/v1_2/Communication/Parsers/XmlEventParser.cs @@ -11,133 +11,64 @@ public class XmlEventParser public static IEnumerable ParseEvents(XElement root) { - foreach (var element in root.Elements()) - { - var parser = new XmlEventParser(); - - switch (element.Name.LocalName) - { - case "ObjectEvent": - parser.ParseObjectEvent(element); break; - case "TransactionEvent": - parser.ParseTransactionEvent(element); break; - case "AggregationEvent": - parser.ParseAggregationEvent(element); break; - case "QuantityEvent": - parser.ParseQuantityEvent(element); break; - case "extension": - parser.ParseEventListExtension(element); break; - default: - throw new ArgumentException($"Element '{element.Name.LocalName}' not expected in this context"); - } - - yield return parser._evt; - } + return root.Elements().Select(ParseEvent); } - private Event ParseEventListExtension(XElement element) + public static Event ParseEvent(XElement element) { - var eventElement = element.Elements().First(); + var parser = new XmlEventParser(); - return eventElement.Name.LocalName switch + switch (element.Name.LocalName) { - "TransformationEvent" => ParseTransformationEvent(eventElement), - "extension" => ParseEventListSubExtension(eventElement), - _ => throw new ArgumentException($"Element '{element.Name.LocalName}' not expected in this context") - }; - } - - private Event ParseEventListSubExtension(XElement element) - { - var eventElement = element.Elements().First(); + case "QuantityEvent": + parser.ParseQuantityEvent(element); break; + case "ObjectEvent": + parser.ParseEvent(element, EventType.ObjectEvent); break; + case "TransactionEvent": + parser.ParseEvent(element, EventType.TransactionEvent); break; + case "AggregationEvent": + parser.ParseEvent(element, EventType.AggregationEvent); break; + case "extension": + ParseEventListExtension(parser, element); break; + default: + throw new ArgumentException($"Element '{element.Name.LocalName}' not expected in this context"); + } - return eventElement.Name.LocalName == "AssociationEvent" - ? ParseAssociationEvent(eventElement) - : throw new ArgumentException($"Element '{element.Name.LocalName}' not expected in this context"); + return parser._evt; } - public Event ParseObjectEvent(XElement eventRoot) + private static void ParseEventListExtension(XmlEventParser parser, XElement element) { - ParseBase(eventRoot, EventType.ObjectEvent); - ParseTransactions(eventRoot.Element("bizTransactionList")); - ParseEpcList(eventRoot.Element("epcList"), EpcType.List); - ParseObjectExtension(eventRoot.Element("extension")); - - _evt.Action = Enum.Parse(eventRoot.Element("action").Value, true); - - return _evt; - } + var eventElement = element.Elements().First(); - private void ParseObjectExtension(XElement element) - { - if (element == null || element.IsEmpty) + switch (eventElement.Name.LocalName) { - return; + case "TransformationEvent": + parser.ParseEvent(eventElement, EventType.TransformationEvent); break; + case "extension": + ParseEventListSubExtension(parser, eventElement); break; + default: + throw new ArgumentException($"Element '{eventElement.Name.LocalName}' not expected in this context"); } - - ParseEpcQuantityList(element.Element("quantityList"), EpcType.Quantity); - ParseSources(element.Element("sourceList")); - ParseDestinations(element.Element("destinationList")); - ParseIlmd(element.Element("ilmd")); - ParseV2Extensions(element.Element("extension")); } - public Event ParseAggregationEvent(XElement eventRoot) + private static void ParseEventListSubExtension(XmlEventParser parser, XElement element) { - ParseBase(eventRoot, EventType.AggregationEvent); - ParseParentId(eventRoot.Element("parentID")); - ParseEpcList(eventRoot.Element("childEPCs"), EpcType.ChildEpc); - ParseTransactions(eventRoot.Element("bizTransactionList")); - ParseAggregationExtension(eventRoot.Element("extension")); - - _evt.Action = Enum.Parse(eventRoot.Element("action").Value, true); - - return _evt; - } + var eventElement = element.Elements().First(); - private void ParseAggregationExtension(XElement element) - { - if (element == null || element.IsEmpty) + if (eventElement.Name.LocalName == "AssociationEvent") { - return; + parser.ParseEvent(eventElement, EventType.AssociationEvent); } - - ParseEpcQuantityList(element.Element("childQuantityList"), EpcType.ChildQuantity); - ParseSources(element.Element("sourceList")); - ParseDestinations(element.Element("destinationList")); - ParseV2Extensions(element.Element("extension")); - } - - public Event ParseTransactionEvent(XElement eventRoot) - { - ParseBase(eventRoot, EventType.TransactionEvent); - ParseParentId(eventRoot.Element("parentID")); - ParseTransactions(eventRoot.Element("bizTransactionList")); - ParseEpcList(eventRoot.Element("epcList"), EpcType.List); - ParseTransactionExtension(eventRoot.Element("extension")); - - _evt.Action = Enum.Parse(eventRoot.Element("action").Value, true); - - return _evt; - } - - private void ParseTransactionExtension(XElement element) - { - if (element == null || element.IsEmpty) + else { - return; + throw new ArgumentException($"Element '{eventElement.Name.LocalName}' not expected in this context"); } - - ParseEpcQuantityList(element.Element("quantityList"), EpcType.Quantity); - ParseSources(element.Element("sourceList")); - ParseDestinations(element.Element("destinationList")); - ParseV2Extensions(element.Element("extension")); } - public Event ParseQuantityEvent(XElement element) + private void ParseQuantityEvent(XElement element) { - ParseBase(element, EventType.QuantityEvent); - ParseExtension(element.Element("extension"), FieldType.Extension); + ParseEvent(element, EventType.QuantityEvent); _evt.Epcs.Add(new Epc { @@ -145,261 +76,264 @@ public Event ParseQuantityEvent(XElement element) Quantity = float.TryParse(element.Element("quantity")?.Value, NumberStyles.AllowDecimalPoint, new CultureInfo("en-GB"), out var quantity) ? quantity : default, Type = EpcType.Quantity }); - - return _evt; } - public Event ParseTransformationEvent(XElement eventRoot) + private void ParseEvent(XElement element, EventType eventType) { - ParseBase(eventRoot, EventType.TransformationEvent); - ParseTransactions(eventRoot.Element("bizTransactionList")); - ParseSources(eventRoot.Element("sourceList")); - ParseDestinations(eventRoot.Element("destinationList")); - ParseIlmd(eventRoot.Element("ilmd")); - ParseEpcList(eventRoot.Element("inputEPCList"), EpcType.InputEpc); - ParseEpcQuantityList(eventRoot.Element("inputQuantityList"), EpcType.InputQuantity); - ParseEpcList(eventRoot.Element("outputEPCList"), EpcType.OutputEpc); - ParseEpcQuantityList(eventRoot.Element("outputQuantityList"), EpcType.OutputQuantity); - ParseV2Extensions(eventRoot.Element("extension")); - - _evt.TransformationId = eventRoot.Element("transformationID")?.Value; - - return _evt; - } + _evt = new Event { Type = eventType }; - public Event ParseAssociationEvent(XElement eventRoot) - { - ParseBase(eventRoot, EventType.AssociationEvent); - ParseParentId(eventRoot.Element("parentID")); - ParseEpcList(eventRoot.Element("childEPCs"), EpcType.ChildEpc); - ParseTransactions(eventRoot.Element("bizTransactionList")); - ParseAssociationExtension(eventRoot.Element("extension")); - - _evt.Action = Enum.Parse(eventRoot.Element("action").Value, true); - - return _evt; - } - - private void ParseAssociationExtension(XElement element) - { - if (element == null || element.IsEmpty) + foreach (var field in element.Elements()) { - return; + if (string.IsNullOrEmpty(field.Name.NamespaceName)) + { + switch (field.Name.LocalName) + { + case "action": + _evt.Action = Enum.Parse(field.Value, true); break; + case "recordTime": // Discard - this will be overridden + case "epcClass": // These fields are reserved for the (deprecated) Quantity event. Ignore them. + case "quantity": + break; + case "eventTime": + _evt.EventTime = DateTime.Parse(field.Value, null, DateTimeStyles.AdjustToUniversal); break; + case "certificationInfo": + _evt.CertificationInfo = field.Value; break; + case "eventTimeZoneOffset": + _evt.EventTimeZoneOffset = field.Value; break; + case "bizStep": + _evt.BusinessStep = field.Value; break; + case "disposition": + _evt.Disposition = field.Value; break; + case "transformationID": + _evt.TransformationId = field.Value; break; + case "readPoint": + ParseReadPoint(field); break; + case "bizLocation": + ParseBusinessLocation(field); break; + case "eventID": + _evt.EventId = field.Value; break; + case "baseExtension": + ParseBaseExtension(field); break; + case "parentID": + _evt.Epcs.Add(new Epc { Type = EpcType.ParentId, Id = field.Value }); break; + case "epcList": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.List)); break; + case "childEPCs": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.ChildEpc)); break; + case "inputEPCList": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.InputEpc)); break; + case "outputEPCList": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.OutputEpc)); break; + case "quantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.Quantity)); break; + case "childQuantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.ChildQuantity)); break; + case "inputQuantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.InputQuantity)); break; + case "outputQuantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.OutputQuantity)); break; + case "bizTransactionList": + _evt.Transactions.AddRange(ParseTransactionList(field)); break; + case "sourceList": + _evt.Sources.AddRange(ParseSources(field)); break; + case "destinationList": + _evt.Destinations.AddRange(ParseDestinations(field)); break; + case "ilmd": + ParseFields(field, FieldType.Ilmd); break; + case "extension": + ParseEventExtension(field); break; + default: + throw new EpcisException(ExceptionType.ImplementationException, $"Unexpected event field: {field.Name}"); + } + } + else + { + ParseCustomFields(field, FieldType.CustomField, null, null); + } } - - ParseEpcQuantityList(element.Element("childQuantityList"), EpcType.ChildQuantity); - ParseSources(element.Element("sourceList")); - ParseDestinations(element.Element("destinationList")); - ParseV2Extensions(element.Element("extension")); } - public void ParseBase(XElement eventRoot, EventType eventType) - { - _evt = new Event - { - Type = eventType, - EventTime = DateTime.Parse(eventRoot.Element("eventTime").Value, null, DateTimeStyles.AdjustToUniversal), - EventTimeZoneOffset = eventRoot.Element("eventTimeZoneOffset").Value, - BusinessStep = eventRoot.Element("bizStep")?.Value, - Disposition = eventRoot.Element("disposition")?.Value, - }; - - ParseReadPoint(eventRoot.Element("readPoint")); - ParseBusinessLocation(eventRoot.Element("bizLocation")); - ParseBaseExtension(eventRoot.Element("baseExtension")); - ParseFields(eventRoot, FieldType.CustomField); - } - - private void ParseReadPoint(XElement readPoint) + private void ParseEventExtension(XElement element) { - if (readPoint == null || readPoint.IsEmpty) + foreach (var field in element.Elements()) { - return; + switch (field.Name.LocalName) + { + case "childEPCs": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.ChildEpc)); break; + case "inputEPCList": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.InputEpc)); break; + case "outputEPCList": + _evt.Epcs.AddRange(ParseEpcList(field, EpcType.OutputEpc)); break; + case "quantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.Quantity)); break; + case "childQuantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.ChildQuantity)); break; + case "inputQuantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.InputQuantity)); break; + case "outputQuantityList": + _evt.Epcs.AddRange(ParseEpcQuantityList(field, EpcType.OutputQuantity)); break; + case "bizTransactionList": + _evt.Transactions.AddRange(ParseTransactionList(field)); break; + case "sourceList": + _evt.Sources.AddRange(ParseSources(field)); break; + case "destinationList": + _evt.Destinations.AddRange(ParseDestinations(field)); break; + case "ilmd": + ParseFields(field, FieldType.Ilmd); break; + case "persistentDisposition": + _evt.PersistentDispositions.AddRange(ParsePersistentDisposition(field)); break; + case "sensorElementList": + _evt.SensorElements.AddRange(ParseSensorList(field)); break; + case "extension": + ParseEventExtension(field); break; + default: + ParseCustomFields(field, FieldType.Extension, null, null); break; + } } - - _evt.ReadPoint = readPoint.Element("id")?.Value; - ParseExtension(readPoint.Element("extension"), FieldType.ReadPointExtension); - ParseFields(readPoint, FieldType.ReadPointCustomField); } - private void ParseBusinessLocation(XElement bizLocation) + private void ParseBaseExtension(XElement element) { - if (bizLocation == null || bizLocation.IsEmpty) + foreach (var field in element.Elements()) { - return; + if (string.IsNullOrEmpty(field.Name.NamespaceName)) + { + switch (field.Name.LocalName) + { + case "eventID": + _evt.EventId = field.Value; break; + case "errorDeclaration": + ParseErrorDeclaration(field); break; + case "extension": + ParseFields(field, FieldType.BaseExtension); break; + default: + throw new EpcisException(ExceptionType.ImplementationException, $"Unexpected event field: {field.Name}"); + } + } + else + { + ParseCustomFields(field, FieldType.BaseExtension, null, null); + } } - - _evt.BusinessLocation = bizLocation.Element("id")?.Value; - ParseExtension(bizLocation.Element("extension"), FieldType.BusinessLocationExtension); - ParseFields(bizLocation, FieldType.BusinessLocationCustomField); } - private void ParseParentId(XElement element) + private void ParseReadPoint(XElement readPoint) { - if (element == null || element.IsEmpty) + foreach (var field in readPoint.Elements()) { - return; + if (string.IsNullOrEmpty(field.Name.NamespaceName)) + { + switch (field.Name.LocalName) + { + case "id": + _evt.ReadPoint = field.Value; break; + case "extension": + ParseFields(field, FieldType.ReadPointExtension); break; + default: + throw new EpcisException(ExceptionType.ImplementationException, $"Unexpected event field: {field.Name}"); + } + } + else + { + ParseCustomFields(field, FieldType.ReadPointCustomField, null, null); + } } - - _evt.Epcs.Add(new Epc { Id = element.Value, Type = EpcType.ParentId }); } - private void ParseIlmd(XElement element) + private void ParseBusinessLocation(XElement bizLocation) { - if (element == null || element.IsEmpty) + foreach (var field in bizLocation.Elements()) { - return; + if (string.IsNullOrEmpty(field.Name.NamespaceName)) + { + switch (field.Name.LocalName) + { + case "id": + _evt.BusinessLocation = field.Value; break; + case "extension": + ParseFields(field, FieldType.BusinessLocationExtension); break; + default: + throw new EpcisException(ExceptionType.ImplementationException, $"Unexpected event field: {field.Name}"); + } + } + else + { + ParseCustomFields(field, FieldType.BusinessLocationCustomField, null, null); + } } - - ParseFields(element, FieldType.Ilmd); - ParseExtension(element.Element("extension"), FieldType.IlmdExtension); } - private void ParseEpcList(XElement element, EpcType type) + private static IEnumerable ParseEpcList(XElement element, EpcType type) { - if (element == null || element.IsEmpty) - { - return; - } - - _evt.Epcs.AddRange(element.Elements("epc").Select(x => new Epc { Id = x.Value, Type = type })); + return element.Elements("epc").Select(x => new Epc { Id = x.Value, Type = type }); } - private void ParseEpcQuantityList(XElement element, EpcType type) + private static IEnumerable ParseEpcQuantityList(XElement element, EpcType type) { - if (element == null || element.IsEmpty) - { - return; - } - - _evt.Epcs.AddRange(element.Elements("quantityElement").Select(x => new Epc + return element.Elements("quantityElement").Select(x => new Epc { Id = x.Element("epcClass").Value, Quantity = float.TryParse(x.Element("quantity")?.Value, NumberStyles.AllowDecimalPoint, new CultureInfo("en-GB"), out float quantity) ? quantity : default(float?), UnitOfMeasure = x.Element("uom")?.Value, Type = type - })); - } - - private void ParseBaseExtension(XElement element) - { - if (element == null || element.IsEmpty) - { - return; - } - - _evt.EventId = element.Element("eventID")?.Value; - ParseErrorDeclaration(element.Element("errorDeclaration")); - ParseExtension(element.Element("extension"), FieldType.BaseExtension); + }); } - private void ParseV2Extensions(XElement element) + private void ParseErrorDeclaration(XElement element) { - if (element == null || element.IsEmpty) - { - return; - } - foreach (var field in element.Elements()) { - switch (field.Name.LocalName) + if (string.IsNullOrEmpty(field.Name.NamespaceName)) { - case "persistentDisposition": - _evt.PersistentDispositions.AddRange(ParsePersistentDisposition(field)); break; - case "sensorElementList": - _evt.SensorElements.AddRange(ParseSensorList(field)); break; - default: - _evt.Fields.AddRange(ParseCustomFields(field, FieldType.Extension, null)); break; + switch (field.Name.LocalName) + { + case "declarationTime": + _evt.CorrectiveDeclarationTime = DateTime.Parse(field.Value, null, DateTimeStyles.AdjustToUniversal); break; + case "reason": + _evt.CorrectiveReason = field.Value; break; + case "correctiveEventIDs": + _evt.CorrectiveEventIds.AddRange(field.Elements("correctiveEventID").Select(x => new CorrectiveEventId { CorrectiveId = x.Value })); break; + case "extension": + ParseFields(field, FieldType.ErrorDeclarationExtension); break; + default: + throw new EpcisException(ExceptionType.ImplementationException, $"Unexpected event field: {field.Name}"); + } + } + else + { + ParseCustomFields(field, FieldType.ErrorDeclarationCustomField, null, null); } } - - ParseExtension(element.Element("extension"), FieldType.Extension); - } - - private void ParseErrorDeclaration(XElement element) - { - if (element == null || element.IsEmpty) - { - return; - } - - _evt.CorrectiveDeclarationTime = DateTime.Parse(element.Element("declarationTime").Value, null, DateTimeStyles.AdjustToUniversal); - _evt.CorrectiveReason = element.Element("reason")?.Value; - _evt.CorrectiveEventIds.AddRange(element.Element("correctiveEventIDs")?.Elements("correctiveEventID")?.Select(x => new CorrectiveEventId { CorrectiveId = x.Value })); - ParseExtension(element.Element("extension"), FieldType.ErrorDeclarationExtension); - ParseFields(element, FieldType.ErrorDeclarationCustomField); - } - - internal void ParseFields(XElement element, FieldType type) - { - if (element == null || element.IsEmpty) - { - return; - } - - var customFields = element.Elements().Where(x => !string.IsNullOrEmpty(x.Name.NamespaceName)); - _evt.Fields.AddRange(customFields.SelectMany(x => ParseCustomFields(x, type, null))); - } - - internal void ParseExtension(XElement element, FieldType type) - { - if (element == null || element.IsEmpty) - { - return; - } - - var customFields = element.Elements().Where(x => string.IsNullOrEmpty(x.Name.NamespaceName)); - _evt.Fields.AddRange(customFields.SelectMany(x => ParseCustomFields(x, type, null))); - } - - internal void ParseSources(XElement element) - { - if (element == null || element.IsEmpty) - { - return; - } - - _evt.Sources.AddRange(element.Elements("source").Select(CreateSource)); } - internal void ParseDestinations(XElement element) + internal static IEnumerable ParseSources(XElement element) { - if (element == null || element.IsEmpty) + return element.Elements("source").Select(x => new Source { - return; - } - - _evt.Destinations.AddRange(element.Elements("destination").Select(CreateDest)); + Type = x.Attribute("type").Value, + Id = x.Value + }); } - internal void ParseTransactions(XElement element) + internal static IEnumerable ParseDestinations(XElement element) { - if (element == null || element.IsEmpty) + return element.Elements("destination").Select(x => new Destination { - return; - } - - _evt.Transactions.AddRange(element.Elements("bizTransaction").Select(CreateBusinessTransaction)); + Type = x.Attribute("type").Value, + Id = x.Value + }); } - private static BusinessTransaction CreateBusinessTransaction(XElement element) + internal static IEnumerable ParseTransactionList(XElement element) { - return new() + return element.Elements("bizTransaction").Select(x => new BusinessTransaction { - Id = element.Value, - Type = element.Attribute("type")?.Value ?? string.Empty - }; - } - - private static Source CreateSource(XElement element) - { - return new() { Type = element.Attribute("type").Value, Id = element.Value }; + Id = x.Value, + Type = x.Attribute("type")?.Value ?? string.Empty + }); } - private static Destination CreateDest(XElement element) - { - return new() { Type = element.Attribute("type").Value, Id = element.Value }; - } public static IEnumerable ParsePersistentDisposition(XElement field) { return field.Elements().Select(x => new PersistentDisposition @@ -433,7 +367,7 @@ private SensorElement ParseSensorElement(XElement element) } else { - _evt.Fields.AddRange(ParseCustomFields(field, FieldType.Sensor, null)); + ParseCustomFields(field, FieldType.Sensor, null, null); } } @@ -504,11 +438,11 @@ private SensorReport ParseSensorReport(SensorElement sensorElement, XElement ele } else { - _evt.Fields.Add(ParseCustomFields(field, FieldType.SensorReport)); + ParseCustomFields(field, FieldType.SensorReport, null, null); } } - return report; + return report; } private void ParseSensorMetadata(SensorElement sensorElement, XElement metadata) @@ -541,18 +475,26 @@ private void ParseSensorMetadata(SensorElement sensorElement, XElement metadata) } else { - _evt.Fields.Add(ParseCustomFields(field, FieldType.SensorMetadata)); + ParseCustomFields(field, FieldType.SensorMetadata, null, null); } } } - public IEnumerable ParseCustomFields(XElement element, FieldType fieldType, int? parentIndex) + private void ParseFields(XElement element, FieldType fieldType) + { + foreach (var field in element.Elements()) + { + ParseCustomFields(field, fieldType, null, null); + } + } + + private void ParseCustomFields(XElement element, FieldType fieldType, int? parentIndex, int? entityIndex) { - var parsed = new List(); var field = new Field { Index = ++_index, ParentIndex = parentIndex, + EntityIndex = entityIndex, Type = fieldType, Name = element.Name.LocalName, Namespace = string.IsNullOrWhiteSpace(element.Name.NamespaceName) ? default : element.Name.NamespaceName, @@ -561,39 +503,47 @@ public IEnumerable ParseCustomFields(XElement element, FieldType fieldTyp DateValue = element.HasElements ? default : DateTime.TryParse(element.Value, null, DateTimeStyles.AdjustToUniversal, out DateTime dateValue) ? dateValue : default(DateTime?) }; - parsed.Add(field); - parsed.AddRange(element.Elements().SelectMany(x => ParseCustomFields(x, fieldType, field.Index))); - parsed.AddRange(element.Attributes().Where(x => !x.IsNamespaceDeclaration).Select(x => ParseAttribute(x, field.Index))); + foreach (var children in element.Elements()) + { + ParseCustomFields(children, fieldType, field.Index, entityIndex); + } + foreach (var attribute in element.Attributes().Where(x => !x.IsNamespaceDeclaration)) + { + ParseAttribute(attribute, field.Index, entityIndex); + } - return parsed; + _evt.Fields.Add(field); } - public Field ParseCustomFields(XAttribute element, FieldType fieldType) + private void ParseCustomFields(XAttribute element, FieldType fieldType, int? parentIndex, int? entityIndex) { - return new() + _evt.Fields.Add(new() { Index = ++_index, + ParentIndex = parentIndex, + EntityIndex = entityIndex, Type = fieldType, Name = element.Name.LocalName, Namespace = string.IsNullOrWhiteSpace(element.Name.NamespaceName) ? default : element.Name.NamespaceName, TextValue = element.Value, NumericValue = float.TryParse(element.Value, NumberStyles.AllowDecimalPoint, new CultureInfo("en-GB"), out float floatValue) ? floatValue : default(float?), DateValue = DateTime.TryParse(element.Value, null, DateTimeStyles.AdjustToUniversal, out DateTime dateValue) ? dateValue : default(DateTime?) - }; + }); } - public Field ParseAttribute(XAttribute element, int parentIndex) + private void ParseAttribute(XAttribute element, int? parentIndex, int? entityIndex) { - return new() + _evt.Fields.Add(new() { Index = ++_index, ParentIndex = parentIndex, + EntityIndex = entityIndex, Type = FieldType.Attribute, Name = element.Name.LocalName, Namespace = element.Name.NamespaceName, TextValue = element.Value, NumericValue = float.TryParse(element.Value, NumberStyles.AllowDecimalPoint, new CultureInfo("en-GB"), out float floatValue) ? floatValue : default(float?), DateValue = DateTime.TryParse(element.Value, null, DateTimeStyles.AdjustToUniversal, out DateTime dateValue) ? dateValue : default(DateTime?) - }; + }); } } diff --git a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/ObjectEvent_Full.xml b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/ObjectEvent_Full.xml index d2da8de6..d2c2911c 100644 --- a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/ObjectEvent_Full.xml +++ b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/ObjectEvent_Full.xml @@ -8,6 +8,20 @@ urn:epc:id:sscc:4001356.5900000822 OBSERVE + + object:test:event + + 2021-02-15T14:00:00+00:00 + Test reason + + 1234 + 5678 + + + + value + + urn:epcglobal:cbv:bizstep:inspecting urn:epcglobal:cbv:disp:active @@ -28,6 +42,13 @@ KGM + + src + + + src + src2 + 230501 diff --git a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/TransformationEvent_Full.xml b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/TransformationEvent_Full.xml index 6c043765..90edab92 100644 --- a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/TransformationEvent_Full.xml +++ b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/Resources/Events/TransformationEvent_Full.xml @@ -1,49 +1,52 @@  - - 2013-10-31T14:58:56.591Z - -02:00 - - urn:epc:id:sgtin:4012345.011122.25 - urn:epc:id:sgtin:4000001.065432.99886655 - - - - urn:epc:class:lgtin:4012345.011111.4444 - 10 - KGM - - - urn:epc:class:lgtin:0614141.077777.987 - 30 - - - - urn:epc:idpat:sgtin:4012345.066666.* - 220 - - - - - urn:epc:id:sgtin:4012345.077889.25 - urn:epc:id:sgtin:4012345.077889.26 - urn:epc:id:sgtin:4012345.077889.27 - urn:epc:id:sgtin:4012345.077889.28 - - urn:epcglobal:cbv:bizstep:commissioning - urn:epcglobal:cbv:disp:in_progress - - urn:epc:id:sgln:4012345.00001.0 - - - - 2014-12-10 - - XYZ - - Example of a vendor/user extension - \ No newline at end of file + + + 2013-10-31T14:58:56.591Z + 2013-10-31T15:00:00.000Z + -02:00 + + urn:epc:id:sgtin:4012345.011122.25 + urn:epc:id:sgtin:4000001.065432.99886655 + + + + urn:epc:class:lgtin:4012345.011111.4444 + 10 + KGM + + + urn:epc:class:lgtin:0614141.077777.987 + 30 + + + + urn:epc:idpat:sgtin:4012345.066666.* + 220 + + + + + urn:epc:id:sgtin:4012345.077889.25 + urn:epc:id:sgtin:4012345.077889.26 + urn:epc:id:sgtin:4012345.077889.27 + urn:epc:id:sgtin:4012345.077889.28 + + urn:epcglobal:cbv:bizstep:commissioning + urn:epcglobal:cbv:disp:in_progress + + urn:epc:id:sgln:4012345.00001.0 + + + + 2014-12-10 + + XYZ + + Example of a vendor/user extension + + \ No newline at end of file diff --git a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidAggregationEvent.cs b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidAggregationEvent.cs index e5eb3f0b..66ecc02c 100644 --- a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidAggregationEvent.cs +++ b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidAggregationEvent.cs @@ -14,7 +14,7 @@ public class WhenParsingAValidAggregationEvent : XmlParsingTestCase [TestInitialize] public void When() { - Event = new XmlEventParser().ParseAggregationEvent(ParseResource(ResourceName).Root); + Event = XmlEventParser.ParseEvent(ParseResource(ResourceName).Root); } [TestMethod] diff --git a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidObjectEvent.cs b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidObjectEvent.cs index 7f2c143e..a452fdac 100644 --- a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidObjectEvent.cs +++ b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidObjectEvent.cs @@ -14,7 +14,7 @@ public class WhenParsingAValidObjectEvent : XmlParsingTestCase [TestInitialize] public void When() { - Event = new XmlEventParser().ParseObjectEvent(ParseResource(ResourceName).Root); + Event = XmlEventParser.ParseEvent(ParseResource(ResourceName).Root); } [TestMethod] @@ -73,7 +73,7 @@ public void BizTransactionsShouldBeParsedCorrectly() [TestMethod] public void ExtensionFieldsShouldBeParsedCorrectly() { - Assert.AreEqual(1, Event.Fields.Where(x => x.Type == FieldType.Extension).Count()); + Assert.AreEqual(1, Event.Fields.Count(x => x.Type == FieldType.Extension)); Assert.AreEqual(3, Event.Fields.Count(x => x.ParentIndex.HasValue), "children fields should be parsed"); } @@ -99,4 +99,19 @@ public void IlmdShouldBeParsedCorrectly() { Assert.AreEqual(1, Event.Fields.Count(x => x.Type == FieldType.Ilmd)); } + + [TestMethod] + public void ErrorDeclarationShouldBeParsed() + { + Assert.IsNotNull(Event.CorrectiveDeclarationTime); + Assert.IsNotNull(Event.CorrectiveReason); + Assert.AreEqual(2, Event.CorrectiveEventIds.Count); + } + + [TestMethod] + public void ItShouldParseSourceAndDestination() + { + Assert.AreEqual(1, Event.Sources.Count); + Assert.AreEqual(2, Event.Destinations.Count); + } } diff --git a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidTransformationEvent.cs b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidTransformationEvent.cs index abe87cdb..0211aa96 100644 --- a/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidTransformationEvent.cs +++ b/tests/FasTnT.Host.Tests/Features/v1_2/Communication/WhenParsingAValidTransformationEvent.cs @@ -14,7 +14,7 @@ public class WhenParsingAValidTransformationEvent : XmlParsingTestCase [TestInitialize] public void When() { - Event = new XmlEventParser().ParseTransformationEvent(ParseResource(ResourceName).Root); + Event = XmlEventParser.ParseEvent(ParseResource(ResourceName).Root); } [TestMethod]