io.github.mike10004.vhs.HeuristicEntryMatcher Maven / Gradle / Ivy
package io.github.mike10004.vhs;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import io.github.mike10004.vhs.ParsedEntry.HttpRespondableCreator;
import io.github.mike10004.vhs.harbridge.ParsedRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Objects.requireNonNull;
public class HeuristicEntryMatcher implements EntryMatcher {
private static final Logger log = LoggerFactory.getLogger(HeuristicEntryMatcher.class);
private final ImmutableList entries;
private final Heuristic heuristic;
private final int thresholdExclusive;
HeuristicEntryMatcher(Heuristic heuristic, int thresholdExclusive, Collection entries) {
this.entries = ImmutableList.copyOf(entries);
this.thresholdExclusive = thresholdExclusive;
this.heuristic = requireNonNull(heuristic);
}
public static EntryMatcherFactory factory(Heuristic heuristic, int thresholdExclusive) {
return new Factory(heuristic, thresholdExclusive);
}
private static class Factory implements EntryMatcherFactory {
private static final Logger log = LoggerFactory.getLogger(Factory.class);
private final Heuristic heuristic;
private final int thresholdExclusive;
private Factory(Heuristic heuristic, int thresholdExclusive) {
this.thresholdExclusive = thresholdExclusive;
this.heuristic = heuristic;
}
@Override
public EntryMatcher createEntryMatcher(List entries, EntryParser requestParser) throws IOException {
log.trace("constructing heuristic from {} har entries", entries.size());
List parsedEntries = new ArrayList<>(entries.size());
for (E entry : entries) {
ParsedRequest request = requestParser.parseRequest(entry);
HttpRespondableCreator respondableCreator = newRequest -> {
return requestParser.parseResponse(newRequest, entry);
};
ParsedEntry parsedEntry = new ParsedEntry(request, respondableCreator);
parsedEntries.add(parsedEntry);
}
return new HeuristicEntryMatcher(heuristic, thresholdExclusive, parsedEntries);
}
}
@Override
@Nullable
public HttpRespondable findTopEntry(ParsedRequest request) {
AtomicInteger topRating = new AtomicInteger(thresholdExclusive);
@Nullable HttpRespondableCreator topEntry = entries.stream()
.max(Ordering.natural().onResultOf(entry -> {
int rating = heuristic.rate(requireNonNull(entry).request, request);
if (rating > thresholdExclusive) {
topRating.set(rating);
}
return rating;
}))
.map(entry -> entry.responseCreator)
.orElse(null);
if (topEntry != null && topRating.get() > thresholdExclusive) {
try {
return topEntry.createRespondable(request);
} catch (IOException e) {
log.warn("could not create response for top-rated entry", e);
}
}
return null;
}
}