Skip to content

Commit 822bb9e

Browse files
committed
Further refactoring of LicenseTextHelper to reduce complexity
Signed-off-by: Gary O'Neall <[email protected]>
1 parent 918f779 commit 822bb9e

File tree

1 file changed

+70
-36
lines changed

1 file changed

+70
-36
lines changed

src/main/java/org/spdx/licenseTemplate/LicenseTextHelper.java

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.List;
1717
import java.util.Map;
1818
import java.util.Set;
19+
import java.util.function.Predicate;
1920
import java.util.regex.Matcher;
2021
import java.util.regex.Pattern;
2122

@@ -100,6 +101,43 @@ public class LicenseTextHelper {
100101
NORMALIZE_TOKENS.put("\"", "'");
101102
NORMALIZE_TOKENS.put("merchantability", "merchantability");
102103
}
104+
105+
/**
106+
* Class to encapsulate Token iterator
107+
*/
108+
private static class TokenIterator {
109+
private final String[] tokens;
110+
private int position = 0;
111+
private String current;
112+
113+
TokenIterator(String[] tokens) {
114+
this.tokens = tokens;
115+
this.current = getTokenAt(tokens, position++);
116+
}
117+
118+
String current() {
119+
return current;
120+
}
121+
122+
boolean hasNext() {
123+
return current != null;
124+
}
125+
126+
void advance() {
127+
current = getTokenAt(tokens, position++);
128+
}
129+
130+
void skipWhile(Predicate<String> condition) {
131+
while (current != null && condition.test(current)) {
132+
advance();
133+
}
134+
}
135+
136+
boolean hasOnlySkippableTokensRemaining() {
137+
skipWhile(LicenseTextHelper::canSkip);
138+
return current == null;
139+
}
140+
}
103141

104142
private LicenseTextHelper() {
105143
// static class
@@ -143,45 +181,41 @@ public static boolean isLicenseTextEquivalent(String licenseTextA, String licens
143181
* @return true if the license text is equivalent
144182
*/
145183
public static boolean isLicenseTextEquivalent(String[] licenseATokens, String[] licenseBTokens) {
146-
int bTokenCounter = 0;
147-
int aTokenCounter = 0;
148-
String nextAToken = getTokenAt(licenseATokens, aTokenCounter++);
149-
String nextBToken = getTokenAt(licenseBTokens, bTokenCounter++);
150-
while (nextAToken != null) {
151-
if (nextBToken == null) {
152-
// end of b stream
153-
while (canSkip(nextAToken)) {
154-
nextAToken = getTokenAt(licenseATokens, aTokenCounter++);
155-
}
156-
if (nextAToken != null) {
157-
return false; // there is more stuff in the license text B, so not equal
158-
}
159-
} else if (tokensEquivalent(nextAToken, nextBToken)) {
160-
// just move onto the next set of tokens
161-
nextAToken = getTokenAt(licenseATokens, aTokenCounter++);
162-
nextBToken = getTokenAt(licenseBTokens, bTokenCounter++);
163-
} else {
164-
// see if we can skip through some B tokens to find a match
165-
while (canSkip(nextBToken)) {
166-
nextBToken = getTokenAt(licenseBTokens, bTokenCounter++);
167-
}
168-
// just to be sure, skip forward on the A license
169-
while (canSkip(nextAToken)) {
170-
nextAToken = getTokenAt(licenseATokens, aTokenCounter++);
171-
}
172-
if (!tokensEquivalent(nextAToken, nextBToken)) {
173-
return false;
174-
} else {
175-
nextAToken = getTokenAt(licenseATokens, aTokenCounter++);
176-
nextBToken = getTokenAt(licenseBTokens, bTokenCounter++);
177-
}
184+
TokenIterator iterA = new TokenIterator(licenseATokens);
185+
TokenIterator iterB = new TokenIterator(licenseBTokens);
186+
187+
while (iterA.hasNext()) {
188+
if (!iterB.hasNext()) {
189+
return iterA.hasOnlySkippableTokensRemaining();
190+
}
191+
192+
if (tokensEquivalent(iterA.current(), iterB.current())) {
193+
iterA.advance();
194+
iterB.advance();
195+
} else if (!trySkipToMatch(iterA, iterB)) {
196+
return false;
178197
}
179198
}
180-
// need to make sure B is at the end
181-
while (canSkip(nextBToken)) {
182-
nextBToken = getTokenAt(licenseBTokens, bTokenCounter++);
199+
return iterB.hasOnlySkippableTokensRemaining();
200+
}
201+
202+
/**
203+
* Skips any tokens that can be skipped and attempts to match the remaining tokens
204+
// * @param iterA Token iterator for comparison
205+
* @param iterB Token iterator for comparison
206+
* @return true if the tokens match
207+
*/
208+
private static boolean trySkipToMatch(TokenIterator iterA, TokenIterator iterB) {
209+
iterB.skipWhile(LicenseTextHelper::canSkip);
210+
iterA.skipWhile(LicenseTextHelper::canSkip);
211+
212+
if (!tokensEquivalent(iterA.current(), iterB.current())) {
213+
return false;
183214
}
184-
return (nextBToken == null);
215+
216+
iterA.advance();
217+
iterB.advance();
218+
return true;
185219
}
186220

187221
/**

0 commit comments

Comments
 (0)