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.collect.ImmutableSet; import org.inferred.freebuilder.processor.util.ParameterizedType; import org.inferred.freebuilder.processor.util.PreconditionExcerpts; import org.inferred.freebuilder.processor.util.SourceBuilder; import org.inferred.freebuilder.processor.util.StaticExcerpt; import java.util.AbstractSet; import java.util.Comparator; import java.util.Iterator; import java.util.NavigableSet; import java.util.Set; /** * Excerpts defining a navigable set implementation that delegates to a provided add method to * perform element validation and insertion into a backing set. */ public class CheckedNavigableSet { public static Set<StaticExcerpt> excerpts() { return ImmutableSet.of(CHECKED_NAVIGABLE_SET); } private static final StaticExcerpt CHECKED_NAVIGABLE_SET = new StaticExcerpt(TYPE, "CheckedNavigableSet") { @Override @SuppressWarnings("checkstyle:methodlength") public void addTo(SourceBuilder code) { ParameterizedType consumer = code.feature(FUNCTION_PACKAGE).consumer().orNull(); if (consumer == null) { return; } code.addLine("") .addLine("/**") .addLine(" * A set implementation that delegates to a provided add method") .addLine(" * to perform element validation and insertion into a backing set.") .addLine(" */") .addLine("private static class CheckedNavigableSet<E>") .addLine(" extends %s<E> implements %s<E> {", AbstractSet.class, NavigableSet.class) .addLine("") .addLine(" private final %s<E> set;", NavigableSet.class) .addLine(" private final %s<E> add;", consumer.getQualifiedName()) .addLine(" private final E fromElement;") .addLine(" private final boolean fromInclusive;") .addLine(" private final E toElement;") .addLine(" private final boolean toInclusive;") .addLine("") .addLine(" CheckedNavigableSet(%s<E> set, %s<E> add) {", NavigableSet.class, consumer.getQualifiedName()) .addLine(" this.set = set;") .addLine(" this.add = add;") .addLine(" this.fromElement = null;") .addLine(" this.fromInclusive = false;") .addLine(" this.toElement = null;") .addLine(" this.toInclusive = false;") .addLine(" }") .addLine("") .addLine(" CheckedNavigableSet(") .addLine(" %s<E> set,", NavigableSet.class) .addLine(" %s<E> add,", consumer.getQualifiedName()) .addLine(" E fromElement,") .addLine(" boolean fromInclusive,") .addLine(" E toElement,") .addLine(" boolean toInclusive) {") .addLine(" this.set = set;") .addLine(" this.add = add;") .addLine(" this.fromElement = fromElement;") .addLine(" this.fromInclusive = fromInclusive;") .addLine(" this.toElement = toElement;") .addLine(" this.toInclusive = toInclusive;") .addLine(" }") .addLine("") .addLine("") .addLine(" @Override public %s<E> iterator() {", Iterator.class) .addLine(" return set.iterator();") .addLine(" }") .addLine("") .addLine(" @Override public int size() {") .addLine(" return set.size();") .addLine(" }") .addLine("") .addLine(" @Override public boolean contains(Object e) {") .addLine(" return set.contains(e);") .addLine(" }") .addLine("") .addLine(" @Override public boolean add(E e) {") .addLine(" if (fromElement != null || toElement != null) {") .addLine(" %s<? super E> comparator = set.comparator();", Comparator.class) .addLine(" if (comparator == null) {") .addLine(" @SuppressWarnings(\"unchecked\")") .addLine(" %1$s<? super E> lowerBound = (%1$s<? super E>) fromElement;", Comparable.class) .addLine(" @SuppressWarnings(\"unchecked\")") .addLine(" %1$s<? super E> upperBound = (%1$s<? super E>) toElement;", Comparable.class) .add(PreconditionExcerpts.checkArgument( "lowerBound == null || lowerBound.compareTo(e) <= (fromInclusive ? 0 : -1)", "element must be %s %s (got %s)", "(fromInclusive ? \"at least\" : \"greater than\")", "lowerBound", "e")) .add(PreconditionExcerpts.checkArgument( "upperBound == null || upperBound.compareTo(e) >= (toInclusive ? 0 : 1)", "element must be %s %s (got %s)", "(toInclusive ? \"at most\" : \"less than\")", "upperBound", "e")) .addLine(" } else {") .add(PreconditionExcerpts.checkArgument( "fromElement == null " + "|| comparator.compare(fromElement, e) <= (fromInclusive ? 0 : -1)", "element must be %s %s (got %s) using comparator %s", "(fromInclusive ? \"at least\" : \"greater than\")", "fromElement", "e", "comparator")) .add(PreconditionExcerpts.checkArgument( "toElement == null " + "|| comparator.compare(toElement, e) >= (toInclusive ? 0 : 1)", "element must be %s %s (got %s) using comparator %s", "(toInclusive ? \"at most\" : \"less than\")", "toElement", "e", "comparator")) .addLine(" }") .addLine(" }") .addLine(" if (!set.contains(e)) {") .addLine(" add.accept(e);") .addLine(" return true;") .addLine(" } else {") .addLine(" return false;") .addLine(" }") .addLine(" }") .addLine("") .addLine(" @Override public boolean remove(Object e) {") .addLine(" return set.remove(e);") .addLine(" }") .addLine("") .addLine(" @Override public %s<? super E> comparator() {", Comparator.class) .addLine(" return set.comparator();") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> subSet(E fromElement, E toElement) {", NavigableSet.class) .add(PreconditionExcerpts.checkNotNull("fromElement")) .add(PreconditionExcerpts.checkNotNull("toElement")) .addLine(" %s<E> subSet = set.subSet(fromElement, true, toElement, false);", NavigableSet.class) .addLine(" return new CheckedNavigableSet<>(" + "subSet, add, fromElement, true, toElement, false);") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> headSet(E toElement) {", NavigableSet.class) .add(PreconditionExcerpts.checkNotNull("toElement")) .addLine(" %s<E> headSet = set.headSet(toElement, false);", NavigableSet.class) .addLine(" return new CheckedNavigableSet<>(" + "headSet, add, fromElement, fromInclusive, toElement, false);") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> tailSet(E fromElement) {", NavigableSet.class) .add(PreconditionExcerpts.checkNotNull("fromElement")) .addLine(" %s<E> tailSet = set.tailSet(fromElement, true);", NavigableSet.class) .addLine(" return new CheckedNavigableSet<>(" + "tailSet, add, fromElement, true, toElement, toInclusive);") .addLine(" }") .addLine("") .addLine(" @Override public E first() {") .addLine(" return set.first();") .addLine(" }") .addLine("") .addLine(" @Override public E last() {") .addLine(" return set.last();") .addLine(" }") .addLine("") .addLine(" @Override public E lower(E element) {") .addLine(" return set.lower(element);") .addLine(" }") .addLine("") .addLine(" @Override public E floor(E element) {") .addLine(" return set.floor(element);") .addLine(" }") .addLine("") .addLine(" @Override public E ceiling(E element) {") .addLine(" return set.ceiling(element);") .addLine(" }") .addLine("") .addLine(" @Override public E higher(E element) {") .addLine(" return set.higher(element);") .addLine(" }") .addLine("") .addLine(" @Override public E pollFirst() {") .addLine(" return set.pollFirst();") .addLine(" }") .addLine("") .addLine(" @Override public E pollLast() {") .addLine(" return set.pollLast();") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> descendingSet() {", NavigableSet.class) .addLine(" %s<E> descendingSet = set.descendingSet();", NavigableSet.class) .addLine(" return new CheckedNavigableSet(" + "descendingSet, add, toElement, toInclusive, fromElement, fromInclusive);") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> descendingIterator() {", Iterator.class) .addLine(" return set.descendingIterator();") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> subSet(", NavigableSet.class) .addLine(" E fromElement,") .addLine(" boolean fromInclusive,") .addLine(" E toElement,") .addLine(" boolean toInclusive) {") .add(PreconditionExcerpts.checkNotNull("fromElement")) .add(PreconditionExcerpts.checkNotNull("toElement")) .addLine(" %s<E> subSet = set.subSet(" + "fromElement, fromInclusive, toElement, toInclusive);", NavigableSet.class) .addLine(" return new CheckedNavigableSet<>(" + "subSet, add, fromElement, fromInclusive, toElement, toInclusive);") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> headSet(", NavigableSet.class) .addLine(" E toElement,") .addLine(" boolean inclusive) {") .add(PreconditionExcerpts.checkNotNull("toElement")) .addLine(" %s<E> headSet = set.headSet(toElement, inclusive);", NavigableSet.class) .addLine(" return new CheckedNavigableSet<>(" + "headSet, add, fromElement, fromInclusive, toElement, inclusive);") .addLine(" }") .addLine("") .addLine(" @Override public %s<E> tailSet(", NavigableSet.class) .addLine(" E fromElement,") .addLine(" boolean inclusive) {") .add(PreconditionExcerpts.checkNotNull("fromElement")) .addLine(" %s<E> tailSet = set.tailSet(fromElement, inclusive);", NavigableSet.class) .addLine(" return new CheckedNavigableSet<>(" + "tailSet, add, fromElement, inclusive, toElement, toInclusive);") .addLine(" }") .addLine("}"); } }; private CheckedNavigableSet() {} }