package sk.stuba.fiit.perconik.core.java.dom.difference; import java.util.Iterator; import java.util.List; import java.util.Set; import com.google.common.collect.ForwardingSet; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import org.eclipse.jdt.core.dom.ASTNode; import static com.google.common.collect.Lists.newArrayList; public final class NodeDeltaSet<N extends ASTNode> extends ForwardingSet<NodeDelta<N>> { private static final NodeDeltaSet<?> none = new NodeDeltaSet<>(ImmutableSet.<NodeDelta<ASTNode>>of()); private final Set<NodeDelta<N>> deltas; private NodeDeltaSet(final Set<NodeDelta<N>> deltas) { assert deltas != null; this.deltas = deltas; } public static <N extends ASTNode> NodeDeltaSet<N> of() { @SuppressWarnings("unchecked") NodeDeltaSet<N> casted = (NodeDeltaSet<N>) none; return casted; } public static <N extends ASTNode> NodeDeltaSet<N> of(final NodeDelta<N> delta) { return new NodeDeltaSet<>(ImmutableSet.of(delta)); } public static <N extends ASTNode> NodeDeltaSet<N> of(final Iterable<? extends NodeDelta<N>> deltas) { if (Iterables.isEmpty(deltas)) { return of(); } return new NodeDeltaSet<>(ImmutableSet.copyOf(deltas)); } public static <N extends ASTNode> NodeDeltaSet<N> of(final Iterator<? extends NodeDelta<N>> deltas) { if (!deltas.hasNext()) { return of(); } return new NodeDeltaSet<>(ImmutableSet.copyOf(deltas)); } public static final class Builder<N extends ASTNode> { private final List<NodeDelta<N>> deltas; public Builder() { this.deltas = newArrayList(); } public Builder<N> add(final N node) { this.deltas.add(NodeAddition.of(node)); return this; } public Builder<N> addAndDelete(final N added, final N deleted) { this.add(added); this.delete(deleted); return this; } public Builder<N> delete(final N node) { this.deltas.add(NodeDeletion.of(node)); return this; } public Builder<N> deleteAndAdd(final N deleted, final N added) { this.delete(deleted); this.add(added); return this; } public Builder<N> modify(final N original, final N revised) { this.deltas.add(NodeModification.of(original, revised)); return this; } public NodeDeltaSet<N> build() { return NodeDeltaSet.of(this.deltas); } } public static <N extends ASTNode> Builder<N> builder() { return new Builder<>(); } @Override protected Set<NodeDelta<N>> delegate() { return this.deltas; } }