package com.fujitsu.iflowqa.testframe;

// iflow classes.
import com.fujitsu.iflow.common.BaseSystemEnvironment;
import java.awt.Point;
import java.util.Vector;

import org.apache.commons.httpclient.HttpURL;
import org.apache.webdav.lib.WebdavResource;
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.datatype.Name;
import org.uddi4j.datatype.binding.BindingTemplate;
import org.uddi4j.response.AuthToken;
import org.uddi4j.response.BindingDetail;
import org.uddi4j.response.BusinessInfo;
import org.uddi4j.response.BusinessList;
import org.uddi4j.response.ServiceInfo;
import org.uddi4j.response.ServiceList;
import org.uddi4j.response.TModelInfo;
import org.uddi4j.response.TModelInfos;
import org.uddi4j.response.TModelList;
import org.uddi4j.util.CategoryBag;
import org.uddi4j.util.FindQualifier;
import org.uddi4j.util.FindQualifiers;
import org.uddi4j.util.KeyedReference;

import com.fujitsu.iflow.common.DOMUtils;
import com.fujitsu.iflow.model.workflow.DataItemRef;
import com.fujitsu.iflow.model.workflow.Node;
import com.fujitsu.iflow.model.workflow.Plan;
import com.fujitsu.iflow.model.workflow.WFObjectFactory;
import com.fujitsu.iflow.model.workflow.WFObjectList;
import com.fujitsu.iflow.server.dataobjects.FilterEnum;
import com.fujitsu.iflow.utilities.XPATHUtils;


public class MetaDataPublishingTest extends BPMTestBase
{

    public static String WSDL_TYPE_TMODELKEY = "uuid:6e090afa-33e5-36eb-81b7-1ca18373f457";
    public static String WSDL_TYPE_KEYNAME   = "WSDL type";

    public static String FILE_DELIMITER       = "@";
    public static String FORWARDSLASH         = "/";
    public static String DOT_XPDL             = ".xpdl";
    public static String DOT_SVG              = ".svg";
    public static String DOT_XML              = ".xml";
    public static String MD_FOLDER_NAME       = "BusinessProcessMetaData";    
    public static String IBPM_WS_SERVICE_NAME = "IFWebServicesService";
    public static String WFXML_SERVICE_NAME   = "Registry_Service";
    public static int OBSOLETE_PLAN   = 1;
    public static int DELETE_PLAN   = 2;
    
    private long timeToSleep = 10000; // ten seconds.
    private String businessName   = "";
    private String uddiInquiryUrl = "";
    private String uddiPublishUrl = "";
    private String uddiPublisherUserName = "";
    private String uddiPublisherPwd = "";
    private String webDAVRepUrl       = "";
    private String ibpmServerName = "";
    
    private UDDIProxy uddiProxy;
    private AuthToken authToken;
    private BusinessInfo businessInfo = null;
    
    
    /*
     * Zero argument constructor.
     */
    public
    MetaDataPublishingTest() {
        super();
    }

    /*
     * This method runs the rest.
     */
    public
    void
    runTests(
        TestRecorder recorder)
        throws Exception
    {
        init(recorder);

        try {
        
            login();
            
            tr.log("Logged in Successfully :" + username);
            
            // initilize the test case.
            init();

            // check if all the required parameters for the test case are present in 
            // the test.conf. If all the params are present then continue with the
            // test or else just print the message 'failure to execute test case' and
            // return
            
            if ( ((businessName != null && businessName.length() > 0) &&
                 (uddiInquiryUrl != null && uddiInquiryUrl.length() > 0) &&
                 (uddiPublishUrl != null && uddiPublishUrl.length() > 0) &&
                 (uddiPublisherUserName != null && uddiPublisherUserName.length() > 0) &&
                 (uddiPublisherPwd != null && uddiPublisherPwd.length() > 0) &&
                 (webDAVRepUrl != null && webDAVRepUrl.length() > 0)) == false ) 
            {
                tr.log("Unable to execute the test case because of missing parameters ");
                tr.log("Required Parameters are : UddiBusinessName, UddiInquiryURL, UddiPublishURL, " +
                    "UddiPublisherUserName, UddiPublisherPassword, MetaDataRepositoryURL");                
                return; 
            }

            /* 1.
             * Creates a Plan and publishes the same plan and check
             * whether the Plan information is published both in the 
             * WebDAV Repository and in the UDDI repository.
             */
            tr.log("Testing test case #1");
            Plan p = verifyPublishPlan();
            
            /* Obsoletes the given published Plan and checks if the plan has been obsoleted
             * and checks if the plan information has been deleted/unpuplished from 
             * both WebDAV  and UDDI repository
             */
            verifyUnPublish(p, OBSOLETE_PLAN);

                        
            /* 2.
             * Creates a Plan and publishes the same plan and check
             * whether the Plan information is published both in the 
             * WebDAV Repository and in the UDDI repository.
             */
            tr.log("Testing test case #2");
            p = verifyPublishPlan();
            /* Deletes the given published Plan and checks if the plan has been deleted
             * and checks if the plan information has been deleted/unpuplished from 
             * both WebDAV  and UDDI repository
             */
            verifyUnPublish(p, DELETE_PLAN);
            
            
            /* 3.
             * Creates multiple versions (say 5 versions)of the same template. 
             * Publishes the 3rd version of the template and checks if the template 
             * state has been changed to PUBLISHED and checks if the same template
             * version is published in both UDDI and in the WebDAV repository.
             * 
             * Then publishes the 4th version of the sample template and checks
             * if the 3 rd version of the has been obsoleted and the same information
             * has been deleted/unpublished from the UDDI and WebDAV Repository and checks 
             * if the 4th template version has been published and the plan infomation
             * exits both in the UDDI and in WebDAV repository.
             */
            tr.log("Testing test case #3");             
            createMultipleVersionsAndPublish();
            
            /* 4.
             * Creates 10 templates and names them as MDPublishingTestPlanSyncUp_1 ... MDPublishingTestPlanSyncUp_10
             * Publishes all of them and deletes/unpublishes all of those plans from both
             * WebDAV and from UDDI repository in order to make IBPM and the MDR in UnSync.
             * 
             * Then calls the WfAdminSession.syncUpWithRepository() to sync up both IBPM and the MDR and then
             * cross checks if published plans on the IBPM exits in both UDDI and in WebDAV repository.
             */
            tr.log("Testing test case #4");             
            verifySynchronization();
            
        }
        catch (Exception e) 
        {
            e.printStackTrace();
            throw new ExceptionWrapper("Exception caught in main test level", e);
        } 
        finally 
        {
            try {
                cleanUp();
                logOut();
            } catch (Exception e) {
                // have to ignore this exception
            }
        }
    }
    
    /**
     * This method test the WFAdminSession.syncUpWithRepository()
     * @throws Exception
     */
    public
    void
    verifySynchronization()
        throws Exception
    {
        tr.log("verifySynchronization()");
        unSynchronizeIBPMAndIMR();
        synchronizeIBPMAndIMR();     
        // finally mark as passed.
        tr.markPassed("WFAdminSession.syncUpWithRepository()");
    }

    /**
     * This method publishes a template in the IBPM cross checks if the same has been 
     * published in the WebDAV Repository and the UDDI Repository.
     * @throws Exception
     */
    public
    Plan
    verifyPublishPlan()
        throws Exception
    {

        tr.log("Verifying the Plan Publish");    
        // first create the plan on the server.1
        String planName = "";
        Plan p = createTemplate();
        planName = p.getName();
        
        // now publish the plan.
        wfSession.publishPlan(p.getId());
        Thread.sleep(this.timeToSleep);
                
        // check if the plan is published in the ibpm server
        p = WFObjectFactory.getPlan(p.getId(), wfSession);
        if (p.getState() != Plan.STATE_PUBLISHED) {
            throw new Exception(" Plan '" + p.getName() +
            "' was not published on the server: Current state is : " +p.getState());
        }
        tr.log("Plan name ' " + p.getName() + "' has been published");        
        
        // check if the plan is published in the UDDI Repository
        if (isPlanPublishedInUDDI(planName, p.getVersion())) {
            tr.log("Plan '" + planName + "' information exists in the UDDI ");
        }
        else {
            tr.markFailed("Failed to Publish Plan", "Unable to find the plan "  
                        + " information in the UDDI for plan '" + planName + "');");    
        }
        
        // check if the plan is published in the WebDAV Repository
        if (isPlanPublishedInWebDAV(planName, p.getVersion())) {
            tr.log("Plan '" + planName + "' information exists in the MetaData Repository ");
        }
        else {
            tr.markFailed("Failed to Publish Plan", "Unable to find the plan "  
                        + " information in the MetaData Repository for plan '" + planName + "');");              
        }
        
        tr.markPassed("Publish Plan : ' " + p.getName() + "' has been successfully published in IBPM server");
        
        return p;
    } 

    /** 
     * This method deletes/ obsolutes a template in the IBPM cross checks if the same has been 
     * unpublished from the WebDAV Repository and from the UDDI Repository.
     * @throws Exception
     */
    public
    void
    verifyUnPublish(
        Plan p,
        int obsoleteOrDelete)
        throws Exception
    {

        tr.log("Verifying the Plan Unpublish");    
        // first create the plan on the server.
        String planName = "";
        planName = p.getName();
        
        // now un publish the plan.
        if (obsoleteOrDelete == this.OBSOLETE_PLAN)      
            wfSession.obsoletePlan(p.getId());
        else
            wfSession.deletePlan(p.getId());
        
        Thread.sleep(this.timeToSleep);
        
        // check if the plan is un published in the ibpm server
         // now check the state of the plan in the server side.
        p = WFObjectFactory.getPlan(p.getId(), wfSession);
        if (p.getState() == Plan.STATE_PUBLISHED) {
            throw new Exception(" Plan '" + p.getName() + "' is in Published state");
        }
        tr.log("Plan name ' " + p.getName() + "' has been un published");        
        
        // check if the plan is information is removed form the UDDI Repository
        if (isPlanPublishedInUDDI(planName, p.getVersion())) {
            tr.markFailed("UnPublishing from UDDI falied", "Still able to find the plan "  
                        + " information in the UDDI for plan '" + planName + "');");    
        }
        else {
            tr.log("Plan '" + planName + "' information doesn't exists in the UDDI ");
        }
        
        // check if the plan is published in the UDDI Repository
        if (isPlanPublishedInWebDAV(planName, p.getVersion())) 
        {
            tr.markFailed("UnPublishing from MetaData Repository falied", "Still able to find the plan "  
                        + " information in the MetaData Repository for plan '" + planName + "');");              
        }
        else {
            tr.log("Plan '" + planName + "' information doesn't exists in the MetaData Repository ");
        }
        
        tr.markPassed("UnPublish Plan : ' " + p.getName() + "' has been successfully Unpublished from IBPM server");
    }
    
    /**
     * This method creates multiple versions of the sample template and publishes a particular
     * template version in the IBPM cross checks if the same has been 
     * published in the WebDAV Repository and the UDDI Repository. And later on it
     * selects another version of the same template and pulilshes it and cross check if the
     * same version has been published and also check if the previous published version becomes 
     * obsolute and unpublished fromt the WebDAV and the UDDI repository.
     * @throws Exception
     */    
    public
    void
    createMultipleVersionsAndPublish()
        throws Exception
    {
    
        tr.log("createMultipleVersionsAndPublish()");
        
        Plan[] plans = new Plan[5];
        
        for (int i=0; i<plans.length; i++) 
        {
            plans[i] = createTemplate("MDataPublishingTestPlan");
        }
        
        // publish only the 3rd plan.
        wfSession.publishPlan(plans[2].getId());
        Thread.sleep(this.timeToSleep);

        String thirdPlanVersion = plans[2].getVersion();
        
        // now check if the 3rd plan is published.
        if ( isPlanPublishedInWebDAV("MDataPublishingTestPlan", thirdPlanVersion ) && 
             isPlanPublishedInUDDI("MDataPublishingTestPlan", thirdPlanVersion) &&
             plans[2].getState() == Plan.STATE_PUBLISHED)  
        {
            tr.markPassed("Publish Plan : Multiple Version of the same Plan exists "+
                "and a particular Plan version was published");
        }
        else 
        {
            tr.markFailed("Publish Plan", "Multiple Version of the same Plan exists " +
                "and publishing a particular version failed.");
        }

        // now publish the 4 th plan.
        wfSession.publishPlan(plans[3].getId());
        Thread.sleep(this.timeToSleep);
        
        String fouthPlanVersion = plans[3].getVersion();
        
        if ( isPlanPublishedInWebDAV("MDataPublishingTestPlan", fouthPlanVersion ) && 
             isPlanPublishedInUDDI("MDataPublishingTestPlan", fouthPlanVersion) && 
             plans[2].getState() == Plan.STATE_OBSOLETE &&
             plans[3].getState() == Plan.STATE_PUBLISHED )  
        {
            tr.markPassed("Multiple Version of the same Plan exists with one version already published and " + 
                        "Publishing another plan made the previous one obsolete");
        }
        else 
        {
            tr.markFailed("Publish Plan", "Multiple Version of the same Plan exists with one version already published and " + 
                        "Publishing another plan failed");
        }
    }
    
    /**
     * This method deliberately goes and deletes some of the Plans information from the
     * WebDAV Repository and from the UDDI Repository so that both the IBPM and the IMR 
     * are out of sync.
     * @throws Exception
     */
    public
    void
    unSynchronizeIBPMAndIMR()
        throws Exception
    {
        
        tr.log("unSynchronizeIBPMAndIMR()");
        // Create 10 plans and publish them for testing the sync.
        for (int i=1; i<=10; i++) 
        {
            tr.log("Creating ProcessDefinition : MDPublishingTestPlanSyncUp_"+i);
            Plan p = createTemplate("MDPublishingTestPlanSyncUp_" + i);
            wfSession.publishPlan(p.getId());
            Thread.sleep(this.timeToSleep);
        }
        
        Object[] pList = getAllPublishedPlansFromIBPM();
        for (int i=0; i<pList.length; i++) {
            Plan plan =  (Plan) pList[i];
            unPublishPlanFromRepository(plan.getName(), plan.getVersion());
        }
        
        // delete the IBPM WS and the WFXML Registry services from the UDDI Repository.
        unPublishPlanFromUDDI(IBPM_WS_SERVICE_NAME, null);
        unPublishPlanFromUDDI(WFXML_SERVICE_NAME, null);
    }
    
    /**
     * This method performs WFAdminSession.syncUpWithRepository() and checks if all the 
     * published plans in the IBPM exists in the WebDAV and in the UDDI repository
     * @throws Exception
     */    
    public
    void
    synchronizeIBPMAndIMR()
        throws Exception
    {
        wfSession.syncUpWithRepository();
        Thread.sleep(this.timeToSleep);
        
        Object[] pList = getAllPublishedPlansFromIBPM();
        for (int i=0; i<pList.length; i++) {
            Plan plan =  (Plan) pList[i];
            if (isPlanPublishedInRepository(plan) == false && 
                isPlanPublishedInUDDI(IBPM_WS_SERVICE_NAME, null) && 
                isPlanPublishedInUDDI(WFXML_SERVICE_NAME, null)) 
            {
                tr.markFailed("WFAdminSession.syncUpWithRepository() failed", "Error occured while performing Repository Sync up");
            }
        }
        
    }
    
    /**
     * This method returns the list of all published plans in the IBPM
     * @return Object[] list of Plans.
     * @throws Exception
     */
    public
    Object[]
    getAllPublishedPlansFromIBPM()
        throws Exception
    {
        tr.log("getAllPublishedPlansFromIBPM() ");
        
         // get all published plans.
        WFObjectList wfObjectList = null;
        wfObjectList = WFObjectFactory.getWFObjectList(wfSession);
        wfObjectList.addFilter(WFObjectList.LISTFIELD_PLAN_STATE,
                    WFObjectList.SQLOP_EQUALTO, "'" +
                    String.valueOf(Plan.STATE_PUBLISHED) + "'");
        wfObjectList.openBatchedList(FilterEnum._AllProcessDefinitions);
        
        Object[] pList = wfObjectList.getNextBatch(2000);
        wfObjectList.closeList();

        if (pList == null)
            return new Plan[0];
        else
            return pList;
        
    }

    /**
     * This method returns the list of all published plans in the WebDAV Repository
     * @return String[] list of Plan names.
     * @throws Exception
     */
    public
    String[]
    getAllPublishedPlansFromWebDAV()
        throws Exception
    {
            
        WebdavResource wRes = null;
        String[] planNames = new String[0];
        
        try {
            
            wRes = getWebdavResource(getMDRepositoryURL());
            
            Vector v = new Vector();
            WebdavResource[] wResList = wRes.listWebdavResources();
            if (wResList != null) {
                for (int i=0; i<wResList.length; i++) {
                    String resName = wResList[i].getName();
                    if ( wResList[i].isCollection() && 
                         resName.startsWith(ibpmServerName + FILE_DELIMITER))
                    {
                        String planName = resName.substring(resName.indexOf(FILE_DELIMITER)+1, 
                                            resName.length());
                        v.add(planName);
                    }
                }
                planNames = new String[v.size()];
                v.copyInto(planNames);
            }
        }
        finally  {
            closeWebdavResource(wRes);
        }
        return planNames;
    }
    
    /**
     * This method returns the list of all published plans in the UDDI Repository
     * @return String[] list of Plan names.
     * @throws Exception
     */
    public
    String[]
    getAllPublishedPlansFromUDDI()
        throws Exception
    {
                
        Vector serviceNames = new Vector();
        Name sName = new Name("%Factory_Service");
        serviceNames.add(sName);
        
        CategoryBag categoryBag = new CategoryBag();
        KeyedReference spTypeKR = getBPMKeyedReference();
        categoryBag.add(spTypeKR);
        
        ServiceList serviceList = uddiProxy.find_service(businessInfo.getBusinessKey(),
                                serviceNames, categoryBag, null, null, 0);

        Vector serviceInfoVector = serviceList.getServiceInfos().getServiceInfoVector();
        
        String[] pNames = new String[serviceInfoVector.size()];
        
        for(int i = 0; i < serviceInfoVector.size(); i++) 
        {
            ServiceInfo serviceinfo = (ServiceInfo)serviceInfoVector.elementAt(i);
            pNames[i] = getPlanNameFromServiceName(serviceinfo.getNameString());
        }
        return pNames;
    }    

    /**
     * Creates a simple template
     * @return Plan newly created plan.
     * @throws Exception
     */
    public
    Plan
    createTemplate()
        throws Exception
    {
        return createTemplate("MDataPublishingTestPlan");
    }

    /**
     * Creates a simple template with the given name.
     * @return Plan newly created plan.
     * @throws Exception
     */
    public
    Plan
    createTemplate(String planName)
        throws Exception
    {
        if (planName == null || planName.length() == 0)
            planName = "MDataPublishingTestPlan";
        
        Plan plan = null;
        
        try {
            plan = WFObjectFactory.getPlan();
            plan.setWFSession(wfSession);
            plan.startEdit();
            plan.setName( planName );
            plan.setTitle( planName + " title" );
            plan.setDesc( planName + " description" );
            plan.setPlanIdentifier("Global");
            
            //Add data items to the template
            DataItemRef dataItem = null;
            dataItem = plan.addDataItemRef("Name", "STRING", "John Smith");
            dataItem = plan.addDataItemRef("Age","INTEGER", "25");
            dataItem = plan.addDataItemRef("Description", "STRING", "This is a description field");
            dataItem = plan.addDataItemRef("Salary", "FLOAT", "1010.99");
            dataItem = plan.addDataItemRef("AccountBalance", "BIGDECIMAL", "1253430424.99");
            dataItem = plan.addDataItemRef("YearsOfService", "LONG", "123543544532");
            dataItem = plan.addDataItemRef("DOB", "DATE", String.valueOf(System.currentTimeMillis()));
            dataItem = plan.addDataItemRef("IsPermanent", "BOOLEAN", "true");

            Node startNode = plan.addNode( "Start", Node.TYPE_START );
            int startX = 50;
            int startY = 100;
            
            startNode.setPosition( new Point( startX, startY ) );
            
            Node firstActNode = plan.addNode( "My Activity", Node.TYPE_ACTIVITY );
            firstActNode.setPosition( new Point( startX + 200, startY ) );
            firstActNode.setRole("Role");
            firstActNode.setDesc("Activity: " + "Description");
            
            plan.addArrow( "Activity", startNode, firstActNode );
            Node exitNode = plan.addNode( "EXIT", Node.TYPE_EXIT );
            exitNode.setPosition( new Point( startX + 200, startY + 200) );
            plan.addArrow( "Exit", firstActNode, exitNode);
            
            plan = plan.createProcessDef();
            
        } catch (Exception e) 
        {
            logAndRethrow("Failed to create Template", e);
        }
        return plan;
    }

    /**
     * Logs the exception and re throws the same.
     * @param message
     * @param e
     * @throws Exception
     */
    public
    void
    logAndRethrow(
        String message,
        Exception e)
            throws Exception
    {
        tr.log(message);
        throw new ExceptionWrapper(message, e);
    }
    
    /**
     * Initializes the test case.
     * @throws Exception
     */
    public
    void
    init()
        throws Exception
    {
        
        tr.log("init test case");
        
        businessName          = tr.getRequiredProperty(BaseSystemEnvironment.kUddiBusinessName);
        
        if (businessName == null || businessName.trim().length() == 0)
            return;
        
        uddiInquiryUrl        = tr.getRequiredProperty(BaseSystemEnvironment.kUddiInquiryURL);
        uddiPublishUrl        = tr.getRequiredProperty(BaseSystemEnvironment.kUddiPublishURL);
        uddiPublisherUserName = tr.getProperty(BaseSystemEnvironment.kUddiPublisherUserName, "");
        uddiPublisherPwd      = tr.getProperty(BaseSystemEnvironment.kUddiPublisherPassword, "");
        webDAVRepUrl          = tr.getRequiredProperty(BaseSystemEnvironment.kMetaDataRepositoryURL);
        
        webDAVRepUrl          = getMDRepositoryURL();
        
        ibpmServerName = wfSession.getServerOption("TWFServerName");
        uddiProxy = getUDDIProxy(uddiInquiryUrl, uddiPublishUrl, uddiPublisherUserName, uddiPublisherPwd);
        
        
        if (getBusinessInfo(businessName) == null) 
        {
            throw new Exception(" Unable to find the Business Entity '" + businessName
                +"' in the UDDI registry : " + uddiInquiryUrl);
        }
    }
 
 
    /**
     * This return the WebdavResource object for the given URL path.
     * @param path The URL representing the WebDAV resource.
     * @return WebdavResource
     * @throws Exception
     */
    public
    WebdavResource
    getWebdavResource(
        String path)
        throws Exception
    {
        WebdavResource res = null;
        
        try 
        {
            HttpURL url = new HttpURL(path);
            url.setUserinfo(username, password);
            res = new WebdavResource(url);
        }
        catch (Exception e)
        {
            logAndRethrow("Unable to access the WebDAV Resource : " +  path + " by user : " + username, e);
        }
        return res;
    }

    /**
     * returns the WebDAV repository URL.
     * @return 
     */
    public String getMDRepositoryURL()
    {
        String url = webDAVRepUrl;
        if (url.endsWith(FORWARDSLASH) == false) {
            url = url + FORWARDSLASH;
        }
        if (url.endsWith(FORWARDSLASH + MD_FOLDER_NAME + FORWARDSLASH) == false) {
            url = url + MD_FOLDER_NAME + FORWARDSLASH;
        }
        return url;
    }

    /**
     * Returns the Plan metadata folder name.
     * @param planName
     * @return MetaData folder name. for ex. IbpmServerName@PlanName
     */
    public String getPlanMetaDataFolderName(String planName) 
    {
        return ibpmServerName + FILE_DELIMITER + planName;
    }
    
    /**
     * Returns the Full URL of the PlanMeta Data folder which is IbpmServerName@PlanName
     * @param planName Given plan name.
     * @return full path of the plan metadata folder.
     */
    public String getPlanMDFoldeURL(String planName)
    {
        return getMDRepositoryURL() + ibpmServerName + FILE_DELIMITER + planName;
    }
 

    /**
     * Returns the BusinessInfo object for the given business name.
     * @param busEntityName Business Entity name.
     * @return BusinessInfo
     * @throws Exception
     */
    public
    BusinessInfo
    getBusinessInfo(
        String busEntityName)
        throws Exception
    {
        
        if (busEntityName == null || busEntityName.length() == 0)
            return null;
        
        Vector nameVector = new Vector();
        nameVector.add(new Name(busEntityName));

        FindQualifiers qualifiers = getFindQualifiers();

        BusinessList businesslist = uddiProxy.find_business(nameVector, null, null, null, null, qualifiers, 0);
        Vector businessInfoVector = businesslist.getBusinessInfos().getBusinessInfoVector();

        for(int i = 0; i < businessInfoVector.size(); i++) 
        {
            businessInfo = (BusinessInfo)businessInfoVector.elementAt(i);
            if (businessInfo.getNameString().startsWith(busEntityName))
                return businessInfo;
        }
        return businessInfo;
    }
 
    /**
     * @return Returns the Exact Match FindQualifiers.
     */
    public
    FindQualifiers
    getFindQualifiers()
    {
        FindQualifiers qualifiers = new FindQualifiers();
        Vector qualifier = new Vector();
        qualifier.add(new FindQualifier(FindQualifier.exactNameMatch));
        qualifiers.setFindQualifierVector(qualifier);
        return qualifiers;
    }
    
    /**
     * Returns the UDDI Proxy Object.
     * @param inUrl Inquiry URL
     * @param pubUrl Publisher URL
     * @param uName User Name
     * @param pwd Password
     * @return UDDIProxy
     * @throws Exception
     */
    public
    UDDIProxy
    getUDDIProxy(String inUrl, String pubUrl, String uName, String pwd)
        throws Exception
    {
        
        UDDIProxy proxy = null;
        try {
            proxy = new UDDIProxy();
            proxy.setInquiryURL(inUrl);
            proxy.setPublishURL(pubUrl);                        
            authToken = proxy.get_authToken(uName, pwd);
        }
        catch (Exception e) 
        {
            e.printStackTrace();
            logAndRethrow("Unable to access the UDDI Resource : " +  pubUrl + " by user : " + uName, e);
        }
        return proxy;
    }
    
    /**
     * Returns the UDDI Service Name for the given IBPM Plan Name.
     * @param plan name.
     * @return UDDI service Name.
     */
    public
    String
    getServiceNameFromPlan(
        String planName) 
    {
    
        if ( planName.equalsIgnoreCase(IBPM_WS_SERVICE_NAME) || 
             planName.equalsIgnoreCase(WFXML_SERVICE_NAME)) 
        {
            return planName;
        }
        else
        {
            return planName + "Factory_Service";
        }    
    }

    /**
     * Returns the Plan Name for the given UDDI Service name.
     * @param service name.
     * @return plan name.
     */
    public
    String
    getPlanNameFromServiceName(
        String serviceName) 
    {
        return serviceName.substring(0, serviceName.indexOf("Factory_Service"));
    }
    
    /**
     * This method check if the given plan name exits as a service in the UDDI repository.
     * @param planName
     * @return result
     * @throws Exception
     */
    public boolean isServiceExists(String planName, String version) 
        throws Exception
    {
        if (planName == null)
            return false;

        CategoryBag categoryBag = new CategoryBag();
        KeyedReference nameKR = getKeyedReference(planName, version);   
        if (nameKR != null) {
            categoryBag.add(nameKR);
        }

        Vector serviceNames = new Vector();
        Name sName = new Name(getServiceNameFromPlan(planName));
        serviceNames.add(sName);
        
        ServiceList serviceList = uddiProxy.find_service( businessInfo.getBusinessKey(),
                                serviceNames, categoryBag, null, getFindQualifiers(), 0);
        
        boolean result = false;
        Vector serviceInfoVector = serviceList.getServiceInfos().getServiceInfoVector();
        if (serviceInfoVector != null && serviceInfoVector.size() > 0) 
        {
            String serviceKey = ((ServiceInfo)serviceInfoVector.get(0)).getServiceKey();
            result = (serviceKey != null && serviceKey.length() > 0);
        }
        return result;
    }
    
    /**
     * Unpublishes the given plan information from the WebDAV and UDDI repository.
     * @param planName
     * @throws Exception
     */
    public
    void
    unPublishPlanFromRepository(
        String planName,
        String version)
        throws Exception
    {
        unPublishPlanFromUDDI(planName, version);
        unPublishPlanFromWedDAV(planName);
    }
    
    /**
     * Unpublishes the given plan information from the UDDI repository.
     * @param planName
     * @throws Exception
     */
    public
    void
    unPublishPlanFromUDDI(
        String planName,
        String version)
        throws Exception
    {
        
        
        tr.log("unPublishPlanFromUDDI() " + planName);
        
        // exact match qualifier.
        FindQualifiers qualifiers = getFindQualifiers();
        tr.log(" getFindQualifiers : " + qualifiers);

        // get the business key.
        String businessKey = businessInfo.getBusinessKey();

        tr.log(" businessKey : " + businessKey);

        // add the categorbag filter
        CategoryBag categoryBag = new CategoryBag();

        KeyedReference nameKR = getKeyedReference(planName, version);

        tr.log(" getKeyedReference : " + nameKR);

        if (nameKR != null) {
            categoryBag.add(nameKR);
        }

        Vector serviceNameVector = new Vector();
        serviceNameVector.add(new Name( getServiceNameFromPlan(planName)));
                
        tr.log(" getServiceNameFromPlan : " + getServiceNameFromPlan(planName));
                
        // find the service and delete it.
        ServiceList serviceList = uddiProxy.find_service(businessKey, serviceNameVector, categoryBag, null, qualifiers, 0);
        
        tr.log(" uddiProxy.find_service : " + serviceList);        
        
        Vector serviceInfoVector = serviceList.getServiceInfos().getServiceInfoVector();
        if (serviceInfoVector != null  && serviceInfoVector.size() > 0) 
        {
            Vector serviceKeyVector = new Vector();
            for( int i=0; i<serviceInfoVector.size(); i++ )
            {
                ServiceInfo serviceInfo = (ServiceInfo) serviceInfoVector.elementAt(i);
                String serviceKey = serviceInfo.getServiceKey();
                serviceKeyVector.add(serviceKey);
                
                // find and delete template bindings for the service key.
                BindingDetail bindingDetail = uddiProxy.find_binding(qualifiers, serviceKey, null, 0);
                
                tr.log("uddiProxy.find_binding : " + bindingDetail);
                
                Vector bindingTemplateVector = bindingDetail.getBindingTemplateVector();
                
                tr.log("bindingDetail.getBindingTemplateVector : " + bindingTemplateVector);
                
                Vector bindingKeysVector = new Vector();
                for( int j=0; j<bindingTemplateVector.size(); j++ ) 
                {
                    BindingTemplate bindingTemplate = (BindingTemplate) bindingTemplateVector.elementAt(j);
                    String bindingKey = bindingTemplate.getBindingKey();
                    bindingKeysVector.add(bindingKey);
                }
                uddiProxy.delete_binding(authToken.getAuthInfoString(), bindingKeysVector);
                tr.log(" uddiProxy.delete_binding");
                
            }
            uddiProxy.delete_service(authToken.getAuthInfoString(), serviceKeyVector);
            tr.log(" uddiProxy.delete_service");
        }
        
        // find and delete all the tmodels for the given plan.
        TModelList tModelList = uddiProxy.find_tModel("%"+planName + "Factory_", null, null, null, 0);
        
        tr.log(" uddiProxy.find_tModel : " + tModelList);
        
        TModelInfos tModelInfos = tModelList.getTModelInfos(); 
        Vector tModelInfoVector = tModelInfos.getTModelInfoVector();
        Vector tModelKeyVector = new Vector();
        for (int i=0; i<tModelInfoVector.size(); i++)
        {
            TModelInfo tModelInfo = (TModelInfo) tModelInfoVector.elementAt(i);
            tModelKeyVector.add(tModelInfo.getTModelKey());
        }
        
        uddiProxy.delete_tModel(authToken.getAuthInfoString(), tModelKeyVector);
        tr.log(" uddiProxy.delete_tModel : " + tModelList);
        
    }


    /**
     * Unpublishes the given plan information from the WebDAV repository.
     * @param planName
     * @throws Exception
     */
    public
    void
    unPublishPlanFromWedDAV(
        String planName)
        throws Exception
    {
        
        if (planName == null || planName.length() == 0)
            return;
        
        tr.log("unPublishPlanFromWedDAV() " + planName);
        WebdavResource root = null;
        WebdavResource planMetaDataFolder = null;

        try 
        {
            root = getWebdavResource(getMDRepositoryURL());
            
            WebdavResource[] list = root.listWebdavResources();

            String metaDataFolderName = getPlanMetaDataFolderName(planName);
            
            for(int i=0; i<list.length; i++) 
            {
                if (list[i].isCollection()) 
                {
                    String dirName = list[i].getName();
                    if (dirName.equalsIgnoreCase(metaDataFolderName))
                    {
                        planMetaDataFolder = list[i];
                        break;
                    }
                }
            }
            
            if (planMetaDataFolder != null) 
            {
                String path = root.getPath() + metaDataFolderName;
                boolean result = root.deleteMethod(path);
            }
        }
        finally {
            closeWebdavResource(root);
        }
    }
    
    /**
     * Returns KeyedReference for the WFXML PD
     * @param planName
     * @return KeyedReference
     */
    public 
    KeyedReference
    getKeyedRefForWfXmlPd(
        String planName,
        String version)
    {
        String tModelKey = "uuid:2e0a7200-8991-11d9-8457-a6f741887991";
        
        // "fujitsu:interstage:bpm:wfxml:pd:" + planName;
        String keyName = "fujitsu:interstage:bpm:wfxml:pd:" 
                            + ibpmServerName + ":" + planName + ":" + version;
        String keyValue = keyName;
        KeyedReference kr = new KeyedReference(keyName, keyValue, tModelKey);
        return kr;

    }

    /**
     * Returns KeyedReference for the WFXML
     * @return KeyedReference
     */
    public
    KeyedReference
    getKeyedRefForWfXml()
    {
        String tModelKey = "uuid:2e0a7200-8991-11d9-8457-a6f741887991";
        // "fujitsu:interstage:bpm:wfxml:pd:" + pds.label;
        String keyName = "fujitsu:interstage:bpm:wfxml:"+ ibpmServerName + ":"
                            + "registry";
        String keyValue = keyName;
        KeyedReference kr = new KeyedReference(keyName, keyValue, tModelKey);
        return kr;
    }


    /**
     * Returns KeyedReference for the IBPM WS
     * @return KeyedReference
     */
    public
    KeyedReference
    getKeyedRefForIbpmWs()
    {
        String tModelKey = "uuid:2e0a7200-8991-11d9-8457-a6f741887991";
        // "fujitsu:interstage:bpm:ws";
        String keyName = "fujitsu:interstage:bpm:"+ ibpmServerName + ":" + "ws";
        String keyValue = keyName;
        KeyedReference kr = new KeyedReference(keyName, keyValue, tModelKey);
        return kr;
         
    }
    
    /**
     * Returns KeyedReference for the BPM Web Service
     * @return KeyedReference
     */    
    public
    KeyedReference
    getBPMKeyedReference() 
    {
        KeyedReference spTypeKR = new KeyedReference("BPM Web Service",
                                 "uuid:2e0a7200-8991-11d9-8457-a6f741887991",
                                 "uuid:2dafcee0-8991-11d9-8457-f2038ed2fcd0");

        return spTypeKR;
    }
    
    /**
     * Return if the given plan is published in both WebDAV Repository and the UDDI repository.
     * @param plan The given Plan Object.
     * @return Result
     * @throws Exception
     */
    public
    boolean
    isPlanPublishedInRepository(
        Plan plan)
        throws Exception
    {
        
        boolean result = false;
        
        if (plan == null)
            return result;
            
        result = ( isPlanPublishedInUDDI(plan.getName(), plan.getVersion()) && 
            isPlanPublishedInWebDAV(plan.getName(), plan.getVersion()));
        
        tr.log("isPlanPublishedInRepository('" + plan.getName() + "'" + result);
        
        return result;
    }

    /**
     * Return if the given plan is published in both WebDAV Repository and the UDDI repository.
     * @param planName The given Plan name.
     * @param version The given Plan version.
     * @return Result
     * @throws Exception
     */
    public
    boolean
    isPlanPublishedInRepository(
        String planName,
        String version)
        throws Exception
    {
        
        boolean result = false;
        if (planName == null || planName.length() == 0)
            return result;    
            
        result = (isPlanPublishedInUDDI(planName, version) && isPlanPublishedInWebDAV(planName, version));
        
        tr.log("isPlanPublishedInRepository('" + planName + "' Version " + version + " Result : " + result);

        return result;
    }
    
    /**
     * Return if the given plan is published in UDDI repository.
     * @param planName The given Plan name.
     * @return Result
     * @throws Exception
     */    
    public
    boolean
    isPlanPublishedInUDDI(
        String planName,
        String version) 
        throws Exception
    {
        
        boolean result = isServiceExists(planName, version);
        tr.log("isPlanPublishedInUDDI('" + planName + "' Version : " + version + " Result : " + result);
        return result;
    }
    
    /**
     * Return if the given plan is published in WebDAV repository.
     * @param planName The given Plan name.
     * @param version The given Plan version.
     * @return Result
     * @throws Exception
     */       
    public 
    boolean
    isPlanPublishedInWebDAV(
        String planName,
        String version)
        throws Exception
    {
        tr.log("isPlanPublishedInWebDAV( ) "+ planName + " Version " +  version);
        
        boolean result = true;
        WebdavResource wRes = null;
        
        boolean xpdlPublished = false;
        String xpdlContents = null;
        
        boolean metaDataPublished = false;
        String metaDataContents = "";

        boolean svgPublished = false;
        
        try {
            wRes = getWebdavResource(getPlanMDFoldeURL(planName));
            if (wRes == null)
                return false;
            
            WebdavResource[] wResList = wRes.listWebdavResources();
            
            if (wResList != null)
            {
                for (int i=0; i<wResList.length; i++) {
                
                    if (wResList[i].getName().equalsIgnoreCase(planName + DOT_XPDL)) {
                        xpdlContents = wResList[i].getMethodDataAsString();
                        xpdlPublished = true;
                    }
                    
                    if (wResList[i].getName().equalsIgnoreCase(planName + DOT_SVG)) {
                        svgPublished = true;
                    }
                    if (wResList[i].getName().equalsIgnoreCase(planName + DOT_XML)) {
                        metaDataContents = wResList[i].getMethodDataAsString();
                        metaDataPublished = true;
                    }
                }
            } else 
            {
                return false;
            }
            
            // now check if the plan on the server and the plan information 
            // in the MD repository matches. (just check the version number).
            String versionInServer = version;
            String versionInMDR = "";
            
            if (metaDataContents != null && metaDataContents.length() >0) 
            {           
                versionInMDR = XPATHUtils.getXpathValue(DOMUtils.convertStringToDocument(metaDataContents),
                                                    "/BpmSummary/Version/text()");
                
                if (versionInServer.equals(versionInMDR.trim()) == false) {
                    return false;                    
                }
            }
            
            // now check if the plan on the server and the plan information 
            // in the MD repository matches. (just check XPDL).
            if (xpdlContents != null && xpdlContents.length() > 0) 
            {
                // versionInMDR = XPATHUtils.getXpathValue(DOMUtils.convertStringToDocument(xpdlContents.trim()),
                //             "//Package/WorkflowProcesses/WorkflowProcess/RedefinableHeader/Version/text()");
                
                versionInMDR = xpdlContents.substring( xpdlContents.indexOf("<Version>") + 9,
                                                       xpdlContents.indexOf("</Version>"));
                
                if (versionInServer.equals(versionInMDR.trim()) == false)
                {
                    xpdlPublished = false;                    
                }
            }
            
           if ( metaDataPublished == false ||  xpdlPublished == false || svgPublished == false) {
                return false;
           }
           
        } catch (Exception e) 
        {
            return false;
        }
        finally 
        {
            closeWebdavResource(wRes);
        }
        
        return result;
    }
    
    /**
     * Returns the KeyedReference
     * @param planName
     * @return 
     */
    public 
    KeyedReference
    getKeyedReference(
        String planName,
        String version) 
    { 
        
        KeyedReference nameKR = null;
        
        if ( planName.equalsIgnoreCase(IBPM_WS_SERVICE_NAME)) {
            nameKR = getKeyedRefForIbpmWs();
        }
        else if (planName.equalsIgnoreCase(WFXML_SERVICE_NAME)) {
            nameKR = getKeyedRefForWfXml();
        } 
        else
        {
            nameKR = getKeyedRefForWfXmlPd(planName, version);
        }
        
        return nameKR;
    }
    

    /**
     * Closes the given WebdavResource.
     * @param wRes WebdavResource to close.
     */
    public
    void
    closeWebdavResource(
        WebdavResource  wRes) 
    {   
        try {
            if (wRes != null) {
                wRes.close();
                wRes = null;
            }
        } catch (Exception e) {
            // thats OK if unable to close the resource.
        }
    }
    
    /*
     * Delete all the processdefinitions that were created for the test case.
     */ 
    private void
    cleanUp() 
        throws Exception
    {
         // get all test case relates plans and delete them.
        WFObjectList wfObjectList = null;
        wfObjectList = WFObjectFactory.getWFObjectList(wfSession);
        wfObjectList.addFilter(WFObjectList.LISTFIELD_PLAN_NAME, 
                               WFObjectList.SQLOP_LIKE ,
                               "'MDPublishingTestPlan%'");
        wfObjectList.addFilter(WFObjectList.LISTFIELD_PLAN_STATE, 
                               WFObjectList.SQLOP_NOTEQUALTO ,
                               "'" + Plan.STATE_DELETED + "'");

        wfObjectList.openBatchedList(FilterEnum._AllProcessDefinitions);
        
        Object[] pList = wfObjectList.getNextBatch(2000); 
        wfObjectList.closeList();
        
        if (pList == null)
            return;
        
        for (int i=0; i<pList.length; i++) {
            wfSession.deletePlan( ((Plan) pList[i]).getId());
        }
    }
    
}