package mhfc.net.common.util.parsing.valueholders; import java.util.Arrays; import java.util.Iterator; import java.util.Objects; import java.util.function.Supplier; import java.util.stream.Stream; import com.google.common.collect.Iterators; import mhfc.net.common.util.parsing.Holder; import mhfc.net.common.util.parsing.IValueHolder; public class Arguments implements Iterable<IValueHolder> { public static class PermissiveIterator<E> implements Iterator<E> { private final Iterator<E> base; private final Supplier<E> defaultE; public PermissiveIterator(Iterator<E> base, E defaultE) { this.base = Objects.requireNonNull(base); this.defaultE = () -> defaultE; } public PermissiveIterator(Iterator<E> base, Supplier<E> defaultE) { this.base = Objects.requireNonNull(base); this.defaultE = Objects.requireNonNull(defaultE); } @Override public boolean hasNext() { return base.hasNext(); } @Override public E next() { return base.next(); } /** * Returns the next object from the contained iterator if that has a next one. Else the object from the * contained {@link Supplier} is returned.<br> * Thus this method can even return objects when the iterator is finished. * * @return */ public E permissiveNext() { return hasNext() ? next() : defaultE.get(); } /** * Makes this iterator usable in an infinite iteration. The iterator returned will always have a next element * which is either the next element from the contained {@link Iterator} or the element from the * {@link Supplier}.<br> * Keep in mind that this will not tie this iterator. Items that are iterated over by the returned iterator will * not be available in this iterator anymore. * * @return */ public Iterator<E> iteratePermissive() { return Iterators.concat(this.base, Stream.generate(this.defaultE).iterator()); } } private final IValueHolder[] args; public Arguments(IValueHolder... expressions) { this.args = mhfc.net.common.util.Objects.requireNonNullDeep(expressions); } public int getArgCount() { return args.length; } /** * permissive, if out of range, will return * * @param index * @return */ public IValueHolder getArgument(int index) { if (index >= args.length) { return getOutOfRange(); } return args[index]; } private Holder getOutOfRange() { return Holder.empty(); } /** * Returns a {@link PermissiveIterator} that will return {@link Noop#instance} when it runs out of regular * arguments. */ @Override public PermissiveIterator<IValueHolder> iterator() { return new PermissiveIterator<IValueHolder>(Arrays.stream(args).iterator(), this::getOutOfRange); } @Override public String toString() { return this.args.toString(); } }