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

rinde.sim.serializers.DotGraphSerializer Maven / Gradle / Ivy

There is a newer version: 4.4.6
Show newest version
package rinde.sim.serializers;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.HashMap;

import rinde.sim.core.graph.Connection;
import rinde.sim.core.graph.ConnectionData;
import rinde.sim.core.graph.Graph;
import rinde.sim.core.graph.LengthData;
import rinde.sim.core.graph.MultiAttributeData;
import rinde.sim.core.graph.MultimapGraph;
import rinde.sim.core.graph.Point;

/**
 * Dot format serializer for a road model graph. Allows for reading storing maps
 * in dot format. The default implementation of the serializer for graphs with
 * edge length information can be obtained via calling
 * {@link DotGraphSerializer#getLengthGraphSerializer(SerializerFilter...)}
 * 
 * @author Bartosz Michalik 
 * 
 */
public class DotGraphSerializer extends
    AbstractGraphSerializer {

  private SerializerFilter[] filters;
  private ConnectionSerializer serializer;

  public static final String POS = "p";
  public static final String NODE_PREFIX = "n";
  public static final String DISTANCE = "d";
  public static final String MAX_SPEED = "s";

  public DotGraphSerializer(ConnectionSerializer connectionSerializer,
      SerializerFilter... filters) {
    if (connectionSerializer == null) {
      throw new IllegalArgumentException("connectionSerializer cannot be null");
    }
    this.filters = filters;
    if (filters == null) {
      this.filters = new SerializerFilter[0];
    }
    this.serializer = connectionSerializer;
  }

  public DotGraphSerializer(ConnectionSerializer serializer) {
    this(serializer, new SerializerFilter[0]);
  }

  @Override
  public Graph read(Reader r) throws IOException {

    final BufferedReader reader = new BufferedReader(r);

    final MultimapGraph graph = new MultimapGraph();

    final HashMap nodeMapping = new HashMap();
    String line;
    while ((line = reader.readLine()) != null) {
      if (line.contains(POS + "=")) {
        final String nodeName = line.substring(0, line.indexOf("[")).trim();
        final String[] position = line.split("\"")[1].split(",");
        final Point p = new Point(Double.parseDouble(position[0]),
            Double.parseDouble(position[1]));
        nodeMapping.put(nodeName, p);
      } else if (line.contains("->")) {
        // example:
        // node1004 -> node820[label="163.3"]
        final String[] names = line.split("->");
        final String fromStr = names[0].trim();
        final String toStr = names[1].substring(0, names[1].indexOf("["))
            .trim();
        final Point from = nodeMapping.get(fromStr);
        final Point to = nodeMapping.get(toStr);
        for (final SerializerFilter f : filters) {
          if (f.filterOut(from, to)) {
            continue;
          }
        }
        final E data = serializer.deserialize(line);
        graph.addConnection(from, to, data);

      }
    }
    return graph;

  }

  @Override
  public void write(Graph graph, Writer writer) throws IOException {
    final BufferedWriter out = new BufferedWriter(writer);

    final StringBuilder string = new StringBuilder();
    string.append("digraph mapgraph {\n");

    int nodeId = 0;
    final HashMap idMap = new HashMap();
    for (final Point p : graph.getNodes()) {
      string.append(NODE_PREFIX).append(nodeId).append('[').append(POS)
          .append("=\"").append(p.x).append(',').append(p.y).append("\"]\n");
      idMap.put(p, nodeId);
      nodeId++;
    }

    for (final Connection entry : graph.getConnections()) {
      string.append(serializer.serializeConnection(idMap.get(entry.from), idMap
          .get(entry.to), entry));
    }
    string.append('}');
    out.append(string);
    out.close(); // it is important to close the BufferedWriter! otherwise
                 // there is no guarantee that it has reached the end..
  }

  /**
   * Used to serialize graphs
   * @author Bartosz Michalik 
   * 
   * @param 
   * @since 2.0
   */
  public static abstract class ConnectionSerializer {
    public abstract String serializeConnection(int idFrom, int idTo,
        Connection conn);

    public abstract E deserialize(String connection);
  }

  private static class LengthConnectionSerializer extends
      ConnectionSerializer {

    public LengthConnectionSerializer() {}

    @Override
    public String serializeConnection(int idFrom, int idTo,
        Connection conn) {
      final StringBuffer buffer = new StringBuffer();
      buffer.append(NODE_PREFIX).append(idFrom).append(" -> ")
          .append(NODE_PREFIX).append(idTo);
      buffer.append('[').append(DISTANCE).append("=\"")
          .append(Math.round(conn.getData().getLength()) / 10d).append("\"]\n");
      return buffer.toString();
    }

    @Override
    public LengthData deserialize(String connection) {
      final double distance = Double.parseDouble(connection.split("\"")[1]);
      return new LengthData(distance);
    }
  }

  private static class MultiAttributeConnectionSerializer extends
      ConnectionSerializer {
    public MultiAttributeConnectionSerializer() {}

    @Override
    public String serializeConnection(int idFrom, int idTo,
        Connection conn) {
      final StringBuffer buffer = new StringBuffer();
      buffer.append(NODE_PREFIX).append(idFrom).append(" -> ")
          .append(NODE_PREFIX).append(idTo);
      buffer.append('[').append(DISTANCE).append("=\"")
          .append(Math.round(conn.getData().getLength()) / 10d);
      if (!Double.isNaN(conn.getData().getMaxSpeed())
          && conn.getData().getMaxSpeed() > 0) {
        buffer.append("\", ").append(MAX_SPEED).append("=\"")
            .append(conn.getData().getMaxSpeed());
      }
      buffer.append("\"]\n");
      return buffer.toString();
    }

    @Override
    public MultiAttributeData deserialize(String connection) {
      final double distance = Double.parseDouble(connection.split("\"")[1]);
      try {
        final double maxSpeed = Double.parseDouble(connection.split("\"")[3]);
        return new MultiAttributeData(distance, maxSpeed);
      } catch (final Exception e) {
        return new MultiAttributeData(distance);
      }
    }
  }

  /**
   * Get instance of the serializer that can read write graph with the edges
   * length information
   * @param filters
   * @return
   */
  public static DotGraphSerializer getLengthGraphSerializer(
      SerializerFilter... filters) {
    return new DotGraphSerializer(new LengthConnectionSerializer(),
        filters);
  }

  public static DotGraphSerializer getMultiAttributeGraphSerializer(
      SerializerFilter... filters) {
    return new DotGraphSerializer(
        new MultiAttributeConnectionSerializer(), filters);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy