eu.interedition.collatex.util.VariantGraphRanking.java Source code

Java tutorial

Introduction

Here is the source code for eu.interedition.collatex.util.VariantGraphRanking.java

Source

/*
 * Copyright (c) 2013 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 <http://www.gnu.org/licenses/>.
 */

package eu.interedition.collatex.util;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;

import javax.annotation.Nullable;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Ordering;
import com.google.common.collect.RowSortedTable;
import com.google.common.collect.Sets;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeBasedTable;
import com.google.common.collect.TreeMultimap;

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

/**
 * @author <a href="http://gregor.middell.net/" title="Homepage">Gregor Middell</a>
 * @author Ronald Haentjens Dekker
 */
public class VariantGraphRanking implements Iterable<Set<VariantGraph.Vertex>>,
        Function<VariantGraph.Vertex, Integer>, Comparator<VariantGraph.Vertex> {

    private final Map<VariantGraph.Vertex, Integer> byVertex = Maps.newHashMap();
    private final SortedSetMultimap<Integer, VariantGraph.Vertex> byRank = TreeMultimap.create(Ordering.natural(),
            Ordering.arbitrary());
    private final VariantGraph graph;
    private final Set<Witness> witnesses;

    VariantGraphRanking(VariantGraph graph, Set<Witness> witnesses) {
        this.graph = graph;
        this.witnesses = witnesses;
    }

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

    public static VariantGraphRanking of(VariantGraph graph, Set<Witness> witnesses) {
        final VariantGraphRanking ranking = new VariantGraphRanking(graph, witnesses);
        for (VariantGraph.Vertex v : graph.vertices(witnesses)) {
            int rank = -1;
            for (VariantGraph.Edge e : v.incoming(witnesses)) {
                rank = Math.max(rank, ranking.byVertex.get(e.from()));
            }
            rank++;
            ranking.byVertex.put(v, rank);
            ranking.byRank.put(rank, v);
        }
        return ranking;
    }

    public static VariantGraphRanking ofOnlyCertainVertices(VariantGraph graph, Set<Witness> witnesses,
            Set<VariantGraph.Vertex> vertices) {
        final VariantGraphRanking ranking = new VariantGraphRanking(graph, witnesses);
        for (VariantGraph.Vertex v : graph.vertices(witnesses)) {
            int rank = -1;
            for (VariantGraph.Edge e : v.incoming(witnesses)) {
                rank = Math.max(rank, ranking.byVertex.get(e.from()));
            }
            if (vertices.contains(v)) {
                rank++;
            }
            ranking.byVertex.put(v, rank);
            ranking.byRank.put(rank, v);
        }
        return ranking;
    }

    public Set<Witness> witnesses() {
        return Objects.firstNonNull(witnesses, graph.witnesses());
    }

    public Map<VariantGraph.Vertex, Integer> getByVertex() {
        return Collections.unmodifiableMap(byVertex);
    }

    public SortedSetMultimap<Integer, VariantGraph.Vertex> getByRank() {
        return Multimaps.unmodifiableSortedSetMultimap(byRank);
    }

    public int size() {
        return byRank.keySet().size();
    }

    @Override
    public Iterator<Set<VariantGraph.Vertex>> iterator() {
        return new AbstractIterator<Set<VariantGraph.Vertex>>() {
            private final Iterator<Integer> it = byRank.keySet().iterator();

            @Override
            protected Set<VariantGraph.Vertex> computeNext() {
                return (it.hasNext() ? byRank.get(it.next()) : endOfData());
            }
        };
    }

    public RowSortedTable<Integer, Witness, Set<Token>> asTable() {
        final TreeBasedTable<Integer, Witness, Set<Token>> table = TreeBasedTable.create(Ordering.natural(),
                Witness.SIGIL_COMPARATOR);
        for (Map.Entry<VariantGraph.Vertex, Integer> rank : byVertex.entrySet()) {
            final int row = rank.getValue();
            for (Token token : rank.getKey().tokens(witnesses)) {
                final Witness column = token.getWitness();

                Set<Token> cell = table.get(row, column);
                if (cell == null) {
                    table.put(row, column, cell = Sets.newHashSet());
                }
                cell.add(token);
            }
        }
        return table;
    }

    public VariantGraph.Vertex[][] asArray() {
        final Set<Integer> ranks = byRank.keySet();
        final VariantGraph.Vertex[][] arr = new VariantGraph.Vertex[ranks.size()][];
        for (final Iterator<Integer> it = ranks.iterator(); it.hasNext();) {
            final Integer rank = it.next();
            final SortedSet<Vertex> vertices = byRank.get(rank);
            arr[rank] = vertices.toArray(new Vertex[vertices.size()]);
        }
        return arr;
    }

    @Override
    public Integer apply(@Nullable VariantGraph.Vertex vertex) {
        return byVertex.get(vertex);
    }

    @Override
    public int compare(VariantGraph.Vertex o1, VariantGraph.Vertex o2) {
        final Integer o1Rank = byVertex.get(o1);
        final Integer o2Rank = byVertex.get(o2);

        Preconditions.checkState(o1Rank != null, o1);
        Preconditions.checkState(o2Rank != null, o2);

        return (o1Rank.intValue() - o2Rank.intValue());
    }
}