Android Open Source - smartnavi Kml Document






From Project

Back to project page smartnavi.

License

The source code is released under:

Apache License

If you think the Android project smartnavi listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.osmdroid.bonuspack.kml;
/*w  ww .  j  a v a 2 s.  c  om*/
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.JsonWriter;

import org.osmdroid.bonuspack.utils.BonusPackHelper;
import org.osmdroid.bonuspack.utils.HttpConnection;
import org.osmdroid.util.GeoPoint;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
 * Object handling a whole KML document.
 * This is the entry point to read, handle and save KML content. <br>
 * Features are stored in the kmlRoot attribute, which is a KmlFolder.
 * Shared components (like styles) are stored in specific attributes. <br>
 * <p/>
 * Supports the following KML Geometry: Point, LineString, Polygon and MultiGeometry. <br>
 * Supports KML Document and Folder hierarchy. <br>
 * Supports NetworkLink. <br>
 * Supports GroundOverlay. <br>
 * Supports LineStyle, PolyStyle and IconStyle - shared and inline. <br>
 * Supports colorMode: normal, random<br>
 * Supports ExtendedData inside Features, with support for Data elements and SimpleData elements.
 * In all cases, values are stored as Java String, there is no handling of Schema definition. <br>
 *
 * @author M.Kergall
 * @see KmlFeature
 * @see Style
 */
public class KmlDocument implements Parcelable {

    public static final Parcelable.Creator<KmlDocument> CREATOR = new Parcelable.Creator<KmlDocument>() {
        @Override
        public KmlDocument createFromParcel(Parcel source) {
            return new KmlDocument(source);
        }

        @Override
        public KmlDocument[] newArray(int size) {
            return new KmlDocument[size];
        }
    };
    /**
     * the root of KML features contained in this document
     */
    public KmlFolder mKmlRoot;
    /**
     * list of shared Styles in this document
     */
    protected HashMap<String, Style> mStyles;
    protected int mMaxStyleId;

    /**
     * default constructor, with the kmlRoot as an empty Folder
     */
    public KmlDocument() {
        mStyles = new HashMap<String, Style>();
        mMaxStyleId = 0;
        mKmlRoot = new KmlFolder();
    }

    public KmlDocument(Parcel in) {
        mKmlRoot = in.readParcelable(KmlFeature.class.getClassLoader());
        //mStyles = in.readHashMap(Style.class.getClassLoader());
        int size = in.readInt();
        mStyles = new HashMap<String, Style>(size);
        for (int i = 0; i < size; i++) {
            String key = in.readString();
            Style value = in.readParcelable(Style.class.getClassLoader());
            mStyles.put(key, value);
        }
        mMaxStyleId = in.readInt();
    }

    /**
     * similar to GeoPoint.fromInvertedDoubleString, with exceptions handling
     */
    protected static GeoPoint parseKmlCoord(String input) {
        int end1 = input.indexOf(',');
        int end2 = input.indexOf(',', end1 + 1);
        try {
            if (end2 == -1) {
                double lon = Double.parseDouble(input.substring(0, end1));
                double lat = Double.parseDouble(input.substring(end1 + 1, input.length()));
                return new GeoPoint(lat, lon);
            } else {
                double lon = Double.parseDouble(input.substring(0, end1));
                double lat = Double.parseDouble(input.substring(end1 + 1, end2));
                double alt = Double.parseDouble(input.substring(end2 + 1, input.length()));
                return new GeoPoint(lat, lon, alt);
            }
        } catch (NumberFormatException e) {
            return null;
        } catch (IndexOutOfBoundsException e) {
            return null;
        }
    }

    /**
     * KML coordinates are: lon,lat{,alt} tuples separated by separators (space, tab, cr).
     */
    protected static ArrayList<GeoPoint> parseKmlCoordinates(String input) {
        LinkedList<GeoPoint> tmpCoords = new LinkedList<GeoPoint>();
        int i = 0;
        int tupleStart = 0;
        int length = input.length();
        boolean startReadingTuple = false;
        while (i < length) {
            char c = input.charAt(i);
            if (c == ' ' || c == '\n' || c == '\t') {
                if (startReadingTuple) { //just ending coords portion:
                    String tuple = input.substring(tupleStart, i);
                    GeoPoint p = parseKmlCoord(tuple);
                    if (p != null)
                        tmpCoords.add(p);
                    startReadingTuple = false;
                }
            } else { //data
                if (!startReadingTuple) { //just ending space portion
                    startReadingTuple = true;
                    tupleStart = i;
                }
                if (i == length - 1) { //at the end => handle last tuple:
                    String tuple = input.substring(tupleStart, i + 1);
                    GeoPoint p = parseKmlCoord(tuple);
                    if (p != null)
                        tmpCoords.add(p);
                }
            }
            i++;
        }
        ArrayList<GeoPoint> coordinates = new ArrayList<GeoPoint>(tmpCoords.size());
        coordinates.addAll(tmpCoords);
        //Various attempts to optimize - without significant result
        /*
        String[] splitted = input.split("\\s+");
    ArrayList<GeoPoint> coordinates = new ArrayList<GeoPoint>(splitted.length);
    for (int i=0; i<splitted.length; i++){
      GeoPoint p = parseKmlCoord(splitted[i]);
      if (p != null)
        coordinates.add(p);
    }
    */
        /*
        String[] splitted = input.split("\\s+");
    int[][] coords = new int[splitted.length][3];
    int end = 0;
    for (int i=0; i<splitted.length; i++){
      boolean ok = parseKmlCoord2(splitted[i], coords[end]);
      if (ok)
        end++;
    }
    ArrayList<GeoPoint> coordinates = new ArrayList<GeoPoint>(10);
    if (end > 0)
      coordinates.add(new GeoPoint(coords[0][0], coords[0][1], coords[0][2]));
    */
        return coordinates;
    }

  /*
    protected static boolean parseKmlCoord2(String input, int tuple[]){
    int end1 = input.indexOf(',');
    int end2 = input.indexOf(',', end1+1);
    try {
      if (end2 == -1){
        tuple[1] = (int)(Double.parseDouble(input.substring(0, end1))*1E6); //lon
        tuple[0] = (int)(Double.parseDouble(input.substring(end1+1, input.length()))*1E6); //lat
      } else {
        tuple[1] = (int)(Double.parseDouble(input.substring(0, end1))*1E6);
        tuple[0] = (int)(Double.parseDouble(input.substring(end1+1, end2))*1E6);
        tuple[2] = (int)(Double.parseDouble(input.substring(end2+1, input.length()))*1E6);
      }
      return true;
    } catch (NumberFormatException e) {
      return false;
    } catch (IndexOutOfBoundsException e) {
      return false;
    }
  }
  */

    /**
     * @return the shared Style associated to the styleId, or null if none
     */
    public Style getStyle(String styleId) {
        return mStyles.get(styleId);
    }
  
  /* nice utils for DOM parsing - to keep somewhere else
  public static String getChildText(Element element) {
    StringBuilder builder = new StringBuilder();
    NodeList list = element.getChildNodes();
    for(int i = 0; i < list.getLength(); i++) {
      Node node = list.item(i);
      short type = node.getNodeType();
      if(type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) {
        builder.append(node.getNodeValue());
      }
    }
    return builder.toString();
  }
  
  public static List<Element> getChildrenByTagName(Element parent, String name) {
    List<Element> nodeList = new ArrayList<Element>();
    boolean getAll = name.equals("*");
    for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (child.getNodeType() == Node.ELEMENT_NODE && (getAll || name.equals(child.getNodeName()))) {
        nodeList.add((Element) child);
      }
    }
      return nodeList;
  }
  */

    /**
     * put the style in the list of shared Styles, associated to its styleId
     */
    public void putStyle(String styleId, Style style) {
        //Check if maxStyleId needs an update:
        try {
            int id = Integer.parseInt(styleId);
            mMaxStyleId = Math.max(mMaxStyleId, id);
        } catch (NumberFormatException e) {
            //styleId was not a number: nothing to do
        }
        mStyles.put(styleId, style);
    }

    /**
     * Add the Style in the shared Styles
     *
     * @param style to add
     * @return the unique styleId assigned for this style
     */
    public String addStyle(Style style) {
        mMaxStyleId++;
        String newId = "" + mMaxStyleId;
        putStyle(newId, style);
        return newId;
    }

    /**
     * Parse a KML document from a url, and build the KML structure in kmlRoot.
     * If the KML file has a "Document" node, kmlRoot will be a Folder "mapping" to this Document.
     * In all other cases, kmlRoot will be a Folder, containing the features of the KML file.
     *
     * @param url
     * @return true if OK, false if any error.
     */
    public boolean parseUrl(String url) {
        Log.d(BonusPackHelper.LOG_TAG, "KmlProvider.parseUrl:" + url);
        HttpConnection connection = new HttpConnection();
        connection.doGet(url);
        InputStream stream = connection.getStream();
        boolean ok;
        if (stream == null) {
            ok = false;
        } else {
            ok = parseKMLStream(stream, url, null);
        }
        connection.close();
        //Log.d(BonusPackHelper.LOG_TAG, "KmlProvider.parseUrl - end");
        return ok;
    }

    /**
     * Get the default path for KML file on Android: on the external storage, in a "kml" directory.
     * Creates the directory if necessary.
     *
     * @param fileName
     * @return full path, as a File, or null if error.
     */
    public File getDefaultPathForAndroid(String fileName) {
        try {
            File path = new File(Environment.getExternalStorageDirectory(), "kml");
            path.mkdir();
            File file = new File(path.getAbsolutePath(), fileName);
            return file;
        } catch (NullPointerException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Parse a KML document from a file, to build the KML structure.
     *
     * @param file full file path
     * @return true if OK, false if any error.
     * @see parseUrl
     */
    public boolean parseKMLFile(File file) {
        Log.d(BonusPackHelper.LOG_TAG, "KmlProvider.parseKMLFile:" + file.getAbsolutePath());
        InputStream stream = null;
        boolean ok;
        try {
            stream = new BufferedInputStream(new FileInputStream(file));
            ok = parseKMLStream(stream, file.getAbsolutePath(), null);
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
            ok = false;
        }
        //Log.d(BonusPackHelper.LOG_TAG, "KmlProvider.parseFile - end");
        return ok;
    }

    // KmlSaxHandler -------------

    /**
     * Parse a local KMZ document.
     *
     * @param file full file path
     * @return true if OK.
     */
    public boolean parseKMZFile(File file) {
        Log.d(BonusPackHelper.LOG_TAG, "KmlProvider.parseKMZFile:" + file.getAbsolutePath());
        try {
            ZipFile kmzFile = new ZipFile(file);
            String rootFileName = null;
            //Iterate in the KMZ to find the first ".kml" file:
            Enumeration<? extends ZipEntry> list = kmzFile.entries();
            while (list.hasMoreElements() && rootFileName == null) {
                ZipEntry ze = list.nextElement();
                String name = ze.getName();
                if (name.endsWith(".kml") && !name.contains("/"))
                    rootFileName = name;
            }
            boolean result;
            if (rootFileName != null) {
                ZipEntry rootEntry = kmzFile.getEntry(rootFileName);
                InputStream stream = kmzFile.getInputStream(rootEntry);
                String fullFilePath = file.getAbsolutePath();
                Log.d(BonusPackHelper.LOG_TAG, "KML root:" + rootFileName);
                result = parseKMLStream(stream, fullFilePath, kmzFile);
            } else {
                Log.d(BonusPackHelper.LOG_TAG, "No .kml entry found.");
                result = false;
            }
            kmzFile.close();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Parse a KML content from an InputStream.
     *
     * @param stream       the InputStream
     * @param fullFilePath of the content, which is used inside the parser to handle "relative" files, to determine their full file path.
     *                     Note that relative files are supported only for regular files.
     * @param kmzContainer KMZ file containing this KML file - or null if not applicable.
     * @return true if OK, false if any error.
     */
    public boolean parseKMLStream(InputStream stream, String fullFilePath, ZipFile kmzContainer) {
        KmlSaxHandler handler = new KmlSaxHandler(fullFilePath, kmzContainer);
        boolean ok;
        try {
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            parser.parse(stream, handler);
            mKmlRoot = handler.mKmlRoot;
            ok = true;
        } catch (Exception e) {
            e.printStackTrace();
            ok = false;
        }
        return ok;
    }

    /**
     * save the document as a KML file on writer
     *
     * @param writer
     * @return false if error
     */
    public boolean saveAsKML(Writer writer) {
        try {
            writer.write("<?xml version='1.0' encoding='UTF-8'?>\n");
            writer.write("<kml xmlns='http://www.opengis.net/kml/2.2'>\n");
            boolean result = true;
            if (mKmlRoot != null)
                result = mKmlRoot.writeAsKML(writer, true, this);
            writer.write("</kml>\n");
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public void writeKMLStyles(Writer writer) {
        for (HashMap.Entry<String, Style> entry : mStyles.entrySet()) {
            String styleId = entry.getKey();
            Style style = entry.getValue();
            style.writeAsKML(writer, styleId);
        }
    }

    /**
     * Save the document as a KML file
     *
     * @param file full path of the destination file
     * @return false if error
     */
    public boolean saveAsKML(File file) {
        try {
            Log.d(BonusPackHelper.LOG_TAG, "Saving " + file.getAbsolutePath());
            FileWriter fw = new FileWriter(file);
            BufferedWriter writer = new BufferedWriter(fw, 8192);
            boolean result = saveAsKML(writer);
            writer.close();
            Log.d(BonusPackHelper.LOG_TAG, "Saved.");
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean saveAsGeoJSON(Writer writer) {
        JsonObject json = mKmlRoot.asGeoJSON(true);
        if (json == null)
            return false;
        try {
            Gson gson = new GsonBuilder().create();
            JsonWriter jsonWriter = new JsonWriter(writer);
            gson.toJson(json, jsonWriter);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Save the document as a GeoJSON file
     *
     * @param file full path of the destination file
     * @return false if error
     * @see http://geojson.org
     */
    public boolean saveAsGeoJSON(File file) {
        try {
            FileWriter fw = new FileWriter(file);
            BufferedWriter writer = new BufferedWriter(fw, 8192);
            boolean result = saveAsGeoJSON(writer);
            writer.close();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Parse a GeoJSON object.
     */
    public boolean parseGeoJSON(JsonObject json) {
        KmlFeature feature = KmlFeature.parseGeoJSON(json);
        if (feature instanceof KmlFolder)
            mKmlRoot = (KmlFolder) feature;
        else {
            mKmlRoot = new KmlFolder();
            mKmlRoot.add(feature);
        }
        return true;
    }

    /**
     * Parse a GeoJSON String
     */
    public boolean parseGeoJSON(String jsonString) {
        try {
            JsonParser parser = new JsonParser();
            JsonElement json = parser.parse(jsonString);
            return parseGeoJSON(json.getAsJsonObject());
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            return false;
        }
    }

    //Parcelable implementation ------------

    /**
     * Parse a GeoJSON File
     */
    public boolean parseGeoJSON(File file) {
        try {
            FileInputStream input = new FileInputStream(file);
            String s = BonusPackHelper.convertStreamToString(input);
            input.close();
            return parseGeoJSON(s);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * WARNING - Parcel mechanism doesn't work with very large objects. Refer to Android doc, and use carefully.
     */
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeParcelable(mKmlRoot, flags);
        //write styles map:
        //out.writeMap(mStyles); - not recommended in the Google JavaDoc, for mysterious reasons, so:
        out.writeInt(mStyles.size());
        for (String key : mStyles.keySet()) {
            out.writeString(key);
            out.writeParcelable(mStyles.get(key), flags);
        }
        out.writeInt(mMaxStyleId);
    }

    class KmlSaxHandler extends DefaultHandler {

        public KmlFolder mKmlRoot;
        Style mCurrentStyle;
        String mCurrentStyleId;
        ColorStyle mColorStyle;
        String mDataName;
        boolean mIsNetworkLink;
        boolean mIsInnerBoundary;
        String mFullPath; //to get the path of relative sub-files
        ZipFile mKMZFile;
        double mNorth, mEast, mSouth, mWest;
        private StringBuilder mStringBuilder = new StringBuilder(1024);
        private KmlFeature mKmlCurrentFeature;
        private KmlGroundOverlay mKmlCurrentGroundOverlay; //if GroundOverlay, pointer to mKmlCurrentFeature
        private ArrayList<KmlFeature> mKmlFeatureStack;
        private KmlGeometry mKmlCurrentGeometry;
        private ArrayList<KmlGeometry> mKmlGeometryStack;

        public KmlSaxHandler(String fullPath, ZipFile kmzContainer) {
            mFullPath = fullPath;
            mKMZFile = kmzContainer;
            mKmlRoot = new KmlFolder();
            mKmlFeatureStack = new ArrayList<KmlFeature>();
            mKmlFeatureStack.add(mKmlRoot);
            mKmlGeometryStack = new ArrayList<KmlGeometry>();
            mIsNetworkLink = false;
            mIsInnerBoundary = false;
        }

        protected void loadNetworkLink(String href, ZipFile kmzContainer) {
            KmlDocument subDocument = new KmlDocument();
            boolean ok;
            if (href.startsWith("http://") || href.startsWith("https://"))
                ok = subDocument.parseUrl(href);
            else if (kmzContainer == null) {
                File file = new File(mFullPath);
                File subFile = new File(file.getParent() + '/' + href);
                ok = subDocument.parseKMLFile(subFile);
            } else {
                try {
                    final ZipEntry fileEntry = kmzContainer.getEntry(href);
                    InputStream stream = kmzContainer.getInputStream(fileEntry);
                    Log.d(BonusPackHelper.LOG_TAG, "Load NetworkLink:" + href);
                    ok = subDocument.parseKMLStream(stream, mFullPath, kmzContainer);
                } catch (Exception e) {
                    ok = false;
                }
            }
            if (ok) {
                //add subDoc root to the current feature, which is -normally- the NetworkLink:
                ((KmlFolder) mKmlCurrentFeature).add(subDocument.mKmlRoot);
                //add all subDocument styles to mStyles:
                mStyles.putAll(subDocument.mStyles);
            } else {
                Log.e(BonusPackHelper.LOG_TAG, "Error reading NetworkLink:" + href);
            }
        }

        public void startElement(String uri, String localName, String name,
                                 Attributes attributes) throws SAXException {
            if (localName.equals("Document")) {
                mKmlCurrentFeature = mKmlRoot; //If there is a Document, it will be the root.
                mKmlCurrentFeature.mId = attributes.getValue("id");
            } else if (localName.equals("Folder")) {
                mKmlCurrentFeature = new KmlFolder();
                mKmlCurrentFeature.mId = attributes.getValue("id");
                mKmlFeatureStack.add(mKmlCurrentFeature); //push on stack
            } else if (localName.equals("NetworkLink")) {
                mKmlCurrentFeature = new KmlFolder();
                mKmlCurrentFeature.mId = attributes.getValue("id");
                mKmlFeatureStack.add(mKmlCurrentFeature); //push on stack
                mIsNetworkLink = true;
            } else if (localName.equals("GroundOverlay")) {
                mKmlCurrentGroundOverlay = new KmlGroundOverlay();
                mKmlCurrentFeature = mKmlCurrentGroundOverlay;
                mKmlCurrentFeature.mId = attributes.getValue("id");
                mKmlFeatureStack.add(mKmlCurrentFeature); //push on stack
            } else if (localName.equals("Placemark")) {
                mKmlCurrentFeature = new KmlPlacemark();
                mKmlCurrentFeature.mId = attributes.getValue("id");
                mKmlFeatureStack.add(mKmlCurrentFeature); //push on Feature stack
            } else if (localName.equals("Point")) {
                mKmlCurrentGeometry = new KmlPoint();
                mKmlGeometryStack.add(mKmlCurrentGeometry); //push on Geometry stack
            } else if (localName.equals("LineString")) {
                mKmlCurrentGeometry = new KmlLineString();
                mKmlGeometryStack.add(mKmlCurrentGeometry);
            } else if (localName.equals("Polygon")) {
                mKmlCurrentGeometry = new KmlPolygon();
                mKmlGeometryStack.add(mKmlCurrentGeometry);
            } else if (localName.equals("innerBoundaryIs")) {
                mIsInnerBoundary = true;
            } else if (localName.equals("MultiGeometry")) {
                mKmlCurrentGeometry = new KmlMultiGeometry();
                mKmlGeometryStack.add(mKmlCurrentGeometry);
            } else if (localName.equals("Style")) {
                mCurrentStyle = new Style();
                mCurrentStyleId = attributes.getValue("id");
            } else if (localName.equals("LineStyle")) {
                mCurrentStyle.mLineStyle = new LineStyle();
                mColorStyle = mCurrentStyle.mLineStyle;
            } else if (localName.equals("PolyStyle")) {
                mCurrentStyle.mPolyStyle = new ColorStyle();
                mColorStyle = mCurrentStyle.mPolyStyle;
            } else if (localName.equals("IconStyle")) {
                mCurrentStyle.mIconStyle = new IconStyle();
                mColorStyle = mCurrentStyle.mIconStyle;
            } else if (localName.equals("hotSpot")) {
                if (mCurrentStyle != null && mCurrentStyle.mIconStyle != null) {
                    mCurrentStyle.mIconStyle.mHotSpotX = Float.parseFloat(attributes.getValue("x"));
                    mCurrentStyle.mIconStyle.mHotSpotY = Float.parseFloat(attributes.getValue("y"));
                }
            } else if (localName.equals("Data") || localName.equals("SimpleData")) {
                mDataName = attributes.getValue("name");
            }
            mStringBuilder.setLength(0);
        }

        public
        @Override
        void characters(char[] ch, int start, int length)
                throws SAXException {
            mStringBuilder.append(ch, start, length);
        }

        public void endElement(String uri, String localName, String name)
                throws SAXException {
            if (localName.equals("Document")) {
                //Document is the root, nothing to do.
            } else if (localName.equals("Folder") || localName.equals("Placemark")
                    || localName.equals("NetworkLink") || localName.equals("GroundOverlay")) {
                //this was a Feature:
                KmlFolder parent = (KmlFolder) mKmlFeatureStack.get(mKmlFeatureStack.size() - 2); //get parent
                parent.add(mKmlCurrentFeature); //add current in its parent
                mKmlFeatureStack.remove(mKmlFeatureStack.size() - 1); //pop current from stack
                mKmlCurrentFeature = mKmlFeatureStack.get(mKmlFeatureStack.size() - 1); //set current to top of stack
                if (localName.equals("NetworkLink"))
                    mIsNetworkLink = false;
                else if (localName.equals("GroundOverlay"))
                    mKmlCurrentGroundOverlay = null;
            } else if (localName.equals("innerBoundaryIs")) {
                mIsInnerBoundary = false;
            } else if (localName.equals("Point") || localName.equals("LineString") || localName.equals("Polygon")
                    || localName.equals("MultiGeometry")) {
                //this was a Geometry:
                if (mKmlGeometryStack.size() == 1) {
                    //no MultiGeometry parent: add this Geometry in the current Feature:
                    ((KmlPlacemark) mKmlCurrentFeature).mGeometry = mKmlCurrentGeometry;
                    mKmlGeometryStack.remove(mKmlGeometryStack.size() - 1); //pop current from stack
                    mKmlCurrentGeometry = null;
                } else {
                    KmlMultiGeometry parent = (KmlMultiGeometry) mKmlGeometryStack.get(mKmlGeometryStack.size() - 2); //get parent
                    parent.addItem(mKmlCurrentGeometry); //add current in its parent
                    mKmlGeometryStack.remove(mKmlGeometryStack.size() - 1); //pop current from stack
                    mKmlCurrentGeometry = mKmlGeometryStack.get(mKmlGeometryStack.size() - 1); //set current to top of stack
                }
            } else if (localName.equals("name")) {
                mKmlCurrentFeature.mName = mStringBuilder.toString();
            } else if (localName.equals("description")) {
                mKmlCurrentFeature.mDescription = mStringBuilder.toString();
            } else if (localName.equals("visibility")) {
                mKmlCurrentFeature.mVisibility = ("1".equals(mStringBuilder.toString()));
            } else if (localName.equals("open")) {
                mKmlCurrentFeature.mOpen = ("1".equals(mStringBuilder.toString()));
            } else if (localName.equals("coordinates")) {
                if (mKmlCurrentFeature instanceof KmlPlacemark) {
                    if (!mIsInnerBoundary) {
                        mKmlCurrentGeometry.mCoordinates = parseKmlCoordinates(mStringBuilder.toString());
                        //mKmlCurrentFeature.mBB = BoundingBoxE6.fromGeoPoints(mKmlCurrentGeometry.mCoordinates);
                    } else { //inside a Polygon innerBoundaryIs element: new hole
                        KmlPolygon polygon = (KmlPolygon) mKmlCurrentGeometry;
                        if (polygon.mHoles == null)
                            polygon.mHoles = new ArrayList<ArrayList<GeoPoint>>();
                        ArrayList<GeoPoint> hole = parseKmlCoordinates(mStringBuilder.toString());
                        polygon.mHoles.add(hole);
                    }
                }
            } else if (localName.equals("styleUrl")) {
                if (mStringBuilder.charAt(0) == '#')
                    mKmlCurrentFeature.mStyle = mStringBuilder.substring(1); //remove the #
                else //external url: keep as is:
                    mKmlCurrentFeature.mStyle = mStringBuilder.toString();
            } else if (localName.equals("color")) {
                if (mCurrentStyle != null) {
                    if (mColorStyle != null)
                        mColorStyle.mColor = ColorStyle.parseKMLColor(mStringBuilder.toString());
                } else if (mKmlCurrentGroundOverlay != null) {
                    mKmlCurrentGroundOverlay.mColor = ColorStyle.parseKMLColor(mStringBuilder.toString());
                }
            } else if (localName.equals("colorMode")) {
                if (mCurrentStyle != null && mColorStyle != null)
                    mColorStyle.mColorMode = (mStringBuilder.toString().equals("random") ? ColorStyle.MODE_RANDOM : ColorStyle.MODE_NORMAL);
            } else if (localName.equals("width")) {
                if (mCurrentStyle != null && mCurrentStyle.mLineStyle != null)
                    mCurrentStyle.mLineStyle.mWidth = Float.parseFloat(mStringBuilder.toString());
            } else if (localName.equals("scale")) {
                if (mCurrentStyle != null && mCurrentStyle.mIconStyle != null) {
                    mCurrentStyle.mIconStyle.mScale = Float.parseFloat(mStringBuilder.toString());
                }
            } else if (localName.equals("heading")) {
                if (mCurrentStyle != null && mCurrentStyle.mIconStyle != null) {
                    mCurrentStyle.mIconStyle.mHeading = Float.parseFloat(mStringBuilder.toString());
                }
            } else if (localName.equals("href")) {
                if (mCurrentStyle != null && mCurrentStyle.mIconStyle != null) {
                    //href of an Icon in an IconStyle:
                    String href = mStringBuilder.toString();
                    mCurrentStyle.setIcon(href, mFullPath, mKMZFile);
                } else if (mIsNetworkLink) {
                    //href of a NetworkLink:
                    String href = mStringBuilder.toString();
                    loadNetworkLink(href, mKMZFile);
                } else if (mKmlCurrentGroundOverlay != null) {
                    //href of a GroundOverlay Icon:
                    mKmlCurrentGroundOverlay.setIcon(mStringBuilder.toString(), mFullPath, mKMZFile);
                }
            } else if (localName.equals("Style")) {
                if (mCurrentStyleId != null)
                    putStyle(mCurrentStyleId, mCurrentStyle);
                else {
                    mCurrentStyleId = addStyle(mCurrentStyle);
                    if (mKmlCurrentFeature != null) {
                        //this is an inline style. Set its style id to the KmlObject container:
                        mKmlCurrentFeature.mStyle = mCurrentStyleId;
                    }
                }
                mCurrentStyle = null;
            } else if (localName.equals("north")) {
                mNorth = Double.parseDouble(mStringBuilder.toString());
            } else if (localName.equals("south")) {
                mSouth = Double.parseDouble(mStringBuilder.toString());
            } else if (localName.equals("east")) {
                mEast = Double.parseDouble(mStringBuilder.toString());
            } else if (localName.equals("west")) {
                mWest = Double.parseDouble(mStringBuilder.toString());
            } else if (localName.equals("rotation")) {
                mKmlCurrentGroundOverlay.mRotation = Float.parseFloat(mStringBuilder.toString());
            } else if (localName.equals("LatLonBox")) {
                if (mKmlCurrentGroundOverlay != null) {
                    mKmlCurrentGroundOverlay.setLatLonBox(mNorth, mSouth, mEast, mWest);
                }
            } else if (localName.equals("SimpleData")) {
                //We don't check the schema from SchemaData. We just pick the name and the value from SimpleData:
                mKmlCurrentFeature.setExtendedData(mDataName, mStringBuilder.toString());
                mDataName = null;
            } else if (localName.equals("value")) {
                mKmlCurrentFeature.setExtendedData(mDataName, mStringBuilder.toString());
                mDataName = null;
            }
        }

    }

}




Java Source Code List

com.ilm.sandwich.BackgroundService.java
com.ilm.sandwich.BuildConfig.java
com.ilm.sandwich.Config.java
com.ilm.sandwich.GoogleMapActivity.java
com.ilm.sandwich.Info.java
com.ilm.sandwich.MySupportMapFragment.java
com.ilm.sandwich.OsmMapActivity.java
com.ilm.sandwich.Settings.java
com.ilm.sandwich.StartChooser.java
com.ilm.sandwich.TouchableWrapper.java
com.ilm.sandwich.tools.Core.java
com.ilm.sandwich.tools.HttpRequests.java
com.ilm.sandwich.tools.Locationer.java
com.ilm.sandwich.tools.MapDownload.java
com.ilm.sandwich.tools.MyItemizedOverlay.java
com.ilm.sandwich.tools.PlacesAutoComplete.java
com.ilm.sandwich.tools.PlacesTextSearch.java
com.ilm.sandwich.tools.Statistics.java
com.ilm.sandwich.tools.SuggestionsAdapter.java
org.osmdroid.bonuspack.BuildConfig.java
org.osmdroid.bonuspack.BuildConfig.java
org.osmdroid.bonuspack.cachemanager.CacheManager.java
org.osmdroid.bonuspack.clustering.GridMarkerClusterer.java
org.osmdroid.bonuspack.clustering.MarkerClusterer.java
org.osmdroid.bonuspack.clustering.StaticCluster.java
org.osmdroid.bonuspack.kml.ColorStyle.java
org.osmdroid.bonuspack.kml.IconStyle.java
org.osmdroid.bonuspack.kml.KmlDocument.java
org.osmdroid.bonuspack.kml.KmlFeature.java
org.osmdroid.bonuspack.kml.KmlFolder.java
org.osmdroid.bonuspack.kml.KmlGeometry.java
org.osmdroid.bonuspack.kml.KmlGroundOverlay.java
org.osmdroid.bonuspack.kml.KmlLineString.java
org.osmdroid.bonuspack.kml.KmlMultiGeometry.java
org.osmdroid.bonuspack.kml.KmlPlacemark.java
org.osmdroid.bonuspack.kml.KmlPoint.java
org.osmdroid.bonuspack.kml.KmlPolygon.java
org.osmdroid.bonuspack.kml.LineStyle.java
org.osmdroid.bonuspack.kml.Style.java
org.osmdroid.bonuspack.location.FlickrPOIProvider.java
org.osmdroid.bonuspack.location.GeoNamesPOIProvider.java
org.osmdroid.bonuspack.location.GeocoderGisgraphy.java
org.osmdroid.bonuspack.location.GeocoderNominatimOld.java
org.osmdroid.bonuspack.location.GeocoderNominatim.java
org.osmdroid.bonuspack.location.NominatimPOIProvider.java
org.osmdroid.bonuspack.location.POI.java
org.osmdroid.bonuspack.location.PicasaPOIProvider.java
org.osmdroid.bonuspack.mapsforge.GenericMapView.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileModuleProvider.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileProvider.java
org.osmdroid.bonuspack.mapsforge.MapsForgeTileSource.java
org.osmdroid.bonuspack.overlays.DefaultInfoWindow.java
org.osmdroid.bonuspack.overlays.ExtendedOverlayItem.java
org.osmdroid.bonuspack.overlays.FolderOverlay.java
org.osmdroid.bonuspack.overlays.GroundOverlay.java
org.osmdroid.bonuspack.overlays.InfoWindow.java
org.osmdroid.bonuspack.overlays.ItemizedOverlayWithBubble.java
org.osmdroid.bonuspack.overlays.MapEventsOverlay.java
org.osmdroid.bonuspack.overlays.MapEventsReceiver.java
org.osmdroid.bonuspack.overlays.MarkerInfoWindow.java
org.osmdroid.bonuspack.overlays.Marker.java
org.osmdroid.bonuspack.overlays.Polygon.java
org.osmdroid.bonuspack.overlays.Polyline.java
org.osmdroid.bonuspack.routing.GoogleRoadManager.java
org.osmdroid.bonuspack.routing.MapQuestRoadManager.java
org.osmdroid.bonuspack.routing.OSRMRoadManager.java
org.osmdroid.bonuspack.routing.RoadLeg.java
org.osmdroid.bonuspack.routing.RoadManager.java
org.osmdroid.bonuspack.routing.RoadNode.java
org.osmdroid.bonuspack.routing.Road.java
org.osmdroid.bonuspack.utils.BonusPackHelper.java
org.osmdroid.bonuspack.utils.DouglasPeuckerReducer.java
org.osmdroid.bonuspack.utils.HttpConnection.java
org.osmdroid.bonuspack.utils.PolylineEncoder.java
org.osmdroid.bonuspack.utils.WebImageCache.java