/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.resource.internal.mbean;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.management.MBeanException;


import org.ow2.jonas.deployment.common.lib.JEntityResolver;
import org.ow2.jonas.deployment.rar.ConnectorDTDs;
import org.ow2.jonas.deployment.rar.ConnectorSchemas;
import org.ow2.jonas.deployment.rar.JonasConnectorDTDs;
import org.ow2.jonas.deployment.rar.JonasConnectorSchemas;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;

/**
 * A RAR specific MBean which provides the schemas and EntityResolver
 * needed to validate a jonas-ra.xml file or an ra.xml file.
 * @author Patrick Smith
 * @author Greg Lapouchnian
 */
public class RarConfigMBean extends ArchiveConfigMBean {

    /**
     * A default constructor which calls the parent constructor.
     * @throws MBeanException from the super class.
     */
    public RarConfigMBean() throws MBeanException {
        super();
    }

    /**
     * Returns an EntityResolver for the schemas and dtds of
     * ra.xml and jonas-ra.xml.
     * @return an EntityResolver for the schemas and dtds
     * for ra.xml and jonas-ra.xml.
     */
    public EntityResolver getEntityResolver() {
        JEntityResolver jer = new JEntityResolver();

        // add both the generic and Jonas-specific schemas
        jer.addSchemas(new ConnectorSchemas());
        jer.addSchemas(new JonasConnectorSchemas());

        // add the connector DTDs
        jer.addDtds(new ConnectorDTDs());
        jer.addDtds(new JonasConnectorDTDs());

        return jer;
    }

    /**
     * Get a list of schemas available for RARs.
     * @return a list of schemas for RAR validation.
     */
    protected List getSchemaList() {
        // check if this schemas is part of connector schemas
        List schemas = new ArrayList();
        schemas.addAll(new ConnectorSchemas().getlocalSchemas());
        schemas.addAll(new JonasConnectorSchemas().getlocalSchemas());
        return schemas;
    }

    public void updateXML(String archiveName, Map map) throws Exception {
        String xmlFilePath = "META-INF/jonas-ra.xml";
        Document doc = extractDocument(archiveName, xmlFilePath);

        Node poolParams = getPoolParams(doc);
        TreeMap poolNames = getPoolTagMap();
        if (poolParams != null) {
            NodeList poolChildren = poolParams.getChildNodes();
            for (int i = 0; i < poolChildren.getLength(); i++) {
                String name = poolChildren.item(i).getNodeName();
                if (poolNames.containsKey(name)) {
                    if (poolChildren.item(i).getFirstChild() != null
                            && poolChildren.item(i).getFirstChild()
                                    .getNodeType() == Node.TEXT_NODE) {
                        poolChildren.item(i).getFirstChild().setNodeValue(
                                (String) map.get(poolNames.get(name)));
                    } else {
                        poolChildren.item(i).appendChild(
                                doc.createTextNode((String) map.get(poolNames
                                        .get(name))));
                    }
                }
            }
        }

        Node jdbcParams = getJDBCParams(doc);
        TreeMap jdbcNames = getJDBCTagMap();
        if (jdbcParams != null) {
            NodeList jdbcChildren = jdbcParams.getChildNodes();
            for (int j = 0; j < jdbcChildren.getLength(); j++) {
                String jdbcName = jdbcChildren.item(j).getNodeName();
                if (jdbcNames.containsKey(jdbcName)) {
                    if (jdbcChildren.item(j).getFirstChild() != null
                            && jdbcChildren.item(j).getFirstChild()
                                    .getNodeType() == Node.TEXT_NODE) {
                        jdbcChildren.item(j).getFirstChild().setNodeValue(
                                (String) map.get(jdbcNames.get(jdbcName)));
                    } else {
                        jdbcChildren.item(j).appendChild(
                                doc.createTextNode((String) map.get(jdbcNames
                                        .get(jdbcName))));
                    }
                }
            }
        }

        verifyDocument(doc);
        saveXML(archiveName, xmlFilePath, doc);
    }

    protected TreeMap getJDBCTagMap() {
        TreeMap names = new TreeMap();
        names.put("jdbc-check-level", "jdbcConnCheckLevel");
        names.put("jdbc-test-statement", "jdbcTestStatement");
        return names;
    }

    protected TreeMap getPoolTagMap() {
        TreeMap names = new TreeMap();
        names.put("pool-max-age", "connMaxAge");
        names.put("pool-max-opentime", "maxOpentime");
        names.put("pool-max", "maxSize");
        names.put("pool-min", "minSize");
        names.put("pool-max-waittime", "maxWaitTime");
        names.put("pool-max-waiters", "maxWaiters");
        names.put("pool-sampling-period", "samplingPeriod");
        return names;
    }

    protected Node getPoolParams(Document doc) {
        if (doc.getElementsByTagName("pool-params").getLength() == 0) {
            return null;
        } else {
            return doc.getElementsByTagName("pool-params").item(0);
        }
    }

    protected Node getJDBCParams(Document doc) {
        if (doc.getElementsByTagName("jdbc-conn-params").getLength() == 0) {
            return null;
        } else {
            return doc.getElementsByTagName("jdbc-conn-params").item(0);
        }
    }
}
