/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework 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 any later version.
 *
 * Nuts Framework 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 Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.core.oxm.adapter;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

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

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * StringAdapter adapts a Java String value to a DOM Element with the specified
 * property name containing the String's text. e.g. a property
 * 
 * <pre>
 * String getFoo() {
 * 	return &quot;My Text!&quot;;
 * }
 * </pre>
 * 
 * will appear in the result DOM as: <foo>MyText!</foo>
 * 
 * Subclasses may override the getStringValue() method in order to use
 * StringAdapter as a simplified custom XML adapter for Java types. A subclass
 * can enable XML parsing of the value string via the setParseStringAsXML()
 * method and then override getStringValue() to return a String containing the
 * custom formatted XML.
 * 
 */
public class XmlStringAdapter extends AbstractElementAdapter {

	public XmlStringAdapter() {
	}

	public XmlStringAdapter(AdapterFactory adapterFactory, NodeAdapter parent,
			String propertyName, String value) {
		setContext(adapterFactory, parent, propertyName, value);
	}

	/**
	 * Get the object to be adapted as a String value.
	 * <p/>
	 * This method can be overridden by subclasses that wish to use
	 * StringAdapter as a simplified customizable XML adapter for Java types. A
	 * subclass can enable parsing of the value string as containing XML text
	 * via the setParseStringAsXML() method and then override getStringValue()
	 * to return a String containing the custom formatted XML.
	 */
	protected String getStringValue() {
		return getPropertyValue().toString();
	}

	protected List<Node> buildChildAdapters() {
		Node node;
		// Parse the String to a DOM, then proxy that as our child
		node = parseXmlString();
		node = getAdapterFactory().proxyNode(this, node);

		List<Node> children = new ArrayList<Node>(1);
		children.add(node);
		return children;
	}

	protected Node parseXmlString() {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			Document doc = db.parse(new InputSource(new StringReader(
					getStringValue())));
			return doc;
		}
		catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}
		catch (SAXException e) {
			throw new RuntimeException(e);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
}
