package org.inferred.freebuilder.processor.excerpt; import static org.inferred.freebuilder.processor.util.StaticExcerpt.Type.TYPE; import static org.inferred.freebuilder.processor.util.feature.FunctionPackage.FUNCTION_PACKAGE; import com.google.common.base.Preconditions; import com.google.common.collect.ForwardingMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multiset; import org.inferred.freebuilder.processor.util.ParameterizedType; import org.inferred.freebuilder.processor.util.SourceBuilder; import org.inferred.freebuilder.processor.util.StaticExcerpt; import java.util.Collection; import java.util.Set; import javax.annotation.Nullable; /** * Excerpts defining a multiset implementation that delegates to a provided setCount method to * perform element validation and insertion into a backing multiset. */ public class CheckedMultiset { public static Set<StaticExcerpt> excerpts() { return ImmutableSet.of(CHECKED_MULTISET); } private static final StaticExcerpt CHECKED_MULTISET = new StaticExcerpt(TYPE, "CheckedMultiset") { @Override public void addTo(SourceBuilder code) { ParameterizedType biConsumer = code.feature(FUNCTION_PACKAGE).biConsumer().orNull(); if (biConsumer == null) { return; } code.addLine("") .addLine("/**") .addLine(" * A multiset implementation that delegates to a provided setCount method") .addLine(" * to perform element validation and insertion into a backing multiset.") .addLine(" */") .addLine("private static class CheckedMultiset<E> extends %s<E> {", ForwardingMultiset.class) .addLine("") .addLine(" private final %s<E> multiset;", Multiset.class) .addLine(" private final %s<E, Integer> setCount;", biConsumer.getQualifiedName()) .addLine("") .addLine(" CheckedMultiset(%s<E> multiset, %s<E, Integer> setCount) {", Multiset.class, biConsumer.getQualifiedName()) .addLine(" this.multiset = multiset;") .addLine(" this.setCount = setCount;") .addLine(" }") .addLine("") .addLine(" @Override protected %s<E> delegate() {", Multiset.class) .addLine(" return multiset;") .addLine(" }") .addLine("") .addLine(" @Override public boolean add(@%s E element) {", Nullable.class) .addLine(" return standardAdd(element);") .addLine(" }") .addLine("") .addLine(" @Override public int add(@%s E element, int occurrences) {", Nullable.class) .addLine(" %s.checkArgument(occurrences >= 0,", Preconditions.class) .addLine(" \"occurrences cannot be negative: %%s\", occurrences);") .addLine(" int oldCount = multiset.count(element);") .addLine(" if (occurrences > 0) {") .addLine(" long newCount = (long) oldCount + occurrences;") .addLine(" %s.checkArgument(newCount <= %s.MAX_VALUE,", Preconditions.class, Integer.class) .addLine(" \"too many occurrences: %%s\", newCount);") .addLine(" setCount.accept(element, (int) newCount);") .addLine(" }") .addLine(" return oldCount;") .addLine(" }") .addLine("") .addLine(" @Override public boolean addAll(%s<? extends E> elementsToAdd) {", Collection.class) .addLine(" return standardAddAll(elementsToAdd);") .addLine(" }") .addLine("") .addLine(" @Override public int setCount(@%s E element, int count) {", Nullable.class) .addLine(" return standardSetCount(element, count);") .addLine(" }") .addLine("") .addLine(" @Override public boolean setCount(") .addLine(" @%s E element, int oldCount, int newCount) {", Nullable.class) .addLine(" return standardSetCount(element, oldCount, newCount);") .addLine(" }") .addLine("}"); } }; }