/*
 *  ClientReplyVisitor.java v0.10 20-DEC-1999
 *  Copyright (c) TKK/TLM/Calypso
 *  Author: Alexey Mednonogov
 */

package codec.visit;

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

import codec.*;
import codec.adapt.*;
import codec.convert.*;
import codec.debug.*;
import codec.dyntree.*;
import codec.export.*;
import codec.orb.*;
import codec.pco.*;
import codec.server.*;
import codec.client.*;
import codec.visit.*;
import codec.build.*;

/** Class implementing introspection of Client Reply PDU received from
 *  Tester in order to prepare a response to Client invocation. */
public class ClientReplyVisitor extends ServerCallVisitor {

    // --------------------- CLASS OUTPUT PARAMETERS --------------------

   	protected ClientRequest clientRequest;
	protected boolean isVisitorFinalized;

   	/** Get invocation request prepared by Visitor. */
   	public ClientRequest getClientRequest()
        throws com.t3.ot.misc.OtException {

		if (!isVisitorFinalized) finalizeVisitor();
		return clientRequest;
	}

    // ----------------------- CLASS CONSTRUCTOR ------------------------

   	public ClientReplyVisitor(String pcoName_, com.t3.ot.pco.ASP asp_)
		throws com.t3.ot.misc.OtException {

		super(pcoName_, asp_);

        // Add this section to allow subclasses derived from this class
		// override initialization procedure introduced by it:

        Class thisClass = null;
        try { thisClass = Class.forName(
			"codec.visit.ClientReplyVisitor"); }
        catch (ClassNotFoundException cnfe) { }

        if (!this.getClass().getName().equals(
			thisClass.getName())) return;

        // "This" class initialization procedure:

        isVisitorFinalized = false;
        isContextPresent = false;

        // Get CORBA object for which request is being prepared:
		CodecObject codec = CorbaServer.getCodecObject();

        CorbaObject corbaObject =
            codec.getCorbaObjectPool().getObject(pcoName);

        if (corbaObject == null) throw new VisitorPcoUnreg();
		if (corbaObject.getPcoType() != CorbaObject.PCO_TYPE_CLIENT)
			throw new VisitorNotClient();

        object = corbaObject.getObject();

		long callID_ = 0;
		try { callID_ = asp.element("CALL_ID").getLong(); }
		catch (com.t3.ot.misc.NotFound nfe) {

			throw new VisitorInvalidFormat(
				"CALL_ID field was not found in PDU.");
		}
        catch (com.t3.ot.misc.WrongType wte) {

			throw new VisitorInvalidFormat(
				"Type of CALL_ID field is other than INTEGER.");
		}
        catch (com.t3.ot.misc.OutOfRange ore) {

			throw new VisitorInvalidFormat(
				"Value of CALL_ID field is out of range.");
		}

		clientRequest = codec.getClientRequestPool().getRequest(callID_);
		if (clientRequest == null) {

			throw new VisitorInvalidFormat("Reply PDU is sent as " +
                "a response to operation for which corresponding " +
			    "internal binding was not found.");
		}

        if (!clientRequest.getPcoName().equals(pcoName_)) {

            throw new VisitorInvalidFormat("Reply PDU is sent as " +
                "a response to operation which has been initially " +
                "sent through different PCO.");
		}

        if (!asp.getName().startsWith("pREPLY_i")) {

            throw new VisitorInvalidFormat("Reply PDU name is invalid.");
		}
        if ((asp.getName().length() < 9) || 
            (clientRequest.getAspName().length() < 8) ||
            (!asp.getName().substring(8).equals(
				clientRequest.getAspName().substring(7)))) {

            throw new VisitorInvalidFormat("Reply PDU attempts to respond " +
                "to operation which name does not match Reply PDU name.");
		}

        // Prepare NVList and result from ClientRequest:

        nvList = clientRequest.nvList;
        if (nvList == null) {

			throw new VisitorInvalidFormat("Reply PDU is sent as " +
                "a response to operation for which corresponding " +
			    "internal NVList was not constructed beforehand.");
		}

        org.omg.CORBA.Any any = clientRequest.result;
        if (any == null) {

			throw new VisitorInvalidFormat("Reply PDU is sent as " +
                "a response to operation for which corresponding " +
			    "\"result\" was not constructed beforehand.");
		}

        org.omg.CORBA.NamedValue result = orb.create_named_value(
            "RET_value", any, org.omg.CORBA.ARG_OUT.value);

        // Assign initial state to state automaton represented by Visitor:
		adapter = new VisitorAdapter();
		adapter.create(nvList, result, VisitorAdapter.OPTIONS_CLIENT_REPLY);
		dynIterator = adapter.iterator();
	}

    // ----------------------- CLASS POSTPROCESSOR ----------------------

   	/** Make final actions on invocation request prepared by Visitor
     *  after Visitor is accepted. */
   	protected void finalizeVisitor() throws com.t3.ot.misc.OtException {

        super.finalizeVisitor();
        adapter.updateContents();
        isVisitorFinalized = true;
	}
}
