package com.google.maps.android.kml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.HashMap; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; /** * Parses the styles of a given KML file into a KmlStyle object */ /* package */ class KmlStyleParser { private final static String STYLE_TAG = "styleUrl"; private final static String ICON_STYLE_HEADING = "heading"; private final static String ICON_STYLE_URL = "Icon"; private final static String ICON_STYLE_SCALE = "scale"; private final static String ICON_STYLE_HOTSPOT = "hotSpot"; private final static String COLOR_STYLE_COLOR = "color"; private final static String COLOR_STYLE_MODE = "colorMode"; private final static String STYLE_MAP_KEY = "key"; private final static String STYLE_MAP_NORMAL_STYLE = "normal"; private final static String LINE_STYLE_WIDTH = "width"; private final static String POLY_STYLE_OUTLINE = "outline"; private final static String POLY_STYLE_FILL = "fill"; /** * Parses the IconStyle, LineStyle and PolyStyle tags into a KmlStyle object */ /* package */ static KmlStyle createStyle(XmlPullParser parser) throws IOException, XmlPullParserException { KmlStyle styleProperties = new KmlStyle(); setStyleId(parser.getAttributeValue(null, "id"), styleProperties); int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals("Style"))) { if (eventType == START_TAG) { if (parser.getName().equals("IconStyle")) { createIconStyle(parser, styleProperties); } else if (parser.getName().equals("LineStyle")) { createLineStyle(parser, styleProperties); } else if (parser.getName().equals("PolyStyle")) { createPolyStyle(parser, styleProperties); } else if (parser.getName().equals("BalloonStyle")) { createBalloonStyle(parser, styleProperties); } } eventType = parser.next(); } return styleProperties; } /** * * @param styleProperties */ private static void setStyleId(String id, KmlStyle styleProperties) { if (id != null) { // Append # to a local styleUrl String styleId = "#" + id; styleProperties.setStyleId(styleId); } } /** * Recieves input from an XMLPullParser and assigns relevant properties to a KmlStyle. * * @param style Style to apply properties to * @return true if icon style has been set */ private static void createIconStyle(XmlPullParser parser, KmlStyle style) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals("IconStyle"))) { if (eventType == START_TAG) { if (parser.getName().equals(ICON_STYLE_HEADING)) { style.setHeading(Float.parseFloat(parser.nextText())); } else if (parser.getName().equals(ICON_STYLE_URL)) { setIconUrl(parser, style); } else if (parser.getName().equals(ICON_STYLE_HOTSPOT)) { setIconHotSpot(parser, style); } else if (parser.getName().equals(ICON_STYLE_SCALE)) { style.setIconScale(Double.parseDouble(parser.nextText())); } else if (parser.getName().equals(COLOR_STYLE_COLOR)) { style.setMarkerColor(parser.nextText()); } else if (parser.getName().equals(COLOR_STYLE_MODE)) { style.setIconColorMode(parser.nextText()); } } eventType = parser.next(); } } /** * Parses the StyleMap property and stores the id and the normal style tag */ /* package */ static HashMap<String, String> createStyleMap(XmlPullParser parser) throws XmlPullParserException, IOException { HashMap<String, String> styleMaps = new HashMap<String, String>(); // Indicates if a normal style is to be stored Boolean isNormalStyleMapValue = false; // Append # to style id String styleId = "#" + parser.getAttributeValue(null, "id"); int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals("StyleMap"))) { if (eventType == START_TAG) { if (parser.getName().equals(STYLE_MAP_KEY) && parser.nextText().equals(STYLE_MAP_NORMAL_STYLE)) { isNormalStyleMapValue = true; } else if (parser.getName().equals(STYLE_TAG) && isNormalStyleMapValue) { styleMaps.put(styleId, parser.nextText()); isNormalStyleMapValue = false; } } eventType = parser.next(); } return styleMaps; } /** * Sets relevant styling properties to the KmlStyle object that are found in the IconStyle tag * Supported tags include scale, heading, Icon, href, hotSpot * * @param style Style object to add properties to */ private static void createBalloonStyle(XmlPullParser parser, KmlStyle style) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals("BalloonStyle"))) { if (eventType == START_TAG && parser.getName().equals("text")) { style.setInfoWindowText(parser.nextText()); } eventType = parser.next(); } } /** * Sets the icon url for the style * * @param style Style to set the icon url to */ private static void setIconUrl(XmlPullParser parser, KmlStyle style) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals(ICON_STYLE_URL))) { if (eventType == START_TAG && parser.getName().equals("href")) { style.setIconUrl(parser.nextText()); } eventType = parser.next(); } } /** * Sets the hot spot for the icon * * @param style Style object to apply hotspot properties to */ private static void setIconHotSpot(XmlPullParser parser, KmlStyle style) { Float xValue, yValue; String xUnits, yUnits; xValue = Float.parseFloat(parser.getAttributeValue(null, "x")); yValue = Float.parseFloat(parser.getAttributeValue(null, "y")); xUnits = parser.getAttributeValue(null, "xunits"); yUnits = parser.getAttributeValue(null, "yunits"); style.setHotSpot(xValue, yValue, xUnits, yUnits); } /** * Sets relevant styling properties to the KmlStyle object that are found in the LineStyle tag * Supported tags include color, width * * @param style Style object to add properties to */ private static void createLineStyle(XmlPullParser parser, KmlStyle style) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals("LineStyle"))) { if (eventType == START_TAG) { if (parser.getName().equals(COLOR_STYLE_COLOR)) { style.setOutlineColor(parser.nextText()); } else if (parser.getName().equals(LINE_STYLE_WIDTH)) { style.setWidth(Float.valueOf(parser.nextText())); } else if (parser.getName().equals(COLOR_STYLE_MODE)) { style.setLineColorMode(parser.nextText()); } } eventType = parser.next(); } } /** * Sets relevant styling properties to the KmlStyle object that are found in the PolyStyle tag * Supported tags include color, outline, fill * * @param style Style object to add properties to */ private static void createPolyStyle(XmlPullParser parser, KmlStyle style) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); while (!(eventType == END_TAG && parser.getName().equals("PolyStyle"))) { if (eventType == START_TAG) { if (parser.getName().equals(COLOR_STYLE_COLOR)) { style.setFillColor(parser.nextText()); } else if (parser.getName().equals(POLY_STYLE_OUTLINE)) { style.setOutline(KmlBoolean.parseBoolean(parser.nextText())); } else if (parser.getName().equals(POLY_STYLE_FILL)) { style.setFill(KmlBoolean.parseBoolean(parser.nextText())); } else if (parser.getName().equals(COLOR_STYLE_MODE)) { style.setPolyColorMode(parser.nextText()); } } eventType = parser.next(); } } }