package jeql.command.io.kml;
import java.io.Reader;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import jeql.command.io.NameStack;
import jeql.command.io.xml.XMLParseUtil;
import com.ctc.wstx.exc.WstxIOException;
import com.ctc.wstx.stax.WstxInputFactory;
public class KMLObjectReader
{
static final int STATE_DOC = 1;
static final int STATE_STYLE = 2;
static final int STATE_FOLDER = 3;
static final int STATE_PLACEMARK = 4;
private XMLStreamReader xmlRdr;
private PlacemarkParser placemarkParser;
private int parseState = STATE_DOC;
private String currentComposite = null;
private NameStack folderStack = new NameStack("/");
private DocumentModel model;
public KMLObjectReader() {
super();
}
public void open(Reader rdr)
throws Exception
{
WstxInputFactory fact = new WstxInputFactory();
xmlRdr = fact.createXMLStreamReader(rdr);
model = new DocumentModel();
placemarkParser = new PlacemarkParser(xmlRdr);
parsePrologue();
}
private void parsePrologue()
throws XMLStreamException
{
DocumentParser docParser = new DocumentParser(xmlRdr);
docParser.parse(model);
// System.out.println("---- name: " + model.getName());
// System.out.println("---- desc: " + model.getDescription());
StyleParser styleParser = new StyleParser(xmlRdr);
styleParser.parse(model);
}
public DocumentModel getModel()
{
return model;
}
private static boolean isComposite(String tag)
{
if (tag.length() <= 0) return false;
return Character.isUpperCase(tag.charAt(0));
}
/**
* Returns next Placemark record
* @return
* @throws XMLStreamException
*/
public Placemark next()
throws XMLStreamException
{
String locName = null;
while (xmlRdr.hasNext()) {
int event = xmlRdr.getEventType();
if (event == XMLStreamConstants.START_ELEMENT) {
locName = xmlRdr.getLocalName();
if (isComposite(locName))
currentComposite = locName;
if (locName.equals(KMLConstants.FOLDER)) {
parseState = STATE_FOLDER;
}
else if (locName.equals(KMLConstants.DOCUMENT)) {
parseState = STATE_DOC;
}
// this is a bit cheesy, but at least is fairly robust to schema change
else if (currentComposite.equals(KMLConstants.FOLDER)
&& locName.equals(KMLConstants.NAME)) {
String name = XMLParseUtil.parseValue(xmlRdr);
// System.out.println(">>>> Folder name = " + name);
folderStack.push(name);
}
else if (locName.equals(KMLConstants.PLACEMARK)) {
parseState = STATE_PLACEMARK;
// at this point we can parse an entire Placemark
Placemark pm = placemarkParser.parse(model);
pm.setFolder(folderStack.getNameList());
return pm;
}
// otherwise just print tag
// System.out.println(">>>> " + locName);
}
else if (event == XMLStreamConstants.END_ELEMENT) {
locName = xmlRdr.getLocalName();
// System.out.println("/" + locName);
if (locName.equals(KMLConstants.FOLDER)) {
folderStack.pop();;
}
xmlRdr.next();
}
else if (event == XMLStreamConstants.END_DOCUMENT) {
break;
}
// consume the event
try {
xmlRdr.next();
}
catch (WstxIOException e) {
// can't do much about this, so carry on
e.printStackTrace();
throw e;
}
}
return null;
}
public void close()
{
try {
xmlRdr.close();
}
catch (XMLStreamException e) {
// eat it - nothing we can do
}
}
}