/*
 * 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 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.Subscriber;
import org.apache.savan.util.UtilFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
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;

/**
 * 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 = "action";
    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 = protocol.getMappingRules();

        Iterator actionsIterator = element.getChildrenWithName(new QName(ACTION));
        while (actionsIterator.hasNext()) {
            OMElement actionElement = (OMElement)actionsIterator.next();
            String action = actionElement.getText();
            mappingRules.addRule(MappingRules.MAPPING_TYPE_ACTION, action);
        }

    }

    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 Subscriber 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 (Subscriber)getObject(subscriberBean.getClazz());
	}
	
}
