/* * Copyright (C) 2009. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 or * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ package uk.me.parabola.imgfmt.app.map; import java.io.Closeable; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.Deque; import java.util.List; import uk.me.parabola.imgfmt.Utils; import uk.me.parabola.imgfmt.app.Area; import uk.me.parabola.imgfmt.app.lbl.City; import uk.me.parabola.imgfmt.app.lbl.Country; import uk.me.parabola.imgfmt.app.lbl.LBLFileReader; import uk.me.parabola.imgfmt.app.lbl.Region; import uk.me.parabola.imgfmt.app.lbl.Zip; import uk.me.parabola.imgfmt.app.net.NETFileReader; import uk.me.parabola.imgfmt.app.net.RoadDef; import uk.me.parabola.imgfmt.app.trergn.Point; import uk.me.parabola.imgfmt.app.trergn.Polygon; import uk.me.parabola.imgfmt.app.trergn.Polyline; import uk.me.parabola.imgfmt.app.trergn.RGNFileReader; import uk.me.parabola.imgfmt.app.trergn.Subdivision; import uk.me.parabola.imgfmt.app.trergn.TREFileReader; import uk.me.parabola.imgfmt.app.trergn.Zoom; import uk.me.parabola.imgfmt.fs.DirectoryEntry; import uk.me.parabola.imgfmt.fs.FileSystem; import uk.me.parabola.imgfmt.fs.ImgChannel; import uk.me.parabola.imgfmt.sys.ImgFS; /** * This is a view of a .img file when we are reading it. The {@link Map} * class is the equivalent for writing. * * @author Steve Ratcliffe */ public class MapReader implements Closeable { private final TREFileReader treFile; private final RGNFileReader rgnFile; private final LBLFileReader lblFile; private final NETFileReader netFile; public static final boolean WITH_EXT_TYPE_DATA = true; public static final boolean WITHOUT_EXT_TYPE_DATA = false; private final Deque<Closeable> toClose = new ArrayDeque<Closeable>(); public MapReader(String filename) throws FileNotFoundException { FileSystem fs = ImgFS.openFs(filename); saveForClose(fs); List<DirectoryEntry> entries = fs.list(); // Find the TRE entry String mapname = null; for (DirectoryEntry ent : entries) { if ("TRE".equals(ent.getExt())) { mapname = ent.getName(); break; } } if (mapname == null) throw new FileNotFoundException("No TRE entry in img file"); ImgChannel chan = fs.open(mapname + ".TRE", "r"); treFile = new TREFileReader(chan); saveForClose(treFile, chan); chan = fs.open(mapname + ".RGN", "r"); rgnFile = new RGNFileReader(chan); saveForClose(rgnFile, chan); chan = fs.open(mapname + ".LBL", "r"); lblFile = new LBLFileReader(chan); saveForClose(lblFile, chan); // The NET file is optional NETFileReader nr; try { chan = fs.open(mapname + ".NET", "r"); nr = new NETFileReader(chan); nr.setLabels(lblFile); nr.setCities(lblFile.getCities()); nr.setZips(lblFile.getZips()); saveForClose(nr); } catch (FileNotFoundException e) { nr = null; } netFile = nr; rgnFile.setNetFile(netFile); rgnFile.setLblFile(lblFile); } /** * Get a list of all the points for a given level. * @param level The level, lower numbers are the most detailed. */ public List<Point> pointsForLevel(int level, boolean withExtType) { List<Point> points = new ArrayList<Point>(); Subdivision[] subdivisions = treFile.subdivForLevel(level); for (Subdivision sd : subdivisions) { List<Point> subdivPoints = rgnFile.pointsForSubdiv(sd, withExtType); points.addAll(subdivPoints); } return points; } public Zoom[] getLevels() { return treFile.getMapLevels(); } public String[] getCopyrights(){ return treFile.getCopyrights(lblFile); } /** * Get a list of all the lines for a given level. * @param level The level, lower numbers are the most detailed. */ public List<Polyline> linesForLevel(int level) { ArrayList<Polyline> lines = new ArrayList<Polyline>(); Subdivision[] subdivisions = treFile.subdivForLevel(level); for (Subdivision div : subdivisions) { List<Polyline> subdivLines = rgnFile.linesForSubdiv(div); lines.addAll(subdivLines); } return lines; } public List<Polygon> shapesForLevel(int level) { ArrayList<Polygon> shapes = new ArrayList<Polygon>(); Subdivision[] subdivisions = treFile.subdivForLevel(level); for (Subdivision div : subdivisions) { List<Polygon> subdivShapes = rgnFile.shapesForSubdiv(div); shapes.addAll(subdivShapes); } return shapes; } public void close() throws IOException { for (Closeable c : toClose) Utils.closeFile(c); } private void saveForClose(Closeable c1, Closeable c2) { saveForClose(c1); saveForClose(c2); } private void saveForClose(Closeable c) { toClose.push(c); } public List<City> getCities() { return lblFile.getCities(); } public List<Country> getCountries() { return lblFile.getCountries(); } public List<Region> getRegions() { return lblFile.getRegions(); } public List<Zip> getZips() { // need to be joined with zip information from the addresses // where are the addresses stored? return lblFile.getZips(); } public Area getTreBounds() { return treFile.getBounds(); } public java.util.Map<Integer, String> getLabels() { return lblFile.getLabels(); } public List<RoadDef> getRoads() { if (netFile == null) return Collections.emptyList(); return netFile.getRoads(); } public int getEncodingType(){ return lblFile.getEncodingType(); } }