blob: f0123b1d2620c4e582e0385a1dd1233f2b04869b [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.android.tools.idea.gradle.project.compatibility;
import com.android.sdklib.repository.FullRevision;
import com.android.sdklib.repository.FullRevision.PreviewComparison;
import com.android.sdklib.repository.PreciseRevision;
import com.google.common.base.Splitter;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* A version range. It parses text in the following formats:
* <ul>
* <li>Version X to Y, with including and excluding endpoints (e.g. "[1, 10]", "(1, 10)", "[1, +)")</li>
* <li>Version X or newer (e.g. "23+", which is equivalent to "[23, +)")</li>
* <li>Version X (e,g, "1.0.0", "M")</li>
* </ul>
*/
class VersionRange {
@NonNls private static final char OR_GREATER = '+';
@NonNls private static final char START_INCLUSIVE = '[';
@NonNls private static final char START_EXCLUSIVE = '(';
@NonNls private static final char END_INCLUSIVE = ']';
@NonNls private static final char END_EXCLUSIVE = ')';
@NotNull private final String myMinVersion;
@Nullable private final FullRevision myMinRevision;
private final boolean myMinVersionInclusive;
@Nullable private final FullRevision myMaxRevision;
@Nullable private final String myMaxVersion;
private final boolean myMaxVersionInclusive;
@NotNull
static VersionRange parse(@NotNull String value) {
if (value.isEmpty()) {
throw new IllegalArgumentException("Empty string is not a valid value");
}
int size = value.length();
char lastChar = value.charAt(size - 1);
if (lastChar == OR_GREATER) {
String minVersion = value.substring(0, size - 1);
return new VersionRange(minVersion, true, null, false);
}
char firstChar = value.charAt(0);
if (firstChar == START_INCLUSIVE || firstChar == START_EXCLUSIVE) {
boolean minVersionInclusive = firstChar == START_INCLUSIVE;
if (lastChar != END_INCLUSIVE && lastChar != END_EXCLUSIVE) {
throw new IllegalArgumentException(String.format("Value '%1$s' should end with ']' or ')'", value));
}
boolean maxVersionInclusive = lastChar == END_INCLUSIVE;
String rangeValue = value.substring(1, size - 1);
List<String> values = Splitter.on(',').splitToList(rangeValue);
if (values.size() != 2) {
throw new IllegalArgumentException(String.format("Range '%1$s' should contain 2 values", value));
}
String minVersion = values.get(0).trim();
String maxVersion = values.get(1).trim();
if (maxVersion.length() == 1) {
if (maxVersion.charAt(0) == OR_GREATER) {
maxVersion = null;
}
}
return new VersionRange(minVersion, minVersionInclusive, maxVersion, maxVersionInclusive);
}
return new VersionRange(value, false, null, false);
}
private VersionRange(@NotNull String minVersion, boolean minVersionInclusive, @Nullable String maxVersion, boolean maxVersionInclusive) {
myMinVersion = minVersion;
myMinRevision = asRevision(minVersion);
myMinVersionInclusive = minVersionInclusive;
myMaxVersion = maxVersion;
myMaxRevision = asRevision(maxVersion);
myMaxVersionInclusive = maxVersionInclusive;
}
boolean contains(@NotNull String value) {
if (myMinRevision != null) {
boolean contains = false;
FullRevision revision = asRevision(value);
if (revision != null) {
if (myMinVersionInclusive) {
contains = revision.compareTo(myMinRevision, PreviewComparison.IGNORE) >= 0;
}
else {
contains = revision.compareTo(myMinRevision, PreviewComparison.IGNORE) > 0;
}
if (contains && myMaxRevision != null) {
if (myMaxVersionInclusive) {
contains = revision.compareTo(myMaxRevision, PreviewComparison.IGNORE) <= 0;
}
else {
contains = revision.compareTo(myMaxRevision, PreviewComparison.IGNORE) < 0;
}
}
}
return contains;
}
return value.equals(myMinVersion) || value.equals(myMaxVersion);
}
@Nullable
private static FullRevision asRevision(@Nullable String version) {
if (version != null) {
try {
return PreciseRevision.parseRevision(version);
}
catch (NumberFormatException ignored) {
}
}
return null;
}
@NotNull
String getDescription() {
if (myMinVersion.equals(myMaxVersion)) {
return myMinVersion;
}
else if (myMaxVersion == null) {
return String.format("%1$s (or newer)", myMinVersion);
}
return "versions " + myMinVersion + inclusiveness(myMinVersionInclusive) + " to " + myMaxVersion + inclusiveness(myMaxVersionInclusive);
}
private static String inclusiveness(boolean inclusive) {
return "(" + (inclusive ? "inclusive" : "exclusive") + ")";
}
}