All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwind.formats.georss.GeoRSSParser Maven / Gradle / Ivy

/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.formats.georss;

import gov.nasa.worldwind.exception.WWRuntimeException;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.Logging;
import org.w3c.dom.*;
import org.xml.sax.*;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;

/**
 * @author tag
 * @version $Id: GeoRSSParser.java 1171 2013-02-11 21:45:02Z dcollins $
 */

public class GeoRSSParser
{
    public static final String GEORSS_URI = "http://www.georss.org/georss";
    public static final String GML_URI = "http://www.opengis.net/gml";

    public static List parseFragment(String fragmentString, NamespaceContext nsc)
    {
        return parseShapes(fixNamespaceQualification(fragmentString));
    }

    public static List parseShapes(String docString)
    {
        if (docString == null)
        {
            String message = Logging.getMessage("nullValue.StringIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (docString.length() < 1) // avoid empty strings
            return null;

        try
        {
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setNamespaceAware(true);
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(new InputSource(new StringReader(docString)));

            List shapes = parseShapes(doc);

            if (shapes == null || shapes.size() < 1)
            {
                Logging.logger().log(Level.WARNING, "GeoRSS.NoShapes", docString);
                return null;
            }

            return shapes;
        }
        catch (ParserConfigurationException e)
        {
            String message = Logging.getMessage("GeoRSS.ParserConfigurationException");
            Logging.logger().log(Level.SEVERE, message, e);
            throw new WWRuntimeException(message, e);
        }
        catch (IOException e)
        {
            String message = Logging.getMessage("GeoRSS.IOExceptionParsing", docString);
            Logging.logger().log(Level.SEVERE, message, e);
            throw new WWRuntimeException(message, e);
        }
        catch (SAXException e)
        {
            String message = Logging.getMessage("GeoRSS.IOExceptionParsing", docString);
            Logging.logger().log(Level.SEVERE, message, e);
            throw new WWRuntimeException(message, e);
        }
    }

    private static String fixNamespaceQualification(String xmlString)
    {
        String lcaseString = xmlString.toLowerCase();
        StringBuffer qualifiers = new StringBuffer();

        if (lcaseString.contains("georss:") && !lcaseString.contains(GEORSS_URI))
        {
            qualifiers.append(" xmlns:georss=\"");
            qualifiers.append(GEORSS_URI);
            qualifiers.append("\"");
        }

        if (lcaseString.contains("gml:") && !lcaseString.contains(GML_URI))
        {
            qualifiers.append(" xmlns:gml=\"");
            qualifiers.append(GML_URI);
            qualifiers.append("\"");
        }

        if (qualifiers.length() > 0)
        {
            StringBuffer sb = new StringBuffer();
            sb.append("");
            sb.append(xmlString);
            sb.append("");

            return sb.toString();
        }

        return xmlString;
    }

    private static String surroundWithNameSpaces(String docString)
    {
        StringBuffer sb = new StringBuffer();
        sb.append("");
        sb.append(docString);
        sb.append("");
//        System.out.println(sb.toString());

        return sb.toString();
    }

    public static List parseShapes(File file)
    {
        if (file == null)
        {
            String message = Logging.getMessage("nullValue.FileIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        try
        {
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setNamespaceAware(false);
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(file);

            List shapes = parseShapes(doc);

            if (shapes == null || shapes.size() < 1)
            {
                Logging.logger().log(Level.WARNING, "GeoRSS.NoShapes", file.getPath());
                return null;
            }

            return shapes;
        }
        catch (ParserConfigurationException e)
        {
            String message = Logging.getMessage("GeoRSS.ParserConfigurationException");
            Logging.logger().log(Level.SEVERE, message, e);
            throw new WWRuntimeException(message, e);
        }
        catch (IOException e)
        {
            String message = Logging.getMessage("GeoRSS.IOExceptionParsing", file.getPath());
            Logging.logger().log(Level.SEVERE, message, e);
            throw new WWRuntimeException(message, e);
        }
        catch (SAXException e)
        {
            String message = Logging.getMessage("GeoRSS.IOExceptionParsing", file.getPath());
            Logging.logger().log(Level.SEVERE, message, e);
            throw new WWRuntimeException(message, e);
        }
    }

    public static List parseShapes(Document xmlDoc)
    {
        if (xmlDoc == null)
        {
            String message = Logging.getMessage("nullValue.DocumentIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        ArrayList shapeNodes = new ArrayList();
        ArrayList attributeNodes = new ArrayList();

        // Shapes
        NodeList nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "where");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(shapeNodes, nodes);

        nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "point");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(shapeNodes, nodes);

        nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "line");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(shapeNodes, nodes);

        nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "polygon");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(shapeNodes, nodes);

        nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "box");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(shapeNodes, nodes);

        // Attributes
        nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "radius");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(attributeNodes, nodes);

        nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "elev");
        if (nodes != null && nodes.getLength() > 0)
            addNodes(attributeNodes, nodes);

        ArrayList shapes = new ArrayList();

        if (shapeNodes.size() < 1)
            return null; // No warning here. Let the calling method inform of this case.

        for (Node node : shapeNodes)
        {
            Renderable shape = null;
            String localName = node.getLocalName();

            if (localName.equals("point"))
                shape = makePointShape(node, attributeNodes);

            else if (localName.equals("where"))
                shape = makeWhereShape(node);

            else if (localName.equals("line"))
                shape = makeLineShape(node, attributeNodes);

            else if (localName.equals("polygon"))
                shape = makePolygonShape(node, attributeNodes);

            else if (localName.equals("box"))
                shape = makeBoxShape(node, attributeNodes);

            if (shape != null)
                shapes.add(shape);
        }

        return shapes;
    }

    private static void addNodes(ArrayList nodeList, NodeList nodes)
    {
        for (int i = 0; i < nodes.getLength(); i++)
        {
            nodeList.add(nodes.item(i));
        }
    }

    private static Renderable makeWhereShape(Node node)
    {
        Node typeNode = findChildByLocalName(node, "Polygon");
        if (typeNode != null)
            return makeGMLPolygonShape(typeNode);

        typeNode = findChildByLocalName(node, "Envelope");
        if (typeNode != null)
            return makeGMLEnvelopeShape(typeNode);

        typeNode = findChildByLocalName(node, "LineString");
        if (typeNode != null)
            return makeGMLineStringShape(typeNode);

        typeNode = findChildByLocalName(node, "Point");
        if (typeNode != null)
            return makeGMLPointShape(typeNode);

        Logging.logger().log(Level.WARNING, "GeoRSS.MissingElementContent", "where");
        return null;
    }

    private static Renderable makeGMLPolygonShape(Node node)
    {
        Node n = findChildByLocalName(node, "exterior");
        if (n == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.MissingElement", "exterior");
            return null;
        }

        n = findChildByLocalName(n, "LinearRing");
        if (n == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.MissingElement", "LinearRing");
            return null;
        }

        return makePolygonShape(n, null);
    }

    private static Renderable makePolygonShape(Node node, Iterable attrs)
    {
        String valuesString = node.getTextContent();
        if (valuesString == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.NoCoordinates", node.getLocalName());
            return null;
        }

        ArrayList values = getDoubleValues(valuesString);
        if (values.size() < 8 || values.size() % 2 != 0)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", node.getLocalName());
            return null;
        }

        ArrayList positions = new ArrayList();
        for (int i = 0; i < values.size(); i += 2)
        {
            positions.add(LatLon.fromDegrees(values.get(i), values.get(i + 1)));
        }

        double elevation = attrs != null ? getElevation(node, attrs) : 0d;
        if (elevation != 0)
        {
            Polyline pl = new Polyline(positions, elevation);
            pl.setFilled(true);
            pl.setPathType(Polyline.GREAT_CIRCLE);

            return pl;
        }
        else
        {
            return new SurfacePolygon(positions);
        }
    }

    private static Renderable makeGMLEnvelopeShape(Node node)
    {
        Node n = findChildByLocalName(node, "lowerCorner");
        if (n == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.MissingElement", " lowerCorner");
            return null;
        }

        String lowerCornerString = n.getTextContent();
        if (lowerCornerString == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", " lowerCorner");
            return null;
        }

        n = findChildByLocalName(node, "upperCorner");
        if (n == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", " upperCorner");
            return null;
        }

        String upperCornerString = n.getTextContent();
        if (upperCornerString == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", " upperCorner");
            return null;
        }

        ArrayList lv = getDoubleValues(lowerCornerString);
        if (lv.size() != 2)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", " lowerCorner");
            return null;
        }

        ArrayList uv = getDoubleValues(upperCornerString);
        if (uv.size() != 2)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", " upperCorner");
            return null;
        }

        return new SurfaceSector(Sector.fromDegrees(lv.get(0), uv.get(0), lv.get(1), uv.get(1)));
    }

    private static Renderable makeBoxShape(Node node, Iterable attrs)
    {
        String valuesString = node.getTextContent();
        if (valuesString == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.NoCoordinates", node.getLocalName());
            return null;
        }

        ArrayList p = getDoubleValues(valuesString);
        if (p.size() != 4)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", node.getLocalName());
            return null;
        }

        double elevation = getElevation(node, attrs);
        if (elevation != 0)
            return new Quadrilateral(LatLon.fromDegrees(p.get(0), p.get(1)),
                LatLon.fromDegrees(p.get(2), p.get(3)), elevation);
        else
            return new SurfaceSector(Sector.fromDegrees(p.get(0), p.get(2), p.get(1), p.get(3)));
    }

    private static Renderable makeGMLineStringShape(Node node)
    {
        Node n = findChildByLocalName(node, "posList");
        if (n == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.MissingElement", "posList");
            return null;
        }

        return makeLineShape(n, null);
    }

    private static Renderable makeLineShape(Node node, Iterable attrs)
    {
        String valuesString = node.getTextContent();
        if (valuesString == null)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.NoCoordinates", node.getLocalName());
            return null;
        }

        ArrayList values = getDoubleValues(valuesString);
        if (values.size() < 4)
        {
            Logging.logger().log(Level.WARNING, "GeoRSS.InvalidCoordinateCount", node.getLocalName());
            return null;
        }

        ArrayList positions = new ArrayList();
        for (int i = 0; i < values.size(); i += 2)
        {
            positions.add(LatLon.fromDegrees(values.get(i), values.get(i + 1)));
        }

        double elevation = attrs != null ? getElevation(node, attrs) : 0d;
        if (elevation != 0)
        {
            Polyline pl = new Polyline(positions, elevation);
            pl.setPathType(Polyline.GREAT_CIRCLE);
            return pl;
        }
        else
        {
            return new Polyline(positions, 0);
        }
    }

    @SuppressWarnings({"UnusedDeclaration"})
    private static Renderable makeGMLPointShape(Node node)
    {
        return null; // No shape provided for points. Expect app to use icons.
    }

    @SuppressWarnings({"UnusedDeclaration"})
    private static Renderable makePointShape(Node node, Iterable attrs)
    {
        return null; // No shape provided for points. Expect app to use icons.
    }

    private static Node findChildByLocalName(Node parent, String localName)
    {
        NodeList children = parent.getChildNodes();
        if (children == null || children.getLength() < 1)
            return null;

        for (int i = 0; i < children.getLength(); i++)
        {
            String ln = children.item(i).getLocalName();
            if (ln != null && ln.equals(localName))
                return children.item(i);
        }

        return null;
    }

    private static Node findSiblingAttribute(String attrName, Iterable attribs, Node shapeNode)
    {
        for (Node attrib : attribs)
        {
            if (!attrib.getLocalName().equals(attrName))
                continue;

            if (attrib.getParentNode().equals(shapeNode.getParentNode()))
                return attrib;
        }

        return null;
    }

    private static ArrayList getDoubleValues(String stringValues)
    {
        String[] tokens = stringValues.trim().split("[ ,\n]");
        if (tokens.length < 1)
            return null;

        ArrayList arl = new ArrayList();
        for (String s : tokens)
        {
            if (s == null || s.length() < 1)
                continue;

            double d;
            try
            {
                d = Double.parseDouble(s);
            }
            catch (NumberFormatException e)
            {
                Logging.logger().log(Level.SEVERE, "GeoRSS.NumberFormatException", s);
                continue;
            }

            arl.add(d);
        }

        return arl;
    }

    private static double getElevation(Node shapeNode, Iterable attrs)
    {
        double elevation = 0d;

        Node elevNode = findSiblingAttribute("elev", attrs, shapeNode);
        if (elevNode != null)
        {
            ArrayList ev = getDoubleValues(elevNode.getTextContent());
            if (ev != null && ev.size() > 0)
            {
                elevation = ev.get(0);
            }
            else
            {
                Logging.logger().log(Level.WARNING, "GeoRSS.MissingElementContent",  "elev");
            }
        }

        return elevation;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy