Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ianj-als/omtc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java')
-rw-r--r--src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java
new file mode 100644
index 0000000..017d675
--- /dev/null
+++ b/src/main/java/com/capitati/omtc/core/negotiation/SemanticVersionComparator.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright Capita Translation and Interpreting 2013
+ *
+ * This file is part of OMTC.
+ *
+ * OMTC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OMTC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with OMTC. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.capitati.omtc.core.negotiation;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.collections.iterators.ArrayIterator;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+/**
+ * A comparator for two semantic versions.
+ *
+ * @author ian
+ * @see <a href="http://semver.org/">Semantic Versioning 2.0.0-rc.1</a> for
+ * the specification on how this comparator operates.
+ */
+public class SemanticVersionComparator {
+ public static final ImmutablePair<Integer, SemanticVersionComponent> compare(
+ final ISemanticVersion verOne,
+ final ISemanticVersion verTwo) {
+ if(verOne.equals(verTwo) == true) {
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ 0, SemanticVersionComponent.INVALID);
+ }
+
+ if(verOne.getMajor() == verTwo.getMajor()) {
+ if(verOne.getMinor() == verTwo.getMinor()) {
+ if(verOne.getPatch() == verTwo.getPatch()) {
+ /*
+ * Compare the pre-release components.
+ */
+ final ImmutablePair<Integer, Boolean> preReleaseCompResult =
+ compareArray(verOne.getPreRelease(), verTwo.getPreRelease());
+ /*
+ * Compare the build components.
+ */
+ final ImmutablePair<Integer, Boolean> buildCompResult =
+ compareArray(verOne.getBuild(), verTwo.getBuild());
+
+ /*
+ * Unpack the comparison values.
+ */
+ final int prc = preReleaseCompResult.getLeft();
+ final int bc = buildCompResult.getLeft();
+
+ if((preReleaseCompResult.getRight() == true) &&
+ (buildCompResult.getRight() == true)) {
+ /*
+ * There was at most one pre-release component, and at most one
+ * build component in both versions.
+ */
+ if((Math.abs(prc) == 1) && (Math.abs(bc) == 1)) {
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ (Math.signum((float )prc) == 1.0) ? -1 : 1,
+ SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION);
+ } else if((Math.abs(prc) == 1) && (bc == 0)) {
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ (Math.signum((float )prc) == 1.0) ? -1 : 1,
+ SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION);
+ }
+
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ bc, SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION);
+ } else if((preReleaseCompResult.getRight() == true) &&
+ (buildCompResult.getRight() == false)) {
+ /*
+ * One of the versions had a null pre-release.
+ */
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ bc, SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION);
+ }
+
+ /*
+ * Either one of the version has a null build or both versions where
+ * fully specified.
+ */
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ (Math.abs(prc) == 1) ? prc : bc,
+ SemanticVersionComponent.PRE_RELEASE_AND_BUILD_VERSION);
+ } else {
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ verOne.getPatch() - verTwo.getPatch(),
+ SemanticVersionComponent.PATCH_VERSION);
+ }
+ } else {
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ verOne.getMinor() - verTwo.getMinor(),
+ SemanticVersionComponent.MINOR_VERSION);
+ }
+ }
+
+ return new ImmutablePair<Integer, SemanticVersionComponent>(
+ verOne.getMajor() - verTwo.getMajor(),
+ SemanticVersionComponent.MAJOR_VERSION);
+ }
+
+ /**
+ * Lexically compare the components of two string arrays.
+ *
+ * @param one - First string array.
+ * @param two - The array that is compared to one.
+ * @return If one array is determined to be lexically less than two then
+ * -1 is returned. If one is determined to be lexically greater then two then
+ * 1 is returned. Otherwise, 0 is returned.
+ */
+ private static ImmutablePair<Integer, Boolean> compareArray(
+ final String[] one,
+ final String[] two) {
+ if((one == null) && (two == null)) {
+ return new ImmutablePair<Integer, Boolean>(0, true);
+ }
+
+ if((one == null) && (two != null)) {
+ return new ImmutablePair<Integer, Boolean>(-1, true);
+ }
+
+ if((one != null) && (two == null)) {
+ return new ImmutablePair<Integer, Boolean>(1, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ final Iterator<String> oneIterator = new ArrayIterator(one);
+ @SuppressWarnings("unchecked")
+ final Iterator<String> twoIterator = new ArrayIterator(two);
+ String oneComp = null;
+ String twoComp = null;
+ int comp = 0;
+
+ while(true) {
+ try {
+ oneComp = oneIterator.next();
+ } catch(final NoSuchElementException ex) {
+ oneComp = null;
+ }
+
+ try {
+ twoComp = twoIterator.next();
+ } catch(final NoSuchElementException ex) {
+ twoComp = null;
+ }
+
+ if((oneComp == null) && (twoComp == null)) {
+ break;
+ }
+
+ comp = componentCompare(oneComp, twoComp);
+ if(comp != 0) {
+ break;
+ }
+ }
+
+ return new ImmutablePair<Integer, Boolean>(comp, false);
+ }
+
+ /**
+ * Compare two components from the pre-release and build string arrays as
+ * detailed in the Semantic Versioning 2.0.0-rc.1 specification.
+ *
+ * @param oneComp - first value.
+ * @param twoComp - second value.
+ * @return If first value is determined to be less than the second value then
+ * return -1. If one value is determined to be greater than the second value
+ * then return 1. Otherwise, 0 is returned.
+ * @see <a href="http://semver.org/">Semantic Versioning 2.0.0-rc.1</a>
+ */
+ private static int componentCompare(
+ final String oneComp, final String twoComp) {
+ if((oneComp == null) && (twoComp == null)) {
+ return 0;
+ }
+
+ if((oneComp == null) && (twoComp != null)) {
+ return -1;
+ }
+
+ if((oneComp != null) && (twoComp == null)) {
+ return 1;
+ }
+
+ boolean isOneInt = false;
+ boolean isTwoInt = false;
+ int oneInt = 0;
+ int twoInt = 0;
+
+ try {
+ oneInt = Integer.parseInt(oneComp);
+ isOneInt = true;
+ } catch(final NumberFormatException ex) {
+ isOneInt = false;
+ }
+
+ try {
+ twoInt = Integer.parseInt(twoComp);
+ isTwoInt = true;
+ } catch(final NumberFormatException ex) {
+ isTwoInt = false;
+ }
+
+ final int comp = ((isOneInt == true) && (isTwoInt == true)) ?
+ oneInt - twoInt :
+ oneComp.compareTo(twoComp);
+ final int compValue = (comp > 0) ? 1 : (comp < 0) ? -1 : 0;
+
+ return compValue;
+ }
+}