From 240ca5ba7fd89681597bd05c106eb6e3634f4b14 Mon Sep 17 00:00:00 2001
From: Nathanael Jourdane <nathanael.jourdane@irap.omp.eu>
Date: Wed, 10 Feb 2016 17:20:40 +0100
Subject: [PATCH] Add the VOTable parser

---
 src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+), 0 deletions(-)
 create mode 100644 src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java

diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java
new file mode 100644
index 0000000..3ed8a2b
--- /dev/null
+++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java
@@ -0,0 +1,117 @@
+/**
+ * This file is a part of EpnTAPClient.
+ * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer.
+ * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861
+ * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie.
+ * 
+ * This program is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or (at your option) any later
+ * version. 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. You should have received a copy of
+ * the GNU General Public License along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+package eu.omp.irap.vespa.epntapclient.votable.controller;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.xml.sax.SAXException;
+
+import eu.omp.irap.vespa.epntapclient.utils.Log;
+import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE;
+
+/**
+ * @author N. Jourdane
+ */
+public class VOTableParser {
+
+	/** The path of the VOTable to verify the VOTable XML file. */
+	private static final String VOTABLE_SHEMA = "http://www.ivoa.net/xml/VOTable/v";
+
+	/**
+	 * The version of the VOTable with which VOTables will be parsed with JAXB (ie. the last
+	 * published VOTable version by IVOA).
+	 */
+	private static final String JAXB_VOTABLE_VERSION = "1.3";
+
+	/** The VOTable package where are the generated .java which represents the VOTable model. */
+	private static final String VOTABLE_MODEL_PACKAGE = "eu.omp.irap.vespa.epntapclient.votable.model";
+
+	/**
+	 * @param voTablePath The path of the VOTable.
+	 * @return The VOTable resulting of the XML document.
+	 * @throws Exception Can not parse the VOTable.
+	 */
+	public static VOTABLE parseVOTable(String voTablePath) throws Exception {
+		changeVOTableSchemaLocation(voTablePath);
+		// TODO: modifier le nom de la 2ème balise INFO dans le XML plutôt que modifier le XSD.
+		VOTABLE voTable;
+		try {
+			JAXBContext jc = JAXBContext.newInstance(VOTABLE_MODEL_PACKAGE);
+			Unmarshaller unmarshaller = jc.createUnmarshaller();
+			voTable = (VOTABLE) unmarshaller.unmarshal(new File(voTablePath));
+		} catch (Exception e) {
+			throw new SAXException("Can not parse the VOTable.", e);
+		}
+
+		return voTable;
+	}
+
+	/**
+	 * Change the version of the VOTable to the last supported version (1.3 as 2016/02/05). This
+	 * allows JAXB to parse the VOTable even it's not the same namespace than the XSD. Because
+	 * VOTables schemas are retro-compatibles, there is no problem to parse a VOTable with a XML
+	 * schema with a higher version. In the same way, this method check if the file is a valid XML.
+	 * 
+	 * @param voTablePath The path of the VOTable XML file.
+	 * @throws Exception Can not read or write the XML file.
+	 */
+	private static void changeVOTableSchemaLocation(String voTablePath)
+			throws Exception {
+		try {
+			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+			Document doc = docBuilder.parse(voTablePath);
+			NamedNodeMap votAttrs = doc.getFirstChild().getAttributes();
+
+			String version = votAttrs.getNamedItem("version").getTextContent();
+			if (version != JAXB_VOTABLE_VERSION) {
+				Log.LOGGER.info("VOTable version is " + version + ", changing VOTable svhema to "
+						+ JAXB_VOTABLE_VERSION);
+				votAttrs.getNamedItem("xmlns").setTextContent(VOTABLE_SHEMA + JAXB_VOTABLE_VERSION);
+			} else {
+				Log.LOGGER.info("VOTable version is " + version + ", everything is ok.");
+			}
+
+			// write the content into xml file
+			Transformer transformer = TransformerFactory.newInstance().newTransformer();
+			StreamResult result = new StreamResult(new File(voTablePath));
+			transformer.transform(new DOMSource(doc), result);
+
+		} catch (ParserConfigurationException pce) {
+			throw new Exception("Configuration error when parsing XML file " + voTablePath, pce);
+		} catch (TransformerException tfe) {
+			throw new Exception("Can not change VOTable version in XML file " + voTablePath, tfe);
+		} catch (IOException ioe) {
+			throw new Exception("Can read/write the XML file " + voTablePath, ioe);
+		} catch (SAXException sae) {
+			throw new Exception("Can not parse the XML file " + voTablePath, sae);
+		}
+	}
+}
--
libgit2 0.21.2