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

//******************************************************************************
//
//     FILE: zceCF_DeviceUsesPort.cpp
//
//******************************************************************************


#include "zceCF_DeviceUsesPort.h"


zceCF_DeviceUsesPort::zceCF_DeviceUsesPort( std::string name ZCE_EXC_ENV_ARG ) : 
	port_(::CF::Device::_nil()), name_(name), connectionId_(""), consCount_(0), cardinality_(ZCECF_DEVICEUSESPORT_CARDINALITY_DEFAULT )
{

	ZCE_ASSERT_EXCEPTION_VOID;
	
}

zceCF_DeviceUsesPort::~zceCF_DeviceUsesPort()
{

	//ZCE_ASSERT_EXCEPTION_VOID;
	
}

/*!
 * \brief Applications require the connectPort operation to establish associations
 * between Ports. Ports provide channels through which data and/or control pass.
 * The connectPort operation provides half of a two-way association; therefore two
 * calls are required to create a two-way association.
 *
 * Specification reference:  3.1.3.1.1.5.1
 *
 * The connectPort operation shall make a connection to the component identified
 * by its input parameters. A port may support several connections. The input
 * connectionId is a unique identifier to be used by disconnectPort when breaking
 * this specific connection.
 *
 * \return This operation does not return a value.
 *
 * \throw InvalidPort The connectPort operation shall raise the InvalidPort
 * exception when the input connection parameter is an invalid connection for this
 * Port.
 *
 * \throw OccupiedPort The connectPort operation shall raise the OccupiedPort
 * exception when unable to accept the connections because the Port is already
 * fully occupied.
 *
 */
void zceCF_DeviceUsesPort::connectPort ( CORBA::Object_ptr connection,  const char * connectionId ZCE_EXC_ENV_ARG )
			throw ( CORBA::SystemException, CF::Port::InvalidPort, CF::Port::OccupiedPort )
{

	ZCE_ASSERT_EXCEPTION_VOID;
	
	// The cardinality for uses ports defaults to '1' if you want the posibility of
	// higher cardinality ports, then port_ must be changed to map that maintains the
	// connected ports

	if(consCount_ > cardinality_)
	{
		// 3.1.3.1.1.5.1.5 : unable to accept the connection because the Port is already
		// fully occupied

		ZCE_EXC_THROW ( CF::Port::OccupiedPort, () );
	}

	if(!CORBA::is_nil(connection))
	{
		ZCE_EXC_TRY
		{
			port_ = CF::Device::_narrow(connection);
		}
		ZCE_EXC_CATCHTYPE(CORBA::UserException)
		{
			// 3.1.3.1.1.5.1.5 : the input connection parameter is an invalid connection for
			// this Port
			// 3.1.3.1.1.3.1 : errorCode 1 means the Port component is invalid (unable to
			// narrow object reference) or illegal object reference
			ZCE_EXC_THROW ( CF::Port::InvalidPort, (1, name_.c_str()) );
		}
		ZCE_EXC_CATCHTYPE(CORBA::SystemException)
		{
			// 3.1.3.1.1.5.1.5 : the input connection parameter is an invalid connection for
			// this Port
			// 3.1.3.1.1.3.1 : errorCode 1 means the Port component is invalid (unable to
			// narrow object reference) or illegal object reference
			ZCE_EXC_THROW ( CF::Port::InvalidPort, (1, name_.c_str()) );
		}
		ZCE_EXC_CATCHTYPE(CORBA::Exception)
		{
			// 3.1.3.1.1.5.1.5 : the input connection parameter is an invalid connection for
			// this Port
			// 3.1.3.1.1.3.1 : errorCode 1 means the Port component is invalid (unable to
			// narrow object reference) or illegal object reference
			ZCE_EXC_THROW ( CF::Port::InvalidPort, (1, name_.c_str()) );
		}
		ZCE_EXC_ENDTRY_VOID;
		if(CORBA::is_nil(port_))
		{
			// 3.1.3.1.1.5.1.5 : the input connection parameter is an invalid connection for
			// this Port
			// 3.1.3.1.1.3.1 : errorCode 1 means the Port component is invalid (unable to
			// narrow object reference) or illegal object reference
			ZCE_EXC_THROW ( CF::Port::InvalidPort, (1, name_.c_str()) );
		}

		consCount_++; // increase the consumer count since a connection was made

		connectionId_ = connectionId;
	}
	else
	{
		// 3.1.3.1.1.5.1.5 : the input connection parameter is an invalid connection for
		// this Port
		// 3.1.3.1.1.3.1 : errorCode 1 means the Port component is invalid (unable to
		// narrow object reference) or illegal object reference
		ZCE_EXC_THROW ( CF::Port::InvalidPort, (1, name_.c_str()) );
	}

}

/*!
 * \brief Applications require the disconnectPort operation in order to allow
 * consumer/producer data components to disassociate themselves from their
 * counterparts (consumer/producer).
 *
 * Specification reference:  3.1.3.1.1.5.2
 *
 * The disconnectPort operation shall break the connection to the component
 * identified by the input parameter.
 *
 * \return This operation does not return a value.
 *
 * \throw InvalidPort The disconnectPort operation shall raise the InvalidPort
 * exception when the name passed to disconnectPort is not connected with the Port
 * component.
 *
 */
void zceCF_DeviceUsesPort::disconnectPort ( const char * connectionId ZCE_EXC_ENV_ARG )
			throw ( CORBA::SystemException , CF::Port::InvalidPort )
{

	ZCE_ASSERT_EXCEPTION_VOID;
	if(connectionId_ != connectionId)
	{
		// 3.1.3.1.1.5.1.5 : the input connection parameter is an invalid connection for
		// this Port
		// 3.1.3.1.1.3.1 : errorCode 2 means the Port name is not found (not used by this
		// Port)
		ZCE_EXC_THROW ( CF::Port::InvalidPort, (2, connectionId) );
	}

	port_ = CF::Device::_nil();

	connectionId_ = "";
	consCount_--;

}



bool zceCF_DeviceUsesPort::is_connected( ZCE_EXC_ENV_SINGLE_ARG )
{
	bool _bRetVal = false;
	ZCE_ASSERT_EXCEPTION(_bRetVal);
	
	return ((!CORBA::is_nil(port_)) && (consCount_ > 0)); 
}




/*!	\brief
 *
 *	 Describe operation here.
 * 
 *	\param capacities ( ::CF::Properties ) 
 * 
 *	\throw ::CF::Device::InvalidCapacity
 * 
 *	\throw ::CF::Device::InvalidState
 * 
 */
CORBA::Boolean zceCF_DeviceUsesPort::allocateCapacity( const CF::Properties& capacities ZCE_EXC_ENV_ARG )
{
	CORBA::Boolean _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->allocateCapacity(capacities);

}

/*!	\brief
 *
 *	 Describe operation here.
 * 
 *	\param capacities ( ::CF::Properties ) 
 * 
 *	\throw ::CF::Device::InvalidCapacity
 * 
 *	\throw ::CF::Device::InvalidState
 * 
 */
void zceCF_DeviceUsesPort::deallocateCapacity( const CF::Properties& capacities ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->deallocateCapacity(capacities);

}

CF::Device::UsageType zceCF_DeviceUsesPort::usageState( ZCE_EXC_ENV_SINGLE_ARG )
{
	CF::Device::UsageType _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->usageState();

}

CF::Device::AdminType zceCF_DeviceUsesPort::adminState( ZCE_EXC_ENV_SINGLE_ARG )
{
	CF::Device::AdminType _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->adminState();

}

void zceCF_DeviceUsesPort::adminState( CF::Device::AdminType value  ZCE_EXC_ENV_ARG)
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->adminState( value );

}

CF::Device::OperationalType zceCF_DeviceUsesPort::operationalState( ZCE_EXC_ENV_SINGLE_ARG )
{
	CF::Device::OperationalType _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->operationalState();

}

char* zceCF_DeviceUsesPort::softwareProfile( ZCE_EXC_ENV_SINGLE_ARG )
{
	char* _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->softwareProfile();

}

char* zceCF_DeviceUsesPort::label( ZCE_EXC_ENV_SINGLE_ARG )
{
	char* _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->label();

}

CF::AggregateDevice_ptr zceCF_DeviceUsesPort::compositeDevice( ZCE_EXC_ENV_SINGLE_ARG )
{
	CF::AggregateDevice_ptr _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->compositeDevice();

}

/*!
 * \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_ptr zceCF_DeviceUsesPort::getPort( const char* name ZCE_EXC_ENV_ARG )
{
	CORBA::Object_ptr _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->getPort(name);

}

/*!
 * \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 zceCF_DeviceUsesPort::start( ZCE_EXC_ENV_SINGLE_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->start();

}

/*!
 * \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 zceCF_DeviceUsesPort::stop( ZCE_EXC_ENV_SINGLE_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->stop();

}

char* zceCF_DeviceUsesPort::identifier( ZCE_EXC_ENV_SINGLE_ARG )
{
	char* _retval;
	ZCE_ASSERT_EXCEPTION(_retval);
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	return port_->identifier();

}

/*!
 * \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 zceCF_DeviceUsesPort::configure( const CF::Properties& configProperties ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->configure(configProperties);

}

/*!
 * \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 zceCF_DeviceUsesPort::query( CF::Properties& configProperties ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->query(configProperties);

}

/*!
 * \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 zceCF_DeviceUsesPort::runTest( CORBA::ULong testid, CF::Properties& testValues ZCE_EXC_ENV_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->runTest(testid, testValues);

}

/*!	\brief
 *
 *	 Describe operation here.
 * 
 *	\throw ::CF::LifeCycle::InitializeError
 * 
 */
void zceCF_DeviceUsesPort::initialize( ZCE_EXC_ENV_SINGLE_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->initialize();

}

/*!	\brief
 *
 *	 Describe operation here.
 * 
 *	\throw ::CF::LifeCycle::ReleaseError
 * 
 */
void zceCF_DeviceUsesPort::releaseObject( ZCE_EXC_ENV_SINGLE_ARG )
{
	ZCE_ASSERT_EXCEPTION_VOID;
	if (! is_connected(ZCE_EXC_ENV_SINGLE_PARAM) )
	{
		ZCE_EXC_THROW ( CORBA::OBJECT_NOT_EXIST, (0,CORBA::COMPLETED_NO) );
	}

	port_->releaseObject();

}


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