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

rinde.sim.core.graph.TableGraph Maven / Gradle / Ivy

There is a newer version: 4.4.6
Show newest version
/**
 * 
 */
package rinde.sim.core.graph;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.builder.HashCodeBuilder;

import com.google.common.collect.LinkedHashBasedTable;
import com.google.common.collect.Table;
import com.google.common.collect.Table.Cell;

/**
 * Table-based implementation of a graph. Since this graph is backed by a table
 * look ups for both incoming and outgoing connections from nodes is fast.
 * @author Rinde van Lon 
 * @author Bartosz Michalik  - change to the
 *         parametric version
 * @param  The type of {@link ConnectionData} that is used in the edges.
 */
public class TableGraph extends AbstractGraph {

    private final Table data;
    private final E empty;

    /**
     * Create a new empty graph.
     * @param emptyValue A special connection data instance that is used as the
     *            'empty' instance.
     */
    public TableGraph(E emptyValue) {
        if (emptyValue == null) {
            throw new IllegalArgumentException(
                    "the representation of empty value is needed");
        }
        data = LinkedHashBasedTable.create();
        empty = emptyValue;
    }

    @Override
    public Set getNodes() {
        final Set nodes = new LinkedHashSet(data.rowKeySet());
        nodes.addAll(data.columnKeySet());
        return Collections.unmodifiableSet(nodes);
    }

    @Override
    public boolean hasConnection(Point from, Point to) {
        return data.contains(from, to);
    }

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

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

    @Override
    public boolean containsNode(Point node) {
        return data.containsRow(node) || data.containsColumn(node);
    }

    @Override
    public Collection getOutgoingConnections(Point node) {
        return data.row(node).keySet();
    }

    @Override
    public Collection getIncomingConnections(Point node) {
        return data.column(node).keySet();
    }

    @Override
    public void removeNode(Point node) {
        data.row(node).clear();
        data.column(node).clear();
    }

    @Override
    public void removeConnection(Point from, Point to) {
        if (hasConnection(from, to)) {
            data.remove(from, to);
        } else {
            throw new IllegalArgumentException(
                    "Can not remove non-existing connection: " + from + " -> "
                            + to);
        }

    }

    @Override
    public List> getConnections() {
        final List> connections = new ArrayList>();
        for (final Cell cell : data.cellSet()) {
            if (empty.equals(cell.getValue())) {
                connections.add(new Connection(cell.getRowKey(), cell
                        .getColumnKey(), null));
            } else {
                connections.add(new Connection(cell.getRowKey(), cell
                        .getColumnKey(), cell.getValue()));
            }
        }
        return connections;
    }

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

    @Override
    protected boolean isEmptyConnectionData(E connData) {
        return super.isEmptyConnectionData(connData) || empty.equals(connData);
    }

    @Override
    public Connection getConnection(Point from, Point to) {
        if (!hasConnection(from, to)) {
            throw new IllegalArgumentException(from + " -> " + to
                    + " is not a connection.");
        }
        return new Connection(from, to, connectionData(from, to));
    }

    @Override
    public E connectionData(Point from, Point to) {
        final E e = data.get(from, to);
        if (empty.equals(e)) {
            return null;
        }
        return e;
    }

    @Override
    protected void doAddConnection(Point from, Point to, E edgeData) {
        if (edgeData == null) {
            data.put(from, to, empty);
        } else {
            data.put(from, to, edgeData);
        }
    }

    @Override
    public E setEdgeData(Point from, Point to, E edgeData) {
        if (hasConnection(from, to)) {
            E e;
            if (edgeData == null) {
                e = data.put(from, to, empty);
            } else {
                e = data.put(from, to, edgeData);
            }

            if (empty.equals(e)) {
                return null;
            }
            return e;
        }
        throw new IllegalArgumentException(
                "Can not get connection length from a non-existing connection.");
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(201, 199).append(data).append(empty)
                .toHashCode();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy