package cz.nalezen.osm.extractor.mvcr;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import cz.nalezen.osm.extractor.data.City;
import cz.nalezen.osm.extractor.data.CzechRepublicAddresses;
import cz.nalezen.osm.extractor.data.District;
import cz.nalezen.osm.extractor.data.Street;
class MvcrSaxHandler extends DefaultHandler {
private CzechRepublicAddresses root;
private District districtCtx = null;
private City cityCtx = null;
private Street streetCtx = null;
private static final Logger logger = Logger.getLogger(MvcrSaxHandler.class);
public MvcrSaxHandler(CzechRepublicAddresses root) {
this.root = root;
}
@Override
public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
if (qName.equals("adresy")) {
//root
} else if (qName.equals("oblast")) {
handleDistrict(qName, attributes);
} else if (qName.equals("obec")) {
handleCity(qName, attributes);
} else if (qName.equals("cast")) {
//not used
} else if (qName.equals("ulice")) {
handleStreet(qName, attributes);
} else if (qName.equals("a")) {
handleAddress(qName, attributes);
} else {
logger.error(String.format("Unhandled tag '%s'!", qName));
}
}
@Override
public void endElement (String uri, String localName, String qName) throws SAXException {
if (qName.equals("adresy")) {
//root
} else if (qName.equals("oblast")) {
districtCtx = null;
} else if (qName.equals("obec")) {
cityCtx = null;
} else if (qName.equals("cast")) {
//not used
} else if (qName.equals("ulice")) {
streetCtx = null;
} else if (qName.equals("a")) {
//
} else {
logger.error(String.format("Unhandled tag '%s'!", qName));
}
}
private void handleDistrict(String qName, Attributes attributes) {
String districtName = attributes.getValue("okres");
//ugly hack to define district for capital city Prague compatible with Czech Post data
if ("praha".equals(attributes.getValue("typ"))) {
districtName = "Hlavní město Praha";
}
if (StringUtils.isBlank(districtName)) {
logger.warn(String.format("Problematic district: name=%s okres=%s kraj=%s\n",
attributes.getValue("nazev"),
districtName,
attributes.getValue("kraj")));
return;
}
districtCtx = root.assureDistrict(districtName);
}
private void handleCity(String qName, Attributes attributes) {
String cityName = attributes.getValue("nazev");
if (!hasDistrictCtx(qName, cityName)) {
return;
}
if (StringUtils.isBlank(cityName)) {
logger.warn(String.format("Problematic city: name=%s\n",
cityName));
return;
}
cityCtx = districtCtx.assureCity(cityName);
cityCtx.assureAuxiliaryData().minPostcodeMvcr = NumberUtils.toInt(attributes.getValue("MinPSC"), -1);
cityCtx.assureAuxiliaryData().maxPostcodeMvcr = NumberUtils.toInt(attributes.getValue("MaxPSC"), -1);
}
private void handleStreet(String qName, Attributes attributes) {
String streetName = attributes.getValue("nazev");
if (!hasCityCtx(qName, streetName)) {
return;
}
streetCtx = cityCtx.assureStreet(streetName);
}
private void handleAddress(String qName, Attributes attributes) {
if (!hasCityOrStreetCtx(qName, "*address*")) {
return;
}
String auxNr = attributes.getValue("o");
String mainNr = StringUtils.isBlank(attributes.getValue("p")) ? attributes.getValue("e") : attributes.getValue("p");
if (streetCtx!=null) {
streetCtx.assureAddress(mainNr, auxNr);
} else {
cityCtx.assureAddress(mainNr, auxNr);
}
}
private boolean hasCityOrStreetCtx(String qName, String name) {
if (cityCtx==null && streetCtx==null) {
logger.error(String.format("Tag '%s' with name '%s' out of city or street!", qName, name));
return false;
}
return true;
}
private boolean hasDistrictCtx(String qName, String cityName) {
if (districtCtx==null) {
logger.error(String.format("Tag '%s' with name '%s' out of district!", qName, cityName));
return false;
}
return true;
}
private boolean hasCityCtx(String qName, String streetName) {
if (cityCtx==null) {
logger.error(String.format("Tag '%s' with name '%s' out of city!", qName, streetName));
return false;
}
return true;
}
}