/* 
  FILE: ServletDeploymentTest.java

23-Aug-05  K-03-31  JCN  $$1  Submitted.

*/
package com.ptc.jlink_servlet;

import java.io.File;
import java.util.*;

import com.ptc.cipjava.*;
import com.ptc.pfc.pfcSession.*;
import com.ptc.pfc.pfcModel.*;
import com.ptc.pfc.pfcSolid.*;
import com.ptc.pfc.pfcModelItem.*;
import com.ptc.pfc.pfcFeature.*;
import com.ptc.pfc.pfcExceptions.*;
import com.ptc.pfc.pfcWindow.*;
import com.ptc.pfc.pfcAsyncConnection.*;

/**
 * This the underlying J-Link implementation for the sample servlet.  
 * It handles all Pro/ENGINEER communications for the servlet.
 * Implements Runnable so that the processing can be moved to a subordinate 
 * thread (so that the servlet can inquire of the test status
 * even while the Pro/E communications is underway).
 **/
public class ServletDeploymentTest implements Runnable
{
    /**
     * Main handle to the Pro/E session.
     */
    private Session proeSession;

    /**
     * Handle to the test model.
     */
    private Model proeModel;
    
    /**
     * Success/failure status of the test.
     */
    private boolean status = false;
    
    /**
     * Pro/ENGINEER command supplied by the client.
     */
    private String proeCmd;
    
    /**
     * Pro/ENGINEER loadpoint supplied by the client.
     */
    private String proeLoadpoint;
    
    /**
     * Path to the servlet context, so that the generated image file can 
     * be passed back from the server to the client.
     */
    private String servletContextHome;

    /**
     * Path to the JPEG file.
     */
    private String jpegFileName;
    
    /**
     * Run status of the test.
     */
    private boolean finished = false;
    
    /**
     *  List of feature info used for generating the output tables.
     */
    private ArrayList featureList;

    /**
     * Reference to the library loading class (which must be in the servlet shared location).
     */
    private static com.ptc.jlink_loader.JLinkLoader loader = new com.ptc.jlink_loader.JLinkLoader();

    /**
     * Test constructor; starts a new thread for running the J-Link 
     * implementation.
     */
    public ServletDeploymentTest (String proe_cmd, String proe_loadpoint, String contextHomeDir) throws Exception 
    {
	servletContextHome = contextHomeDir;
	proeCmd = proe_cmd;
	proeLoadpoint = proe_loadpoint;
	featureList = new ArrayList ();
	Thread t = new Thread (this);
	t.setPriority (Thread.MAX_PRIORITY);
	t.start();
    }

    /**
     * The thread implementation.  Starts Pro/E, loads the test model, 
     * executes the tests, and closes Pro/E.
     */
    public void run()
    {
	try
	{
	    AsyncConnection asyncConnection = 
		pfcAsyncConnection.AsyncConnection_Start (proeCmd + 
			        " -g:no_graphics -i:rpc_input", null);
	    
	    proeSession = asyncConnection.GetSession ();
	    
	    status = loadModel();
	    
	    if (status) 
		{
		    /**
		     * Execute all of the portions of the test. 
		     */
		    status = setWorkingDir () && getInfo() && 
			export() && unloadModel();
		}
	    
	    asyncConnection.End();
	}
	catch (Throwable x)
	{
	    ServletDeploymentTest.printMsg ("Unexpected exception caught: "+x);
	    x.printStackTrace ();
	}
	finally
	{
	    /**
	     * Set the finished flag so that the servlet will display 
	     * the results.
	     */
	    finished = true;
	}
    }
  
    /**
   * This function loads the test model and displays it.  The test model is 
   * "pfcinstalltest.prt" from the 
   * Pro/E loadpoint (in the J-Link install test directory).
   **/
    public boolean loadModel()
    {
	try
	{
	    String modelDir = proeLoadpoint;
	    String separator = File.separator;
	    ModelType mdl_type = ModelType.MDL_PART;
	    ModelDescriptor proeModelDescriptor =
		pfcModel.ModelDescriptor_Create (mdl_type, 
						 "pfcinstalltest", "");

	    if (!modelDir.endsWith (separator))
		modelDir+= separator;
	    modelDir+="jlink" + separator + 
		"jlink_appls" + separator + "install_test";
	    printMsg ("Loading model at " + modelDir);
	    proeModelDescriptor.SetPath (modelDir);
	    
	    RetrieveModelOptions opts = 
		pfcSession.RetrieveModelOptions_Create ();
	    
	    proeModel = 
		proeSession.RetrieveModelWithOpts(proeModelDescriptor, opts);
	    proeModel.Display();

	    printMsg("Model was retrieved");
	}
	catch(jxthrowable x)
	{
	    printMsg("pfcException: " + x);
	    x.printStackTrace ();
	    return false;
	}
	return true;
    }

    /**
     * Change the Pro/ENGINEER working dir to the servlet run directory. 
     * Not really necessary for this example, since we use the full path for 
     * generation of the output file.
     */
    private boolean setWorkingDir ()
    {
	try
	{
	    proeSession.ChangeDirectory (servletContextHome);
	}
	catch(jxthrowable x)
	{
	    printMsg("pfcException: " + x);
	    x.printStackTrace ();
	    return false;
	}
	return true;
    }

    /**
	 * Export a JPEG of the displayed model.
	 */
    public boolean export ()
    {
	try
	{
	    jpegFileName = proeModel.GetInstanceName().toLowerCase()+".jpg";
	    String fullFilePath = servletContextHome + jpegFileName;
	    JPEGImageExportInstructions instrs = 
		pfcWindow.JPEGImageExportInstructions_Create (3.5, 2.5);
	    instrs.SetDotsPerInch (DotsPerInch.RASTERDPI_200);
	    proeSession.ExportCurrentRasterImage (fullFilePath, instrs);
	}
	catch(jxthrowable x)
	{
	    printMsg("pfcException: " + x);
	    x.printStackTrace ();
	    jpegFileName = null;
	    return false;
	}
	return true;
    }	

    /**
     * Generates HTML table rows listing information about every 
     * user-visible feature in the test model.
     **/
    public boolean getInfo() 
    {
	int numberOfFeatures;
	Feature proeFeature;
	
	ModelItems proeModelItems;
	try
	{
	    proeModelItems = proeModel.ListItems (ModelItemType.ITEM_FEATURE);
	    
	    numberOfFeatures = proeModelItems.getarraysize();
	    for (int j = 0; j < numberOfFeatures; ++j)
	    {
		proeFeature = (Feature)proeModelItems.get(j);
		if (!proeFeature.GetIsVisible ())
		    continue;
		
		String featureTableEntry = "<TR><TD>";
		
		
		featureTableEntry += proeFeature.GetNumber() + "</TD><TD>";
		String featName = proeFeature.GetName();
	    
		/**
		 * Check if there is a user-defined name; 
		 * if not, use a default name.
		 */
		if (featName == null)
		    {
			featureTableEntry += proeFeature.GetFeatTypeName().toLowerCase()+" id "+proeFeature.GetId () + "</TD><TD>";
		    }
		else
		    featureTableEntry +=  featName + "</TD><TD>";

		featureTableEntry += proeFeature.GetId() + "</TD><TD>";
		featureTableEntry += proeFeature.GetFeatTypeName() + "</TD></TR>";
		
		featureList.add (featureTableEntry);
	    }    
	}
	catch(jxthrowable x)
	{
	    x.printStackTrace ();
	    return false;
	}
	return true;
    }
  
    /**
   * This method erases the test model.
   **/
    private boolean unloadModel()
    {
	try
	{ 
	    proeModel.Erase();
	}
	catch(jxthrowable x)
	{
	    System.out.println("pfcException: " + x);
	    x.printStackTrace ();
	    return false;     
	}
	return true;
    }
    
    /**
     * Returns the success/failure status of the test.
     */
    public boolean getStatus ()
    {
	return status;
    }

    /**
     * Returns the jpeg file.
     */
    public String getJPEGFileName ()
    {
	return jpegFileName;
    }

    /**
     * Indicates if the test has completed.
     */
    public boolean finished ()
    {
	return finished;
    }

    /**
     * Returns an iterator to the feature info table rows.
     */
    public Iterator getFeatureTableRows()
    {
	return featureList.iterator();
    }

    /**
     * Send a message to stdout; many servlet containers will redirect these messages to log files.
     */
    public static void printMsg (String str) 
    {
	System.out.println("J-Link install test: " + str); 
    }
}

   

  
	   


    
    


  
    

    
	    
	    
    
    
    


