package com.tngtech.archunit.integration.junit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.google.common.base.Joiner;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.tngtech.archunit.junit.ExpectedViolation.ExpectedAccess;
import com.tngtech.archunit.junit.MessageAssertionChain;
import static com.google.common.base.Functions.toStringFunction;
import static com.google.common.collect.Collections2.transform;
import static com.google.common.collect.Iterables.getLast;
class CyclicErrorMatcher implements MessageAssertionChain.Link {
private final List<String> cycleDescriptions = new ArrayList<>();
private final Multimap<String, ExpectedAccess> details = LinkedHashMultimap.create();
static CyclicErrorMatcher cycle() {
return new CyclicErrorMatcher();
}
private String cycleText() {
return "Cycle detected: " +
Joiner.on(" -> ").join(FluentIterable.from(cycleDescriptions).append(cycleDescriptions.get(0)));
}
private String detailText() {
return System.lineSeparator() + Joiner.on(System.lineSeparator()).join(detailLines());
}
private List<String> detailLines() {
List<String> result = new ArrayList<>();
for (Map.Entry<String, Collection<ExpectedAccess>> detail : details.asMap().entrySet()) {
result.add("Dependencies of " + detail.getKey());
result.addAll(transform(detail.getValue(), toStringFunction()));
}
return result;
}
public CyclicErrorMatcher from(String sliceName) {
cycleDescriptions.add(sliceName);
return this;
}
public CyclicErrorMatcher byAccess(ExpectedAccess access) {
details.put(getLast(cycleDescriptions), access);
return this;
}
@Override
public MessageAssertionChain.Link.Result filterMatching(List<String> lines) {
return new Result.Builder()
.containsLine(cycleText())
.containsConsecutiveLines(detailLines())
.build(lines);
}
@Override
public String getDescription() {
return String.format("Message contains cycle description '%s' and details '%s'",
cycleText(), detailText());
}
}