001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014
015package org.basepom.mojo.dvc.strategy;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018
019import java.util.Comparator;
020import javax.inject.Named;
021import javax.inject.Singleton;
022
023import com.google.common.base.Strings;
024import org.apache.maven.artifact.versioning.ArtifactVersion;
025import org.apache.maven.artifact.versioning.ComparableVersion;
026import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
027
028/**
029 * Implements Apache versioning strategy for two or three digits. It expects versions formatted as x.y, x.y.z. Versions can have an additional qualifier.
030 * <p>
031 * Version A (xa.ya.za) can replace Version B (xb.yb.zb) if xa == xb and xa &gt;= xb. component z is always compatible.
032 * <p>
033 * If an additional qualifier exists, the qualifiers must match.
034 */
035@Named("apr")
036@Singleton
037public class AprVersionStrategy
038        implements Strategy {
039
040    private final Comparator<ArtifactVersion> comparator = Comparator
041            .comparing(ArtifactVersion::getMajorVersion, this::checkMajorCompatible)
042            .thenComparing(ArtifactVersion::getMinorVersion, this::checkMinorCompatible)
043            .thenComparing(ArtifactVersion::getIncrementalVersion, this::checkPatchCompatible)
044            .thenComparing(ArtifactVersion::getQualifier, (a, e) -> checkQualifierCompatible(Strings.nullToEmpty(a), Strings.nullToEmpty(e)));
045
046    @Override
047    public String getName() {
048        return "apr";
049    }
050
051    @Override
052    public final boolean isCompatible(final ComparableVersion expectedVersion, final ComparableVersion resolvedVersion) {
053        final ArtifactVersion aprExpectedVersion = new DefaultArtifactVersion(checkNotNull(expectedVersion, "expectedVersion is null").getCanonical());
054        final ArtifactVersion aprResolvedVersion = new DefaultArtifactVersion(checkNotNull(resolvedVersion, "resolvedVersion is null").getCanonical());
055
056        // Expected version must be before or equal the resolved version.
057        //
058        // for each method:
059        //
060        // -1 means incompatible.
061        //  0 means more testing.
062        //  1 means compatible.
063        //
064        return comparator.compare(aprExpectedVersion, aprResolvedVersion) >= 0; // more testing or compatible wins here.
065    }
066
067    protected int checkMajorCompatible(int expectedMajor, int resolvedMajor) {
068        if (expectedMajor != resolvedMajor) {
069            return -1; // incompatible if majors differ.
070        }
071        return 0; // otherwise more testing.
072    }
073
074    protected int checkMinorCompatible(int expectedMinor, int resolvedMinor) {
075        if (resolvedMinor < expectedMinor) {
076            return -1; // smaller version is not forward compatible
077        }
078
079        return 0; // otherwise more testing.
080    }
081
082    protected int checkPatchCompatible(int expectedPatch, int resolvedPatch) {
083        return 0; // all patches are compatible, check the qualifiers
084    }
085
086    protected int checkQualifierCompatible(String expectedQualifier, String resolvedQualifier) {
087        if (!expectedQualifier.equals(resolvedQualifier)) {
088            return -1; // if qualifiers don't match, things are not compatible (this makes things like 1.2.3-android and 1.2.3-jre not compatible!
089        }
090        return 0;
091    }
092}