/*
 * Copyright (c) 2013 Red Hat, Inc. and/or its affiliates.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *      Brad Davis - bradsdavis@gmail.com - Initial API and implementation
*/
package org.jboss.windup.util.xml;

import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * XML stream reader which, after parsing, can tell which node appeared on which line.
 */
public class LocationAwareXmlReader
{
	private static final SAXParserFactory factory = SAXParserFactory.newInstance();
	private static final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();

	static {
		factory.setNamespaceAware(true);
		factory.setValidating(false);
		factory.setXIncludeAware(false);
	}

	public static Document readXML(final InputStream is) throws IOException, SAXException {
		final Document doc;
		SAXParser parser;
		try {
			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			parser = factory.newSAXParser();
			doc = docBuilder.newDocument();
		}
		catch (final ParserConfigurationException e) {
			throw new RuntimeException("Can't create SAX parser / DOM builder.", e);
		}

		final DefaultHandler handler = new LocationAwareContentHandler(doc);

		parser.parse(is, handler);
		return doc;
	}

	public static Integer getLineNumber(Node node) {
		return (Integer) node.getUserData(LocationAwareContentHandler.LINE_NUMBER_KEY_NAME);
	}

	public static Set<String> getNamespaces(Document doc) {
		return (Set<String>) doc.getUserData(LocationAwareContentHandler.NAMESPACE_KEY_NAME);
	}
}
