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 {

        BufferedReader reader = new BufferedReader(r);

        MultimapGraph graph = new MultimapGraph();

        HashMap nodeMapping = new HashMap();
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.contains(POS + "=")) {
                String nodeName = line.substring(0, line.indexOf("[")).trim();
                String[] position = line.split("\"")[1].split(",");
                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"]
                String[] names = line.split("->");
                String fromStr = names[0].trim();
                String toStr = names[1].substring(0, names[1].indexOf("["))
                        .trim();
                Point from = nodeMapping.get(fromStr);
                Point to = nodeMapping.get(toStr);
                for (SerializerFilter f : filters) {
                    if (f.filterOut(from, to)) {
                        continue;
                    }
                }
                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;
        HashMap idMap = new HashMap();
        for (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 (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) {
            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) {
            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) {
            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) {
            double distance = Double.parseDouble(connection.split("\"")[1]);
            try {
                double maxSpeed = Double.parseDouble(connection.split("\"")[3]);
                return new MultiAttributeData(distance, maxSpeed);
            } catch (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