Rev 465 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (c) 2009, Chris Miller
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.splitter.kml;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParserException;
import uk.me.parabola.splitter.Area;
import uk.me.parabola.splitter.Utils;
import uk.me.parabola.splitter.xml.parser.AbstractXppParser;
/**
* Parses a KML area file.
*
* @author Chris Miller
*/
public class KmlParser
extends AbstractXppParser
{
private enum State { None, Placemark,
Name,
Polygon, OuterBoundaryIs, LinearRing, Coordinates
}
private State state =
State.
None;
private int currentId
;
private int[] currentCoords =
new int[10];
private List<Area> areas =
new ArrayList<>();
public KmlParser
() throws XmlPullParserException
{
}
public List<Area> getAreas
() {
return areas
;
}
@
Override
protected boolean startElement
(String name
) throws XmlPullParserException
{
switch (state
) {
case None:
if (name.
equals("Placemark"))
state =
State.
Placemark;
break;
case Placemark:
if (name.
equals("name")) {
state =
State.
Name;
} else if (name.
equals("Polygon")) {
state =
State.
Polygon;
}
break;
case Polygon:
if (name.
equals("outerBoundaryIs")) {
state =
State.
OuterBoundaryIs;
}
break;
case OuterBoundaryIs:
if (name.
equals("LinearRing")) {
state =
State.
LinearRing;
}
break;
case LinearRing:
if (name.
equals("coordinates")) {
state =
State.
Coordinates;
}
break;
default:
}
return false;
}
@
Override
protected void text
() throws XmlPullParserException
{
if (state ==
State.
Name) {
String idStr = getTextContent
();
try {
currentId =
Integer.
valueOf(idStr
);
} catch (NumberFormatException e
) {
throw createException
("Unexpected area name encountered. Expected a valid number, found \"" + idStr +
'"');
}
} else if (state ==
State.
Coordinates) {
String coordText = getTextContent
();
String[] coordPairs = coordText.
trim().
split("\\s+");
if (coordPairs.
length !=
5) {
throw createException
("Unexpected number of coordinates. Expected 5, found " + coordPairs.
length +
" in \"" + coordText +
'"');
}
for (int i =
0; i
< 5; i++
) {
String[] coordStrs = coordPairs
[i
].
split(",");
if (coordStrs.
length !=
2) {
throw createException
(
"Unexpected coordinate pair encountered in \"" + coordPairs
[i
] +
"\". Expected 2 numbers, found " + coordStrs.
length);
}
for (int j =
0; j
< 2; j++
) {
try {
Double val =
Double.
valueOf(coordStrs
[j
]);
currentCoords
[i
* 2 + j
] = Utils.
toMapUnit(val
);
} catch (NumberFormatException e
) {
throw createException
("Unexpected coordinate encountered. \"" + coordStrs
[j
] +
"\" is not a valid number");
}
}
}
}
}
@
Override
protected void endElement
(String name
) throws XmlPullParserException
{
if (state ==
State.
Name) {
state =
State.
Placemark;
} else if (state ==
State.
Coordinates) {
state =
State.
LinearRing;
} else if (name.
equals("Placemark")) {
int minLat = currentCoords
[1];
int minLon = currentCoords
[0];
int maxLat = currentCoords
[5];
int maxLon = currentCoords
[4];
Area a =
new Area(minLat, minLon, maxLat, maxLon
);
if (!a.
verify())
throw new IllegalArgumentException("invalid area " + currentId +
" in split file: " + a
);
a.
setMapId(currentId
);
areas.
add(a
);
state =
State.
None;
}
}
}