com.metaeffekt.artifact.analysis.vulnerability.enrichment.VersionComparator Maven / Gradle / Ivy
/*
* Copyright 2021-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.metaeffekt.artifact.analysis.vulnerability.enrichment;
import java.util.Comparator;
/**
* Source
*/
public class VersionComparator implements Comparator {
public final static VersionComparator INSTANCE = new VersionComparator(false);
public final static VersionComparator INSTANCE_COMMON_PARTS = new VersionComparator(true);
private final boolean useOnlyCommonParts;
private VersionComparator(boolean useOnlyCommonParts) {
this.useOnlyCommonParts = useOnlyCommonParts;
}
public boolean equals(String o1, String o2) {
return compare(o1, o2) == 0;
}
public int compare(String o1, String o2) {
final VersionTokenizer tokenizer1 = new VersionTokenizer(o1);
final VersionTokenizer tokenizer2 = new VersionTokenizer(o2);
long number1, number2;
String suffix1, suffix2;
while (tokenizer1.moveNext()) {
if (!tokenizer2.moveNext()) {
if (useOnlyCommonParts) {
// version two is longer than version one, but return 0 as only the common parts are compared
return 0;
}
do {
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
if (number1 != 0 || !suffix1.isEmpty()) {
// Version one is longer than number two, and non-zero
return 1;
}
}
while (tokenizer1.moveNext());
// Version one is longer than version two, but zero
return 0;
}
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number1 < number2) {
// Number one is less than number two
return -1;
}
if (number1 > number2) {
// Number one is greater than number two
return 1;
}
boolean empty1 = suffix1.isEmpty();
boolean empty2 = suffix2.isEmpty();
if (empty1 && empty2) continue; // No suffixes
if (empty1) return 1; // First suffix is empty (1.2 > 1.2b)
if (empty2) return -1; // Second suffix is empty (1.2a < 1.2)
// Lexical comparison of suffixes
int result = suffix1.compareTo(suffix2);
if (result != 0) return result;
}
if (tokenizer2.moveNext()) {
if (useOnlyCommonParts) {
return 0;
}
do {
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number2 != 0 || !suffix2.isEmpty()) {
// Version one is longer than version two, and non-zero
return -1;
}
}
while (tokenizer2.moveNext());
// Version two is longer than version one, but zero
return 0;
}
return 0;
}
private static class VersionTokenizer {
private final String _versionString;
private final int _length;
private int _position;
private long _number;
private String _suffix;
private boolean _hasValue;
public long getNumber() {
return _number;
}
public String getSuffix() {
return _suffix;
}
public boolean hasValue() {
return _hasValue;
}
public VersionTokenizer(String versionString) {
if (versionString == null)
throw new IllegalArgumentException("versionString is null");
_versionString = versionString;
_length = versionString.length();
}
public boolean moveNext() {
_number = 0;
_suffix = "";
_hasValue = false;
// No more characters
if (_position >= _length)
return false;
_hasValue = true;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c < '0' || c > '9') break;
_number = _number * 10 + (c - '0');
_position++;
}
int suffixStart = _position;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c == '.') break;
_position++;
}
_suffix = _versionString.substring(suffixStart, _position);
if (_position < _length) _position++;
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy