/*
 * Copyright  1999-2004 The Apache Software Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.savan.configuration;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.llom.factory.OMXMLBuilderFactory;
import org.apache.savan.SavanConstants;
import org.apache.savan.SavanException;
import org.apache.savan.filters.Filter;
import org.apache.savan.storage.SubscriberStore;
import org.apache.savan.subscribers.AbstractSubscriber;
import org.apache.savan.subscribers.Subscriber;
import org.apache.savan.util.UtilFactory;

/**
 * This is responsible for loading Savan configuration data from a resource
 * for e.g. from a savan-config.xml fie
 */
public class ConfigurationManager {
	
	private HashMap protocolMap = null;
	private HashMap subscriberStoreNamesMap = null;
	private HashMap filterMap = null;
	private HashMap subscribersMap = null;
	
	private final String SAVAN_CONFIG = "savan-config";
	private final String PROTOCOLS = "protocols";
	private final String PROTOCOL = "protocol";
	private final String NAME = "name";
	private final String UTIL_FACTORY = "utilFactory";
	private final String MAPPING_RULES = "mapping-rules";
	private final String ACTION = "mapping-rules";
	private final String SOAP_ACTION = "mapping-rules";
	private final String SUBSCRIBER_STORES = "subscriberStores";
	private final String SUBSCRIBER_STORE = "subscriberStore";
	private final String FILTERS = "filters";
	private final String FILTER = "filter";
	private final String KEY = "key";
	private final String CLASS = "class";
	private final String IDENTIFIER = "identifier";
	private final String SUBSCRIBERS = "subscribers";
	private final String SUBSCRIBER = "subscriber";
	private final String URL_APPENDER = "urlAppender";
	private final String DEFAULT_SUBSCRIBER = "defaultSubscriber";
	private final String DEFAULT_FILTER = "defaultFilter";
	
	
	public ConfigurationManager () {
		protocolMap = new HashMap ();
		subscriberStoreNamesMap = new HashMap ();
		filterMap = new HashMap ();
		subscribersMap = new HashMap ();
	}
	
	/**
	 * To load configurations from a savan-config.xml file in the classpath.
	 * 
	 * @throws SavanException
	 */
	public void configure () throws SavanException {
		ClassLoader classLoader = getClass().getClassLoader();

		configure(classLoader);
	}
	
	public void configure (ClassLoader classLoader) throws SavanException {
		InputStream in = classLoader.getResourceAsStream(SavanConstants.CONFIG_FILE);

		if (in==null)
			throw new SavanException ("Cannot find the savan configuration file. Initialation cannot continue.");
		
		configure(in);
	}
	
	/**
	 * To Load configurations from a file.
	 * 
	 * @param file
	 * @throws SavanException
	 */
	public void configure (File file) throws SavanException {
		try {
			InputStream in = new FileInputStream (file);
			configure(in);
		} catch (IOException e) {
			throw new SavanException (e);
		}
	}
	
	/**
	 * To load configurations from a InputStream.
	 * 
	 * @param in
	 * @throws SavanException
	 */
	public void configure (InputStream in) throws SavanException {

		if (in==null) {
			String message = "Invalid InputStream.";
			throw new SavanException (message);
		}
		
		try {
			XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(in);
			OMFactory factory = OMAbstractFactory.getOMFactory();
			
			StAXOMBuilder builder = OMXMLBuilderFactory.createStAXOMBuilder(factory,parser);
			OMElement document = builder.getDocumentElement();
			
			if (document==null) {
				throw new SavanException ("Configuration XML does not have a document element");
			}
			
			processSavanConfig(document);
		} catch (Exception e) {
			throw new SavanException (e);
		} 
	}
	
	
	private void processSavanConfig (OMElement element) throws SavanException {
		if (!SAVAN_CONFIG.equals(element.getLocalName())) {
			throw new SavanException ("'savan-config'should be the document element of the savan configuration xml file");
		}
		
		OMElement protocolsElement = element.getFirstChildWithName(new QName (PROTOCOLS));
		if (protocolsElement==null) {
			throw new SavanException ("'protocols' element should be present, as a sub-element of the 'savan-config' element");
		}
		processProtocols(protocolsElement);
		
		OMElement subscriberStoresElement = element.getFirstChildWithName(new QName (SUBSCRIBER_STORES));
		if (subscriberStoresElement==null) {
			throw new SavanException ("'subscriberStores' element should be present, as a sub-element of the 'savan-config' element");
		}
		processSubscriberStores(subscriberStoresElement);
		
		OMElement filtersElement = element.getFirstChildWithName(new QName (FILTERS));
		if (subscriberStoresElement==null) {
			throw new SavanException ("'Filters' element should be present, as a sub-element of the 'savan-config' element");
		}
		processFilters (filtersElement);
		
		OMElement subscribersElement = element.getFirstChildWithName(new QName (SUBSCRIBERS));
		if (subscriberStoresElement==null) {
			throw new SavanException ("'Subscribers' element should be present as a sub-element of the 'savan-config' element");
		}
		processSubscribers (subscribersElement);
		
	}
	
	private void processProtocols (OMElement element) throws SavanException {
		Iterator protocolElementsIterator = element.getChildrenWithName(new QName (PROTOCOL));
		while (protocolElementsIterator.hasNext()) {
			OMElement protocolElement = (OMElement) protocolElementsIterator.next();
			processProtocol(protocolElement);
		}
	}
	
	private void processProtocol (OMElement element) throws SavanException {
		Protocol protocol = new Protocol ();
		
		OMElement nameElement = element.getFirstChildWithName(new QName (NAME));
		if (nameElement==null)
			throw new SavanException ("Protocol must have a 'Name' subelement");
		String name = nameElement.getText();
		protocol.setName(name);
		
		OMElement utilFactoryNameElement = element.getFirstChildWithName(new QName (UTIL_FACTORY));
		if (utilFactoryNameElement==null)
			throw new SavanException ("Protocol must have a 'UtilFactory' subelement");
		String utilFactoryName = utilFactoryNameElement.getText();
		Object obj = getObject(utilFactoryName);
		if (!(obj instanceof UtilFactory))
			throw new SavanException ("UtilFactory element" + utilFactoryName + "is not a subtype of the UtilFactory class");
		protocol.setUtilFactory((UtilFactory) obj);
		
		OMElement mappingRulesElement = element.getFirstChildWithName(new QName (MAPPING_RULES));
		if (mappingRulesElement==null)
			throw new SavanException ("Protocol must have a 'mappingRules' sub-element");
		processMappingRules (mappingRulesElement,protocol);
		
		OMElement defaultSubscriberElement = element.getFirstChildWithName(new QName (DEFAULT_SUBSCRIBER));
		if (defaultSubscriberElement==null)
			throw new SavanException ("Protocols must have a 'defaultSubscriber' sub-element");
		String defaultSubscriber = defaultSubscriberElement.getText();
		protocol.setDefaultSubscriber(defaultSubscriber);
		
		OMElement defaultFilterElement = element.getFirstChildWithName(new QName (DEFAULT_FILTER));
		if (defaultFilterElement==null)
			throw new SavanException ("Protocols must have a 'defaultFilter' sub-element");
		String defaultFilter = defaultFilterElement.getText();
		protocol.setDefaultFilter(defaultFilter);
		
		protocolMap.put(protocol.getName(),protocol);
	}
	
	private void processMappingRules (OMElement element, Protocol protocol) {
		
		MappingRules mappingRules = new MappingRules ();
		
		Iterator actionsIterator = element.getChildrenWithName(new QName (ACTION));
		while (actionsIterator.hasNext()) {
			OMElement actionElement = (OMElement) actionsIterator.next();
			String action = actionElement.getText();
			mappingRules.addAction(action);
		}
		
		Iterator SOAPActionsIterator = element.getChildrenWithName(new QName (SOAP_ACTION));
		while (SOAPActionsIterator.hasNext()) {
			OMElement SOAPactionElement = (OMElement) SOAPActionsIterator.next();
			String SOAPaction = SOAPactionElement.getText();
			mappingRules.addAction(SOAPaction);
		}
	}
	
	private void processSubscriberStores (OMElement element) throws SavanException {
		Iterator subscriberStoreElementsIterator = element.getChildrenWithName(new QName (SUBSCRIBER_STORE));
		while (subscriberStoreElementsIterator.hasNext()) {
			OMElement subscriberStoreElement = (OMElement) subscriberStoreElementsIterator.next();
			processSubscriberStore(subscriberStoreElement);
		}
	}
	
	private void processSubscriberStore (OMElement element) throws SavanException {
		OMElement keyElement = element.getFirstChildWithName(new QName (KEY));
		if (keyElement==null)
			throw new SavanException ("SubscriberStore must have a 'key' subelement");
		String key = keyElement.getText();
		
		OMElement classElement = element.getFirstChildWithName(new QName (CLASS));
		if (classElement==null)
			throw new SavanException ("SubscriberStore must have a 'Clazz' subelement'");
		
		String clazz = classElement.getText();
		
		//initialize the class to check weather it is value
		Object obj = getObject(clazz);
		
		if (!(obj instanceof SubscriberStore)) {
			String message = "Class " + clazz + " does not implement the  SubscriberStore interface.";
			throw new SavanException (message);
		}
		
		subscriberStoreNamesMap.put(key,clazz);
	}

	public HashMap getProtocolMap () {
		return protocolMap;
	}
	
	public Protocol getProtocol (String name) {
		return (Protocol) protocolMap.get(name);
	}
	
	public SubscriberStore getSubscriberStoreInstance (String key) throws SavanException {
		String name = (String) subscriberStoreNamesMap.get(key);
		return (SubscriberStore) getObject(name);
	}
	
	public Filter getFilterInstanceFromName (String name) throws SavanException {
		for (Iterator it=filterMap.keySet().iterator();it.hasNext();) {
			String key = (String) it.next();
			FilterBean filterBean = (FilterBean) filterMap.get(key);
			if (name.equals(filterBean.getName()))
				return (Filter) getObject(filterBean.getClazz());
		}
		
		return null;
	}
	
	public Filter getFilterInstanceFromId (String id) throws SavanException {
		FilterBean filterBean = (FilterBean) filterMap.get(id);
		String filterClass = filterBean.getClazz();
		if (filterClass==null)
			return null;
		
		return (Filter) getObject(filterClass);
	}
	
	private Object getObject (String className) throws SavanException {
	
		Object obj;
		try {
			Class c = Class.forName (className);
			 obj = c.newInstance();
		} catch (Exception e) {
			String message = "Can't instantiate the class:" + className;
			throw new SavanException (message,e);
		}
		 
		return obj;
	}
	
	private void processFilters (OMElement element) throws SavanException {
		Iterator filterElementsIterator = element.getChildrenWithName(new QName (FILTER));
		while (filterElementsIterator.hasNext()) {
			OMElement filterElement = (OMElement) filterElementsIterator.next();
			processFilter (filterElement);
		}
	}
	
	private void processFilter (OMElement element) throws SavanException {
		OMElement nameElement = element.getFirstChildWithName(new QName (NAME));
		OMElement identifierElement = element.getFirstChildWithName(new QName (IDENTIFIER));
		OMElement classElement = element.getFirstChildWithName(new QName (CLASS));
		
		if (nameElement==null)
			throw new SavanException ("Name element is not present within the Filter");
		if (identifierElement==null)
			throw new SavanException ("Identifier element is not present within the Filter");
		if (classElement==null)
			throw new SavanException ("Class element is not present within the Filter");
		
		String name = nameElement.getText();
		String identifier = identifierElement.getText();
		String clazz = classElement.getText();
		
		//initialize the class to check weather it is value
		Object obj = getObject(clazz);
		
		if (!(obj instanceof Filter)) {
			String message = "Class " + clazz + " does not implement the  Filter interface.";
			throw new SavanException (message);
		}
		
		FilterBean bean = new FilterBean ();
		bean.setName(name);
		bean.setIdentifier(identifier);
		bean.setClazz(clazz);
		
		filterMap.put(identifier,bean);
	}
	
	private void processSubscribers (OMElement element) throws SavanException {
		Iterator subscriberElementsIterator = element.getChildrenWithName(new QName (SUBSCRIBER));
		while (subscriberElementsIterator.hasNext()) {
			OMElement subscriberElement = (OMElement) subscriberElementsIterator.next();
			processSubscriber (subscriberElement);
		}
	}
	
	private void processSubscriber (OMElement element) throws SavanException {
		OMElement nameElement = element.getFirstChildWithName(new QName (NAME));
		OMElement urlAppenderElement = element.getFirstChildWithName(new QName (URL_APPENDER));
		OMElement classElement = element.getFirstChildWithName(new QName (CLASS));
		
		if (nameElement==null)
			throw new SavanException ("Name element is not present within the AbstractSubscriber");
		if (classElement==null)
			throw new SavanException ("Class element is not present within the Filter");
		
		String name = nameElement.getText();
		String clazz = classElement.getText();
		
		//initialize the class to check weather it is valid
		Object obj = getObject(clazz);
		
		if (!(obj instanceof Subscriber)) {
			String message = "Class " + clazz + " does not implement the  Subscriber interface.";
			throw new SavanException (message);
		}
		
		SubscriberBean bean = new SubscriberBean ();
		bean.setName(name);
		bean.setClazz(clazz);
		
		subscribersMap.put(name,bean);
	}
	
	public Map getSubscriberBeans () {
		return subscribersMap;
	}
	
	public Map getFilterBeans () {
		return filterMap;
	}
	
	public SubscriberBean getSubscriberBean (String subscriberName) {
		return (SubscriberBean) subscribersMap.get(subscriberName);
	}
	
	public AbstractSubscriber getSubscriberInstance (String subscriberName) throws SavanException {
		SubscriberBean subscriberBean = (SubscriberBean) subscribersMap.get(subscriberName);
		if (subscriberBean==null) {
			String message = "A subscriber with the name '" + subscriberName + "' was not found.";
			throw new SavanException (message);
		}
		
		return (AbstractSubscriber) getObject(subscriberBean.getClazz());
	}
	
}
