de.flapdoodle.embed.mongo.packageresolver.ExplainRules Maven / Gradle / Ivy
/*
* Copyright (C) 2011
* Michael Mosmann
* Martin Jöhren
*
* with contributions from
* konstantin-ba@github,Archimedes Trajano (trajano@github)
*
* 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 de.flapdoodle.embed.mongo.packageresolver;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
public final class ExplainRules {
private ExplainRules() {
// no instance
}
public interface Context {
Context oneDeeper();
void label(String label);
void matching(String explainMatch);
void finder(String finderExplained);
}
private static class Output {
private final StringBuilder sb=new StringBuilder();
private final String NEW_LINE=System.lineSeparator();
public String asString() {
return sb.toString();
}
public ContextImpl root() {
return new ContextImpl(0);
}
class ContextImpl implements Context {
private final int level;
public ContextImpl(int level) {
this.level = level;
}
public ContextImpl oneDeeper() {
return new ContextImpl(level+1);
}
public void label(String label) {
sb.append(indent(level)).append("'").append(label).append("'").append(NEW_LINE);
}
public void matching(String explainMatch) {
sb.append(indent(level)).append(explainMatch).append(NEW_LINE);
}
public void finder(String finderExplained) {
sb.append(indent(level+1)).append(finderExplained).append(NEW_LINE);
}
}
}
static String explain(PackageFinderRules rules) {
Output output = new Output();
explain(output.root(), rules);
return output.asString();
}
static void explain(Context context, PackageFinderRules rules) {
rules.rules().forEach(rule -> {
context.matching(explainMatch(rule.match()));
PackageFinder finder = rule.finder();
explain(context, finder);
});
}
public static void explain(Context context, PackageFinder finder) {
if (finder instanceof HasLabel) {
context.label(((HasLabel) finder).label());
}
if (finder instanceof HasPlatformMatchRules) {
explain(context.oneDeeper(), ((HasPlatformMatchRules) finder).rules());
} else {
context.finder(finder(finder));
}
}
public static String finder(PackageFinder finder) {
return finder instanceof HasExplanation
? ((HasExplanation) finder).explain()
: finder.getClass().getSimpleName();
}
public static String finderLabel(PackageFinder finder) {
return finder instanceof HasLabel
? ((HasLabel) finder).label()
: finder.getClass().getSimpleName();
}
static String explainMatch(DistributionMatch match) {
return forType(DistributionMatch.class)
.mapIfInstance(PlatformMatch.class, ExplainRules::explainPlatformMatch)
.orMapIfInstance(DistributionMatch.AndThen.class, andThen -> "" + explainMatch(andThen.first()) + " and " + explainMatch(andThen.second()))
.orMapIfInstance(DistributionMatch.Any.class, any -> any.matcher().stream().map(ExplainRules::explainMatch).collect(Collectors.joining(" or ","(",")")))
.orMapIfInstance(VersionRange.class, ExplainRules::explainVersionRange)
.orMapIfInstance(ToolVersionRange.class, ExplainRules::explainToolsVersionRange)
.orMapIfInstance(DistributionMatch.class, it -> it.getClass().getSimpleName())
.apply(match)
.get();
}
static String explainPlatformMatch(PlatformMatch match) {
List parts=new ArrayList<>();
match.os().ifPresent(os -> parts.add("os="+os));
match.bitSize().ifPresent(bitSize -> parts.add("bitSize="+bitSize));
match.cpuType().ifPresent(cpuType -> parts.add("cpuType="+cpuType));
if (!match.version().isEmpty()) {
parts.add(match.version().stream().map(version -> ""+version)
.collect(Collectors.joining(", ", "(version is any of ", ")")));
}
return !parts.isEmpty()
? parts.stream().collect(Collectors.joining(" and ", "(", ")"))
: "(any)";
}
private static String explainVersionRange(VersionRange versionRange) {
if (versionRange.min().isEqual(versionRange.max())) {
return asHumanReadable(versionRange.min());
}
return asHumanReadable(versionRange.min())+"-"+asHumanReadable(versionRange.max());
}
private static String explainToolsVersionRange(ToolVersionRange versionRange) {
if (versionRange.min().isEqual(versionRange.max())) {
return "tools.version "+asHumanReadable(versionRange.min());
}
return "tools.version "+asHumanReadable(versionRange.min())+"-"+asHumanReadable(versionRange.max());
}
private static String asHumanReadable(NumericVersion version) {
return version.asString();
}
private static String indent(int level) {
return repeat(' ', level * 2);
}
private static String repeat(char c, int level) {
char[] s = new char[level];
for (int i = 0; i < level; i++) {
s[i] = c;
}
return String.valueOf(s);
}
public static HasOptionalBuilder forType(Class sourceType) {
return new HasOptionalBuilder<>();
}
static class HasOptionalBuilder {
HasOptionalResult mapIfInstance(Class type, Function mapIfTypeMatches) {
return ExplainRules.mapIfInstance(type, mapIfTypeMatches);
}
}
interface HasOptionalResult extends Function> {
default HasOptionalResult or(HasOptionalResult other) {
HasOptionalResult that = this;
return s -> {
Optional first = that.apply(s);
return first.isPresent() ? first : other.apply(s);
};
}
default HasOptionalResult orMapIfInstance(Class type, Function mapIfTypeMatches) {
return or(ExplainRules.mapIfInstance(type, mapIfTypeMatches));
}
}
static HasOptionalResult mapIfInstance(Class type, Function mapIfTypeMatches) {
return s -> type.isInstance(s)
? Optional.of(mapIfTypeMatches.apply(type.cast(s)))
: Optional.empty();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy