package org.jvalue.ods.processor.adapter.domain; import com.codahale.metrics.MetricRegistry; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.inject.assistedinject.Assisted; import org.jvalue.ods.api.sources.DataSource; import org.jvalue.ods.processor.adapter.AbstractSourceAdapter; import org.jvalue.ods.processor.adapter.SourceAdapterException; import org.jvalue.ods.processor.adapter.SourceIterator; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.IOException; import java.net.URL; import java.util.LinkedList; import javax.inject.Inject; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; /** * Data adapter for water level provided by the German state Brandenburg. */ public class BrandenburgPegelAdapter extends AbstractSourceAdapter { @Inject BrandenburgPegelAdapter(@Assisted DataSource dataSource, @Assisted String sourceUrl, MetricRegistry registry) { super(dataSource, sourceUrl, registry); } @Override protected SourceIterator doCreateIterator(DataSource source, URL sourceUrl, MetricRegistry registry) { return new BrandenburgSourceIterator(source, sourceUrl, registry); } private static final class BrandenburgSourceIterator extends SourceIterator { private final JsonNodeFactory jsonNodeFactory = JsonNodeFactory.instance; private LinkedList<Element> dataEntries = null; public BrandenburgSourceIterator(DataSource source, URL sourceUrl, MetricRegistry registry) { super(source, sourceUrl, registry); } @Override protected JsonNode doNext() throws IOException { try { if (dataEntries == null) initData(); Element data = dataEntries.removeFirst(); ObjectNode newNode = jsonNodeFactory.objectNode(); // get name newNode.put("name", data.getElementsByTagName("name").item(0).getTextContent()); // get additional data entries NodeList details = ((Element) data.getElementsByTagName("ExtendedData").item(0)).getElementsByTagName("Data"); for (int i = 0; i < details.getLength(); ++i) { Element element = (Element) details.item(i); newNode.put(element.getAttribute("name"), element.getElementsByTagName("value").item(0).getTextContent()); } // parse coordinates String coordinates = ((Element) data.getElementsByTagName("Point").item(0)).getElementsByTagName("coordinates").item(0).getTextContent(); newNode.put("longitude", Double.valueOf(coordinates.split(",")[0])); newNode.put("latitude", Double.valueOf(coordinates.split(",")[1])); return newNode; } catch (ParserConfigurationException | IOException | SAXException e) { throw new SourceAdapterException(e); } } @Override protected boolean doHasNext() throws IOException { try { if (dataEntries == null) initData(); return !dataEntries.isEmpty(); } catch (ParserConfigurationException | IOException | SAXException e) { throw new SourceAdapterException(e); } } private void initData() throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(sourceUrl.openStream()); NodeList nodeList = ((Element) doc.getDocumentElement().getElementsByTagName("Document").item(0)).getElementsByTagName("Placemark"); dataEntries = new LinkedList<>(); for (int i = 0; i < nodeList.getLength(); ++i) { dataEntries.add((Element) nodeList.item(i)); } } } }