001package org.clafer.collection;
002
003import java.lang.reflect.Array;
004import java.util.ArrayList;
005import java.util.List;
006
007/**
008 * A option type. Does not allow nulls.
009 *
010 * @param <T> the type of maybe
011 * @author jimmy
012 */
013public abstract class Maybe<T> {
014
015    private static final Nothing<?> Nothing = new Nothing<>();
016
017    public abstract boolean isNothing();
018
019    public abstract boolean isJust();
020
021    public abstract T fromMaybe(T t);
022
023    public static <T> Nothing<T> nothing() {
024        @SuppressWarnings("unchecked")
025        Nothing<T> maybe = (Nothing<T>) Nothing;
026        return maybe;
027    }
028
029    public static <T> Just<T> just(T t) {
030        return new Just<>(t);
031    }
032
033    public static <T> List<T> filterJust(List<Maybe<? extends T>> maybes) {
034        List<T> justs = new ArrayList<>();
035        for (Maybe<? extends T> maybe : maybes) {
036            T t = maybe.fromMaybe(null);
037            if (t != null) {
038                justs.add(t);
039            }
040        }
041        return justs;
042    }
043
044    @SafeVarargs
045    public static <T> T[] filterJust(Maybe<? extends T>[] maybes, T... array) {
046        List<T> justs = new ArrayList<>();
047        for (Maybe<? extends T> maybe : maybes) {
048            T t = maybe.fromMaybe(null);
049            if (t != null) {
050                justs.add(t);
051            }
052        }
053        @SuppressWarnings("unchecked")
054        T[] to = array.length == justs.size()
055                ? array
056                : (T[]) Array.newInstance(array.getClass().getComponentType(), justs.size());
057        return justs.toArray(to);
058    }
059}