blob: d6c65a04228cb305abb0d1c56ce652c74a7d4214 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.tinkerpop.gremlin.structure.io;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONCompatibility;
import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoCompatibility;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public class Compatibilities {
public static final Compatibilities GRYO_ONLY = Compatibilities.with(GryoCompatibility.class);
public static final Compatibilities UNTYPED_GRAPHSON = Compatibilities.with(GraphSONCompatibility.class)
.configuredAs(".*no-types|v1d0");
private final Class<? extends Enum<? extends Compatibility>> compatibility;
/**
* Initialized to 4.0.0 which is non-existent, but obviously the high-end of whatever would be tested.
*/
private String releaseVersionBefore = "4.0.0";
/**
* Initialized to 3.0.0 which is non-existent, but obviously the low-end of whatever would be tested.
*/
private String releaseVersionAfter = "3.0.0";
/**
* Initialized to 0.0 which is non-existent, but obviously the low-end of whatever would be tested.
*/
private String ioVersionBefore = "4.0";
/**
* Initialized to 3.0 which is non-existent, but obviously the high-end of whatever would be tested.
*/
private String ioVersionAfter = "0.0";
private String configuredAs = ".*";
private List<Compatibilities> compatibilitiesToJoin = Collections.emptyList();
private Compatibilities(final Class<? extends Enum<? extends Compatibility>> c) {
this.compatibility = c;
}
public static Compatibilities with(final Class<? extends Enum<? extends Compatibility>> c) {
return new Compatibilities(c);
}
/**
* Finds {@link Compatibility} instances before (and not inclusive of) the specified version.
*/
public Compatibilities beforeRelease(final String before) {
this.releaseVersionBefore = before;
return this;
}
/**
* Finds {@link Compatibility} instances after (and not inclusive of) the specified version.
*/
public Compatibilities afterRelease(final String after) {
this.releaseVersionAfter = after;
return this;
}
/**
* Finds {@link Compatibility} instances between (and not inclusive of) the specified versions.
*/
public Compatibilities betweenReleases(final String start, final String end) {
return beforeRelease(end).afterRelease(start);
}
/**
* Finds {@link Compatibility} instances before (and not inclusive of) the specified version.
*/
public Compatibilities before(final String before) {
this.ioVersionBefore = before;
return this;
}
/**
* Finds {@link Compatibility} instances after (and not inclusive of) the specified version.
*/
public Compatibilities after(final String after) {
this.ioVersionAfter = after;
return this;
}
/**
* Finds {@link Compatibility} instances between (and not inclusive of) the specified versions.
*/
public Compatibilities between(final String start, final String end) {
return before(end).after(start);
}
public Compatibilities configuredAs(final String regex) {
this.configuredAs = regex;
return this;
}
public Compatibilities join(final Compatibilities... compatibilities) {
this.compatibilitiesToJoin = Arrays.asList(compatibilities);
return this;
}
public List<Compatibility> match() {
final Compatibility[] enumArray = (Compatibility[]) compatibility.getEnumConstants();
final List<Compatibility> enums = Arrays.asList(enumArray);
final Pattern pattern = Pattern.compile(configuredAs);
final List<Compatibility> thisMatch = enums.stream()
.filter(c -> beforeRelease(c, releaseVersionBefore))
.filter(c -> afterRelease(c, releaseVersionAfter))
.filter(c -> beforeIo(c, ioVersionBefore))
.filter(c -> afterIo(c, ioVersionAfter))
.filter(c -> pattern.matcher(c.getConfiguration()).matches())
.collect(Collectors.toList());
final List<Compatibility> matches = new ArrayList<>(thisMatch);
compatibilitiesToJoin.forEach(c -> matches.addAll(c.match()));
return matches;
}
public Compatibility[] matchToArray() {
final List<Compatibility> list = match();
final Compatibility [] compatibilities = new Compatibility[list.size()];
list.toArray(compatibilities);
return compatibilities;
}
private static boolean afterRelease(final Compatibility version, final String after) {
return versionCompare(version.getReleaseVersion(), after) > 0;
}
private static boolean beforeRelease(final Compatibility version, final String before) {
return versionCompare(version.getReleaseVersion(), before) < 0;
}
private static boolean afterIo(final Compatibility version, final String after) {
return versionCompare(version.getVersion(), after) > 0;
}
private static boolean beforeIo(final Compatibility version, final String before) {
return versionCompare(version.getVersion(), before) < 0;
}
/**
* @return The result is a negative integer if v1 is less than v2.
* The result is a positive integer if v1 is greater than v2.
* The result is zero if the strings are equal.
*/
private static int versionCompare(final String v1, final String v2) {
final String[] vals1 = v1.split("\\.");
final String[] vals2 = v2.split("\\.");
int i = 0;
// set index to first non-equal ordinal or length of shortest version string
while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) {
i++;
}
// compare first non-equal ordinal number
if (i < vals1.length && i < vals2.length) {
int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i]));
return Integer.signum(diff);
}
// the strings are equal or one string is a substring of the other
// e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4"
return Integer.signum(vals1.length - vals2.length);
}
}