Skip to content

Commit

Permalink
Path fragment supports range style notation 1..* or 2..4
Browse files Browse the repository at this point in the history
related #170
  • Loading branch information
cleftheris committed Oct 7, 2020
1 parent 82030c0 commit 8d5ed96
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/indice.Edi/EdiPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace indice.Edi
public struct EdiPath : IComparable<EdiPath>, IEquatable<EdiPath>
{

private const string PARSE_PATTERN = @"^([A-Z]{1}[A-Z0-9]{1,3}|\*)?([\[/]{1}(\d+?|\*)\]?)?([\[\/]{1}(\d+?|\*)\]?)?$"; // supports both "STX/2/1 and STX[2][1]"
private const string PARSE_PATTERN = @"^([A-Z]{1}[A-Z0-9]{1,3}|\*)?([\[\/]{1}([\d\.\*]+)\]?)?([\[\/]{1}([\d\.\*]+)\]?)?$"; // supports both "STX/2/1 and STX[2][1]"

private readonly EdiPathFragment _SegmentPart;
private readonly EdiPathFragment _ElementPart;
Expand Down
61 changes: 60 additions & 1 deletion src/indice.Edi/EdiPathFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace indice.Edi
/// </summary>
public struct EdiPathFragment : IComparable, IEquatable<EdiPathFragment>
{
private static Regex _RangePattern = new Regex(@"^(\d+|\*)\.\.(\d+|\*)$");
private readonly string _Value;

/// <summary>
Expand Down Expand Up @@ -42,6 +43,46 @@ public int Index {
}
}

/// <summary>
/// Converts the value to a zero based index.
/// </summary>
public int Min {
get {
if (!IsRange) return Index;
if ("*..*".Equals(Value))
throw new InvalidCastException(string.Format("Cannot convert the fragment value \"{0}\" to range. Use * instead", Value));
var min = _RangePattern.Match(Value).Groups[1].Value;
if ("*".Equals(min)) {
return 0;
}
var index = 0;
if (int.TryParse(min, out index)) {
return index;
}
throw new InvalidCastException(string.Format("Cannot convert the fragment value \"{0}\" to range. Minimum must be the * or a positive integer", Value));
}
}

/// <summary>
/// Converts the value to a zero based index.
/// </summary>
public int Max {
get {
if (!IsRange) return Index;
if ("*..*".Equals(Value))
throw new InvalidCastException(string.Format("Cannot convert the fragment value \"{0}\" to range. Use * instead", Value));
var max = _RangePattern.Match(Value).Groups[2].Value;
if ("*".Equals(max)) {
return int.MaxValue;
}
var index = 0;
if (int.TryParse(max, out index)) {
return index;
}
throw new InvalidCastException(string.Format("Cannot convert the fragment value \"{0}\" to range. Maximum must be the * or a positive integer", Value));
}
}

/// <summary>
/// If the <see cref="IsWildcard"/> is true then the current path fragment can hold any type of value.
/// This means any type of name in case of the segment name fragment OR any positive <see cref="int"/> for the element and component indices.
Expand All @@ -52,6 +93,16 @@ public bool IsWildcard {
}
}

/// <summary>
/// If the <see cref="IsRange"/> is true then the current path fragment can hold a range of possible indexes.
/// This means any type of name in case of the segment name fragment OR any positive <see cref="int"/> for the element and component indices.
/// </summary>
public bool IsRange {
get {
return Value?.Contains("..") == true;
}
}

/// <summary>
/// Gets a value indicating whether the current <see cref="EdiPathFragment"/> has a value.
/// </summary>
Expand Down Expand Up @@ -104,7 +155,15 @@ public override bool Equals(object obj) {
/// <param name="other">The object to check equality with</param>
/// <returns></returns>
public bool Equals(EdiPathFragment other) {
return IsWildcard || other.IsWildcard || (HasIndex && Index.Equals(other.Index)) || Value.Equals(other.Value);
bool eq = IsWildcard || other.IsWildcard || (HasIndex && Index.Equals(other.Index)) || Value.Equals(other.Value);

if (!eq && (IsRange || other.HasIndex)) {
return Min <= other.Index && Max >= other.Index;
}
else if (!eq && (HasIndex || other.IsRange)) {
return other.Min <= Index && other.Max >= Index;
}
return eq;
}

/// <summary>
Expand Down
15 changes: 15 additions & 0 deletions test/indice.Edi.Tests/EdiTextReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,5 +1007,20 @@ public void BadEscapeSequenseErrorCanbeSuppressed() {
Assert.NotNull(interchange);
Assert.Equal("XYZCOMPANY AVAILABILITY", interchange.AvailabilityRequest.Description[0].Text);
}


[Fact, Trait(Traits.Tag, "EDIFact"), Trait(Traits.Issue, "#170")]
public void EdiFact_ElementList_PathAnnotation_ShouldWork_OnClass() {
var grammar = EdiGrammar.NewEdiFact();
var interchange = default(EdiFact_Issue170_ElementList);
using (var stream = Helpers.GetResourceStream("edifact.Issue170.ElementList.edi")) {
interchange = new EdiSerializer().Deserialize<EdiFact_Issue170_ElementList>(new StreamReader(stream), grammar);
}
Assert.Equal(3, interchange.Msg.InteractiveFreeTexts.Count);
Assert.Equal(3, interchange.Msg.InteractiveFreeTexts[2].Texts.Count);
Assert.Equal("This is the first", interchange.Msg.InteractiveFreeTexts[0].ToString());
Assert.Equal("And this is the seccond", interchange.Msg.InteractiveFreeTexts[1].ToString());
Assert.Equal("while this should come third", interchange.Msg.InteractiveFreeTexts[2].ToString());
}
}
}
44 changes: 44 additions & 0 deletions test/indice.Edi.Tests/Models/EdiFact_Issue170_ElementList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Text;
using indice.Edi.Serialization;

namespace indice.Edi.Tests.Models
{
public class EdiFact_Issue170_ElementList
{
public Message Msg { get; set; }

[EdiMessage]
public class Message
{
public List<InteractiveFreeText> InteractiveFreeTexts { get; set; }
}

[EdiSegment, EdiPath("IFT")]
public class InteractiveFreeText
{
[EdiValue("X(3)", Mandatory = true, Description = "C346-4451", Path = "IFT/0")]
public string Code { get; set; }

[EdiValue("X(4)", Description = "C346-9980", Path = "IFT/0/1")]
public string CodeId { get; set; }

[EdiValue("X(3)", Description = "C346-4405", Path = "IFT/0/2")]
public string Fare { get; set; }

public List<FreeText> Texts { get; set; }

public override string ToString() => string.Join(" ", Texts);
}

[EdiElement, EdiPath("IFT/1..*")] // This take only index [1], but not from [1..*]]
public class FreeText
{
[EdiValue("X(70)", Path = "IFT/*/0")]
public string Text { get; set; }

public override string ToString() => Text;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
UNB+XXXX'
UNH+000001'
IFT+1:1+This+is+the first'
IFT+1:2+And+this is+the seccond'
IFT+1:3+while+this+should come third'
UNT+3'
UNZ+1'

0 comments on commit 8d5ed96

Please sign in to comment.