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

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

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

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import java.util.Collection;
import java.util.Set;

import javax.annotation.Nullable;

import org.apache.commons.math3.random.RandomGenerator;

/**
 * Abstract graph implementation providing basic implementations of several
 * graph functions.
 * @param  The type of {@link ConnectionData} that is used at the
 *          {@link Connection}s.
 * @author Rinde van Lon 
 */
public abstract class AbstractGraph implements
    Graph {

  /**
   * Create a new empty graph.
   */
  public AbstractGraph() {
    super();
  }

  @SuppressWarnings("null")
  @Override
  public double connectionLength(Point from, Point to) {
    checkArgument(hasConnection(from, to),
        "Can not get connection length from a non-existing connection.");
    @Nullable
    final E connData = connectionData(from, to);
    return !isEmptyConnectionData(connData) ? connData.getLength() : Point
        .distance(from, to);
  }

  /**
   * Determines whether a connection data is 'empty'. Default only
   * null is considered as an empty connection data. This can be
   * overridden to include a specific instance of connection data to be the
   * 'empty' instance.
   * @param connData The connection data to check.
   * @return true if the specified connection data is considered
   *         empty, false otherwise.
   */
  protected boolean isEmptyConnectionData(@Nullable E connData) {
    return connData == null;
  }

  @Override
  public void addConnection(Point from, Point to) {
    addConnection(from, to, null);
  }

  @Override
  public void addConnection(Connection c) {
    addConnection(c.from, c.to, c.getData());
  }

  @Override
  public void addConnections(Collection> connections) {
    for (final Connection connection : connections) {
      addConnection(connection);
    }
  }

  @Override
  public void merge(Graph other) {
    addConnections(other.getConnections());
  }

  @Override
  public void addConnection(Point from, Point to, @Nullable E connData) {
    checkArgument(!from.equals(to),
        "A connection cannot be circular: %s -> %s ", from, to);
    checkArgument(!hasConnection(from, to),
        "Connection already exists: %s -> %s ", from, to);
    doAddConnection(from, to, connData);
  }

  /**
   * Must be overridden by implementors. It should add a connection between from
   * and to. It can be assumed that the connection does not yet exist and that
   * it is not circular.
   * @param from Starting point of the connection.
   * @param to End point of the connection.
   * @param connData The data to be associated to the connection.
   */
  protected abstract void doAddConnection(Point from, Point to,
      @Nullable E connData);

  @Override
  @SuppressWarnings({ "unchecked" })
  public boolean equals(@Nullable Object other) {
    return other instanceof Graph ? Graphs.equals(this, (Graph) other)
        : false;
  }

  @Override
  public abstract int hashCode();

  @Override
  public Point getRandomNode(RandomGenerator generator) {
    checkState(!isEmpty(), "Can not find a random node in an empty graph.");
    final Set nodes = getNodes();
    final int idx = generator.nextInt(nodes.size());
    int index = 0;
    for (final Point point : nodes) {
      if (idx == index++) {
        return point;
      }
    }
    throw new IllegalStateException();
  }

  @Override
  public Connection getConnection(Point from, Point to) {
    checkArgument(hasConnection(from, to), "%s -> %s is not a connection.",
        from, to);
    return new Connection(from, to, connectionData(from, to));
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy