package org.apache.ws.scout.registry;

import static org.junit.Assert.assertNotNull;
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.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 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 (expected=JAXRException.class)
	public void testFindRegistryPackages() throws JAXRException{
        login();
        
        	RegistryService rs = connection.getRegistryService();

        	BusinessQueryManager bqm = rs.getBusinessQueryManager();
        	@SuppressWarnings("unused")
			BusinessLifeCycleManager blm = rs.getBusinessLifeCycleManager();

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

        	ArrayList namePatterns = new ArrayList();
        	namePatterns.add("%foo%");
        	
        	ArrayList classifications = new ArrayList();
        	classifications.add(type);

        	@SuppressWarnings("unused")
			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);
    }

}
