/**
 * Copyright (c) 2005 Red Hat, Inc. All rights reserved.
 *
 * 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
 *
 * Component of: Red Hat Application Server
 *
 * Initial Developers: Gregory Lapouchnian
 *                     Patrick Smith
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */
package olstore.client;

import java.net.PasswordAuthentication;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.xml.registry.BulkResponse;
import javax.xml.registry.BusinessQueryManager;
import javax.xml.registry.Connection;
import javax.xml.registry.ConnectionFactory;
import javax.xml.registry.JAXRException;
import javax.xml.registry.RegistryService;
import javax.xml.registry.infomodel.ExternalLink;
import javax.xml.registry.infomodel.Organization;
import javax.xml.registry.infomodel.Service;
import javax.xml.registry.infomodel.ServiceBinding;
import javax.xml.registry.infomodel.SpecificationLink;

/**
 * Connect to the UDDI registry and retrieve WSDL URLs for the OLstore client.
 */
public class RegistryConnector {

    /** A connection to the UDDI registry. */
    private Connection connection;

    /** Used to send queries to the registry. */
    private BusinessQueryManager bqm;

    /** The list of URLs found for the OLStore specials endpoint. */
    private List specialsWSDLLocations;

    /** The list of URLs found for the OLStore shopping cart endpoint. */
    private List cartWSDLLocations;

    /**
     * Prepare a registry connector to query the UDDI registry for WSDL
     * information.
     */
    public RegistryConnector() {
        specialsWSDLLocations = new ArrayList();
        cartWSDLLocations = new ArrayList();
    }

    /**
     * Create a connection and retrieve the endpoint locations.
     * @throws Exception if an error occurs while connecting and querying the
     * registry
     */
    public void retrieveWSDLLocations() throws Exception {
        // only connect to the registry if the WSDL location lists are empty
        if (cartWSDLLocations.isEmpty() || specialsWSDLLocations.isEmpty()) {
            try {
                makeConnection();
                findWSDLLocations();
                closeConnection();
            } catch (JAXRException e) {
                throw new Exception(
                        "Could not retrieve WSDL locations from the UDDI registry.\n"
                                + e.getMessage());
            }
        }
    }

    /**
     * Close the connection to the UDDI registry.
     * @throws JAXRException if the connection could not be closed
     */
    public void closeConnection() throws JAXRException {
        connection.close();
    }

    /**
     * Create a connection to the UDDI registry.
     * @throws Exception if there is a problem creating a connection.
     */
    public void makeConnection() throws Exception {

        Configure config = new Configure();

        Properties props = new Properties();
        props.setProperty("javax.xml.registry.queryManagerURL", config.getProperty("queryURL"));
        props.setProperty("javax.xml.registry.lifeCycleManagerURL", config.getProperty("publishURL"));

        try {
            // Create the connection, passing it the configuration properties
            ConnectionFactory factory = ConnectionFactory.newInstance();
            factory.setProperties(props);
            connection = factory.createConnection();

            // Get registry service and managers
            RegistryService rs = connection.getRegistryService();

            // Get manager capabilities from registry service
            bqm = rs.getBusinessQueryManager();

            // Set client authorization information for privileged registry
            // operations
            PasswordAuthentication passwdAuth = new PasswordAuthentication(
                    config.getProperty("user"), config.getProperty("pass")
                            .toCharArray());
            Set creds = new HashSet();
            creds.add(passwdAuth);

            // Set credentials on the JAXR provider
            connection.setCredentials(creds);

            // Set communication preference
            connection.setSynchronous(true);

        } catch (Exception e) {
            // try to close the connection if it was created
            if (connection != null) {
                try {
                    connection.close();
                } catch (JAXRException je) {
                    throw je;
                }
            }
            throw e;
        }
    }

    /**
     * Find all the endpoint URLs in the registry for OLStore.
     * @throws JAXRException if there is a problem with querying the registry
     */
    public void findWSDLLocations() throws JAXRException {

        Collection names = new ArrayList();
        String orgName = "Red Hat Olstore";
        names.add(orgName);

        BulkResponse br = bqm.findOrganizations(null, names, null, null, null,
                null);
        Iterator iter = br.getCollection().iterator();

        while (iter.hasNext()) {
            Organization org = (Organization) iter.next();
            Iterator serviceIter = org.getServices().iterator();

            while (serviceIter.hasNext()) {
                Service service = (Service) serviceIter.next();

                // get the service bindings
                Collection serviceBindings = service.getServiceBindings();

                Iterator sbIter = serviceBindings.iterator();
                while (sbIter.hasNext()) {
                    ServiceBinding serviceBinding = (ServiceBinding) sbIter
                            .next();

                    // Get a collection of SpecificationLinks
                    Collection specificationLinks = serviceBinding
                            .getSpecificationLinks();

                    Iterator linkIter = specificationLinks.iterator();
                    while (linkIter.hasNext()) {
                        SpecificationLink specificationLink = (SpecificationLink) linkIter
                                .next();

                        // Get a collection of ExternalLinks 
                        Collection externalLinks = specificationLink
                                .getExternalLinks();

                        Iterator elinkIter = externalLinks.iterator();
                        while (elinkIter.hasNext()) {
                            ExternalLink externalLink = (ExternalLink) elinkIter.next();
                            String externalURI = externalLink.getExternalURI();

                            // put this WSDL URL into the appropriate list
                            if (service.getName().getValue().equals("Red Hat Olstore - Shopping cart")) {
                                cartWSDLLocations.add(externalURI);
                            } else {
                                specialsWSDLLocations.add(externalURI);
                            }

                        }
                    }
                }
            }
        }

    }

    /**
     * Get the list of shopping cart endpoint locations.
     *
     * @return Returns the cartWSDLLocations.
     */
    public List getCartWSDLLocations() {
        return cartWSDLLocations;
    }

    /**
     * Get the list of OLStore endpoint locations.
     *
     * @return Returns the specialsWSDLLocations.
     */
    public List getSpecialsWSDLLocations() {
        return specialsWSDLLocations;
    }
}
