All Downloads are FREE. Search and download functionalities are using the official Maven repository.

monniasza.collects.Collects Maven / Gradle / Ivy

Go to download

Dependency for the MultiMachineBuilder, a voxel game about building an industrial empire in a finite world. THIS RELEASE IS NOT PLAYABLE. To play the game, donwload from >ITCH.IO LINK HERE< or >GH releases link here<

The newest version!
/**
 * 
 */
package monniasza.collects;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;

import javax.swing.DefaultListModel;
import javax.swing.ListModel;
import javax.swing.event.ListDataListener;

import com.google.common.collect.Iterators;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multiset;
import com.google.common.collect.SetMultimap;

import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import mmb.NN;
import mmb.Nil;
import mmb.engine.item.ItemEntry;
import mmb.engine.recipe.RecipeOutput;
import monniasza.collects.grid.Grid;
import monniasza.collects.selfset.SelfSet;

/**
 * A set of operations on collections used in MultiMachineBuilder
 * @author oskar
 */
public class Collects {
	private Collects() {}
	
	//Iterators
	/**
	 * Down-casts the iterator
	 * @param  type of the output iterator
	 * @param iter iterator
	 * @return downcasted iterator
	 */
	@SuppressWarnings("unchecked")
	@NN public static  Iterator downcastIterator(Iterator iter) {
		return (Iterator) iter;
	}
	/**
	 * Converts an {@link Iterator} to an {@link Iterable}
	 * @param  type of iterator
	 * @param iter iterator to be converted
	 * @return wrapped iterator object
	 */
	@NN public static  Iterable iter(Iterator iter){
		return () -> iter;
	}
	/**
	 * Converts an {@link Enumeration} to an {@link Iterable}
	 * @param  type of enumeration
	 * @param iter enumeration to be converted
	 * @return wrapped enumeration object
	 */
	@SuppressWarnings("null")
	public static  Iterable iter(Enumeration iter) {
		return iter::asIterator;
	}
	
	//List models
	/**
	 * Wraps the {@link ListModel} in a {@link List}, to allow Java Collections Framework operations to be used
	 * @param 
	 * @param list the ListModel to be wrapped
	 * @return the wrapped list
	 */
	@NN public static  List fromListModel(ListModel list){
		return new AbstractList<>() {
			@Override public T get(int index) {
				return list.getElementAt(index);
			}
			@Override public int size() {
				return list.getSize();
			}
		};
	}
	/**
	 * Wraps the list to a list model
	 * @param  type of the list
	 * @param list list to wrap
	 * @return a list model
	 * @apiNote The list model does not support listeners
	 */
	@NN public static  ListModel toListModel(List list){
		return new ListModel<>() {
			@Override
			public void addListDataListener(@Nil ListDataListener l) {
				throw new UnsupportedOperationException("ListModel from List does not support listeners");
			}
			@Override
			public T getElementAt(int index) {
				return list.get(index);
			}
			@Override
			public int getSize() {
				return list.size();
			}
			@Override
			public void removeListDataListener(@Nil ListDataListener l) {
				throw new UnsupportedOperationException("ListModel from List oes not support listeners");
			}
		};
	}
	/**
	 * Wraps a list model
	 * @param  type of the list model
	 * @param list list model
	 * @return a list wrapper
	 */
	@NN public static  List toWritableList(DefaultListModel list){
		return new AbstractList<>() {
			@Override
			public T get(int index) {
				return list.get(index);
			}
			@Override
			public int size() {
				return list.getSize();
			}
			@Override
			public void add(int index, @Nil T element) {
				list.add(index, element);
			}
			@Override
			public boolean add(@Nil T e) {
				list.addElement(e);
				return true;
			}
			@Override
			public T remove(int index) {
				return list.remove(index);
			}
			@Override
			public T set(int index, @SuppressWarnings("null") @Nil T e) {
				return list.set(index, e);
			}
			@Override
			public boolean isEmpty() {
				return list.isEmpty();
			}
			@Override
			public boolean contains(@Nil Object o) {
				return list.contains(list);
			}
			@SuppressWarnings("null")
			@Override
			public @NN Iterator iterator() {
				return list.elements().asIterator();
			}
			@SuppressWarnings("null")
			@Override
			public Object @NN [] toArray() {
				return list.toArray();
			}
			@Override
			public  U @NN [] toArray(U[] a) {
				list.copyInto(a);
				return a;
			}
			@Override
			public boolean remove(@Nil Object o) {
				return list.removeElement(o);
			}
			@Override
			public boolean containsAll(Collection c) {
				for(Object e: c) {
					if(!list.contains(e)) return false;
				}
				return true;
			}
			@Override
			public boolean addAll(Collection c) {
				list.addAll(c);
				return true;
			}
			@Override
			public boolean addAll(int index, Collection c) {
				list.addAll(index, c);
				return true;
			}
			@Override
			public boolean removeAll(Collection c) {
				boolean result = false;
				for(Object e: c) {
					result |= list.removeElement(e);
				}
				return result;
			}
			@Override
			public boolean retainAll(Collection c) {
				List copy = new ArrayList<>(this);
				boolean result = copy.retainAll(c);
				list.addAll(copy);
				return result;
			}
			@Override
			public void clear() {
				list.removeAllElements();
			}
			@Override
			public int indexOf(@Nil Object o) {
				return list.indexOf(o);
			}
			@Override
			public int lastIndexOf(@Nil Object o) {
				return list.lastIndexOf(o);
			}
			
		};
	}
	@NN public static  DefaultListModel newListModel(Collection list){
		DefaultListModel model = new DefaultListModel<>();
		model.addAll(list);
		return model;
	}
	
	//Self-sets
	/**
	 * @param  type of keys of the output set
	 * @param  type of values of the output set
	 * @param set self-set to wrap
	 * @return an unmodifiable wrapper around the self-set
	 */
	@NN public static  SelfSet unmodifiableSelfSet(SelfSet set){
		return new SelfSet<>() {
			@Override
			public boolean add(@Nil V e) {
				return false;
			}

			@Override
			public boolean addAll(Collection c) {
				throw new UnsupportedOperationException();
			}

			@Override
			public void clear() {
				throw new UnsupportedOperationException();
			}

			@Override
			public boolean containsAll(Collection c) {
				return set.containsAll(c);
			}

			@Override
			public boolean isEmpty() {
				return set.isEmpty();
			}

			@Override
			public Iterator iterator() {
				return downcastIterator(set.iterator());
			}

			@Override
			public boolean removeAll(Collection c) {
				throw new UnsupportedOperationException();
			}

			@Override
			public boolean retainAll(Collection c) {
				throw new UnsupportedOperationException();
			}

			@Override
			public int size() {
				return set.size();
			}

			@Override
			public Object[] toArray() {
				return set.toArray();
			}

			@Override
			public  T[] toArray(T[] a) {
				return set.toArray(a);
			}

			@Override
			public Set keys() {
				return Collections.unmodifiableSet(set.keys());
			}

			@Override
			public Set values() {
				return Collections.unmodifiableSet(set.values());
			}

			@Override
			public V get(@Nil Object  key) {
				return set.get(key);
			}

			@SuppressWarnings("unchecked") //cast is required to accept a supertype, it will never fail
			@Override
			public V getOrDefault(@Nil Object key, V defalt) {
				return ((SelfSet)set).getOrDefault(key, defalt);
			}

			@Override
			public boolean removeKey(K key) {
				throw new UnsupportedOperationException();
			}

			@Override
			public boolean containsKey(@Nil Object key) {
				return set.containsKey(key);
			}

			@Override
			public boolean test(@Nil Object o) {
				return set.test(o);
			}

			@Override
			public K id(Object value) {
				return set.id(value);
			}

			@Override
			public boolean nullable() {
				return set.nullable();
			}

			@SuppressWarnings("unchecked")
			@Override
			public Class type() {
				return (Class) set.type();
			}
		};
	}
	
	//Lists
	/**
	 * Adds the second input to the first one in-place
	 * @param  type of elements
	 * @param list list to add to
	 * @param collect elements to be added
	 * @return first input
	 */
	@NN public static  List inplaceAddLists(List list, Collection collect){
		list.addAll(collect);
		return list;
	}
	/**
	 * Adds two inputs out of place
	 * @param 
	 * @param a first half of the list
	 * @param b second half of the list
	 * @param supplier creates lists
	 * @return a new list
	 */
	@NN public static  List ooplaceAddLists(Collection a, Collection b, Supplier> supplier){
		List list0 = supplier.get();
		list0.addAll(a);
		list0.addAll(b);
		return list0;
	}
	/**
	 * Creates an out-of-place list added
	 * @param  type of values
	 * @param supplier creates lists
	 * @return a list addition function
	 */
	@NN public static  BiFunction<@NN Collection, @NN Collection, List> ooplaceListAdder(Supplier> supplier){
		return (a, b) -> ooplaceAddLists(a, b, supplier);
	}
	
	//Multimaps
	/**
	 * Creates an empty multimap
	 * @param  type of keys
	 * @param  type of values
	 * @return an empty, immutable multimap
	 */
	@SuppressWarnings("unchecked")
	@NN public static  SetMultimap emptyMultimap(){
		return (SetMultimap) emptyMultiMap;
	}
	@NN private static final SetMultimap emptyMultiMap = new EmptySetMultimap();
	/**
	 * Creates an empty multiset
	 * @param  type of values
	 * @return an empty, immutable multiset
	 */
	@SuppressWarnings("unchecked")
	@NN public static  Multiset emptyMultiset(){
		return (Multiset) emptyMultiSet;
	}
	@NN private static final Multiset emptyMultiSet = new EmptyMultiSet();
	
	//Maps
	/**
	 * Creates an int-to-any map from a stream
	 * @param  type of values
	 * @param  type of maps
	 * @param mapsup creates maps
	 * @return an int/obj map collector
	 */
	@NN public static > Collector, Object2IntMap, M> collectToIntMap(Supplier mapsup){
		return new IntMapCollector<>(mapsup);
	}
	/**
	 * Adds the second input to the first input
	 * @param  type of values
	 * @param  type of the modified map
	 * @param list map to be modified
	 * @param collect map to be added to the first input
	 * @return first input
	 */
	@NN public static > M inplaceAddIntMaps(M list, Object2IntMap collect){
		list.putAll(collect);
		return list;
	}

	//Grids
	/**
	 * Prevents changes to a grid
	 * @param grid grid to prevent changes to
	 * @return an unmodifiable view of the input grid
	 */
	public static  Grid unmodifiableGrid(Grid grid) {
		return new Grid<>() {
			@Override
			public void set(int x, int y, T data) {
				throw new UnsupportedOperationException();
			}
			@Override
			public T get(int x, int y) {
				return grid.get(x, y);
			}
			@Override
			public int width() {
				return grid.width();
			}
			@Override
			public int height() {
				return grid.height();
			}
			@SuppressWarnings("null")
			@Override
			public Iterator iterator() {
				return Iterators.unmodifiableIterator(grid.iterator());
			}	
		};
	}
	/**
	 * Creates a dynamically-mapped view of a grid
	 * @param  type of the input grid
	 * @param  type of the output grid
	 * @param forward forward mapper
	 * @param backward backward mapper
	 * @param grid input grid
	 * @return a transformed view of the grid. The view is backed by the grid, so any changes made to the original are reflected in the view and vice versa
	 */
	public static  Grid mapGrid(Function forward, @Nil Function backward, Grid grid){
		return new Grid<>() {
			@Override
			public void set(int x, int y, Tout data) {
				if(backward == null) throw new UnsupportedOperationException("no backwards function");
				grid.set(x, y, backward.apply(data));
			}
			@Override
			public Tout get(int x, int y) {
				return forward.apply(grid.get(x, y));
			}
			@Override
			public int width() {
				return grid.width();
			}
			@Override
			public int height() {
				return grid.height();
			}
			@Override
			public Iterator iterator() {
				Iterator iter = grid.iterator();
				return new Iterator<>() {

					@Override
					public boolean hasNext() {
						return iter.hasNext();
					}

					@Override
					public Tout next() {
						return forward.apply(iter.next());
					}

					@Override
					public void remove() {
						iter.remove();
					}
				};
			}	
		};
	}

	//Iteration
	/**
	 * Gets the first item using iteration
	 * @param c collection to get items from
	 * @return the first item
	 * @throws NoSuchElementException when there is no requested item
	 */
	public static  T first(Iterable c) {
		return c.iterator().next();
	}

	//All/any boolean operations
	/**
	 * Checks if all values meet a predicate
	 * @param  type of values
	 * @param collection collection to test
	 * @param predicate condition
	 * @return do all items meet a criterion?
	 */
	public static  boolean isAll(Iterable collection, Predicate predicate) {
		for(T value: collection) 
			if(!predicate.test(value)) return false;
		return true;
	}
	/**
	 * Checks if any value meets a predicate
	 * @param  type of values
	 * @param collection collection to test
	 * @param predicate condition
	 * @return does any items meet a criterion?
	 */
	public static  boolean isAny(Iterable collection, Predicate predicate) {
		for(T value: collection) 
			if(predicate.test(value)) return true;
		return false;
	}
}
class IntMapCollector> implements Collector, Object2IntMap, M>{
	@NN private final Supplier mapsup;

	public IntMapCollector(Supplier mapsup) {
		this.mapsup = mapsup;
	}

	@Override
	public Supplier> supplier() {
		return Object2IntOpenHashMap::new;
	}

	@Override
	public BiConsumer, Object2IntMap.Entry> accumulator() {
		return (map, entry) -> map.put(entry.getKey(), entry.getIntValue());
	}

	@Override
	public BinaryOperator> combiner() {
		return Collects::inplaceAddIntMaps;
	}

	@SuppressWarnings("null")
	@Override
	public Function, M> finisher() {
		return map -> {
			M result = mapsup.get();
			return Collects.inplaceAddIntMaps(result, map);
		};
	}

	@Override
	public Set characteristics() {
		return Set.of(Characteristics.UNORDERED);
	}
}
class EmptyMultiSet implements Multiset{

	@Override
	public boolean isEmpty() {
		return true;
	}

	@Override
	public Object @NN [] toArray() {
		return new Object[0];
	}

	@Override
	public  T @NN [] toArray(T[] a) {
		return a;
	}

	@Override
	public boolean addAll(Collection c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void clear() {
		throw new UnsupportedOperationException();
	}

	@Override
	public int size() {
		return 0;
	}

	@Override
	public int count(Object element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public int add(@Nil Object element, int occurrences) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean add(@Nil Object element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public int remove(Object element, int occurrences) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean remove(@Nil Object element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public int setCount(@Nil Object element, int count) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean setCount(@Nil Object element, int oldCount, int newCount) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Set elementSet() {
		return Collections.emptySet();
	}

	@Override
	public Set> entrySet() {
		return Collections.emptySet();
	}

	@Override
	public Iterator iterator() {
		return Collections.emptyIterator();
	}

	@Override
	public boolean contains(@Nil Object element) {
		return false;
	}

	@Override
	public boolean containsAll(Collection elements) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean removeAll(Collection c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean retainAll(Collection c) {
		throw new UnsupportedOperationException();
	}
	
}
class EmptySetMultimap implements SetMultimap{

	@Override
	public int size() {
		return 0;
	}

	@Override
	public boolean isEmpty() {
		return true;
	}

	@Override
	public boolean containsKey(Object key) {
		return false;
	}

	@Override
	public boolean containsValue(Object value) {
		return false;
	}

	@Override
	public boolean containsEntry(Object key, Object value) {
		return false;
	}

	@Override
	public boolean put(@Nil Object key, @Nil Object value) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean remove(Object key, Object value) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean putAll(@Nil Object key, Iterable values) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean putAll(Multimap multimap) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Set replaceValues(Object key, Iterable values) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Set removeAll(Object key) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void clear() {
		throw new UnsupportedOperationException();
	}

	@Override
	public Set get(Object key) {
		return Collections.emptySet();
	}

	@Override
	public Set keySet() {
		return Collections.emptySet();
	}

	@Override
	public Multiset keys() {
		return Collects.emptyMultiset();
	}

	@Override
	public Collection values() {
		return Collections.emptyList();
	}

	@Override
	public Set> entries() {
		return Collections.emptySet();
	}

	@Override
	public Map> asMap() {
		return Collections.emptyMap();
	}
	
}