/** * This file is part of OSM2ShareNav * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * Copyright (C) 2008 Kai Krueger * Copyright (C) 2008 sk750 */ package net.sharenav.osmToShareNav; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Collection; import java.util.HashSet; import java.util.Hashtable; import java.util.LinkedList; import java.util.Set; import java.util.Vector; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import net.sharenav.osmToShareNav.Configuration; import net.sharenav.osmToShareNav.model.ConditionTuple; import net.sharenav.osmToShareNav.model.Connection; import net.sharenav.osmToShareNav.model.Damage; import net.sharenav.osmToShareNav.model.Entity; import net.sharenav.osmToShareNav.model.EntityDescription; import net.sharenav.osmToShareNav.model.POIdescription; import net.sharenav.osmToShareNav.model.RouteAccessRestriction; import net.sharenav.osmToShareNav.model.TollRule; import net.sharenav.osmToShareNav.model.TravelMode; import net.sharenav.osmToShareNav.model.TravelModes; import net.sharenav.osmToShareNav.model.WayDescription; public class LegendParser extends DefaultHandler implements ErrorHandler { public static Configuration config; private Hashtable<String, Hashtable<String, Set<EntityDescription>>> poiMap; private Hashtable<String, Hashtable<String, Set<EntityDescription>>> wayMap; private LongTri<EntityDescription> pois; private LongTri<EntityDescription> ways; private POIdescription currentPoi; private TravelMode currentTravelMode; private WayDescription currentWay; private String currentKey; private Hashtable<String, Set<EntityDescription>> keyValuesPoi; private Hashtable<String, Set<EntityDescription>> keyValuesWay; private Hashtable<String, Integer> maxSpeedTemplates; private Hashtable<String, Boolean> relationExpansions; private Hashtable<String, Boolean> relationExpansionsCombine; private static final Vector<Damage> damages = new Vector<Damage>(); private final byte READING_WAYS = 0; private final byte READING_POIS = 1; private final byte READING_ROUTEMODES = 3; private final byte READING_COLORS = 4; private final byte READING_MAXSPEED = 5; private final byte READING_TILESCALELEVELS = 6; private final byte READING_DAMAGES = 7; private byte readingType = READING_WAYS; private int poiIdx = 0; private int wayIdx = 0; private boolean nonValidStyleFile; public static int tileScaleLevel[] = { Integer.MAX_VALUE, 900000, 180000, 45000 }; public static boolean tileScaleLevelIsAllowedForRoutableWays[] = {true, true, true, true}; public static boolean tileScaleLevelContainsRoutableWays[] = {false, false, false, false}; public static int tileLevelAttractsAreasWithSmallerBoundsDiameterThan[] = {0, 0, 0, 0}; private static HashSet<String> relevantKeys; public class DTDresolver implements EntityResolver { /* * (non-Javadoc) * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, * java.lang.String) */ @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { /* Use the style-file.dtd that is internl to the Osm2ShareNav jar */ if (systemId.endsWith("style-file.dtd")) { InputStream is = this.getClass().getResourceAsStream("/style-file.dtd"); if (is != null) { return new InputSource(is); } else { System.out.println("Warning: Could not read internal dtd file"); return null; } } if (config.verbose >= 0) { System.out.println("Trying to resolve XML entity " + systemId); } try { InputStream is = new URL(systemId).openStream(); if (is != null) { if (config.verbose >= 0) { System.out.println("Resolved entity externally"); } return new InputSource(is); } } catch (FileNotFoundException fnfe) { InputStream is = this.getClass().getResourceAsStream(systemId.substring(systemId.lastIndexOf('/'))); if (is != null) { if (config.verbose >= 0) { System.out.println("No such file, resolved entity internally instead"); } return new InputSource(is); } } return null; } } public LegendParser(InputStream i) { if (config == null) { config = Configuration.getConfiguration(); } if (config.verbose >= 0) { System.out.println("Style file parser started..."); } init(i); } private void init(InputStream i) { try { relevantKeys = new HashSet<String>(); initSpecialcasedRelevantKeys(); poiMap = new Hashtable<String, Hashtable<String, Set<EntityDescription>>>(); pois = new LongTri<EntityDescription>(); currentPoi = new POIdescription(); maxSpeedTemplates = new Hashtable<String, Integer>(); relationExpansions = new Hashtable<String, Boolean>(); relationExpansionsCombine = new Hashtable<String, Boolean>(); /* Add a bogous POI description, to reserve type 0 as a special marker */ // polish.api.bigstyles currentPoi.typeNum = (short) poiIdx++; currentPoi.key = "A key that should never be hot"; currentPoi.value = "A value that should never be triggered"; currentPoi.description = "No description"; pois.put(currentPoi.typeNum, currentPoi); wayMap = new Hashtable<String, Hashtable<String, Set<EntityDescription>>>(); ways = new LongTri<EntityDescription>(); currentWay = new WayDescription(); /** * Add a bogous Way description, to reserve type 0 as a special * marker */ // polish.api.bigstyles currentWay.typeNum = (short) wayIdx++; currentWay.key = "A key that should never be hot"; currentWay.value = "A value that should never be triggered"; currentWay.description = "No description"; ways.put(currentWay.typeNum, currentWay); SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); // Parse the input nonValidStyleFile = false; XMLReader xmlReader = factory.newSAXParser().getXMLReader(); xmlReader.setEntityResolver(new DTDresolver()); xmlReader.setContentHandler(this); xmlReader.setErrorHandler(this); xmlReader.parse(new InputSource(i)); if (nonValidStyleFile) { System.out.println("ERROR: your style file is not valid. Please correct the file and try Osm2ShareNav again"); System.exit(1); } if (config.verbose >= 0) { System.out.println("Style-file: You have " + (poiIdx - 1) + " POI types defined and " + (wayIdx - 1) + " way types"); } if (poiIdx > 126) { // polish.api.bigstyles config.mediumStyles = true; config.map66search = true; if (poiIdx > 253) { config.bigStyles = true; System.out.println("WARNING: your style file contains > 253 POI types, you'll need a \"bigstyles\" ShareNav."); } //System.exit(1); } if (wayIdx > 126) { // polish.api.bigstyles config.mediumStyles = true; config.map66search = true; if (poiIdx > 253) { config.bigStyles = true; System.out.println("WARNING: your style file contains > 253 way types, you'll need a \"bigstyles\" ShareNav."); } //System.exit(1); } // check if all colors are defined in the style-file boolean colorsComplete = true; for (int n = 0; n < Configuration.COLOR_COUNT; n++) { if (Configuration.COLORS[n] == 0xFFFFFFFF) { colorsComplete = false; System.out.println("ERROR: your style-file contains no color for \"" + Configuration.COLORNAMES[n] + "\""); } } if (!colorsComplete) { System.exit(1); } // check if all routeModes specified with useRouting are also // defined in the style-file if (Configuration.attrToBoolean(config.useRouting) >= 0) { for (int n = 0; n < TravelModes.travelModeCount; n++) { if (!TravelModes.travelModes[n].routeModeDefined) { System.out.println("ERROR: useRouting=" + config.useRouting + " is specified in your .properties file but in your style-file there's no routeMode called " + TravelModes.travelModes[n].getName()); System.exit(1); } } } /** * Calculate the relevant keys that we need to care about in the XML stream */ for (EntityDescription e : pois.values()) { relevantKeys.add(e.key); relevantKeys.add(e.nameKey); relevantKeys.add(e.nameFallbackKey); relevantKeys.add(e.helperTag); if (e.houseNumberMatchTag != null) { relevantKeys.add(e.houseNumberMatchTag); } if (e.specialisation != null) { for (ConditionTuple ct : e.specialisation) { relevantKeys.add(ct.key); } } } for (EntityDescription e : ways.values()) { relevantKeys.add(e.key); relevantKeys.add(e.nameKey); relevantKeys.add(e.nameFallbackKey); relevantKeys.add(e.helperTag); if (e.houseNumberMatchTag != null) { relevantKeys.add(e.houseNumberMatchTag); } if (e.specialisation != null) { for (ConditionTuple ct : e.specialisation) { if (!ct.properties) { relevantKeys.add(ct.key); } } } } for (TravelMode tm : TravelModes.travelModes) { if (tm == null) continue; if (tm.getRouteAccessRestrictions() != null) { for (RouteAccessRestriction rar : tm.getRouteAccessRestrictions()) { relevantKeys.add(rar.key); } } if (tm.getTollRules() != null) { for (TollRule tr : tm.getTollRules()) { relevantKeys.add(tr.key); } } } for (Damage d : damages) { relevantKeys.add(d.key); } } catch (FileNotFoundException fnfe) { System.out.println("ERROR, could not find necessary file: " + fnfe.getMessage()); System.exit(1); } catch (IOException e) { System.out.println("ERROR: IOException: " + e); System.exit(1); } catch (SAXException e) { System.out.println("ERROR: SAXException: " + e); System.exit(1); } catch (javax.xml.parsers.ParserConfigurationException e) { System.out.println("ERROR: ParserConfigurationException: " + e); System.exit(1); // } catch (Exception e) { // System.out.println("ERROR: Other Exception: " + e); // System.exit(1); } } private void initSpecialcasedRelevantKeys() { /* * Add all the keys that are hardcoded in Osm2ShareNav to be included in the relevantKeys set */ relevantKeys.add("type"); relevantKeys.add("admin_level"); relevantKeys.add("boundary"); relevantKeys.add("natural"); relevantKeys.add("highway"); relevantKeys.add("is_in"); relevantKeys.add("maxspeed"); relevantKeys.add("maxspeed:seasonal:winter"); relevantKeys.add("access"); relevantKeys.add("toll"); relevantKeys.add("junction"); relevantKeys.add("cycleway"); relevantKeys.add("oneway"); relevantKeys.add("restriction"); relevantKeys.add("bridge"); relevantKeys.add("tunnel"); relevantKeys.add("place"); relevantKeys.add("area"); relevantKeys.add("layer"); if (config.useUrlTags) { for (String urlTag : Entity.urlTags) { relevantKeys.add(urlTag); } } if (config.usePhoneTags) { for (String phoneTag : Entity.phoneTags) { relevantKeys.add(phoneTag); } } relevantKeys.add("phone"); // FIXME: switch this on a flag, if true, index all // nodes with addr:housenumber, regardless of whether there's a housenumberindex element if (config.useHouseNumbers) { relevantKeys.add("addr:interpolation"); relevantKeys.add("addr:housenumber"); relevantKeys.add("addr:street"); } relevantKeys.add("barrier"); //relevantKeys.add("direction"); //relevantKeys.add("crossing"); } @Override public void startDocument() { } @Override public void endDocument() { } @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) { // System.out.println("start " + localName + " " + qName); if (qName.equals("pois")) { readingType = READING_POIS; } else if (qName.equals("ways")) { readingType = READING_WAYS; } else if (qName.equals("colors")) { readingType = READING_COLORS; } else if (qName.equals("routeModes")) { readingType = READING_ROUTEMODES; } else if (qName.equals("maxSpeedTemplates")) { readingType = READING_MAXSPEED; } else if (qName.equals("tileScaleLevels")) { readingType = READING_TILESCALELEVELS; } else if (qName.equals("damages")) { readingType = READING_DAMAGES; } // TODO: Suppose the method is called with qName="pois". I think the // 'case' // below with the checks against "key" and "value" and ... will be // called // (same for all the other readingTypes) but it can never match // anything! // Check if this is true, and if yes, the switch needs to go into an // else-clause! switch (readingType) { case READING_POIS: if (qName.equals("key")) { currentKey = atts.getValue("tag"); keyValuesPoi = poiMap.get(currentKey); if (keyValuesPoi == null) { keyValuesPoi = new Hashtable<String, Set<EntityDescription>>(); poiMap.put(currentKey, keyValuesPoi); } } if (qName.equals("value")) { currentPoi = new POIdescription(); // polish.api.bigstyles currentPoi.typeNum = (short)poiIdx++; currentPoi.key = currentKey; currentPoi.value = atts.getValue("name"); currentPoi.hideable = true; String rulePrio = atts.getValue("priority"); if (rulePrio != null) { try { currentPoi.rulePriority = (byte) Integer.parseInt(rulePrio); } catch (NumberFormatException nfe) { System.out.println("WARNING: Rule priority is invalid, using default"); } } Set<EntityDescription> poiDescs = keyValuesPoi.get(currentPoi.value); if (poiDescs == null) { poiDescs = new HashSet<EntityDescription>(); } poiDescs.add(currentPoi); keyValuesPoi.put(currentPoi.value, poiDescs); pois.put(currentPoi.typeNum, currentPoi); } if (qName.equals("specialisation")) { if (currentPoi.specialisation == null) { currentPoi.specialisation = new LinkedList<ConditionTuple>(); } ConditionTuple ct = new ConditionTuple(); ct.key = atts.getValue("key"); ct.value = atts.getValue("value"); ct.regexp = "true".equalsIgnoreCase(atts.getValue("regexp")); ct.properties = "true".equalsIgnoreCase(atts.getValue("properties")); String condition = atts.getValue("condition"); if (condition.equalsIgnoreCase("exclude")) { ct.exclude = true; } else { ct.exclude = false; } currentPoi.specialisation.add(ct); } if (qName.equals("AreaPOI")) { currentPoi.createPOIsForAreas = atts.getValue("createForAreas") .equalsIgnoreCase("true"); } if (qName.equals("description")) { currentPoi.description = atts.getValue("desc"); } if (qName.equals("namekey")) { currentPoi.nameKey = atts.getValue("tag"); } if (qName.equals("helpertag")) { currentPoi.helperTag = atts.getValue("tag"); } if (qName.equals("housenumberindex")) { currentPoi.houseNumberIndex = true; currentPoi.houseNumberMatchTag = atts.getValue("matchtag"); } if (qName.equals("namefallback")) { currentPoi.nameFallbackKey = atts.getValue("tag"); } if (qName.equals("scale")) { try { currentPoi.minEntityScale = config.getRealScale(Integer.parseInt(atts .getValue("scale"))); } catch (NumberFormatException nfe) { System.out.println("Error: scale for " + currentPoi.description + " is incorrect"); } if (currentPoi.minTextScale == 0) { currentPoi.minTextScale = currentPoi.minEntityScale; } } if (qName.equals("textscale")) { try { currentPoi.minTextScale = config.getRealScale(Integer.parseInt(atts .getValue("scale"))); } catch (NumberFormatException nfe) { System.out.println("Error: textscale for " + currentPoi.description + " is incorrect"); } } if (qName.equals("image")) { currentPoi.image = atts.getValue("src"); } if (qName.equals("searchIcon")) { currentPoi.searchIcon = atts.getValue("src"); } if (qName.equals("imageCentered")) { currentPoi.imageCenteredOnNode = atts.getValue("value").equalsIgnoreCase( "true"); } if (qName.equals("hideable")) { currentPoi.hideable = atts.getValue("hideable").equalsIgnoreCase("true"); } if (qName.equals("alert")) { currentPoi.alert = atts.getValue("alert").equalsIgnoreCase("true"); } if (qName.equals("clickable")) { currentPoi.clickable = atts.getValue("clickable").equalsIgnoreCase("true"); } break; case READING_WAYS: if (qName.equals("keyW")) { currentKey = atts.getValue("tag"); keyValuesWay = wayMap.get(currentKey); if (keyValuesWay == null) { keyValuesWay = new Hashtable<String, Set<EntityDescription>>(); wayMap.put(currentKey, keyValuesWay); } } if (qName.equals("Wvalue")) { currentWay = new WayDescription(); // polish.api.bigstyles currentWay.typeNum = (short) wayIdx++; currentWay.key = currentKey; currentWay.value = atts.getValue("name"); currentWay.hideable = true; if (currentKey.equalsIgnoreCase("building")) { currentWay.wayDescFlags |= WayDescription.WDFLAG_BUILDING; } if (currentKey.equalsIgnoreCase("highway")) { if (currentWay.value.toLowerCase().endsWith("_link")) { currentWay.wayDescFlags |= WayDescription.WDFLAG_HIGHWAY_LINK; // System.out.println("Waydescription is a highway link: " + currentWay.value); } String wayValue = ";" + currentWay.value.toLowerCase() + ";"; if (";motorway;motorway_link;".indexOf(wayValue) >= 0) { currentWay.wayDescFlags |= WayDescription.WDFLAG_MOTORWAY; currentWay.wayDescTravelModes |= Connection.CONNTYPE_MOTORWAY; } if (";trunk;trunk_link;primary;primary_link;".indexOf(wayValue) >= 0) { currentWay.wayDescTravelModes |= Connection.CONNTYPE_TRUNK_OR_PRIMARY; } if (";motorway;motorway_link;trunk;trunk_link;primary;primary_link;secondary;secondary_link;tertiary;".indexOf(wayValue) >= 0) { currentWay.wayDescTravelModes |= Connection.CONNTYPE_MAINSTREET_NET; currentWay.wayDescFlags |= WayDescription.WDFLAG_MAINSTREET_NET; } } /* Assign a small default speed for the case that the way * becomes accessible for routing by a RouteAccessRestriction * but the way description itself in the style file contains no * routing information. */ for (int i = 0; i < TravelModes.travelModeCount; i++) { currentWay.typicalSpeed[i] = 5; } Set<EntityDescription> wayDescs = keyValuesWay.get(currentWay.value); if (wayDescs == null) { wayDescs = new HashSet<EntityDescription>(); } wayDescs.add(currentWay); keyValuesWay.put(currentWay.value, wayDescs); String rulePrio = atts.getValue("priority"); if (rulePrio != null) { try { currentWay.rulePriority = (byte) Integer.parseInt(rulePrio); } catch (NumberFormatException nfe) { System.out.println("WARNING: Rule priority is invalid, using default"); } } ways.put(currentWay.typeNum, currentWay); } if (qName.equals("specialisation")) { if (currentWay.specialisation == null) { currentWay.specialisation = new LinkedList<ConditionTuple>(); } ConditionTuple ct = new ConditionTuple(); ct.key = atts.getValue("key"); ct.value = atts.getValue("value"); ct.regexp = "true".equalsIgnoreCase(atts.getValue("regexp")); ct.properties = "true".equalsIgnoreCase(atts.getValue("properties")); String condition = atts.getValue("condition"); if (condition.equalsIgnoreCase("exclude")) { ct.exclude = true; } else { ct.exclude = false; } currentWay.specialisation.add(ct); } if (qName.equals("description")) { currentWay.description = atts.getValue("desc"); } if (qName.equals("namekey")) { currentWay.nameKey = atts.getValue("tag"); } if (qName.equals("namefallback")) { currentWay.nameFallbackKey = atts.getValue("tag"); } if (qName.equals("housenumberindex")) { currentWay.houseNumberIndex = true; currentWay.houseNumberMatchTag = atts.getValue("matchtag"); } if (qName.equals("scale")) { try { currentWay.minEntityScale = config.getRealScale(Integer.parseInt(atts .getValue("scale"))); } catch (NumberFormatException nfe) { System.out.println("Error: scale for " + currentWay.description + " is incorrect"); } if (currentWay.minTextScale == 0) { currentWay.minTextScale = currentWay.minEntityScale; } } if (qName.equals("textscale")) { try { currentWay.minTextScale = config.getRealScale(Integer.parseInt(atts .getValue("scale"))); } catch (NumberFormatException nfe) { System.out.println("Error: textscale for " + currentWay.description + " is incorrect"); } } if (qName.equals("arrowscale")) { try { currentWay.minOnewayArrowScale = config.getRealScale(Integer .parseInt(atts.getValue("scale"))); } catch (NumberFormatException nfe) { System.out.println("Error: oneway arrowscale for " + currentWay.description + " is incorrect"); } } if (qName.equals("descriptionscale")) { try { currentWay.minDescriptionScale = config.getRealScale(Integer .parseInt(atts.getValue("scale"))); } catch (NumberFormatException nfe) { System.out.println("Error: descriptionscale for " + currentWay.description + " is incorrect"); } } if (qName.equals("image")) { currentWay.image = atts.getValue("src"); } if (qName.equals("searchIcon")) { currentWay.searchIcon = atts.getValue("src"); } if (qName.equals("showName")) { currentWay.showNameAsForArea = atts.getValue("style").equalsIgnoreCase("area"); } if (qName.equals("isArea")) { currentWay.isArea = atts.getValue("area").equalsIgnoreCase("true"); } if (qName.equals("asRelation")) { if ("true".equalsIgnoreCase(atts.getValue("relation"))) { if (currentWay.key != null && currentWay.value != null) { System.out.println("Shall expand type=" + currentWay.key + "," + currentWay.key + "=" + currentWay.value + " relations"); relationExpansions.put(currentWay.key + "=" + currentWay.value, true); } } if ("true".equalsIgnoreCase(atts.getValue("combined"))) { if (currentWay.key != null && currentWay.value != null) { System.out.println("Shall combine type=" + currentWay.key + "," + currentWay.key + "=" + currentWay.value + " relations"); relationExpansionsCombine.put(currentWay.key + "=" + currentWay.value, true); } } } if (qName.equals("ignoreOsmAreaTag")) { currentWay.ignoreOsmAreaTag = atts.getValue("ignore").equalsIgnoreCase("true"); } if (qName.equals("lineColor")) { try { currentWay.lineColor = Integer.parseInt(atts.getValue("color"), 16); } catch (NumberFormatException nfe) { System.out.println("Error: lineColor for " + currentWay.description + " is incorrect. Must be a hex coded ARGB value"); } String nightColor = atts.getValue("colorAtNight"); if (nightColor != null) { try { currentWay.lineColorAtNight = Integer.parseInt(nightColor, 16); } catch (NumberFormatException nfe) { System.out.println("Error: lineColor colorAtNight for " + currentWay.description + " is incorrect. Must be a hex coded ARGB value"); } } } if (qName.equals("borderColor")) { try { currentWay.boardedColor = Integer .parseInt(atts.getValue("color"), 16); } catch (NumberFormatException nfe) { System.out.println("Error: borderColor for " + currentWay.description + " is incorrect. Must be a hex coded ARGB value"); } String nightColor = atts.getValue("colorAtNight"); if (nightColor != null) { try { currentWay.boardedColorAtNight = Integer.parseInt(nightColor, 16); } catch (NumberFormatException nfe) { System.out.println("Error: borderColor colorAtNight for " + currentWay.description + " is incorrect. Must be a hex coded ARGB value"); } } } if (qName.equals("wayWidth")) { try { currentWay.wayWidth = Integer.parseInt(atts.getValue("width")); } catch (NumberFormatException nfe) { System.out.println("Error: wayWidth for " + currentWay.description + " is incorrect"); } } if (qName.equals("lineStyle")) { if (isAttributeActivated(atts, "dashed")) { currentWay.wayDescFlags |= WayDescription.WDFLAG_LINESTYLE_DOTTED; } if (isAttributeActivated(atts, "rail")) { currentWay.wayDescFlags |= WayDescription.WDFLAG_LINESTYLE_RAIL; } if (isAttributeActivated(atts, "steps")) { currentWay.wayDescFlags |= WayDescription.WDFLAG_LINESTYLE_STEPS; } if (isAttributeActivated(atts, "powerLine")) { currentWay.wayDescFlags |= WayDescription.WDFLAG_LINESTYLE_POWERLINE; } } if (qName.equals("routing")) { // only use routing rules for the with-parameter specified in // .properties, e.g. useRouting=motorcar int travelModeNr = TravelModes.getTravelModeNrByName(atts.getValue("with")); if (travelModeNr >= 0) { if (atts.getValue("accessible").equalsIgnoreCase("true")) { currentWay.wayDescTravelModes |= 1 << travelModeNr; } String typicalSpeed = atts.getValue("speed"); if (typicalSpeed != null) { try { Float speed = Float.parseFloat(typicalSpeed); currentWay.typicalSpeed[travelModeNr] = Float.parseFloat(typicalSpeed); //currentWay.typicalSpeed[travelModeNr] = Integer.parseInt(typicalSpeed); } catch (NumberFormatException nfe) { System.out.println("Invalid speed for " + currentWay.description); } } else { System.out.println("Warning: no typical speed for " + currentWay.description + ". Using 5 km/h."); currentWay.typicalSpeed[travelModeNr] = 5; } // System.out.println(currentWay.description + " with " + // atts.getValue("with") + ": " + // atts.getValue("accessible") + " typicalSpeed: " + // typicalSpeed + "km/h"); } } if (qName.equals("force_to")) { try { currentWay.forceToLayer = Byte.parseByte(atts.getValue("layer")); } catch (NumberFormatException nfe) { // Just ignore this entry if it is not correct } } if (qName.equals("hideable")) { currentWay.hideable = atts.getValue("hideable").equalsIgnoreCase("true"); } if (qName.equals("alert")) { currentWay.alert = atts.getValue("alert").equalsIgnoreCase("true"); } if (qName.equals("clickable")) { currentWay.clickable = atts.getValue("clickable").equalsIgnoreCase("true"); } break; case READING_COLORS: if (qName.equals("color")) { String colorName = atts.getValue("of"); boolean colorFound = false; for (int i = 0; i < Configuration.COLORNAMES.length; i++) { if (Configuration.COLORNAMES[i].equalsIgnoreCase(colorName)) { int rgb = 0; try { rgb = Integer.parseInt(atts.getValue("is"), 16); } catch (NumberFormatException nfe) { System.out.println("Error: color of " + colorName + " is invalid. Must be a hex coded ARGB value"); } Configuration.COLORS[i] = rgb; String nightColor = atts.getValue("isAtNight"); if (nightColor != null) { try { rgb = Integer.parseInt(nightColor, 16); Configuration.COLORS_AT_NIGHT[i] = rgb; } catch (NumberFormatException nfe) { System.out.println("Error: color isAtNight of " + colorName + " is invalid. Must be a hex coded ARGB value"); } } colorFound = true; break; } } if (!colorFound) { System.out.println("Error: style file contains non-existent colorName: " + colorName); } break; } break; case READING_ROUTEMODES: if (qName.equals("routeMode")) { currentTravelMode = TravelModes.getTravelMode(atts.getValue("modeName")); if (currentTravelMode != null) { currentTravelMode.routeModeDefined = true; String maxPrepareMeters = atts.getValue("maxPrepareMeters"); if (maxPrepareMeters != null) { try { currentTravelMode.maxPrepareMeters = (short) Integer .parseInt(maxPrepareMeters); } catch (NumberFormatException nfe) { System.out.println("Invalid maxPrepareMeters for " + currentTravelMode.getName()); } } else { System.out.println("Warning: no maxPrepareMeters for " + currentTravelMode.getName() + ". Using 500m."); currentTravelMode.maxPrepareMeters = 500; } String maxInMeters = atts.getValue("maxInMeters"); if (maxInMeters != null) { try { currentTravelMode.maxInMeters = (short) Integer.parseInt(maxInMeters); } catch (NumberFormatException nfe) { System.out.println("Invalid maxInMeters for " + currentTravelMode.getName()); } } else { System.out.println("Warning: no maxInMeters for " + currentTravelMode.getName() + ". Using 899m."); currentTravelMode.maxInMeters = 899; } String maxEstimationSpeed = atts.getValue("maxEstimationSpeed"); if (maxEstimationSpeed != null) { try { currentTravelMode.maxEstimationSpeed = (short) Integer .parseInt(maxEstimationSpeed); } catch (NumberFormatException nfe) { System.out.println("Invalid maxEstimationSpeed for " + currentTravelMode.getName()); } } else { System.out.println("Warning: no maxEstimationSpeed for " + currentTravelMode.getName() + ". Using 150km/h."); currentTravelMode.maxEstimationSpeed = 150; } String applyTurnRestrictions = atts.getValue("applyTurnRestrictions"); if (applyTurnRestrictions != null) { if (applyTurnRestrictions.equalsIgnoreCase("true")) { TravelModes.applyTurnRestrictionsTravelModes |= (1 << TravelModes .getTravelModeNrByName(atts.getValue("modeName"))); currentTravelMode.travelModeFlags |= TravelMode.WITH_TURN_RESTRICTIONS; } } String mainStreetNet = atts.getValue("mainStreetNet"); if (mainStreetNet != null) { if (mainStreetNet.equalsIgnoreCase("true")) { currentTravelMode.travelModeFlags |= TravelMode.MAINSTREET_NET_FOR_LARGE_ROUTES; } } String againstAllOneWays = atts.getValue("againstAllOneWays"); if (againstAllOneWays != null) { if (againstAllOneWays.equalsIgnoreCase("true")) { currentTravelMode.travelModeFlags |= TravelMode.AGAINST_ALL_ONEWAYS; } } String bicycleOppositeExceptions = atts .getValue("bicycleOppositeExceptions"); if (bicycleOppositeExceptions != null) { if (bicycleOppositeExceptions.equalsIgnoreCase("true")) { currentTravelMode.travelModeFlags |= TravelMode.BICYLE_OPPOSITE_EXCEPTIONS; } } } } // routeMode if (qName.equals("routeAccessRestriction")) { if (currentTravelMode != null) { currentTravelMode.getRouteAccessRestrictions().addElement( new RouteAccessRestriction(atts.getValue("restrictionKey"), atts.getValue("restrictionValues") + "|", Configuration.attrToBoolean(atts .getValue("restrictionPermit")) > 0)); } } if (qName.equals("tollRule")) { if (currentTravelMode != null) { currentTravelMode.getTollRules().addElement( new TollRule(atts.getValue("tollKey"), atts.getValue("tollValues") + "|", Configuration.attrToBoolean(atts.getValue("enableToll")) > 0, Configuration.attrToBoolean(atts.getValue("debugTollRule")) > 0 ) ); } } break; case READING_MAXSPEED: if (qName.equals("maxSpeedTemplate")) { try { maxSpeedTemplates.put(atts.getValue("name"), new Integer(Integer .parseInt(atts.getValue("maxspeed")))); } catch (NumberFormatException nfe) { System.out.println("Maxspeed in template " + atts.getValue("name") + " must be integer, but was " + atts.getValue("maxspeed")); nonValidStyleFile = true; } } break; case READING_TILESCALELEVELS: if (qName.equals("tileScaleLevel")) { int level = -1; try { level = Integer.parseInt(atts.getValue("level")); } catch (NumberFormatException nfe) { System.out .println("level in tileScaleLevel must be integer, but was " + atts.getValue("level")); nonValidStyleFile = true; } if (level >= 0 && level < 4) { int scale = 0; try { scale = Integer.parseInt(atts.getValue("minScale")); scale = (config.getRealScale(scale) + config .getRealScale(scale + 1) / 2); tileScaleLevel[level] = scale; if (config.verbose >= 0) { System.out.println("tileScaleLevel " + level + ": " + scale); } } catch (NumberFormatException nfe) { System.out .println("scale in tileScaleLevel must be integer, but was " + atts.getValue("scale")); nonValidStyleFile = true; } String allowedForRoutableWays = atts.getValue("allowedForRoutableWays"); if (allowedForRoutableWays != null) { tileScaleLevelIsAllowedForRoutableWays[level] = allowedForRoutableWays.equalsIgnoreCase("true"); } String s = atts.getValue("attractAreasWithSmallerBoundsDiameterThan"); if (s != null) { tileLevelAttractsAreasWithSmallerBoundsDiameterThan[level] = Integer.parseInt(atts.getValue("attractAreasWithSmallerBoundsDiameterThan")); } } } break; // tileScaleLevels case READING_DAMAGES: if (qName.equals("damage")) { damages.add(new Damage(atts.getValue("damageKey"), atts.getValue("damageValues"))); } break; // damages } } // startElement /** * @param string * @return */ private boolean isAttributeActivated(Attributes atts, String string) { String value = atts.getValue(string); if (value != null) { return (value.equalsIgnoreCase("true")); } return false; } @Override public void endElement(String namespaceURI, String localName, String qName) { } @Override public void fatalError(SAXParseException e) throws SAXException { System.out.println("Error: " + e); throw e; } public Hashtable<String, Hashtable<String, Set<EntityDescription>>> getPOIlegend() { return poiMap; } // polish.api.bigstyles public POIdescription getPOIDesc(short type) { return (POIdescription) pois.get(type); } public Collection<EntityDescription> getPOIDescs() { return pois.values(); } public Hashtable<String, Hashtable<String, Set<EntityDescription>>> getWayLegend() { return wayMap; } // polish.api.bigstyles public WayDescription getWayDesc(short type) { return (WayDescription) ways.get(type); } public Collection<EntityDescription> getWayDescs() { return ways.values(); } public Hashtable<String, Integer> getMaxspeedTemplates() { return maxSpeedTemplates; } public Hashtable<String, Boolean> getRelationExpansions() { return relationExpansions; } public Hashtable<String, Boolean> getRelationExpansionsCombine() { return relationExpansionsCombine; } public static Vector<Damage> getDamages() { return damages; } @Override public void warning(SAXParseException e) throws SAXException { System.out.println("Warning on line " + e.getLineNumber() + ": " + e.getMessage()); } @Override public void error(SAXParseException e) throws SAXException { System.out.println("Error on line " + e.getLineNumber() + " (remember ordering matters): " + e.getMessage()); nonValidStyleFile = true; } public static Set<String> getRelevantKeys() { return relevantKeys; } }