package edu.kit.pse.ws2013.routekit.map; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; import edu.kit.pse.ws2013.routekit.models.ProgressReporter; import edu.kit.pse.ws2013.routekit.util.DummyProgressReporter; /** * A street map. */ public class StreetMap { protected String name; protected Graph graph; protected EdgeBasedGraph edgeBasedGraph; private final boolean isDefault; /** * Creates a new {@code StreetMap} object from the given {@link Graph} and * {@link EdgeBasedGraph}. * * @param graph * the map graph * @param edgeBasedGraph * the edge-based graph */ public StreetMap(Graph graph, EdgeBasedGraph edgeBasedGraph) { this(graph, edgeBasedGraph, false); } private StreetMap(Graph graph, EdgeBasedGraph edgeBasedGraph, boolean isDefault) { this.graph = graph; this.edgeBasedGraph = edgeBasedGraph; this.isDefault = isDefault; } /** * Determines if this is a default map. * * @return {@code true} if the map is a default map, else {@code false}. */ public boolean isDefault() { return isDefault; } /** * Returns the {@link EdgeBasedGraph} of this street map. * * @return the edge-based graph */ public EdgeBasedGraph getEdgeBasedGraph() { return edgeBasedGraph; } /** * Returns the {@link Graph} of this street map. * * @return the graph */ public Graph getGraph() { return graph; } /** * Returns the name of this map. * * @return the name, or {@code null} if it has not been set yet */ public String getName() { return name; } /** * Sets the name of this map. * * @param name * the name to be set */ public void setName(String name) { this.name = name; } /** * Ensures that this {@link StreetMap} is completely loaded. This is a noop * for normal maps. * * @param reporter * A {@link ProgressReporter} to report loading progress to. * @see #loadLazily(File) */ public void ensureLoaded(ProgressReporter reporter) { reporter.setSubTasks(new float[] { .9f, .1f }); reporter.pushTask("Lade Graphen"); getGraph(); reporter.nextTask("Lade kantenbasierten Graphen"); getEdgeBasedGraph(); reporter.popTask(); } @Override public String toString() { return name; } /** * Saves the map to the given directory by saving the {@link #getGraph() * Graph} and the {@link #getEdgeBasedGraph() edge-based graph} to the files * {@code <name>.graph} and {@code <name>.egraph}. * * @param directory * The directory to which the map should be saved. * @throws IOException * If the files can’t be written. * @see #load(File) */ public void save(File directory) throws IOException { if (!directory.isDirectory()) { throw new IllegalArgumentException(directory.toString() + " is not a directory!"); } Properties p = new Properties(); p.setProperty("default", Boolean.toString(isDefault())); try (FileWriter writer = new FileWriter(new File(directory, directory.getName() + ".properties"))) { p.store(writer, null); } graph.save(new File(directory, directory.getName() + ".graph")); edgeBasedGraph .save(new File(directory, directory.getName() + ".egraph")); } /** * Loads a map from the given directory by loading the {@link #getGraph() * Graph} and the {@link #getEdgeBasedGraph() edge-based graph} from the * files {@code <name>.graph} and {@code <name>.egraph}. * * @param directory * The directory from which the map should be loaded. * @return A {@link StreetMap} containing the {@link Graph} and * {@link EdgeBasedGraph} from the given directory. * @throws IOException * If the files can’t be read. */ public static StreetMap load(File directory) throws IOException { Properties p = new Properties(); try (FileReader reader = new FileReader(new File(directory, directory.getName() + ".properties"))) { p.load(reader); } catch (IOException e) { // ignore, defaults to false } Graph graph = Graph.load(new File(directory, directory.getName() + ".graph"), new DummyProgressReporter()); EdgeBasedGraph egraph = EdgeBasedGraph.load(new File(directory, directory.getName() + ".egraph")); StreetMap ret = new StreetMap(graph, egraph, Boolean.parseBoolean(p .getProperty("default", "false"))); ret.setName(directory.getName()); return ret; } /** * Loads a map from the given directory in the same way as * {@link #load(File)}, except that the {@link Graph} and * {@link EdgeBasedGraph} are loaded lazily – only on the first access. * * @param directory * The directory from which the map should be loaded. * @return A kind of {@link StreetMap} that loads the {@link Graph} and the * {@link EdgeBasedGraph} lazily. */ public static StreetMap loadLazily(File directory) { Properties p = new Properties(); try (FileReader reader = new FileReader(new File(directory, directory.getName() + ".properties"))) { p.load(reader); } catch (IOException e) { // ignore, defaults to false } return new LazyStreetMap(directory.getName(), new File(directory, directory.getName() + ".graph"), new File(directory, directory.getName() + ".egraph"), Boolean.parseBoolean(p .getProperty("default", "false"))); } private static class LazyStreetMap extends StreetMap { private final File graphFile; private final File egraphFile; public LazyStreetMap(String name, File graphFile, File egraphFile, boolean isDefault) { super(null, null, isDefault); this.name = name; this.graphFile = graphFile; this.egraphFile = egraphFile; } @Override public Graph getGraph() { if (this.graph == null) { try { this.graph = Graph.load(graphFile, new DummyProgressReporter()); } catch (IOException e) { e.printStackTrace(); } } return graph; } @Override public EdgeBasedGraph getEdgeBasedGraph() { if (this.edgeBasedGraph == null) { try { this.edgeBasedGraph = EdgeBasedGraph.load(egraphFile); } catch (IOException e) { e.printStackTrace(); } } return edgeBasedGraph; } @Override public void ensureLoaded(ProgressReporter reporter) { reporter.setSubTasks(new float[] { .9f, .1f }); reporter.pushTask("Lade Graphen"); if (graph == null) { try { this.graph = Graph.load(graphFile, reporter); } catch (IOException e) { e.printStackTrace(); } } reporter.nextTask("Lade kantenbasierten Graphen"); getEdgeBasedGraph(); reporter.popTask(); } } @Override public boolean equals(Object obj) { if (obj instanceof StreetMap) { StreetMap other = (StreetMap) obj; return name.equals(other.getName()) && isDefault == other.isDefault(); } return false; } @Override public int hashCode() { return name.hashCode() ^ Boolean.valueOf(isDefault).hashCode(); } }