package com;
/***************************************************************************
 *   (c) Copyright 2003 NPTest, Inc.                                       *
 *   This computer program includes Confidential, Proprietary Information  *
 *   and is a trade secret of NPTest.  All use, disclosure, and/or         *
 *   reproduction is prohibited unless authorized in writing by an officer *
 *   of NPTest.  All Rights Reserved.                                      *
 ***************************************************************************/
/**
 * @file BinResultConsumer.java
 * Contains all classes related binning data (soft, hard) handling management.
 */


import java.util.Iterator;
import java.util.Vector;

import managers.CapAreaManager;

import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import org.omg.CORBA.ORB;

import Sapphire.CAP.CapArea;
import Sapphire.CAP.CommonAccessPort;
import Sapphire.CAP.ResultManager;
import SapphireTsp.CoreTsp;
import SapphireTsp.TspRuntimeException;


/**
 * @class BinResultConsumer
 * This class also provide basic methods to get bin results.
 * Acitivate anad deactivate methods are dedicated to the registration and
 * unregistration to flow:device information of the result consumer.
 * This class extends the CORBA POA server dedicated to result consumers.
 */ 
public class BinResultConsumer extends Sapphire.CAP.ResultConsumerPOA 
{
  /**
   * @name Private Members
   */
  //@{
  /// Internal class storage of the received sites.
  protected boolean _receivedSites[] = null;
  /// Handle to the CORBA activated object
  protected byte[] _id = null;
  /// Internal class storage of the hard bin information
  public String _hardBinId[] = null;
  /// Internal class storage of the soft bin information
  public String _softBinId[] = null;
  /// Internal class storage of the hard bin name information
  public String _hardBinName[] = null;
  /// Internal class storage of the soft bin name information
  public String _softBinName[] = null;
  public String _softBinDesc[] = null;
  public String _hardBinDesc[] = null;
  /// Internal class storage of the unit id information
  public String _unitId[] = null;
  protected static Vector simSiteVector = new Vector();
  /// Internal class storage of the PASS/FAIL result information
  protected int _binResult[] = null;
   // 14225 ResultHelper used to expand compactData into the normal ResultElement
  ResultHelper _resultHelper = null;
  
  protected boolean simulationMode;
  protected int simulationSiteCnt;
  
  protected boolean debugFlag = false;
  String[] TSPAction={null,null};
  ResultManager rmMgr = null;
  POA portableObjectAdapter = null;
  CapArea tpMgr = null;
  //@}

  //---------------------------------------------------------------------------
  /**
   * Initialize the result consumer.
   * - Clean hard and soft bin storage
   * - Executed Site Mask is stored.
   * - Received Site Mask is cleared.
   *
   * @exception TspRuntimeException thrown when Runtime or Corba error
   */
  //---------------------------------------------------------------------------
  public BinResultConsumer(boolean simMode,int simSiteNum) throws TspRuntimeException
  {
    try {
    	// Allocate the binning arrays
    	int nSites;
    	simulationMode = simMode;
    	if (!simMode)
    	{
    		CapAreaManager capAreaManager = CapAreaManager.instance();
    		tpMgr = capAreaManager.testProgram();
    	
    		CapArea loadedSiteMask = tpMgr.getObject("LoadedSiteMask"); 
    		nSites = loadedSiteMask.getL("Size");
    		loadedSiteMask.cleanUp();
    		
    	}
    	else {
    		nSites = simSiteNum;
    		simulationSiteCnt = simSiteNum;
    	}
    	_hardBinId = new String[nSites];
    	_softBinId = new String[nSites];
    	_hardBinName = new String[nSites];
    	_softBinName = new String[nSites];
    	_softBinDesc= new String[nSites];
    	_hardBinDesc= new String[nSites];
    	_unitId = new String[nSites];
    	_binResult = new int[nSites];
    	_resultHelper = new ResultHelper();
      
    	// Store received Site boolean marker
    	_receivedSites = new boolean[nSites];
    	if (!simMode)
    		activate();
    	
    	}
    catch (Sapphire.lib.error.Fatal f) {
        // Print the exception, the stack and rethrow as TspRuntimeException
  			System.err.println(f.msg);
  			System.err.println(f.where);
        System.err.println(f.getMessage());
        f.printStackTrace(System.err); 
        throw new TspRuntimeException("Result Error");
      }
    catch (Sapphire.lib.error.Basic e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    
  }

  /*
   * Needs to be run prior to recieveing new data.
   */
 public void clean() throws TspRuntimeException 
 {
	try {
		int nSites;
		if (simulationMode) {
			nSites = simulationSiteCnt;
		}
		else {
			CapArea loadedSiteMask = tpMgr.getObject("LoadedSiteMask"); 
    		nSites = loadedSiteMask.getL("Size");
    		loadedSiteMask.cleanUp();
		}
    	_hardBinId = new String[nSites];
    	_softBinId = new String[nSites];
    	_hardBinName = new String[nSites];
    	_softBinName = new String[nSites];
    	_softBinDesc= new String[nSites];
    	_hardBinDesc= new String[nSites];
    	_unitId = new String[nSites];
    	_binResult = new int[nSites];
    	_resultHelper = new ResultHelper();
      
    	// Store received Site boolean marker
    	_receivedSites = new boolean[nSites];
    	}
    
    catch (Sapphire.lib.error.Fatal f) {
        // Print the exception, the stack and rethrow as TspRuntimeException
  			System.err.println(f.msg);
  			System.err.println(f.where);
        System.err.println(f.getMessage());
        f.printStackTrace(System.err); 
        throw new TspRuntimeException("Result Error");
      }
    catch (Sapphire.lib.error.Basic e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
   
	
 }
  //---------------------------------------------------------------------------
  /**
   * Activate (register) the result consumer.
   *
   * @exception TspRuntimeException thrown when Runtime or Corba error
   */
  //---------------------------------------------------------------------------
  public void activate() throws TspRuntimeException
  {
    try {
      // Activate the Result Consumer
    	
    	CapAreaManager capAreaManager = CapAreaManager.instance();
    	
    	CommonAccessPort cap = (CommonAccessPort) capAreaManager.capInterface();;
      
    	ORB orb = org.omg.CORBA.ORB.init(new String[0], null);
    	
    	org.omg.CORBA.Object obj = orb.resolve_initial_references("RootPOA");

  		// create POA <equivalent to narrow() but typecast is used here>
    	portableObjectAdapter = (POA) obj;
    	
    	_id = portableObjectAdapter.activate_object(this);

    	 org.omg.PortableServer.POAManager poaMgr = portableObjectAdapter.the_POAManager();
    	 poaMgr.activate();
    	
      // Subscribe Result Consumer to flow.Device information
      rmMgr = cap.getResultManager();
      
      //*NL* get the handle of resultManager from runtime instance 
      // *NL* pass the servant_locator of servant BinResultConsumer
      rmMgr.subscribe("FlowResult:NODE:DEVICE:flow.Device", _this(), "*", "*", true);
      rmMgr.subscribe("TestResult:Test", _this(), "ReadFuncFuse", "*", true);
    }
    catch (AdapterInactive e)
    {
    	System.err.println("POA is inactive.  This is a CORBA communication related issue.");
    	throw new TspRuntimeException("Internal DataPackage Setup Error.");
    }
    catch (org.omg.PortableServer.POAPackage.ServantAlreadyActive e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    catch (org.omg.PortableServer.POAPackage.WrongPolicy e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    catch (Sapphire.lib.error.Basic e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    catch (Sapphire.lib.error.Fatal e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
  	catch (InvalidName e){
			CoreTsp.out("A CORBA exception occurred induced by the TSP.");
			throw new TspRuntimeException(e);
		}
  }

  //---------------------------------------------------------------------------
  /**
   * Deactivate (unregister) the result consumer.
   *
   * @exception TspRuntimeException thrown when Runtime or Corba error
   */
  //---------------------------------------------------------------------------
  public void deactivate() throws TspRuntimeException 
  {
    try { 
      //rMgr.unsubscribe("*:flow.Device", _this(), "*", "*"); //1415
      rmMgr.unsubscribe("FlowResult:NODE:DEVICE:flow.Device", _this(), "*", "*");
      rmMgr.unsubscribe("TestResult:Test", _this(), "ReadFuncFuse", "*");
      
      // Deactivate the Result Consumer 
      portableObjectAdapter.deactivate_object(_id);
      
    }
    catch (org.omg.PortableServer.POAPackage.ObjectNotActive e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    catch (org.omg.PortableServer.POAPackage.WrongPolicy e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    catch (Sapphire.lib.error.Basic e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
    catch (Sapphire.lib.error.Fatal e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err); 
      throw new TspRuntimeException("Result Error");
    }
  }

  //---------------------------------------------------------------------------
  /**
   * Get the Hard Bin Id
   */
  //---------------------------------------------------------------------------
  public String[] hardBinId() 
  {
    return _hardBinId;
  }
  
  //---------------------------------------------------------------------------
  /**
   * Get the Hard Bin Name
   */
  //---------------------------------------------------------------------------
  public String[] hardBinName() 
  {
    return _hardBinName;
  }

  //---------------------------------------------------------------------------
  /**
   * Get the Hard BinDesc 
   */
  //---------------------------------------------------------------------------
  public String[] hardBinDesc() 
  {
    return _hardBinDesc;
  }

  //---------------------------------------------------------------------------
  /**
   * Get the Soft Bin Id
   */
  //---------------------------------------------------------------------------
  public String[] softBinId() 
  {
    return _softBinId;
  }

  //---------------------------------------------------------------------------
  /**
   * Get the Soft Bin Name
   */
  //---------------------------------------------------------------------------
  public String[] softBinName() 
  {
    return _softBinName;
  }

  //---------------------------------------------------------------------------
  /**
   * Get the Soft Bin Desc
   */
  //---------------------------------------------------------------------------
  public String[] softBinDesc() 
  {
    return _softBinDesc;
  }
//---------------------------------------------------------------------------
  /**
   * Get the Unit Id
   */
  //---------------------------------------------------------------------------
  public String[] unitId() 
  {
    return _unitId;
  }
  //---------------------------------------------------------------------------
  /**
   * Get the PASS/FAIL result
   */
  //---------------------------------------------------------------------------
  public int[] binResult() 
  {
    return _binResult;
  }
  public static void markSimulatedExecutedSite(int site)
  {
	  if(simSiteVector != null)
	  {
		  simSiteVector.add(new Integer(site));
	  } else {
		  CoreTsp.out("Nothing Executed");
	  }
  }
  //---------------------------------------------------------------------------
  /**
   * Get the Done flag (true if all sites received)
   */
  //---------------------------------------------------------------------------
  public boolean isDone() 
  {
    boolean areIdentical = true;
    boolean executedSites[];
    
    // Get executed Site array marker
    if (simulationMode)
    {
    	executedSites = new boolean[simulationSiteCnt];
    	for (int i = 0; i<simulationSiteCnt;i++)
    		executedSites[i] = false;
    	Iterator itr = simSiteVector.iterator();
    	while(itr.hasNext())
    		executedSites[((Integer)itr.next()).intValue()] = true;
    }
    else {
    try {
    		
      Sapphire.CAP.CapArea loadedSiteMask = tpMgr.getObject("LoadedSiteMask"); 
      int nSites = loadedSiteMask.getL("Size");
      loadedSiteMask.cleanUp();
      
      executedSites = new boolean[nSites];
      Sapphire.CAP.CapArea siteMask = tpMgr.getObject("ExecutedSiteMask");
      Sapphire.CAP.CapArea siteMaskItr = null;
      siteMaskItr = siteMask.getArea("Iterator");
      while (siteMaskItr.hasNext()) {
        int site = siteMaskItr.getL("Next");
        executedSites[site] = true;
      }
      siteMaskItr.cleanUp();
      siteMask.cleanUp();
    }
    catch (Sapphire.lib.error.Basic e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err);
      return false;
    }
    catch (Sapphire.lib.error.Fatal e) {
      // Print the exception, the stack and rethrow as TspRuntimeException
			System.err.println(e.msg);
			System.err.println(e.where);
      System.err.println(e.getMessage());
      e.printStackTrace(System.err);
      return false;
    }
    }
    // Compare executed sites and received sites
    for (int i = 0; i < _receivedSites.length; i++) {
      if (executedSites[i] != _receivedSites[i]) {
        areIdentical = false;
      }
    } 
    return areIdentical; 
  }

  //---------------------------------------------------------------------------
  /**
  * Implement the handleResult() to be called by updateResult()
   */
  //---------------------------------------------------------------------------
  public void handleResult(Sapphire.CAP.ResultData resultData)
  {
    for (int idx = 0; idx < resultData.site.length; ++idx) {
      int iSite = resultData.site[idx];

      if (resultData.element.elements == null) {
        continue;
      }
      Sapphire.CAP.ResultElement elmts[] = resultData.element.elements;
      for (int i = 0; i < elmts.length; i++) {
        Sapphire.CAP.ResultElement elmt = elmts[i];
        // Hard Bin Id stored into 'HardBinId' tag
        if (elmt.name.equals("HardBinId"))
        	_hardBinId[iSite] = elmt.value.extract_string();
        else if (elmt.name.equals("HardBinName"))
        	_hardBinName[iSite] = elmt.value.extract_string();
        else if (elmt.name.equals("SoftBinId")) 
        	_softBinId[iSite] = elmt.value.extract_string();
        else if (elmt.name.equals("SoftBinName"))
        	_softBinName[iSite] = elmt.value.extract_string();
        else if (elmt.name.equals("SoftBinDesc"))
            _softBinDesc[iSite] = elmt.value.extract_string();
        else if (elmt.name.equals("HardBinDesc"))
            _hardBinDesc[iSite] = elmt.value.extract_string();
        else if (elmt.name.equals("DeviceDescription"))
        	_unitId[iSite] = elmt.value.extract_string();
	    else if (elmt.name.equals("TestDecision"))
	    	if (elmt.value.extract_string().equals("Pass"))
	    		_binResult[iSite] = 1;
	    	else
	    		_binResult[iSite] = 0;
      }
      // Mark the received site
      _receivedSites[iSite] = true;
    }
  }
  
 /* //added function to get unit ID using PUSH method
  public void retrieveUnitId (Sapphire.CAP.ResultData resultData){
	  //System.out.print("resultData object" + resultData);
	  //CoreTsp.out("resultData object" + resultData);
	  if(_IsSerialNumberObject(resultData) == true){
    	for (int idx = 0; idx < resultData.site.length; ++idx){
  			if (resultData.element.elements == null){
  				continue;
  			}
  			int iSite = resultData.site[idx];
  			if(_receivedSites[iSite] == false){
  				Sapphire.CAP.ResultElement elmts[] = resultData.element.elements;
  				for (int i = 0; i < elmts.length; i++){
  					Sapphire.CAP.ResultElement elmt = elmts[i];
  					String FieldName = elmt.name;
  					if(_isSerialNumberField(FieldName) == true){
  						//added to retrieve unit id
  						//System.out.println("Element Val" + elmt.value.extract_string());
  						//CoreTsp.out("Element Val" + elmt.value.extract_string());
  						_unitId[iSite] = elmt.value.extract_string();
  						//Mark the received site
  						_receivedSites[iSite] = true;
  						break;
  					}
  				}
  			}
  		}
	  }
  }
 */
  private boolean _IsSerialNumberObject(Sapphire.CAP.ResultData resultData){
	  if (resultData.element != null){
		  String Name = resultData.element.name;
		  if(Name.equals("FuseRecord"))
			  return true;
		  else if(Name.equals("JTAG_FUNCFUSE"))
			  return true;
		  else if(Name.equals("JTAG_FUNCFUSE_SH_F"))
			  return true;
		  else if(Name.equals("JTAG_FUNCFUSE_SH_E"))
			  return true;
		  else if(Name.equals("JTAG_FUNCFUSE_JH_E"))
			  return true;
	  }
	  return false;
  }
  
  public boolean _isSerialNumberField (String FieldName){
        String [] SerialNumberFieldNames = {
        "FuseBitValues", 
        "DieFuseBitValues",
        "SerialNum",
        "FuseBits",
        "funcfuse",
        "redundfuse",
        "RedundFuse",
        "RedundFuseCore1",
        "RedundFuseCore1_ProgFuseBits",
        "ReadRedundFuseCore0",
        "ProgramRRDFuseCore0",
        "RedundFuse_VerifyBits",
        "RedundFuseCore1_VerifyBits",
        "FuncFuse",
        "FuncFuse_VerifyBits",
        "funcfuse_VerifyBits",
        "fusereg_ProgFuseBits",
        "funcfuse_ProgFuseBits",
        "redundfuse_ProgFuseBits",
        "RMW_ProgFuseBits",
        "RMW_VerifyBits"
      };
        boolean RetValue = false;
        for (int idx = 0; idx < SerialNumberFieldNames.length; ++idx){
        	if(SerialNumberFieldNames[idx].equals(FieldName)){
        		RetValue = true;
        		break;
        	}
        }
        return RetValue;
  }

  /* Implement the pure virtual updateResult() call back method
   */
  //---------------------------------------------------------------------------
  public void updateResult(Sapphire.CAP.ResultData result)
  {
    // Extract element: Only interested in POP_ELEMENT
    // Skip PUSH ELEMENT
    // Skip POP_TO_ELEMENT
    // Skip ADD_ELEMENT 
	  if (result.elementContext == Sapphire.CAP.ResultContext.POP_ELEMENT
			  ||
			  result.elementContext == Sapphire.CAP.ResultContext.POP_TO_ELEMENT
			  ) {
      if (result.compactData != null && result.compactData.length() > 0) {
        Sapphire.CAP.ResultData resultData = new Sapphire.CAP.ResultData();
        resultData.type = result.type; 
        resultData.elementContext = result.elementContext;
        resultData.flowContext = result.flowContext;
        resultData.site = result.site;
        resultData.element = new Sapphire.CAP.ResultElement();
        
        try {
          _resultHelper.reset();
          while (_resultHelper.expandElement(result.compactData,resultData.element)) {
            handleResult(resultData);
          }
        } catch (TspRuntimeException e) {
          CoreTsp.out("BinResultConsumer::" + e.getMessage());
          e.printStackTrace();
        }
      } else {
        handleResult(result);
      }
    }
	
	/*  //added to retrive Unit Id
	  if (result.elementContext == Sapphire.CAP.ResultContext.ADD_ELEMENT){
		  if (result.compactData != null && result.compactData.length() > 0) {
			  Sapphire.CAP.ResultData resultData = new Sapphire.CAP.ResultData();
		      resultData.type = result.type; 
		      resultData.elementContext = result.elementContext;
		      resultData.flowContext = result.flowContext;
		      resultData.site = result.site;
		      resultData.element = new Sapphire.CAP.ResultElement();
		      
		      try {
		    	  _resultHelper.reset();
		          while (_resultHelper.expandElement(result.compactData,resultData.element)) {
		        	retrieveUnitId(resultData);
		          }
		      } catch (TspRuntimeException e) {
		    	  CoreTsp.out("BinResultConsumer::" + e.getMessage());
		          e.printStackTrace();
		        }
	  } else{
		  retrieveUnitId(result);
	  	}
	  }*/
  }

  //---------------------------------------------------------------------------
  /**
   * Implement the pure virtual quit() call back method
   */
  //---------------------------------------------------------------------------
  public void quit (boolean shutdown)
  {
  }
  
  /**
   * Emulates the functionality of the loadsitemask, which we cannot use
   * in simulation mode.  Therefore, this method should only be called 
   * while in simulation mode.
   */
  public static void setSiteExecuted(int site){
	  simSiteVector.add(new Integer(site));
  }
}