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

eu.interedition.collatex.util.VariantGraphTraversal Maven / Gradle / Ivy

/*
 * Copyright (c) 2015 The Interedition Development Group.
 *
 * This file is part of CollateX.
 *
 * CollateX is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CollateX is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CollateX.  If not, see .
 */

package eu.interedition.collatex.util;

import eu.interedition.collatex.VariantGraph;
import eu.interedition.collatex.Witness;

import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;

/**
 * @author Gregor Middell
 */
public class VariantGraphTraversal implements Iterable {
    private final VariantGraph graph;
    private final Set witnesses;

    private VariantGraphTraversal(VariantGraph graph, Set witnesses) {
        this.graph = graph;
        this.witnesses = witnesses;
    }

    public static VariantGraphTraversal of(VariantGraph graph, Set witnesses) {
        return new VariantGraphTraversal(graph, witnesses);
    }

    public static VariantGraphTraversal of(VariantGraph graph) {
        return new VariantGraphTraversal(graph, null);
    }

    @Override
    public Iterator iterator() {
        return new Iterator() {

            private final Map encountered = new HashMap<>();
            private final Queue queue = new ArrayDeque<>();
            private Optional next = Optional.of(graph.getStart());

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

            @Override
            public VariantGraph.Vertex next() {
                final VariantGraph.Vertex next = this.next.get();
                for (Map.Entry> edge : next.outgoing().entrySet()) {
                    if (witnesses != null && !edge.getValue().stream().anyMatch(witnesses::contains)) {
                        continue;
                    }
                    final VariantGraph.Vertex end = edge.getKey();

                    final long endEncountered = Optional.ofNullable(encountered.get(end)).orElse(0L);
                    final long endIncoming = end.incoming().entrySet().stream().filter(e -> witnesses == null || e.getValue().stream().anyMatch(witnesses::contains)).count();

                    if (endIncoming == endEncountered) {
                        throw new IllegalStateException(String.format("Encountered cycle traversing %s to %s", edge, end));
                    } else if ((endIncoming - endEncountered) == 1) {
                        queue.add(end);
                    }

                    encountered.put(end, endEncountered + 1);
                }
                this.next = Optional.ofNullable(queue.poll());
                return next;
            }
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy