26 package jdk.jpackage.internal; |
26 package jdk.jpackage.internal; |
27 |
27 |
28 import java.util.ArrayList; |
28 import java.util.ArrayList; |
29 import java.util.List; |
29 import java.util.List; |
30 import java.util.Objects; |
30 import java.util.Objects; |
|
31 import java.util.regex.Pattern; |
31 |
32 |
32 /** |
33 /** |
33 * Dotted numeric version string. |
34 * Dotted numeric version string. |
34 * E.g.: 1.0.37, 10, 0.5 |
35 * E.g.: 1.0.37, 10, 0.5 |
35 */ |
36 */ |
36 class DottedVersion implements Comparable<String> { |
37 class DottedVersion implements Comparable<String> { |
37 |
38 |
38 public DottedVersion(String version) { |
39 public DottedVersion(String version) { |
39 components = parseVersionString(version); |
40 greedy = true; |
|
41 components = parseVersionString(version, greedy); |
40 value = version; |
42 value = version; |
|
43 } |
|
44 |
|
45 private DottedVersion(String version, boolean greedy) { |
|
46 this.greedy = greedy; |
|
47 components = parseVersionString(version, greedy); |
|
48 value = version; |
|
49 } |
|
50 |
|
51 public static DottedVersion greedy(String version) { |
|
52 return new DottedVersion(version); |
|
53 } |
|
54 |
|
55 public static DottedVersion lazy(String version) { |
|
56 return new DottedVersion(version, false); |
41 } |
57 } |
42 |
58 |
43 @Override |
59 @Override |
44 public int compareTo(String o) { |
60 public int compareTo(String o) { |
45 int result = 0; |
61 int result = 0; |
46 int[] otherComponents = parseVersionString(o); |
62 int[] otherComponents = parseVersionString(o, greedy); |
47 for (int i = 0; i < Math.min(components.length, otherComponents.length) |
63 for (int i = 0; i < Math.min(components.length, otherComponents.length) |
48 && result == 0; ++i) { |
64 && result == 0; ++i) { |
49 result = components[i] - otherComponents[i]; |
65 result = components[i] - otherComponents[i]; |
50 } |
66 } |
51 |
67 |
54 } |
70 } |
55 |
71 |
56 return result; |
72 return result; |
57 } |
73 } |
58 |
74 |
59 private static int[] parseVersionString(String version) { |
75 private static int[] parseVersionString(String version, boolean greedy) { |
60 Objects.requireNonNull(version); |
76 Objects.requireNonNull(version); |
61 if (version.isEmpty()) { |
77 if (version.isEmpty()) { |
|
78 if (!greedy) { |
|
79 return new int[] {0}; |
|
80 } |
62 throw new IllegalArgumentException("Version may not be empty string"); |
81 throw new IllegalArgumentException("Version may not be empty string"); |
63 } |
82 } |
64 |
83 |
65 int lastNotZeroIdx = -1; |
84 int lastNotZeroIdx = -1; |
66 List<Integer> components = new ArrayList<>(); |
85 List<Integer> components = new ArrayList<>(); |
67 for (var component : version.split("\\.", -1)) { |
86 for (var component : version.split("\\.", -1)) { |
68 if (component.isEmpty()) { |
87 if (component.isEmpty()) { |
|
88 if (!greedy) { |
|
89 break; |
|
90 } |
|
91 |
69 throw new IllegalArgumentException(String.format( |
92 throw new IllegalArgumentException(String.format( |
70 "Version [%s] contains a zero lenght component", version)); |
93 "Version [%s] contains a zero lenght component", version)); |
71 } |
94 } |
72 |
95 |
73 int num = Integer.parseInt(component); |
96 if (!DIGITS.matcher(component).matches()) { |
74 if (num < 0) { |
97 // Catch "+N" and "-N" cases. |
|
98 if (!greedy) { |
|
99 break; |
|
100 } |
|
101 |
75 throw new IllegalArgumentException(String.format( |
102 throw new IllegalArgumentException(String.format( |
76 "Version [%s] contains invalid component [%s]", version, |
103 "Version [%s] contains invalid component [%s]", version, |
77 component)); |
104 component)); |
|
105 } |
|
106 |
|
107 final int num; |
|
108 try { |
|
109 num = Integer.parseInt(component); |
|
110 } catch (NumberFormatException ex) { |
|
111 if (!greedy) { |
|
112 break; |
|
113 } |
|
114 |
|
115 throw ex; |
78 } |
116 } |
79 |
117 |
80 if (num != 0) { |
118 if (num != 0) { |
81 lastNotZeroIdx = components.size(); |
119 lastNotZeroIdx = components.size(); |
82 } |
120 } |
86 if (lastNotZeroIdx + 1 != components.size()) { |
124 if (lastNotZeroIdx + 1 != components.size()) { |
87 // Strip trailing zeros. |
125 // Strip trailing zeros. |
88 components = components.subList(0, lastNotZeroIdx + 1); |
126 components = components.subList(0, lastNotZeroIdx + 1); |
89 } |
127 } |
90 |
128 |
|
129 if (components.isEmpty()) { |
|
130 components.add(0); |
|
131 } |
91 return components.stream().mapToInt(Integer::intValue).toArray(); |
132 return components.stream().mapToInt(Integer::intValue).toArray(); |
92 } |
133 } |
93 |
134 |
94 @Override |
135 @Override |
95 public String toString() { |
136 public String toString() { |
96 return value; |
137 return value; |
97 } |
138 } |
98 |
139 |
99 final private int[] components; |
140 final private int[] components; |
100 final private String value; |
141 final private String value; |
|
142 final private boolean greedy; |
|
143 |
|
144 private static final Pattern DIGITS = Pattern.compile("\\d+"); |
101 } |
145 } |