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

org.semanticweb.owlapi.util.OWLAPIStreamUtils Maven / Gradle / Ivy

There is a newer version: 5.5.1
Show newest version
package org.semanticweb.owlapi.util;

import static java.util.stream.Collectors.toSet;
import static org.semanticweb.owlapi.util.OWLAPIPreconditions.checkNotNull;

import java.util.*;
import java.util.stream.Stream;

import org.semanticweb.owlapi.model.HasComponents;
import org.semanticweb.owlapi.model.OWLObject;

/** A few util methods for common stream operations. */
public class OWLAPIStreamUtils {

    /**
     * Class for pairwise partition
     * 
     * @param 
     *        type
     */
    public static class Pair {

        /** First element. */
        public final T i;
        /** Second element. */
        public final T j;

        /**
         * @param i
         *        first
         * @param j
         *        second
         */
        public Pair(T i, T j) {
            this.i = i;
            this.j = j;
        }
    }

    private OWLAPIStreamUtils() {}

    /**
     * @param s
     *        stream to turn to set. The stream is consumed by this operation.
     * @return set including all elements in the stream
     */
    public static  Set asSet(Stream s) {
        Set set = new LinkedHashSet<>();
        add(set, s);
        return set;
    }

    /**
     * @param s
     *        stream to turn to set. The stream is consumed by this operation.
     * @param type
     *        force return type to be exactly T
     * @param 
     *        type of return collection
     * @return set including all elements in the stream
     */
    @SuppressWarnings("unchecked")
    public static  Set asSet(Stream s, @SuppressWarnings("unused") Class type) {
        Set set = new LinkedHashSet<>();
        add(set, s.map(x -> (T) x));
        return set;
    }

    /**
     * @param s
     *        stream to turn to set. The stream is consumed by this operation.
     * @return set including all elements in the stream
     */
    public static  Set asUnorderedSet(Stream s) {
        return s.collect(toSet());
    }

    /**
     * @param s
     *        stream to turn to set. The stream is consumed by this operation.
     * @param type
     *        force return type to be exactly T
     * @param 
     *        type of return collection
     * @return set including all elements in the stream
     */
    @SuppressWarnings("unchecked")
    public static  Set asUnorderedSet(Stream s, @SuppressWarnings("unused") Class type) {
        return s.map(x -> (T) x).collect(toSet());
    }

    /**
     * @param s
     *        stream to turn to list. The stream is consumed by this operation.
     * @return list including all elements in the stream
     */
    public static  List asList(Stream s) {
        List set = new ArrayList<>();
        add(set, s);
        return set;
    }

    /**
     * @param s
     *        stream to turn to list. The stream is consumed by this operation.
     * @return list including all elements in the stream
     */
    public static  List asListNullsForbidden(Stream s) {
        return asList(s.map(x -> checkNotNull(x)));
    }

    /**
     * @param s
     *        stream to turn to list. The stream is consumed by this operation.
     * @param type
     *        force return type to be exactly T
     * @param 
     *        type of return collection
     * @return list including all elements in the stream
     */
    @SuppressWarnings("unchecked")
    public static  List asList(Stream s, @SuppressWarnings("unused") Class type) {
        return asList(s.map(x -> (T) x));
    }

    /**
     * @param s
     *        stream to check for containment. The stream is consumed at least
     *        partially by this operation
     * @param o
     *        object to search
     * @return true if the stream contains the object
     */
    public static boolean contains(Stream s, Object o) {
        return s.anyMatch(x -> x.equals(o));
    }

    /**
     * @param s
     *        stream of elements to add
     * @param c
     *        collection to add to
     * @return true if any element in the stream is added to the collection
     */
    public static  boolean add(Collection c, Stream s) {
        int size = c.size();
        s.forEach(c::add);
        return c.size() != size;
    }

    /**
     * @param set1
     *        collection to compare
     * @param set2
     *        collection to compare
     * @return negative value if set1 comes before set2, positive value if set2
     *         comes before set1, 0 if the two sets are equal or incomparable.
     */
    public static int compareCollections(Collection set1, Collection set2) {
        SortedSet ss1;
        if (set1 instanceof SortedSet) {
            ss1 = (SortedSet) set1;
        } else {
            ss1 = new TreeSet<>(set1);
        }
        SortedSet ss2;
        if (set2 instanceof SortedSet) {
            ss2 = (SortedSet) set2;
        } else {
            ss2 = new TreeSet<>(set2);
        }
        return compareIterators(ss1.iterator(), ss2.iterator());
    }

    /**
     * Compare streams through iterators (sensitive to order)
     * 
     * @param set1
     *        stream to compare
     * @param set2
     *        stream to compare
     * @return negative value if set1 comes before set2, positive value if set2
     *         comes before set1, 0 if the two sets are equal or incomparable.
     */
    public static int compareStreams(Stream set1, Stream set2) {
        return compareIterators(set1.sorted().iterator(), set2.sorted().iterator());
    }

    /**
     * Compare iterators element by element (sensitive to order)
     * 
     * @param set1
     *        iterator to compare
     * @param set2
     *        iterator to compare
     * @return negative value if set1 comes before set2, positive value if set2
     *         comes before set1, 0 if the two sets are equal or incomparable.
     */
    @SuppressWarnings("unchecked")
    public static int compareIterators(Iterator set1, Iterator set2) {
        while (set1.hasNext() && set2.hasNext()) {
            Object o1 = set1.next();
            Object o2 = set2.next();
            int diff;
            if (o1 instanceof Stream && o2 instanceof Stream) {
                diff = compareIterators(((Stream) o1).iterator(), ((Stream) o2).iterator());
            } else if (o1 instanceof Collection && o2 instanceof Collection) {
                diff = compareIterators(((Collection) o1).iterator(), ((Collection) o2).iterator());
            } else if (o1 instanceof Comparable && o2 instanceof Comparable) {
                diff = ((Comparable) o1).compareTo(o2);
            } else {
                throw new IllegalArgumentException("Incomparable types: '" + o1 + "' with class " + o1.getClass()
                    + ", '" + o2 + "' with class " + o2.getClass() + " found while comparing iterators");
            }
            if (diff != 0) {
                return diff;
            }
        }
        return Boolean.compare(set1.hasNext(), set2.hasNext());
    }

    /**
     * Check iterator contents for equality (sensitive to order)
     * 
     * @param set1
     *        iterator to compare
     * @param set2
     *        iterator to compare
     * @return true if the iterators have the same content, false otherwise.
     */
    public static boolean equalIterators(Iterator set1, Iterator set2) {
        while (set1.hasNext() && set2.hasNext()) {
            Object o1 = set1.next();
            Object o2 = set2.next();
            if (o1 instanceof Stream && o2 instanceof Stream) {
                if (!equalStreams((Stream) o1, (Stream) o2)) {
                    return false;
                }
            } else {
                if (!o1.equals(o2)) {
                    return false;
                }
            }
        }
        return set1.hasNext() == set2.hasNext();
    }

    /**
     * Check streams for equality (sensitive to order)
     * 
     * @param set1
     *        stream to compare
     * @param set2
     *        stream to compare
     * @return true if the streams have the same content, false otherwise.
     */
    public static boolean equalStreams(Stream set1, Stream set2) {
        return equalIterators(set1.iterator(), set2.iterator());
    }

    /**
     * Check lists for equality (sensitive to order)
     * 
     * @param set1
     *        list to compare
     * @param set2
     *        list to compare
     * @return true if the lists have the same content, false otherwise.
     */
    public static int compareLists(List set1, List set2) {
        return compareIterators(set1.iterator(), set2.iterator());
    }

    /**
     * Annotated wrapper for Stream.empty()
     * 
     * @return empty stream
     */
    public static  Stream empty() {
        return Stream.empty();
    }

    /**
     * @param root
     *        the root for the invisit
     * @return recursive invisit of all components included in the root
     *         component; includes the root and all intermediate nodes.
     *         Annotations and other groups of elements will be represented as
     *         streams or collections, same as if the accessor method on the
     *         object was used.
     */
    public static Stream allComponents(HasComponents root) {
        List> streams = new ArrayList<>();
        streams.add(Stream.of(root));
        root.components().forEach(o -> {
            if (o != root) {
                if (o instanceof HasComponents) {
                    streams.add(allComponents((HasComponents) o));
                } else {
                    streams.add(Stream.of(o));
                }
            }
        });
        return streams.stream().flatMap(x -> x);
    }

    /**
     * @param root
     *        the root for the invisit
     * @return recursive invisit of all components included in the root
     *         component; includes the root and all intermediate nodes. Streams
     *         will be flattened.
     */
    public static Stream flatComponents(HasComponents root) {
        List> streams = new ArrayList<>();
        streams.add(Stream.of(root));
        root.components().filter(o -> o != root).forEach(o -> flatIteration(streams, o));
        return streams.stream().flatMap(x -> x);
    }

    protected static void flatIteration(List> streams, Object o) {
        if (o instanceof Stream) {
            ((Stream) o).forEach(o1 -> flatIteration(streams, o1));
        } else if (o instanceof Collection) {
            ((Collection) o).forEach(o1 -> flatIteration(streams, o1));
        } else if (o instanceof HasComponents) {
            ((HasComponents) o).components().forEach(o1 -> flatIteration(streams, o1));
        } else {
            streams.add(Stream.of(o));
        }
    }

    /**
     * @param size
     *        size of matrix
     * @return a stream of coordinates for a triangular matrix of size
     *         {@code size}. For input 3, the values are (1,2), (1,3), (2,3)
     */
    public static Stream pairs(int size) {
        List values = new ArrayList<>((size * size - size) / 2);
        for (int i = 0; i < size - 1; i++) {
            for (int j = i + 1; j < size; j++) {
                values.add(new int[] { i, j });
            }
        }
        return values.stream();
    }

    /**
     * @param size
     *        size of matrix
     * @return a stream of coordinates for a symmetric matrix of size
     *         {@code size}, excluding main diagonal. For input 3, the values
     *         are (1,2), (1,3), (2,3), (2,1),(3,1), (3,2)
     */
    public static Stream allPairs(int size) {
        List values = new ArrayList<>(size * size - size);
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (i != j) {
                    values.add(new int[] { i, j });
                }
            }
        }
        return values.stream();
    }

    /**
     * @param input
     *        collection to partition
     * @return a stream of elements for a triangular matrix of size
     *         {@code l.size()}, where l is the list corresponding to the input
     *         collection. For input of length 3, the values are
     *         (l.get(1),l.get(2)), (l.get(1),l.get(3)), (l.get(2),l.get(3))
     */
    public static  Stream> pairs(Collection input) {
        List l;
        if (input instanceof List) {
            l = (List) input;
        } else {
            l = new ArrayList<>(input);
        }
        int size = l.size();
        List> values = new ArrayList<>((size * size - size) / 2);
        for (int i = 0; i < size - 1; i++) {
            for (int j = i + 1; j < size; j++) {
                values.add(pair(l.get(i), l.get(j)));
            }
        }
        return values.stream();
    }

    /**
     * @param input
     *        collection to partition
     * @return a stream of coordinates for a symmetric matrix of size
     *         {@code l.size()}, where l is the list corresponding to the input
     *         collection, excluding main diagonal. For input 3, the values are
     *         (l.get(1),l.get(2)), (l.get(1),l.get(3)), (l.get(2),l.get(3)),
     *         (l.get(2),l.get(1)),(l.get(3),l.get(1)), (l.get(3),l.get(2))
     */
    public static  Stream> allPairs(Collection input) {
        List l;
        if (input instanceof List) {
            l = (List) input;
        } else {
            l = new ArrayList<>(input);
        }
        int size = l.size();
        List> values = new ArrayList<>(size * size - size);
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (i != j) {
                    values.add(pair(l.get(i), l.get(j)));
                }
            }
        }
        return values.stream();
    }

    /**
     * @param input
     *        collection to partition
     * @return a stream of elements for a triangular matrix of size
     *         {@code l.size()}, where l is the list corresponding to the input
     *         collection. For input of length 3, the values are
     *         (l.get(1),l.get(2)), (l.get(1),l.get(3)), (l.get(2),l.get(3))
     */
    public static  Stream> pairs(Stream input) {
        return pairs(asList(input));
    }

    /**
     * @param input
     *        collection to partition
     * @return a stream of coordinates for a symmetric matrix of size
     *         {@code l.size()}, where l is the list corresponding to the input
     *         collection, excluding main diagonal. For input 3, the values are
     *         (l.get(1),l.get(2)), (l.get(1),l.get(3)), (l.get(2),l.get(3)),
     *         (l.get(2),l.get(1)),(l.get(3),l.get(1)), (l.get(3),l.get(2))
     */
    public static  Stream> allPairs(Stream input) {
        return allPairs(asList(input));
    }

    /**
     * @param i
     *        first
     * @param j
     *        second
     * @return pair of (i,j)
     */
    public static  Pair pair(T i, T j) {
        return new Pair<>(i, j);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy