/**
 *
 * Copyright 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.ws.scout.registry.qa;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.xml.registry.BulkResponse;
import javax.xml.registry.BusinessQueryManager;
import javax.xml.registry.FindQualifier;
import javax.xml.registry.JAXRException;
import javax.xml.registry.JAXRResponse;
import javax.xml.registry.RegistryService;
import javax.xml.registry.infomodel.Association;
import javax.xml.registry.infomodel.Concept;
import javax.xml.registry.infomodel.Key;
import javax.xml.registry.infomodel.Organization;
import javax.xml.registry.infomodel.RegistryObject;

import junit.framework.JUnit4TestAdapter;

import org.apache.ws.scout.BaseTestCase;
import org.apache.ws.scout.Creator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;


/**
 * Tests Publish, Delete (and indirectly, find) for associations.
 * 
 * You can comment out the deletion portion and use Open source UDDI Browser
 * <http://www.uddibrowser.org> to check your intermediate results.
 * 
 * Based on query/publish tests written by <a href="mailto:anil@apache.org">Anil
 * Saldhana</a>.
 * 
 * @author <a href="mailto:dbhole@redhat.com">Deepak Bhole</a>
 * @author <a href="mailto:anil@apache.org">Anil Saldhana</a>
 * 
 * @since Sep 27, 2005
 */
public class JAXR030AssociationsTest extends BaseTestCase {

	private BusinessQueryManager bqm = null;

	String associationType = "AssociationType/RelatedTo";
	private static String tempSrcOrgName = "Apache Source Org -- APACHE SCOUT TEST";
	private static String tempTgtOrgName = "Apache Target Org -- APACHE SCOUT TEST";

	Organization sOrg, tOrg;

    @Before
	public void setUp() {
		super.setUp();
	}

    @After
	public void tearDown() {
		super.tearDown();
	}

	/**
	 * Tests publishing and deleting of associations.
	 * 
	 * Do not break this into testPublish(), testDelete(), etc. Order is
	 * important, and not all jvms can guarantee order since the JUnit framework
	 * uses getMethods() to gather test methods, and getMethods() does not
	 * guarantee order.
	 */
    @Test
	public void testPublishFindAndDeleteAssociation() {
		login();
		try {
			RegistryService rs = connection.getRegistryService();
			bqm = rs.getBusinessQueryManager();
			blm = rs.getBusinessLifeCycleManager();
            Creator creator = new Creator(blm);

			System.out.println("\nCreating temporary organizations...\n");
            Organization org1 = creator.createOrganization(tempSrcOrgName);
            Organization org2 = creator.createOrganization(tempTgtOrgName);
            Collection<Organization> organizations = new ArrayList<Organization>();
            organizations.add(org1);
            organizations.add(org2);
            blm.saveOrganizations(organizations);
           
			System.out.println("\nSearching for newly created organizations...\n");
			ArrayList<Organization> orgs = findTempOrgs();
			sOrg = orgs.get(0);
			tOrg = orgs.get(1);

			System.out.println("\nCreating association...\n");
			createAssociation(sOrg, tOrg);

			// All created ... now try to delete.
			findAndDeleteAssociation();

		} catch (JAXRException e) {
			e.printStackTrace();
			fail(e.getMessage());
		} finally {

		}
	}
    
	private void createAssociation(Organization sOrg, Organization tOrg)
			throws JAXRException {

		Concept type = bqm.findConceptByPath(associationType);
		Association association = blm.createAssociation(tOrg, type);
		sOrg.addAssociation(association);

		ArrayList<Association> associations = new ArrayList<Association>();
		associations.add(association);

		BulkResponse br = blm.saveAssociations(associations, true);
		if (br.getStatus() == JAXRResponse.STATUS_SUCCESS) {
			System.out.println("Association Saved");
			Collection coll = br.getCollection();
			Iterator iter = coll.iterator();
			while (iter.hasNext()) {
				System.out.println("Saved Key=" + iter.next());
			}// end while
		} else {
			System.err.println("JAXRExceptions " + "occurred during save:");
			Collection exceptions = br.getExceptions();
			Iterator iter = exceptions.iterator();
			while (iter.hasNext()) {
				Exception e = (Exception) iter.next();
				System.err.println(e.toString());
			}
            deleteTempOrgs();
		}
	}

	private void findAndDeleteAssociation() throws JAXRException {

		String sOrgID = sOrg.getKey().getId();
		String tOrgID = tOrg.getKey().getId();

		Collection<String> findQualifiers = new ArrayList<String>();
		findQualifiers.add(FindQualifier.SORT_BY_NAME_ASC);

		Concept type = bqm.findConceptByPath(associationType);
		ArrayList<Concept> conceptTypes = new ArrayList<Concept>(1);
		conceptTypes.add(type);

		BulkResponse br = bqm.findAssociations(findQualifiers, sOrgID, tOrgID,
				conceptTypes);
		Collection associations = br.getCollection();

		if (associations == null) {
			System.out.println("\n-- Matched 0 orgs");
            fail("Expected 1 association");

		} else {
			System.out.println("\n-- Matched " + associations.size()
					+ " associations --\n");
            assertEquals(1,associations.size());

			// then step through them
			for (Iterator conceptIter = associations.iterator(); conceptIter
					.hasNext();) {
				Association a = (Association) conceptIter.next();

				System.out.println("Id: " + a.getKey().getId());
				System.out.println("Name: " + a.getName().getValue());

				// Print spacer between messages
				System.out.println(" --- ");

				deleteAssociation(a.getKey());

				System.out.println("\n ============================== \n");
			}
		}
	}

	private void deleteAssociation(Key key) throws JAXRException {

		String id = key.getId();

		System.out.println("\nDeleting association with id " + id + "\n");

		Collection<Key> keys = new ArrayList<Key>();
		keys.add(key);
		BulkResponse response = blm.deleteAssociations(keys);

        assertEquals(BulkResponse.STATUS_SUCCESS, response.getStatus());
		Collection exceptions = response.getExceptions();
		if (exceptions == null) {
			Collection retKeys = response.getCollection();
			Iterator keyIter = retKeys.iterator();
			javax.xml.registry.infomodel.Key orgKey = null;
			if (keyIter.hasNext()) {
				orgKey = (javax.xml.registry.infomodel.Key) keyIter.next();
				id = orgKey.getId();
				System.out
						.println("Association with ID=" + id + " was deleted");
			}
		}
	}

	private ArrayList<Organization> findTempOrgs() throws JAXRException {

		ArrayList<Organization> toReturn = new ArrayList<Organization>(2);
        toReturn.add(null);
        toReturn.add(null);

		// Define find qualifiers and name patterns
		Collection<String> findQualifiers = new ArrayList<String>();
		findQualifiers.add(FindQualifier.SORT_BY_NAME_ASC);
		Collection<String> namePatterns = new ArrayList<String>();
		if ("3.0".equals(uddiversion)) {
			namePatterns.add(tempSrcOrgName);
			namePatterns.add(tempTgtOrgName);
		} else {
			namePatterns.add("%" + tempSrcOrgName + "%");
			namePatterns.add("%" + tempTgtOrgName + "%");
		}
		// Find based upon qualifier type and values
		System.out.println("\n-- searching the registry --\n");
		BulkResponse response = bqm.findOrganizations(findQualifiers,
				namePatterns, null, null, null, null);

		// check how many organisation we have matched
		Collection orgs = response.getCollection();
		if (orgs == null) {
			System.out.println("\n-- Matched 0 orgs");

		} else {
			System.out.println("\n-- Matched " + orgs.size()
					+ " organisations --\n");

			// then step through them
			for (Iterator orgIter = orgs.iterator(); orgIter.hasNext();) {
				Organization org = (Organization) orgIter.next();

				System.out.println("Org name: " + getName(org));
				System.out.println("Org description: " + getDescription(org));
				System.out.println("Org key id: " + getKey(org));

				if (getName(org).indexOf(tempSrcOrgName) > -1) {
					toReturn.add(0, org);
				} else {
					toReturn.add(1, org);
				}

				// Print spacer between organizations
				System.out.println("\n ============================== \n");
			}
		}// end else

		return toReturn;
	}

	private void deleteTempOrgs() {

		try {

			Key sOrgKey = sOrg.getKey();
			Key tOrgKey = tOrg.getKey();

			System.out.println("\nDeleting temporary organizations with ids "
					+ sOrgKey + " and " + tOrgKey + "\n");

			Collection<Key> keys = new ArrayList<Key>();
			keys.add(sOrgKey);
			keys.add(tOrgKey);
			BulkResponse response = blm.deleteOrganizations(keys);

			Collection exceptions = response.getExceptions();
			if (exceptions == null) {
				Collection retKeys = response.getCollection();
				Iterator keyIter = retKeys.iterator();
				Key orgKey = null;
				while (keyIter.hasNext()) {
					orgKey = (javax.xml.registry.infomodel.Key) keyIter.next();
					String id = orgKey.getId();
					System.out.println("Organization with ID=" + id
							+ " was deleted");
				}
			}
		} catch (JAXRException jaxre) {
			jaxre.printStackTrace();
		}
	}

	private static String getName(RegistryObject ro) throws JAXRException {
		if (ro != null && ro.getName() != null) {
			return ro.getName().getValue();
		}
		return "";
	}

	private static String getDescription(RegistryObject ro)
			throws JAXRException {
		if (ro != null && ro.getDescription() != null) {
			return ro.getDescription().getValue();
		}
		return "";
	}

	private static String getKey(RegistryObject ro) throws JAXRException {
		if (ro != null && ro.getKey() != null) {
			return ro.getKey().getId();
		}
		return "";
	}
    
    public static junit.framework.Test suite() {
        return new JUnit4TestAdapter(JAXR030AssociationsTest.class);
    }
}
