/*
 * 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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * ProxyNodeAdapter is a read-only delegating adapter for objects which already
 * implement the Node interface. All methods are proxied to the underlying Node
 * except getParent(), getNextSibling() and getPreviousSibling(), which are
 * implemented by the abstract adapter node to work with the parent adapter.
 */
public abstract class ProxyNodeAdapter extends AbstractNodeAdapter {

	private static Log log = LogFactory.getLog(ProxyNodeAdapter.class);

	public ProxyNodeAdapter(AdapterFactory factory, NodeAdapter parent,
			Node value) {
		setContext(factory, parent, "proxy", value);
		if (log.isDebugEnabled()) {
			log.debug("proxied node is: " + value);
			log.debug("node class is: " + value.getClass());
			log.debug("node type is: " + value.getNodeType());
			log.debug("node name is: " + value.getNodeName());
		}
	}

	/**
	 * Get the proxied Node value
	 */
	protected Node node() {
		return (Node)getPropertyValue();
	}

	/**
	 * Get and adapter to wrap the proxied node.
	 * 
	 * @param node
	 */
	protected Node wrap(Node node) {
		return getAdapterFactory().proxyNode(this, node);
	}

	protected NamedNodeMap wrap(NamedNodeMap nnm) {
		return getAdapterFactory().proxyNamedNodeMap(this, nnm);
	}

	// protected NodeList wrap( NodeList nl ) { }

	// protected Node unwrap( Node child ) {
	// return ((ProxyNodeAdapter)child).node();
	// }

	// Proxied Node methods

	public String getNodeName() {
		return node().getNodeName();
	}

	public String getNodeValue() throws DOMException {
		return node().getNodeValue();
	}

	public short getNodeType() {
		return node().getNodeType();
	}

	public NamedNodeMap getAttributes() {
		NamedNodeMap nnm = wrap(node().getAttributes());
		return nnm;
	}

	public boolean hasChildNodes() {
		return node().hasChildNodes();
	}

	public boolean isSupported(String s, String s1) {
		// Is this ok? What kind of features are they asking about?
		return node().isSupported(s, s1);
	}

	public String getNamespaceURI() {
		return node().getNamespaceURI();
	}

	public String getPrefix() {
		return node().getPrefix();
	}

	public String getLocalName() {
		return node().getLocalName();
	}

	public boolean hasAttributes() {
		return node().hasAttributes();
	}

	// End proxied Node methods

	public String toString() {
		return "ProxyNode for: " + node();
	}
}
