package org.apache.ws.scout.registry;

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

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

import javax.xml.registry.BulkResponse;
import javax.xml.registry.BusinessLifeCycleManager;
import javax.xml.registry.BusinessQueryManager;
import javax.xml.registry.JAXRException;
import javax.xml.registry.LifeCycleManager;
import javax.xml.registry.RegistryService;
import javax.xml.registry.infomodel.Association;
import javax.xml.registry.infomodel.ClassificationScheme;
import javax.xml.registry.infomodel.Concept;
import javax.xml.registry.infomodel.Key;
import javax.xml.registry.infomodel.Organization;
import javax.xml.registry.infomodel.RegistryPackage;

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

/**
 * Additional BusinessQueryManager test methods.
 * 
 * @author Tom Cunningham (tcunning@apache.org)
 */
public class BusinessQueryManager2Test extends BaseTestCase {
	RegistryService rs, rs2;
	private BusinessQueryManager bqm, bqm2;
	private BusinessLifeCycleManager blm, blm2;
	Collection associationKeys = null;
	
    @Before
    public void setUp() {
        super.setUp();
        login();
        loginSecondUser();
		try {
			rs = connection.getRegistryService();
	    	bqm = rs.getBusinessQueryManager();
	    	blm = rs.getBusinessLifeCycleManager();
	        
	    	rs2 = connection2.getRegistryService();
	        blm2 = rs2.getBusinessLifeCycleManager();
	        bqm2 = rs2.getBusinessQueryManager();

		} catch (JAXRException e) {
			fail(e.getMessage());
		}
    }
    
    @After
    public void tearDown() {
        super.tearDown();
    }
	
    @Test
	public void testGetRegistryObjects() {
        login();
        try {
        	RegistryService rs = connection.getRegistryService();

        	BusinessQueryManager bqm = rs.getBusinessQueryManager();
        	@SuppressWarnings("unused")
			BusinessLifeCycleManager blm = rs.getBusinessLifeCycleManager();
        	@SuppressWarnings("unused")
			BulkResponse br = bqm.getRegistryObjects();
		} catch (JAXRException e) {
			e.printStackTrace();
		}
	}
	
    @Test
	public void testFindCallerAssociations() {
        BulkResponse br = null;
    	try {
        	// Are there any associations so far?
            try {
	            br = bqm.findCallerAssociations(null,
	        			new Boolean(true),
	        			new Boolean(true),
	        			null);
	            if (br.getCollection().size() != 0) {
	            	fail("Should not reach here - no associations created yet.");
	            }
	        } catch (Exception e) {
            }

            String orgOne = "Organization One";
            String orgTwo = "Organization Two";
            Organization source = blm.createOrganization(blm.createInternationalString(orgOne));
            Organization target = blm2.createOrganization(blm2.createInternationalString(orgTwo));
	            
			Collection orgs = new ArrayList();
			orgs.add(source);
			br = blm.saveOrganizations(orgs);
			if (br.getExceptions() != null)
			{
				fail("Save Organization failed");
			}
			
			Collection sourceKeys = br.getCollection();
			Iterator iter = sourceKeys.iterator();
			Key savekey = null;
			while (iter.hasNext())
			{
				savekey = (Key) iter.next();
			}
			String sourceid  = savekey.getId();
			Organization queried = (Organization) bqm.getRegistryObject(sourceid, LifeCycleManager.ORGANIZATION);
			assertNotNull("Source Org", queried.getName().getValue());
            
			Collection orgstwo = new ArrayList();
			orgstwo.add(target);
            br = blm2.saveOrganizations(orgstwo);
            if (br.getExceptions() != null)
			{
            	fail("Save Organizations failed");
            }
            Collection targetKeys = br.getCollection();
            iter = targetKeys.iterator();
            while (iter.hasNext())
            {
            	savekey = (Key) iter.next();
            }
            
            String targetid = savekey.getId();
            Organization targetOrg = (Organization) bqm2.getRegistryObject(targetid, LifeCycleManager.ORGANIZATION);
            assertNotNull("Target Org", targetOrg.getName().getValue());

            Concept associationType = null;            
            ClassificationScheme associationTypes =
                bqm.findClassificationSchemeByName(null, "AssociationType");
            Collection types = associationTypes.getChildrenConcepts();
            iter = types.iterator();
            Concept concept = null;
            while (iter.hasNext())
            {
            	concept = (Concept) iter.next();
            	if (concept.getName().getValue().equals("Implements"))
            	{
            		associationType = concept;
            	}
            }
            
            Association a = blm.createAssociation(targetOrg, associationType);
            a.setSourceObject(queried);
            blm2.confirmAssociation(a);

            // publish the Association
            Collection associations = new ArrayList();	
            associations.add(a);
            br = blm2.saveAssociations(associations, false);

            if (br.getExceptions() != null)
            {
            		fail("Save association failed");
            }

            associationKeys = br.getCollection();
            iter = associationKeys.iterator();

            Collection aTypes = new ArrayList();
            aTypes.add(associationType);
            
            br = bqm.findCallerAssociations(null,
            			new Boolean(true),
            			new Boolean(true),
            			aTypes);
            /*
            if (br.getExceptions() == null)
            {
            	Collection results = br.getCollection();
            	if (results.size() > 0)
            	{
            		iter = results.iterator();
            		while (iter.hasNext())
            		{
            			Association a1 = (Association) iter.next();
            			System.out.println("Association : " + a1.toString());
            		}
            	}
            }
            */
		} catch (JAXRException e) {
			fail(e.getMessage());
		}		
	}
	
    @Test
	public void testFindRegistryPackages() {
        login();
        try {
        	RegistryService rs = connection.getRegistryService();

        	BusinessQueryManager bqm = rs.getBusinessQueryManager();
        	BusinessLifeCycleManager blm = rs.getBusinessLifeCycleManager();

        	Concept type = bqm.findConceptByPath("/AssociationType/RelatedTo");

        	ArrayList namePatterns = new ArrayList();
        	namePatterns.add("%foo%");
        	
        	ArrayList classifications = new ArrayList();
        	classifications.add(type);
        	
        	BulkResponse br = bqm.findRegistryPackages(null, namePatterns, classifications, null);
        	fail("findRegistryPackages is currently unsupported");
        	
        	assertEquals(null, br.getExceptions());
        	assertEquals(br.getCollection().size(), 0);
        	
        	RegistryPackage foopack = blm.createRegistryPackage("foo");
        	RegistryPackage barpack = blm.createRegistryPackage("bar");
        	Association assoc = blm.createAssociation(barpack, type);
        	foopack.addAssociation(assoc);
        	ArrayList al = new ArrayList();
            al.add(foopack);
        	br = blm.saveObjects(al);
        	assertEquals(null, br.getExceptions());
        	
        	
        	br = bqm.findRegistryPackages(null, namePatterns, classifications, null);
        	assertEquals(null, br.getExceptions());
        	assertEquals(br.getCollection(), 1);
        
        } catch (JAXRException e) {
        	e.printStackTrace();
		}				
	}
}
