//******************************************************************************
//
// Restricted Rights
// WARNING: This is a restricted distribution Zeligsoft file.
//
//******************************************************************************
//
// Copyright (C) 2006 Zeligsoft Inc. - All Rights Reserved
//

//******************************************************************************
//
//     FILE: zceProcessRxServant.cpp
//
//******************************************************************************


#include <sstream>

#include "PortTypes.h"

#include "zceProcessRxServant.h"
#include "zceProcessRxWorker.h"

#include "zceCPPUtilities.h"


zceProcessRxServant::zceProcessRxServant( const CORBA::ORB_ptr& orb, const ProcessRx_params& execParams ZCE_EXC_ENV_ARG)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	orb_ = CORBA::ORB::_duplicate(orb);

	params_ = execParams;

	state_ = UNINITIALIZED;

	out_portDataOutData = new zcePushPorts_OctetSeqConsumerUsesPort("portDataOutData" ZCE_EXC_ENV_PARAM );
	out_portDataOutVoice = new zcePushPorts_OctetSeqConsumerUsesPort("portDataOutVoice" ZCE_EXC_ENV_PARAM );

	worker_ = new zceProcessRxWorker(execParams, out_portDataOutData, out_portDataOutVoice ZCE_EXC_ENV_PARAM );

	in_portDataIn = new zcePushPorts_OctetSeqConsumerProvidesPort("portDataIn", PROCESSRX_PORTDATAIN, worker_ ZCE_EXC_ENV_PARAM );
}

zceProcessRxServant::~zceProcessRxServant()
{

	MutexLock lock(mutex_);
	delete in_portDataIn;
	in_portDataIn = NULL;
	delete out_portDataOutData;
	out_portDataOutData = NULL;
	delete out_portDataOutVoice;
	out_portDataOutVoice = NULL;
	delete worker_;
	worker_ = NULL;
}

/*!
 * \brief The readonly identifier attribute shall contain the unique identifier
 * for a resource instance.
 *
 * Specification reference:  3.1.3.1.6.4.1
 *
 */
char* zceProcessRxServant::identifier(ZCE_EXC_ENV_SINGLE_ARG)
	throw (CORBA::SystemException)
{
	char * _pcRetVal = NULL;
	ZCE_ASSERT_EXCEPTION(_pcRetVal);
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::identifier";
	worker_->debugMsg(debug_message);
	#endif


	if( state_ == DESTROYED )
	{
		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::identifier - Cannot access the identifier of a component that has been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0, CORBA::COMPLETED_NO ) );
	}

	return CORBA::string_dup(params_.COMPONENT_IDENTIFIER.c_str());
}

/*!
 * \brief The start operation is provided to command a Resource implementing this
 * interface to start internal processing.
 *
 * Specification reference:  3.1.3.1.6.5.2
 *
 * The start operation puts the Resource in an operating condition.
 *
 * \return This operation does not return a value.
 *
 * \throw StartError The start operation shall raise the StartError exception if
 * an error occurs while starting the resource.
 *
 */
void zceProcessRxServant::start(ZCE_EXC_ENV_SINGLE_ARG)
	throw (CORBA::SystemException, CF::Resource::StartError)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	MutexLock lock(mutex_);
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::start";
	worker_->debugMsg(debug_message);
	#endif


	if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"start\" a component that has been released.";

		ZCE_EXC_THROW( CORBA::OBJECT_NOT_EXIST, ( 0, CORBA::COMPLETED_NO ) );
	}
	else if( state_ == UNINITIALIZED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"start\" a component that has not been initialized.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::start - Cannot \"start\" a component that has not been initialized.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CF::Resource::StartError,( CF::CF_EPERM,  CORBA::string_dup(message.c_str()) ) );
	}
	else if( state_ == STARTED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": component is already started.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::start - Component is already started.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CF::Resource::StartError,( CF::CF_EPERM,  CORBA::string_dup(message.c_str()) ) );
	}

	worker_->CF_Resource_start( PROCESSRX_SUPPORTED_INTERFACE ZCE_EXC_ENV_PARAM );


	state_ = STARTED;

}

/*!
 * \brief The stop operation is provided to command a Resource implementing this
 * interface to stop internal processing.
 *
 * Specification reference:  3.1.3.1.6.5.1
 *
 * The stop operation shall disable all current operations and put the Resource in
 * a non-operating condition. Subsequent configure, query, and start operations
 * are not inhibited by the stop operation.
 *
 * \return This operation does not return a value.
 *
 * \throw StopError The stop operation shall raise the StopError exception if an
 * error occurs while stopping the resource.
 *
 */
void zceProcessRxServant::stop(ZCE_EXC_ENV_SINGLE_ARG)
	throw (CORBA::SystemException, CF::Resource::StopError)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	MutexLock lock(mutex_);
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::stop";
	worker_->debugMsg(debug_message);
	#endif


	if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"stop\" a component that has been released.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::stop - Cannot \"stop\" a component that has been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}
	else if( state_ == UNINITIALIZED || state_ == INITIALIZED || state_ == STOPPED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"stop\" a component that has not been started.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::stop - Cannot \"stop\" a component that has not been started.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CF::Resource::StopError,( CF::CF_EPERM,  CORBA::string_dup(message.c_str()) ) );
	}

	worker_->CF_Resource_stop( PROCESSRX_SUPPORTED_INTERFACE ZCE_EXC_ENV_PARAM );

	state_ = STOPPED;

}

/*!
 * \brief The purpose of the initialize operation is to provide a mechanism to set
 * a component to a known initial state. (For example, data structures may be set
 * to initial values, memory may be allocated, hardware devices may be configured
 * to some state, etc.)
 *
 * Specification reference:  3.1.3.1.2.5.1
 *
 * Initialization behavior is implementation dependent.
 *
 * \return This operation does not return a value.
 *
 * \throw InitializeError The initialize operation shall raise an InitializeError
 * exception when an initialization error occurs.
 *
 */
void zceProcessRxServant::initialize(ZCE_EXC_ENV_SINGLE_ARG)
	throw (CORBA::SystemException, CF::LifeCycle::InitializeError)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	MutexLock lock(mutex_);
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::initialize";
	worker_->debugMsg(debug_message);
	#endif


	if( state_ != UNINITIALIZED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;

		if( state_ == INITIALIZED || state_ == STARTED || state_ == STOPPED )
		{
			message += ": Cannot initialize a component that has already been started.";

			#if defined(DEBUG_MSGS)
			std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::initialize - Cannot initialize a component that has already been started.";
			worker_->debugMsg(debug_message);
			#endif

		}
		else if( state_ == DESTROYED )
		{
			message += ": Cannot initialize a component that has already been released.";

			#if defined(DEBUG_MSGS)
			std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::initialize - Cannot initialize a component that has already been released.";
			worker_->debugMsg(debug_message);
			#endif

		}
		CF::StringSequence messages;
		messages.length(1);
		messages[0] = CORBA::string_dup(message.c_str());
		ZCE_EXC_THROW ( CF::LifeCycle::InitializeError,( messages ));
	}

	state_ = INITIALIZED;

	worker_->CF_LifeCycle_initialize( PROCESSRX_SUPPORTED_INTERFACE ZCE_EXC_ENV_PARAM );

}

/*!
 * \brief The purpose of the releaseObject operation is to provide a means by
 * which an instantiated component may be torn down.
 *
 * Specification reference:  3.1.3.1.2.5.2
 *
 * The releaseObject operation releases components from the OE. The releaseObject
 * operation shall release all internal memory allocated by the component during
 * the life of the component. The releaseObject operation shall tear down the
 * component (i.e. released from the CORBA environment).
 *
 * \return This operation does not return a value.
 *
 * \throw ReleaseError The releaseObject operation shall raise a ReleaseError
 * exception when a release error occurs.
 *
 */
void zceProcessRxServant::releaseObject(ZCE_EXC_ENV_SINGLE_ARG)
	throw (CORBA::SystemException, CF::LifeCycle::ReleaseError)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	MutexLock lock(mutex_);

	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::releaseObject";
	worker_->debugMsg(debug_message);
	#endif


	if( state_ == UNINITIALIZED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot release a component that has not been initialized.";
		CF::StringSequence messages;
		messages.length(1);
		messages[0] = CORBA::string_dup(message.c_str());

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::releaseObjectCannot release a component that has not been initialized.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CF::LifeCycle::ReleaseError,( messages ) );
	}
	else if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot release a component that has already been released.";
		CF::StringSequence messages;
		messages.length(1);
		messages[0] = CORBA::string_dup(message.c_str());

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::releaseObjectCannot release a component that has already been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CF::LifeCycle::ReleaseError,( messages ) );
	}

	state_ = DESTROYED;

	worker_->CF_LifeCycle_releaseObject( PROCESSRX_SUPPORTED_INTERFACE ZCE_EXC_ENV_PARAM );

	PortableServer::POA_var poa = _default_POA();
	PortableServer::ObjectId_var oid = poa->servant_to_id(this);
	poa->deactivate_object(oid);

	if(! CORBA::is_nil(orb_))
	{
		SHUTDOWN_COMPONENT(orb_, this, false, ZCE_MACRO_ENV_ARG)

	}

}

/*!
 * \brief The runTest operation allows components to be "blackbox" tested. This
 * allows Built-In Test (BIT) to be implemented and this provides a means to
 * isolate faults (both software and hardware) within the system.
 *
 * Specification reference:  3.1.3.1.3.5.1
 *
 * The runTest operation shall use the testId parameter to determine which of its
 * predefined test implementations should be performed. The testValues parameter
 * CF Properties (id/value pair(s)) shall be used to provide additional
 * information to the implementation-specific test to be run. The runTest
 * operation shall return the result(s) of the test in the testValues parameter.
 *
 * \param testId (unsigned long ) Use the testId parameter to determine which of
 * its predefined test implementations should be performed
 *
 * \param testValues (::CF::Properties ) The testValues parameter CF Properties
 * (id/value pair(s)) shall be used to provide additional information to the
 * implementation-specific test to be run. The runTest operation shall return the
 * result(s) of the test in the testValues parameter.
 *
 * \return The runTest operation shall return the result(s) of the test in the
 * testValues parameter.
 *
 * \throw UnknownTest The runTest operation shall raise the UnknownTest exception
 * when there is no underlying test implementation that is associated with the
 * input testId given.
 *
 * \throw UnknownProperties The runTest operation shall raise the
 * UnknownProperties exception when the input parameter testValues contains any
 * DataTypes that are not known by the component's test implementation or any
 * values that are out of range for the requested test.
 *
 */
void zceProcessRxServant::runTest( CORBA::ULong testId, CF::Properties& testValues ZCE_EXC_ENV_ARG)
	throw (
		CORBA::SystemException,
		CF::TestableObject::UnknownTest,
		CF::UnknownProperties
	)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::runTest";
	worker_->debugMsg(debug_message);
	#endif


	CF::Properties invalidProperties;

	if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"test\" a component that has been released.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::runTest - Cannot \"test\" a component that has been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}

	#if defined(DEBUG_MSGS)
	std::ostringstream oss; oss << "zceProcessRxServant::runTest - " << testId << " is an unknown test.";
	worker_->debugMsg(oss.str());
	#endif

	ZCE_EXC_THROW ( CF::TestableObject::UnknownTest,() );

}

/*!
 * \brief The configure operation allows id/value pair configuration properties to
 * be assigned to components implementing this interface.
 *
 * Specification reference:  3.1.3.1.5.5.1
 *
 * The configure operation shall assign values to the properties as indicated in
 * the configProperties argument. Valid properties for the configure operation
 * shall at a minimum be the configure readwrite and writeonly properties
 * referenced in the component's SPD.
 *
 * \param configProperties (::CF::Properties )
 *
 * \return This operation does not return a value.
 *
 * \throw PartialConfiguration The configure operation shall raise a
 * PartialConfiguration exception when some configuration properties were
 * successfully set and some configuration properties were not successfully set.
 *
 * \throw InvalidConfiguration The configure operation shall raise an
 * InvalidConfiguration exception when a configuration error occurs that prevents
 * any property configuration on the component.
 *
 */
void zceProcessRxServant::configure( const CF::Properties& configProperties ZCE_EXC_ENV_ARG)
	throw (
		CORBA::SystemException,
		CF::PropertySet::InvalidConfiguration,
		CF::PropertySet::PartialConfiguration
	)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::configure";
	worker_->debugMsg(debug_message);
	#endif


	CF::Properties invalidProperties;

	if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"configure\" a component that has been released.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::configure - Cannot \"configure\" a component that has been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}
	else if( state_ == UNINITIALIZED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"configure\" a component that has not been initialized.";

		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::configure - Cannot \"configure\" a component that has not been initialized.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}

	for(unsigned long i = 0; i < configProperties.length(); i++)
	{
		std::istringstream istr((char *) configProperties[i].id.in());
		std::string propertyId;
		if(istr >> propertyId)
		{
			// propDestinationId
			if( IfIsDCEUUIDConvertToUpper(propertyId) == IfIsDCEUUIDConvertToUpper("DestinationId"))
			{
				#if defined(DEBUG_MSGS)
				std::ostringstream configMessage; configMessage << "zceProcessRxServant::configure - Configuring property : " << propertyId << ".";
				worker_->debugMsg(configMessage.str());
				#endif

				CORBA::String_var val;
				const char* str_val;

				if(configProperties[i].value >>= str_val)
				{
					val = CORBA::string_dup(str_val);
					worker_->config_propDestinationId(val ZCE_EXC_ENV_PARAM);
				}
				else
				{
					#if defined(DEBUG_MSGS)
					std::ostringstream oss;
					std::string anyType = configProperties[i].value.type()->id();
					oss << "zceProcessRxServant::configure - " << propertyId << " - Cannot extract value from any type " << anyType << ".";
					worker_->debugMsg(oss.str());
					#endif

					invalidProperties.length(invalidProperties.length()+1);
					invalidProperties[invalidProperties.length()-1] = configProperties[i];
				}
			}
			// propModulation
			else if( IfIsDCEUUIDConvertToUpper(propertyId) == IfIsDCEUUIDConvertToUpper("Modulation"))
			{
				#if defined(DEBUG_MSGS)
				std::ostringstream configMessage; configMessage << "zceProcessRxServant::configure - Configuring property : " << propertyId << ".";
				worker_->debugMsg(configMessage.str());
				#endif

				CORBA::Long val;

				if(configProperties[i].value >>= val)
				{
					worker_->config_propModulation(val ZCE_EXC_ENV_PARAM);
				}
				else
				{
					#if defined(DEBUG_MSGS)
					std::ostringstream oss;
					std::string anyType = configProperties[i].value.type()->id();
					oss << "zceProcessRxServant::configure - " << propertyId << " - Cannot extract value from any type " << anyType << ".";
					worker_->debugMsg(oss.str());
					#endif

					invalidProperties.length(invalidProperties.length()+1);
					invalidProperties[invalidProperties.length()-1] = configProperties[i];
				}
			}
			// propQoS
			else if( IfIsDCEUUIDConvertToUpper(propertyId) == IfIsDCEUUIDConvertToUpper("QoS"))
			{
				#if defined(DEBUG_MSGS)
				std::ostringstream configMessage; configMessage << "zceProcessRxServant::configure - Configuring property : " << propertyId << ".";
				worker_->debugMsg(configMessage.str());
				#endif

				CORBA::Long val;

				if(configProperties[i].value >>= val)
				{
					worker_->config_propQoS(val ZCE_EXC_ENV_PARAM);
				}
				else
				{
					#if defined(DEBUG_MSGS)
					std::ostringstream oss;
					std::string anyType = configProperties[i].value.type()->id();
					oss << "zceProcessRxServant::configure - " << propertyId << " - Cannot extract value from any type " << anyType << ".";
					worker_->debugMsg(oss.str());
					#endif

					invalidProperties.length(invalidProperties.length()+1);
					invalidProperties[invalidProperties.length()-1] = configProperties[i];
				}
			}
			// propApplicationType
			else if( IfIsDCEUUIDConvertToUpper(propertyId) == IfIsDCEUUIDConvertToUpper("ApplicationType"))
			{
				#if defined(DEBUG_MSGS)
				std::ostringstream configMessage; configMessage << "zceProcessRxServant::configure - Configuring property : " << propertyId << ".";
				worker_->debugMsg(configMessage.str());
				#endif

				CORBA::Long val;

				if(configProperties[i].value >>= val)
				{
					worker_->config_propApplicationType(val ZCE_EXC_ENV_PARAM);
				}
				else
				{
					#if defined(DEBUG_MSGS)
					std::ostringstream oss;
					std::string anyType = configProperties[i].value.type()->id();
					oss << "zceProcessRxServant::configure - " << propertyId << " - Cannot extract value from any type " << anyType << ".";
					worker_->debugMsg(oss.str());
					#endif

					invalidProperties.length(invalidProperties.length()+1);
					invalidProperties[invalidProperties.length()-1] = configProperties[i];
				}
			}
			else
			{
				#if defined(DEBUG_MSGS)
				std::ostringstream oss; oss << "zceProcessRxServant::configure - " << propertyId << " is not recognized.";
				worker_->debugMsg(oss.str());
				#endif

				invalidProperties.length(invalidProperties.length()+1);
				invalidProperties[invalidProperties.length()-1] = configProperties[i];
			}
		}
		else
		{
			#if defined(DEBUG_MSGS)
			std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::configure - Cannot extract value from property id.";
			worker_->debugMsg(debug_message);
			#endif

			invalidProperties.length(invalidProperties.length()+1);
			invalidProperties[invalidProperties.length()-1] = configProperties[i];
		}
	}

	if(invalidProperties.length() > 0)
	{
		if(invalidProperties.length() == configProperties.length())
		{
			ZCE_EXC_THROW ( CF::PropertySet::InvalidConfiguration,("No valid properties.", invalidProperties) );
		}
		else
		{
			ZCE_EXC_THROW ( CF::PropertySet::PartialConfiguration,(invalidProperties) );
		}
	}

}

/*!
 * \brief The query operation allows a component to be queried to retrieve its
 * properties.
 *
 * Specification reference:  3.1.3.1.5.5.2
 *
 * The query operation shall return all component properties if the
 * configProperties are zero size.
 *
 * The query operation shall return only those id/value pairs specified in the
 * configProperties if the configProperties are not zero size. Valid properties
 * for the query operation shall at a minimum be the configure, readwrite, and
 * readonly properties, and allocation properties that have an action value of
 * "external" as referenced in the component's SPD.
 *
 * \param configProperties (::CF::Properties )
 *
 * \return This operation does not return a value.
 *
 * \throw  The query operation shall raise the CF UnknownProperties exception when
 * one or more properties being requested are not known by the component.
 *
 */
void zceProcessRxServant::query( CF::Properties& configProperties ZCE_EXC_ENV_ARG)
	throw (CORBA::SystemException, CF::UnknownProperties)
{

	ZCE_ASSERT_EXCEPTION_VOID;
	#if defined(DEBUG_MSGS)
	std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::query";
	worker_->debugMsg(debug_message);
	#endif


	CF::Properties invalidProperties;

	if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"query\" a component that has been released.";
		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::query - Cannot \"query\" a component that has been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}
	else if( state_ == UNINITIALIZED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"query\" a component that has not been initialized.";
		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::query - Cannot \"query\" a component that has not been initialized.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}
	if( configProperties.length() == 0 )
	{
		configProperties.length(4);
		configProperties[0].id = CORBA::string_dup("DestinationId");
		configProperties[1].id = CORBA::string_dup("Modulation");
		configProperties[2].id = CORBA::string_dup("QoS");
		configProperties[3].id = CORBA::string_dup("ApplicationType");
	}
	for(unsigned long i = 0; i < configProperties.length(); ++i)
	{
		std::istringstream istr((char *) configProperties[i].id.in());
		std::string propertyId;
		if(istr >> propertyId)
		{
			// propDestinationId
			if( propertyId == "DestinationId" )
			{
				CORBA::String_var val;
				worker_->query_propDestinationId( val ZCE_EXC_ENV_PARAM);
				configProperties[i].value <<= CORBA::Any::from_string(val, 0);
			}
			// propModulation
			else if( propertyId == "Modulation" )
			{
				CORBA::Long val;
				worker_->query_propModulation( val ZCE_EXC_ENV_PARAM);
				configProperties[i].value <<= val;
			}
			// propQoS
			else if( propertyId == "QoS" )
			{
				CORBA::Long val;
				worker_->query_propQoS( val ZCE_EXC_ENV_PARAM);
				configProperties[i].value <<= val;
			}
			// propApplicationType
			else if( propertyId == "ApplicationType" )
			{
				CORBA::Long val;
				worker_->query_propApplicationType( val ZCE_EXC_ENV_PARAM);
				configProperties[i].value <<= val;
			}
			else
			{
				#if defined(DEBUG_MSGS)
				std::ostringstream oss; oss << "zceProcessRxServant::query - " << propertyId << " is not recognized.";
				worker_->debugMsg(oss.str());
				#endif

				invalidProperties.length(invalidProperties.length()+1);
				invalidProperties[invalidProperties.length()-1] = configProperties[i];
			}
		}
		else
		{
			#if defined(DEBUG_MSGS)
			std::ostringstream oss; oss << "zceProcessRxServant::query - cannot extract property id from any.";
			worker_->debugMsg(oss.str());
			#endif

			invalidProperties.length(invalidProperties.length()+1);
			invalidProperties[invalidProperties.length()-1] = configProperties[i];
		}
	}

	if( invalidProperties.length() > 0 )
	{
		ZCE_EXC_THROW ( CF::UnknownProperties,( invalidProperties ) );
	}

}

/*!
 * \brief The getPort operation provides a mechanism to obtain a specific consumer
 * or producer Port. A PortSupplier may contain zero-to-many consumer and producer
 * port components. The exact number is specified in the component’s Software
 * Profile SCD (section 3.1.3.4). Multiple input and/or output ports provide
 * flexibility for PortSuppliers that must manage varying priority levels and
 * categories of incoming and outgoing messages, provide multi-threaded message
 * handling, or other special message processing.
 *
 * Specification reference:  3.1.3.1.4.5.1
 *
 * The getPort operation returns the object reference to the named port as stated
 * in the component's SCD.
 *
 * \param name (string ) The name of the port being requested.
 *
 * \return The getPort operation shall return the CORBA object reference that is
 * associated with the input port name.
 *
 * \throw UnknownPort The getPort operation shall raise an UnknownPort exception
 * if the port name is invalid.
 *
 */
CORBA::Object* zceProcessRxServant::getPort( const char* name ZCE_EXC_ENV_ARG)
	throw (CORBA::SystemException, CF::PortSupplier::UnknownPort)
{

	CORBA::Object* _pRetVal = NULL;
	ZCE_ASSERT_EXCEPTION(_pRetVal);
	MutexLock lock(mutex_);
		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::getPort";
		worker_->debugMsg(debug_message);
		#endif


	if( state_ == DESTROYED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"getPort\" from a component that has been released.";
		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::getPort - Cannot \"getPort\" from a component that has been released.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}
	else if( state_ == UNINITIALIZED )
	{
		std::string message = "Component instance " + params_.COMPONENT_IDENTIFIER;
		message += ": Cannot \"getPort\" from a component that has not been initialized.";
		#if defined(DEBUG_MSGS)
		std::string debug_message = params_.COMPONENT_IDENTIFIER + ": zceProcessRxServant::getPort - Cannot \"getPort\" from a component that has not been initialized.";
		worker_->debugMsg(debug_message);
		#endif

		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST,( 0, CORBA::COMPLETED_NO ) );
	}
	CORBA::Object_var port;

	if(strcmp(name, "portDataOutData") == 0)
	{
		port = CF::Port::_duplicate(out_portDataOutData->_this());
	}
	else if(strcmp(name, "portDataOutVoice") == 0)
	{
		port = CF::Port::_duplicate(out_portDataOutVoice->_this());
	}
	else if(strcmp(name, "portDataIn") == 0)
	{
		port = PushPorts::OctetSeqConsumer::_duplicate(in_portDataIn->_this());
	}
	else
	{
		#if defined(DEBUG_MSGS)
		std::ostringstream oss; oss << "zceProcessRxServant::getPort - " << name << " is not a recognized port name.";
		worker_->debugMsg(oss.str());
		#endif

		// 3.1.3.1.4.5.1.5 : The getPort operation shall raise an UnknownPort exception if
		// the port name is invalid.
		ZCE_EXC_THROW ( CF::PortSupplier::UnknownPort,() );
	}

	if(CORBA::is_nil(port))
	{
		#if defined(DEBUG_MSGS)
		std::ostringstream oss; oss << "zceProcessRxServant::getPort - " << name << " is not a recognized port name.";
		worker_->debugMsg(oss.str());
		#endif

		// 3.1.3.1.4.5.1.5 : The getPort operation shall raise an UnknownPort exception if
		// the port name is invalid.
		ZCE_EXC_THROW ( CF::PortSupplier::UnknownPort,() );
	}

	return port._retn();

}

// End-Of-File
//------------------------------------------------------------------------------
