/********************************************************************
 * Copyright © 2008 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.util.logging;

import java.net.URL;
import java.util.Map;

import javax.xml.parsers.FactoryConfigurationError;

import org.apache.log4j.Appender;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.config.PropertySetter;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.xml.DOMConfigurator;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Allows for customized behavior of Log4J loading.
 * 
 * Mar 2, 2009
 * 
 * @author DNS   BOHMEG
 */
public class Log4JDOMConfigurator extends DOMConfigurator {

	private Map<String, String> shareableLoggers;

	public Map<String, String> getShareableLoggers() {
		return shareableLoggers;
	}

	public void setShareableLoggers(Map<String, String> shareableLoggers) {
		this.shareableLoggers = shareableLoggers;
	}

	public static void configure(URL url, Map shareableLoggers) throws FactoryConfigurationError {
		(new Log4JDOMConfigurator(shareableLoggers)).doConfigure(url, LogManager
				.getLoggerRepository());
	}

	public Log4JDOMConfigurator(Map shareableLoggers) {
		super();
		this.shareableLoggers = shareableLoggers;
	}

	protected boolean shouldCloseAppenders(Logger cat) {
		if (shareableLoggers != null && shareableLoggers.containsKey(cat.getName()))
			return false;

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.log4j.xml.DOMConfigurator#parseChildrenOfLoggerElement(org
	 * .w3c.dom.Element, org.apache.log4j.Logger, boolean)
	 */
	@Override
	protected void parseChildrenOfLoggerElement(Element catElement, Logger cat, boolean isRoot) {
		// code taken from Log4J 1.2.9

		PropertySetter propSetter = new PropertySetter(cat);

		// CISS
		if (shouldCloseAppenders(cat))
			cat.removeAllAppenders();
		// CISS

		NodeList children = catElement.getChildNodes();
		int length = children.getLength();
		for (int loop = 0; loop < length; loop++) {
			Node currentNode = children.item(loop);
			if (currentNode.getNodeType() == 1) {
				Element currentElement = (Element) currentNode;
				String tagName = currentElement.getTagName();
				if (tagName.equals("appender-ref")) {
					Element appenderRef = (Element) currentNode;
					Appender appender = findAppenderByReference(appenderRef);
					String refName = subst(appenderRef.getAttribute("ref"));
					if (appender != null)
						LogLog.debug("Adding appender named [" + refName + "] to category ["
								+ cat.getName() + "].");
					else
						LogLog.debug("Appender named [" + refName + "] not found.");
					cat.addAppender(appender);
				} else if (tagName.equals("level"))
					parseLevel(currentElement, cat, isRoot);
				else if (tagName.equals("priority"))
					parseLevel(currentElement, cat, isRoot);
				else if (tagName.equals("param"))
					setParameter(currentElement, propSetter);
			}
		}

		propSetter.activate();
	}
}
