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.ImmutableList; import org.inferred.freebuilder.processor.util.ParameterizedType; import org.inferred.freebuilder.processor.util.SourceBuilder; import org.inferred.freebuilder.processor.util.StaticExcerpt; import java.util.AbstractList; import java.util.List; import java.util.RandomAccess; /** * Excerpts defining a list implementation that delegates to a provided add method to perform * element validation and insertion into a random-access backing list. */ public class CheckedList { public static List<StaticExcerpt> excerpts() { return ImmutableList.<StaticExcerpt>of(CHECKED_LIST); } private static final StaticExcerpt CHECKED_LIST = new StaticExcerpt(TYPE, "CheckedList") { @Override public void addTo(SourceBuilder code) { ParameterizedType consumer = code.feature(FUNCTION_PACKAGE).consumer().orNull(); if (consumer == null) { return; } code.addLine("") .addLine("/**") .addLine(" * A list implementation that delegates to a provided add method to perform") .addLine(" * element validation and insertion into a random-access backing list.") .addLine(" */") .addLine("private static class CheckedList<E> extends %s<E> implements %s {", AbstractList.class, RandomAccess.class) .addLine("") .addLine(" private final %s<E> list;", List.class) .addLine(" private final %s<E> add;", consumer.getQualifiedName()) .addLine("") .addLine(" CheckedList(%s<E> list, %s<E> add) {", List.class, consumer.getQualifiedName()) .addLine(" this.list = list;") .addLine(" this.add = add;") .addLine(" }") .addLine("") .addLine(" @Override public int size() {") .addLine(" return list.size();") .addLine(" }") .addLine("") .addLine(" @Override public E get(int index) {") .addLine(" return list.get(index);") .addLine(" }") .addLine("") .addLine(" @Override public E set(int index, E element) {") .addLine(" add.accept(element);") .addLine(" return list.set(index, list.remove(list.size() - 1));") .addLine(" }") .addLine("") .addLine(" @Override public void add(int index, E element) {") .addLine(" // Append to the end of the list with add, then move the inserted element") .addLine(" // to the desired location.") .addLine(" int endIndex = list.size();") .addLine(" add.accept(element);") .addLine(" if (index != endIndex) {") .addLine(" list.add(index, list.remove(endIndex));") .addLine(" }") .addLine(" }") .addLine("") .addLine(" @Override public E remove(int index) {") .addLine(" return list.remove(index);") .addLine(" }") .addLine("") .addLine(" @Override public void clear() {") .addLine(" list.clear();") .addLine(" }") .addLine("") .addLine(" @Override protected void removeRange(int fromIndex, int toIndex) {") .addLine(" list.subList(fromIndex, toIndex).clear();") .addLine(" }") .addLine("}"); } }; private CheckedList() {} }