All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metaeffekt.artifact.analysis.vulnerability.enrichment.VersionComparator Maven / Gradle / Ivy

There is a newer version: 0.132.0
Show newest version
/*
 * 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