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

net.sf.uadetector.VersionNumber Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright 2012 André Rouél
 *
 * 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 net.sf.uadetector;


import net.sf.uadetector.exception.IllegalStateOfArgumentException;
import net.sf.uadetector.internal.Check;
import net.sf.uadetector.internal.util.NaturalOrderComparator;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

/**
 * The {@code VersionNumber} class represents the version number of an operating system or User-Agent.
*
* A {@code VersionNumber} object is immutable, their values cannot be changed after creation. * * @author André Rouél */ public final class VersionNumber implements ReadableVersionNumber, Serializable { /** * Empty extension or addition of a version number */ public static final String EMPTY_EXTENSION = ""; /** * Empty group or category of a version number */ public static final String EMPTY_GROUP = ""; /** * Defines an empty or not set version number */ public static final VersionNumber UNKNOWN = new VersionNumber(EMPTY_GROUP); /** * Minimum number of numeric group a version number */ private static final int MIN_GROUP_SIZE = 3; /** * Regular expression to find only numerical values ​​in strings */ private static final Pattern NUMERIC = Pattern.compile("\\d+"); /** * Separator between numeric groups of a version number */ private static final char SEPARATOR = '.'; /** * Serialization version */ private static final long serialVersionUID = 1L; /** * Extension or suffix of the version number consisting of alphanumeric and special characters */ @javax.validation.constraints.NotNull private final String extension; /** * Groups, segments or categories of the version number */ @javax.validation.constraints.NotNull private final List groups; /** * Constructs a {@code VersionNumber} with the given numeric groups, such as major, minor and bugfix number. * * @param groups * list of numbers of a version number *

*

* if the given argument is {@code null} * * @throws net.sf.uadetector.exception.IllegalStateOfArgumentException * if one of the segments of the version number is smaller than 0 and not empty */ public VersionNumber(@javax.validation.constraints.NotNull List groups) { this(groups, EMPTY_EXTENSION); } /** * Constructs a {@code VersionNumber} with the given numeric groups, such as major, minor and bugfix number and * extension. * * @param groups * list of numbers of a version number * @param extension * extension of a version number *

*

* if one of the given arguments is {@code null} * * @throws net.sf.uadetector.exception.IllegalStateOfArgumentException * if one of the groups of the version number is not empty or a positive number */ public VersionNumber(@javax.validation.constraints.NotNull List groups, @javax.validation.constraints.NotNull String extension) { Check.notNull(groups, "groups"); Check.notNull(extension, "extension"); List segments = replaceNullValueWithEmptyGroup(groups); int i = 0; for (String segment : segments) { if (!EMPTY_GROUP.equals(segment) && !isNumeric(segment)) { throw new IllegalStateOfArgumentException("The segment on position " + i + " (" + segment + ") must be a number."); } i++; } this.groups = segments; this.extension = extension; } /** * Replaces all {@code null} values in the given list of groups with {@code VersionNumber#EMPTY_GROUP}. * * @param groups * list of numbers of a version number * * @return a new list of groups without {@code null} values */ public static List replaceNullValueWithEmptyGroup(@javax.validation.constraints.NotNull List groups) { Check.notNull(groups, "groups"); List result = new ArrayList<>(groups.size()); for (String group : groups) { if (group == null) { result.add(EMPTY_GROUP); } else { result.add(group); } } for (int i = result.size(); i < MIN_GROUP_SIZE; i++) { result.add(EMPTY_GROUP); } return result; } /** * Checks a string that only numerical values ​​are present. Negative numbers are not included. * * @param text * string to be tested * * @return {@code true} if only numeric characters are present, otherwise {@code false} */ private static boolean isNumeric(String text) { return NUMERIC.matcher(text) .matches(); } /** * Constructs a {@code VersionNumber} with the given major number and without a minor and bugfix number. * * @param major * major group of the version number *

*

* if the given argument is {@code null} * * @throws net.sf.uadetector.exception.IllegalStateOfArgumentException * if the major segment is smaller than 0 and not empty */ public VersionNumber(@javax.validation.constraints.NotNull String major) { this(Check.notNull(major, "major"), EMPTY_GROUP); } /** * Constructs a {@code VersionNumber} with the given major, minor number and without a bugfix number. * * @param major * major group of the version number * @param minor * minor group of the version number *

*

* if one of the given arguments is {@code null} * * @throws net.sf.uadetector.exception.IllegalStateOfArgumentException * if the major or minor segment is smaller than 0 and not empty */ public VersionNumber(@javax.validation.constraints.NotNull String major, @javax.validation.constraints.NotNull String minor) { this(Check.notNull(major, "major"), Check.notNull(minor, "minor"), EMPTY_GROUP); } /** * Constructs a {@code VersionNumber} with the given major, minor and bugfix number. * * @param major * major group of the version number * @param minor * minor group of the version number * @param bugfix * bugfix group of the version number *

*

* if one of the given arguments is {@code null} * * @throws net.sf.uadetector.exception.IllegalStateOfArgumentException * if the major, minor or bugfix segment is smaller than 0 and not empty */ public VersionNumber(@javax.validation.constraints.NotNull String major, @javax.validation.constraints.NotNull String minor, @javax.validation.constraints.NotNull String bugfix) { this(Check.notNull(major, "major"), Check.notNull(minor, "minor"), Check.notNull(bugfix, "bugfix"), EMPTY_EXTENSION); } /** * Constructs a {@code VersionNumber} with the given major, minor and bugfix number and extension. * * @param major * major group of the version number * @param minor * minor group of the version number * @param bugfix * bugfix group of the version number * @param extension * extension of a version number *

*

* if one of the given arguments is {@code null} * * @throws net.sf.uadetector.exception.IllegalStateOfArgumentException * if the major, minor or bugfix segment is smaller than 0 and not empty */ public VersionNumber(@javax.validation.constraints.NotNull String major, @javax.validation.constraints.NotNull String minor, @javax.validation.constraints.NotNull String bugfix, @javax.validation.constraints.NotNull String extension) { this(Arrays.asList(Check.notNull(major, "major"), Check.notNull(minor, "minor"), Check.notNull(bugfix, "bugfix")), Check.notNull( extension, "extension")); } /** * Interprets a string with version information. The last version number in the string will be searched and * processed. * * @param text * string with version information * * @return an object of {@code VersionNumber}, never {@code null} */ public static VersionNumber parseLastVersionNumber(@javax.validation.constraints.NotNull String text) { return VersionParser.parseLastVersionNumber(Check.notNull(text, "text")); } /** * Try to determine the version number of the operating system by parsing the user agent string. * * @param family * family of the operating system * @param userAgent * user agent string * * @return extracted version number */ public static VersionNumber parseOperatingSystemVersion(@javax.validation.constraints.NotNull OperatingSystemFamily family, @javax.validation.constraints.NotNull String userAgent) { Check.notNull(family, "family"); Check.notNull(userAgent, "userAgent"); return VersionParser.parseOperatingSystemVersion(family, userAgent); } /** * Interprets a string with version information. The first found group will be taken and processed. * * @param version * version as string * * @return an object of {@code VersionNumber}, never {@code null} */ public static VersionNumber parseVersion(@javax.validation.constraints.NotNull String version) { return VersionParser.parseVersion(Check.notNull(version, "version")); } /** * Compares this version number with the specified version number for order. Returns a negative integer, zero, or a * positive integer as this version number is less than, equal to, or greater than the specified version number. * * @return a negative integer, zero, or a positive integer as this version number is less than, equal to, or greater * than the specified version number. */ @Override public int compareTo(ReadableVersionNumber other) { int result = 0; if (other == null) { result = -1; } else { Check.notNull(other.getGroups(), "other.getGroups()"); int length = groups.size() < other.getGroups() .size() ? groups.size() : other.getGroups() .size(); NaturalOrderComparator comparator = new NaturalOrderComparator(); result = comparator.compare(toVersionString(groups.subList(0, length)), toVersionString(other.getGroups() .subList(0, length))); if (result == 0) { result = Integer.compare(groups.size(), other.getGroups() .size()); } if (result == 0) { result = extension.compareTo(other.getExtension()); } if (result == 0) { result = comparator.compare(toVersionString(), other.toVersionString()); } } return result; } /** * Converts the given list of numbers in a version string. The groups of the version number will be separated by a * dot. * * @param groups * list of numbers of a version number * * @return a formated version string */ private static String toVersionString(@javax.validation.constraints.NotNull List groups) { StringBuilder builder = new StringBuilder(6); int count = 0; for (String segment : groups) { if (EMPTY_GROUP.equals(segment)) { break; } else { if (count > 0) { builder.append(SEPARATOR); } builder.append(segment); } count++; } return builder.toString(); } /** * Gets the bugfix category of the version number. */ @Override public String getBugfix() { return groups.get(2); } /** * Gets the addition or extension of the version number. * * @return extension of the version number */ @Override public String getExtension() { return extension; } /** * Get all groups (or categories) of this version number. The first element in the list is the major category, * followed by the minor and bugfix segment of the version number.
*
* The returned list of the version number segments is immutable. * * @return an unmodifiable view of the of the version number groups */ @Override public List getGroups() { return Collections.unmodifiableList(groups); } /** * Gets the major category of the version number. */ @Override public String getMajor() { return groups.get(0); } /** * Gets the major category of the version number. */ @Override public String getMinor() { return groups.get(1); } /** * Gets this version number as string. * * @return numeric groups as dot separated version number string */ @javax.validation.constraints.NotNull @Override public String toVersionString() { return toVersionString(groups) + extension; } @Override public int hashCode() { int prime = 31; int result = 1; result = prime * result + groups.hashCode(); result = prime * result + extension.hashCode(); return result; } /** * Indicates whether some other object is "equal to" this version number. * * @return {@code true} if the given version number is equal to this one */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } VersionNumber other = (VersionNumber) obj; if (!groups.equals(other.groups)) { return false; } if (!extension.equals(other.extension)) { return false; } return true; } /** * Returns a string representation of the version number. * * @return a string representation of this version number */ @javax.validation.constraints.NotNull @Override public String toString() { return "VersionNumber [groups=" + groups + ", extension=" + extension + "]"; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy