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

com.toomuchcoding.uptodate.dependency.maven.ComparableVersion Maven / Gradle / Ivy

package com.toomuchcoding.uptodate.dependency.maven;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Properties;
import java.util.Stack;

/**
 * Repackaged from Gradle's org.gradle.mvn3.org.apache.maven.artifact.versioning package
 * for compatibility's sake
 */
@SuppressWarnings("unchecked")
public class ComparableVersion implements Comparable {
    private String value;
    private String canonical;
    private ComparableVersion.ListItem items;

    public ComparableVersion(String version) {
        this.parseVersion(version);
    }

    public final void parseVersion(String version) {
        this.value = version;
        this.items = new ComparableVersion.ListItem();
        version = version.toLowerCase(Locale.ENGLISH);
        ComparableVersion.ListItem list = this.items;
        Stack stack = new Stack();
        stack.push(list);
        boolean isDigit = false;
        int startIndex = 0;

        for(int i = 0; i < version.length(); ++i) {
            char c = version.charAt(i);
            if(c == 46) {
                if(i == startIndex) {
                    list.add(ComparableVersion.IntegerItem.ZERO);
                } else {
                    list.add(parseItem(isDigit, version.substring(startIndex, i)));
                }

                startIndex = i + 1;
            } else if(c == 45) {
                if(i == startIndex) {
                    list.add(ComparableVersion.IntegerItem.ZERO);
                } else {
                    list.add(parseItem(isDigit, version.substring(startIndex, i)));
                }

                startIndex = i + 1;
                if(isDigit) {
                    list.normalize();
                    if(i + 1 < version.length() && Character.isDigit(version.charAt(i + 1))) {
                        list.add(list = new ComparableVersion.ListItem());
                        stack.push(list);
                    }
                }
            } else if(Character.isDigit(c)) {
                if(!isDigit && i > startIndex) {
                    list.add(new ComparableVersion.StringItem(version.substring(startIndex, i), true));
                    startIndex = i;
                }

                isDigit = true;
            } else {
                if(isDigit && i > startIndex) {
                    list.add(parseItem(true, version.substring(startIndex, i)));
                    startIndex = i;
                }

                isDigit = false;
            }
        }

        if(version.length() > startIndex) {
            list.add(parseItem(isDigit, version.substring(startIndex)));
        }

        while(!stack.isEmpty()) {
            list = (ComparableVersion.ListItem)stack.pop();
            list.normalize();
        }

        this.canonical = this.items.toString();
    }

    private static ComparableVersion.Item parseItem(boolean isDigit, String buf) {
        return (ComparableVersion.Item)(isDigit?new ComparableVersion.IntegerItem(buf):new ComparableVersion.StringItem(buf, false));
    }

    public int compareTo(ComparableVersion o) {
        return this.items.compareTo(o.items);
    }

    public String toString() {
        return this.value;
    }

    public boolean equals(Object o) {
        return o instanceof ComparableVersion && this.canonical.equals(((ComparableVersion)o).canonical);
    }

    public int hashCode() {
        return this.canonical.hashCode();
    }

    private static class ListItem extends ArrayList implements ComparableVersion.Item {
        private ListItem() {
        }

        public int getType() {
            return 2;
        }

        public boolean isNull() {
            return this.size() == 0;
        }

        void normalize() {
            ListIterator iterator = this.listIterator(this.size());

            while(iterator.hasPrevious()) {
                ComparableVersion.Item item = (ComparableVersion.Item)iterator.previous();
                if(!item.isNull()) {
                    break;
                }

                iterator.remove();
            }

        }

        public int compareTo(ComparableVersion.Item item) {
            if(item == null) {
                if(this.size() == 0) {
                    return 0;
                } else {
                    ComparableVersion.Item left1 = (ComparableVersion.Item)this.get(0);
                    return left1.compareTo((ComparableVersion.Item)null);
                }
            } else {
                switch(item.getType()) {
                case 0:
                    return -1;
                case 1:
                    return 1;
                case 2:
                    Iterator left = this.iterator();
                    Iterator right = ((ComparableVersion.ListItem)item).iterator();

                    int result;
                    do {
                        if(!left.hasNext() && !right.hasNext()) {
                            return 0;
                        }

                        ComparableVersion.Item l = left.hasNext()?(ComparableVersion.Item)left.next():null;
                        ComparableVersion.Item r = right.hasNext()?(ComparableVersion.Item)right.next():null;
                        result = l == null?-1 * r.compareTo(l):l.compareTo(r);
                    } while(result == 0);

                    return result;
                default:
                    throw new RuntimeException("invalid item: " + item.getClass());
                }
            }
        }

        public String toString() {
            StringBuilder buffer = new StringBuilder("(");
            Iterator iter = this.iterator();

            while(iter.hasNext()) {
                buffer.append(iter.next());
                if(iter.hasNext()) {
                    buffer.append(',');
                }
            }

            buffer.append(')');
            return buffer.toString();
        }
    }

    private static class StringItem implements ComparableVersion.Item {
        private static final String[] QUALIFIERS = new String[]{"alpha", "beta", "milestone", "rc", "snapshot", "", "sp"};
        private static final List _QUALIFIERS;
        private static final Properties ALIASES;
        private static final String RELEASE_VERSION_INDEX;
        private String value;

        public StringItem(String value, boolean followedByDigit) {
            if(followedByDigit && value.length() == 1) {
                switch(value.charAt(0)) {
                case 'a':
                    value = "alpha";
                    break;
                case 'b':
                    value = "beta";
                    break;
                case 'm':
                    value = "milestone";
                }
            }

            this.value = ALIASES.getProperty(value, value);
        }

        public int getType() {
            return 1;
        }

        public boolean isNull() {
            return comparableQualifier(this.value).compareTo(RELEASE_VERSION_INDEX) == 0;
        }

        public static String comparableQualifier(String qualifier) {
            int i = _QUALIFIERS.indexOf(qualifier);
            return i == -1?_QUALIFIERS.size() + "-" + qualifier:String.valueOf(i);
        }

        public int compareTo(ComparableVersion.Item item) {
            if(item == null) {
                return comparableQualifier(this.value).compareTo(RELEASE_VERSION_INDEX);
            } else {
                switch(item.getType()) {
                case 0:
                    return -1;
                case 1:
                    return comparableQualifier(this.value).compareTo(comparableQualifier(((ComparableVersion.StringItem)item).value));
                case 2:
                    return -1;
                default:
                    throw new RuntimeException("invalid item: " + item.getClass());
                }
            }
        }

        public String toString() {
            return this.value;
        }

        static {
            _QUALIFIERS = Arrays.asList(QUALIFIERS);
            ALIASES = new Properties();
            ALIASES.put("ga", "");
            ALIASES.put("final", "");
            ALIASES.put("cr", "rc");
            RELEASE_VERSION_INDEX = String.valueOf(_QUALIFIERS.indexOf(""));
        }
    }

    private static class IntegerItem implements ComparableVersion.Item {
        private static final BigInteger BigInteger_ZERO = new BigInteger("0");
        private final BigInteger value;
        public static final ComparableVersion.IntegerItem ZERO = new ComparableVersion.IntegerItem();

        private IntegerItem() {
            this.value = BigInteger_ZERO;
        }

        public IntegerItem(String str) {
            this.value = new BigInteger(str);
        }

        public int getType() {
            return 0;
        }

        public boolean isNull() {
            return BigInteger_ZERO.equals(this.value);
        }

        public int compareTo(ComparableVersion.Item item) {
            if(item == null) {
                return BigInteger_ZERO.equals(this.value)?0:1;
            } else {
                switch(item.getType()) {
                case 0:
                    return this.value.compareTo(((ComparableVersion.IntegerItem)item).value);
                case 1:
                    return 1;
                case 2:
                    return 1;
                default:
                    throw new RuntimeException("invalid item: " + item.getClass());
                }
            }
        }

        public String toString() {
            return this.value.toString();
        }
    }

    private interface Item {
        int INTEGER_ITEM = 0;
        int STRING_ITEM = 1;
        int LIST_ITEM = 2;

        int compareTo(ComparableVersion.Item var1);

        int getType();

        boolean isNull();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy