/*
 * 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.votable.votable;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;

import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE;
import eu.omp.irap.vespa.votable.utils.XmlUtils;
import eu.omp.irap.vespa.votable.votable.VOTableException.CantParseVOTableException;

/**
 * @author N. Jourdane
 */
public final class VOTableXMLParser {

	/**
	 * 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 REQUIRED_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";

	/** The path of the VOTable to verify the VOTable XML file. */
	private static final String VOTABLE_SHEMA = "http://www.ivoa.net/xml/VOTable/v";


	/** Constructor to hide the implicit public one. */
	private VOTableXMLParser() {
	}

	/**
	 * @param voTablePath The path of the VOTable.
	 * @return The VOTable resulting of the XML document.
	 * @throws CantParseVOTableException Can not modify XML VOTable or parse th VOTable.
	 */
	public static VOTABLE parse(String voTablePath) throws CantParseVOTableException {
		VOTABLE voTable;
		JAXBContext jc;
		try {
			changeVOTableSchemaLocation(voTablePath);
		} catch (IOException e) {
			throw new CantParseVOTableException(
					"Can not modify the VOTable XML file " + voTablePath,
					e);
		}
		try {
			System.out.println("VoTable path = " + voTablePath);
			jc = JAXBContext.newInstance(VOTableXMLParser.VOTABLE_MODEL_PACKAGE);
			Unmarshaller unmarshaller = jc.createUnmarshaller();
			System.out.println("unmarshaller = " + unmarshaller.toString());
			voTable = (VOTABLE) unmarshaller.unmarshal(new File(voTablePath));
			System.out.println("voTable = " + voTable.toString());
		} catch (JAXBException e) {
			throw new CantParseVOTableException("Can not get a VOTable object from the XML file.",
					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 IOException Can not read or write the XML file.
	 */
	private static void changeVOTableSchemaLocation(String voTablePath) throws IOException {
		Map<String, String> attributes = new HashMap<>();
		attributes.put("xmlns", VOTABLE_SHEMA + REQUIRED_VOTABLE_VERSION);
		XmlUtils.changeRootAttributes(voTablePath, attributes);
	}
}
