All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.google.inject.internal.DuplicateElementError Maven / Gradle / Ivy
package com.google.inject.internal;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.ErrorDetail;
import java.util.Collection;
import java.util.Formatter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Error reported by Guice when duplicate elements are found in a {@link Multibinder} that does not
* permit duplicates.
*/
final class DuplicateElementError extends InternalErrorDetail> {
private final Key> setKey;
private final ImmutableMultimap> elements;
DuplicateElementError(
Key> setKey, List> bindings, T[] values, List sources) {
this(setKey, indexElements(bindings, values), sources);
}
private DuplicateElementError(
Key> setKey, ImmutableMultimap> elements, List sources) {
super(
ErrorId.DUPLICATE_ELEMENT,
String.format("Duplicate elements found in Multibinder %s.", Messages.convert(setKey)),
sources,
null);
this.setKey = setKey;
this.elements = elements;
}
@Override
protected void formatDetail(List> others, Formatter formatter) {
formatter.format("\n%s\n", Messages.bold("Duplicates:"));
int duplicateIndex = 1;
for (Map.Entry>> entry : elements.asMap().entrySet()) {
formatter.format("%-2s: ", duplicateIndex++);
if (entry.getValue().size() > 1) {
Set valuesAsString =
entry.getValue().stream()
.map(element -> element.value.toString())
.collect(Collectors.toSet());
if (valuesAsString.size() == 1) {
// String representation of the duplicates elements are the same, so only print out one.
formatter.format("Element: %s\n", Messages.redBold(valuesAsString.iterator().next()));
formatter.format(" Bound at:\n");
int index = 1;
for (Element element : entry.getValue()) {
formatter.format(" %-2s: ", index++);
formatElement(element, formatter);
}
} else {
// Print out all elements as string when there are different string representations of the
// elements. To keep the logic simple, same strings are not grouped together unless all
// elements have the same string represnetation. This means some strings may be printed
// out multiple times.
// There is no indentation for the first duplicate element.
boolean indent = false;
for (Element element : entry.getValue()) {
if (indent) {
formatter.format(" ");
} else {
indent = true;
}
formatter.format("Element: %s\n", Messages.redBold(element.value.toString()));
formatter.format(" Bound at: ");
formatElement(element, formatter);
}
}
}
}
formatter.format("\n%s\n", Messages.bold("Multibinder declared at:"));
// Multibinder source includes the key of the set. Filter it out since it's not useful in the
// printed error stack.
List filteredSource =
getSources().stream()
.filter(
source -> {
if (source instanceof Dependency) {
return !((Dependency>) source).getKey().equals(setKey);
}
return true;
})
.collect(Collectors.toList());
ErrorFormatter.formatSources(filteredSource, formatter);
}
private void formatElement(Element element, Formatter formatter) {
Object source = element.binding.getSource();
new SourceFormatter(
source,
formatter,
/** omitPreposition= */
true)
.format();
}
@Override
public DuplicateElementError withSources(List newSources) {
return new DuplicateElementError<>(setKey, elements, newSources);
}
static ImmutableMultimap> indexElements(List> bindings, T[] values) {
ImmutableMultimap.Builder> map = ImmutableMultimap.builder();
for (int i = 0; i < values.length; i++) {
map.put(values[i], new Element(values[i], bindings.get(i)));
}
return map.build();
}
static class Element {
T value;
Binding binding;
Element(T value, Binding binding) {
this.value = value;
this.binding = binding;
}
}
}