Skip to content

Commit dbf91ae

Browse files
committed
Move MavenVersion and MavenVersionRange from XABT.
1 parent 4c2fdbe commit dbf91ae

File tree

6 files changed

+484
-4
lines changed

6 files changed

+484
-4
lines changed

src/Java.Interop.Tools.Maven/Extensions/MavenNetExtensions.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ namespace Java.Interop.Tools.Maven.Extensions;
77

88
static class MavenNetExtensions
99
{
10-
public static bool HasValue ([NotNullWhen (true)] this string? str) => !string.IsNullOrEmpty (str);
11-
12-
public static string OrEmpty (this string? str) => str ?? string.Empty;
13-
1410
public static string GetInheritedProperty (this ResolvedDependency dependency, ResolvedProject project, Func<ResolvedDependency, string?> property)
1511
{
1612
// Check our <dependencyManagement> section
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace Java.Interop.Tools.Maven.Extensions;
4+
5+
static class StringExtensions
6+
{
7+
/// <summary>
8+
/// Shortcut for !string.IsNullOrWhiteSpace (s)
9+
/// </summary>
10+
public static bool HasValue ([NotNullWhen (true)] this string? s) => !string.IsNullOrWhiteSpace (s);
11+
12+
/// <summary>
13+
/// Shortcut for s ?? string.Empty
14+
/// </summary>
15+
public static string OrEmpty (this string? str) => str ?? string.Empty;
16+
17+
/// <summary>
18+
/// Removes the first subset of a delimited string. ("127.0.0.1" -> "0.0.1")
19+
/// </summary>
20+
[return: NotNullIfNotNull (nameof (s))]
21+
public static string? ChompFirst (this string? s, char separator)
22+
{
23+
if (!s.HasValue ())
24+
return s;
25+
26+
var index = s.IndexOf (separator);
27+
28+
if (index < 0)
29+
return string.Empty;
30+
31+
return s.Substring (index + 1);
32+
}
33+
34+
/// <summary>
35+
/// Removes the final subset of a delimited string. ("127.0.0.1" -> "127.0.0")
36+
/// </summary>
37+
[return: NotNullIfNotNull (nameof (s))]
38+
public static string? ChompLast (this string? s, char separator)
39+
{
40+
if (!s.HasValue ())
41+
return s;
42+
43+
var index = s.LastIndexOf (separator);
44+
45+
if (index < 0)
46+
return string.Empty;
47+
48+
return s.Substring (0, index);
49+
}
50+
51+
/// <summary>
52+
/// Returns the first subset of a delimited string. ("127.0.0.1" -> "127")
53+
/// </summary>
54+
[return: NotNullIfNotNull (nameof (s))]
55+
public static string? FirstSubset (this string? s, char separator)
56+
{
57+
if (!s.HasValue ())
58+
return s;
59+
60+
var index = s.IndexOf (separator);
61+
62+
if (index < 0)
63+
return s;
64+
65+
return s.Substring (0, index);
66+
}
67+
68+
/// <summary>
69+
/// Returns the final subset of a delimited string. ("127.0.0.1" -> "1")
70+
/// </summary>
71+
[return: NotNullIfNotNull (nameof (s))]
72+
public static string? LastSubset (this string? s, char separator)
73+
{
74+
if (!s.HasValue ())
75+
return s;
76+
77+
var index = s.LastIndexOf (separator);
78+
79+
if (index < 0)
80+
return s;
81+
82+
return s.Substring (index + 1);
83+
}
84+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
using System;
2+
using Java.Interop.Tools.Maven.Extensions;
3+
4+
namespace Java.Interop.Tools.Maven.Models;
5+
6+
// https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855
7+
public class MavenVersion : IComparable, IComparable<MavenVersion>, IEquatable<MavenVersion>
8+
{
9+
public string? Major { get; private set; }
10+
public string? Minor { get; private set; }
11+
public string? Patch { get; private set; }
12+
public string RawVersion { get; private set; }
13+
public bool IsValid { get; private set; } = true;
14+
15+
MavenVersion (string rawVersion) => RawVersion = rawVersion;
16+
17+
public static MavenVersion Parse (string version)
18+
{
19+
var mv = new MavenVersion (version);
20+
21+
if (!version.HasValue ()) {
22+
mv.IsValid = false;
23+
return mv;
24+
}
25+
26+
// We're going to parse through this assuming it's a valid Maven version
27+
mv.Major = version.FirstSubset ('.');
28+
version = version.ChompFirst ('.');
29+
30+
if (!TryParsePart (mv.Major, out var _, out var _))
31+
mv.IsValid = false;
32+
33+
if (!version.HasValue ())
34+
return mv;
35+
36+
mv.Minor = version.FirstSubset ('.');
37+
version = version.ChompFirst ('.');
38+
39+
if (!TryParsePart (mv.Minor, out var _, out var _))
40+
mv.IsValid = false;
41+
42+
if (!version.HasValue ())
43+
return mv;
44+
45+
mv.Patch = version.FirstSubset ('.');
46+
version = version.ChompFirst ('.');
47+
48+
if (!TryParsePart (mv.Patch, out var _, out var _))
49+
mv.IsValid = false;
50+
51+
if (!version.HasValue ())
52+
return mv;
53+
54+
// If there's something left, this is a nonstandard Maven version and all bets are off
55+
mv.IsValid = false;
56+
57+
return mv;
58+
}
59+
60+
public int CompareTo (object obj)
61+
{
62+
return CompareTo (obj as MavenVersion);
63+
}
64+
65+
public int CompareTo (MavenVersion? other)
66+
{
67+
if (other is null)
68+
return 1;
69+
70+
// If either instance is nonstandard, Maven does a simple string compare
71+
if (!IsValid || !other.IsValid)
72+
return string.Compare (RawVersion, other.RawVersion);
73+
74+
var major_compare = ComparePart (Major ?? "0", other.Major ?? "0");
75+
76+
if (major_compare != 0)
77+
return major_compare;
78+
79+
var minor_compare = ComparePart (Minor ?? "0", other.Minor ?? "0");
80+
81+
if (minor_compare != 0)
82+
return minor_compare;
83+
84+
return ComparePart (Patch ?? "0", other.Patch ?? "0");
85+
}
86+
87+
public bool Equals (MavenVersion other)
88+
{
89+
return CompareTo (other) == 0;
90+
}
91+
92+
int ComparePart (string a, string b)
93+
{
94+
// Check if they're the same string
95+
if (a == b)
96+
return 0;
97+
98+
// Don't need to check the return because this shouldn't be called if IsValid = false
99+
TryParsePart (a, out var a_version, out var a_qualifier);
100+
TryParsePart (b, out var b_version, out var b_qualifier);
101+
102+
// If neither have a qualifier, treat them like numbers
103+
if (a_qualifier is null && b_qualifier is null)
104+
return a_version.CompareTo (b_version);
105+
106+
// If the numeric versions are different, just use those
107+
if (a_version != b_version)
108+
return a_version.CompareTo (b_version);
109+
110+
// Identical versions with different qualifier fields are compared by using basic string comparison.
111+
if (a_qualifier is not null && b_qualifier is not null)
112+
return a_qualifier.CompareTo (b_qualifier);
113+
114+
// All versions with a qualifier are older than the same version without a qualifier (release version).
115+
if (a_qualifier is not null)
116+
return -1;
117+
118+
return 1;
119+
}
120+
121+
static bool TryParsePart (string part, out int version, out string? qualifier)
122+
{
123+
// These can look like:
124+
// 1
125+
// 1-anything
126+
var version_string = part.FirstSubset ('-');
127+
qualifier = null;
128+
129+
// The first piece must be a number
130+
if (!int.TryParse (version_string, out version))
131+
return false;
132+
133+
part = part.ChompFirst ('-');
134+
135+
if (part.HasValue ())
136+
qualifier = part;
137+
138+
return true;
139+
}
140+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.Collections.Generic;
2+
using Java.Interop.Tools.Maven.Extensions;
3+
4+
namespace Java.Interop.Tools.Maven.Models;
5+
6+
public class MavenVersionRange
7+
{
8+
public string? MinVersion { get; private set; }
9+
public string? MaxVersion { get; private set; }
10+
public bool IsMinInclusive { get; private set; } = true;
11+
public bool IsMaxInclusive { get; private set; }
12+
public bool HasLowerBound { get; private set; }
13+
public bool HasUpperBound { get; private set; }
14+
15+
// Adapted from https://github.com/Redth/MavenNet/blob/master/MavenNet/MavenVersionRange.cs
16+
// Original version uses NuGetVersion, which doesn't cover all "valid" Maven version cases
17+
public static IEnumerable<MavenVersionRange> Parse (string range)
18+
{
19+
if (!range.HasValue ())
20+
yield break;
21+
22+
// Do a pass over the range string to parse out version groups
23+
// eg: (1.0],(1.1,]
24+
var in_group = false;
25+
var current_group = string.Empty;
26+
27+
foreach (var c in range) {
28+
if (c == '(' || c == '[') {
29+
current_group += c;
30+
in_group = true;
31+
} else if (c == ')' || c == ']' || (!in_group && c == ',')) {
32+
// Don't add the , separating groups
33+
if (in_group)
34+
current_group += c;
35+
36+
in_group = false;
37+
38+
if (current_group.HasValue ())
39+
yield return ParseSingle (current_group);
40+
41+
current_group = string.Empty;
42+
} else {
43+
current_group += c;
44+
}
45+
}
46+
47+
if (!string.IsNullOrEmpty (current_group))
48+
yield return ParseSingle (current_group);
49+
}
50+
51+
static MavenVersionRange ParseSingle (string range)
52+
{
53+
var mv = new MavenVersionRange ();
54+
55+
// Check for opening ( or [
56+
if (range [0] == '(') {
57+
mv.IsMinInclusive = false;
58+
range = range.Substring (1);
59+
} else if (range [0] == '[') {
60+
range = range.Substring (1);
61+
}
62+
63+
var last = range.Length - 1;
64+
65+
// Check for closing ) or ]
66+
if (range [last] == ')') {
67+
mv.IsMaxInclusive = false;
68+
range = range.Substring (0, last);
69+
} else if (range [last] == ']') {
70+
mv.IsMaxInclusive = true;
71+
range = range.Substring (0, last);
72+
}
73+
74+
// Look for a single value
75+
if (!range.Contains (",")) {
76+
mv.MinVersion = range;
77+
mv.HasLowerBound = true;
78+
79+
// Special case [1.0]
80+
if (mv.IsMinInclusive && mv.IsMaxInclusive) {
81+
mv.MaxVersion = range;
82+
mv.HasUpperBound = true;
83+
}
84+
85+
return mv;
86+
}
87+
88+
// Split the 2 values (note either can be empty)
89+
var lower = range.FirstSubset (',').Trim ();
90+
var upper = range.LastSubset (',').Trim ();
91+
92+
if (lower.HasValue ()) {
93+
mv.MinVersion = lower;
94+
mv.HasLowerBound = true;
95+
}
96+
97+
if (upper.HasValue ()) {
98+
mv.MaxVersion = upper;
99+
mv.HasUpperBound = true;
100+
}
101+
102+
return mv;
103+
}
104+
105+
public bool ContainsVersion (MavenVersion version)
106+
{
107+
if (HasLowerBound) {
108+
var min_version = MavenVersion.Parse (MinVersion!);
109+
110+
if (IsMinInclusive && version.CompareTo (min_version) < 0)
111+
return false;
112+
else if (!IsMinInclusive && version.CompareTo (min_version) <= 0)
113+
return false;
114+
}
115+
116+
if (HasUpperBound) {
117+
var max_version = MavenVersion.Parse (MaxVersion!);
118+
119+
if (IsMaxInclusive && version.CompareTo (max_version) > 0)
120+
return false;
121+
else if (!IsMaxInclusive && version.CompareTo (max_version) >= 0)
122+
return false;
123+
}
124+
125+
return true;
126+
}
127+
}

0 commit comments

Comments
 (0)