void copySubsystem( ESMoL::Subsystem inputSubSubsystem, ESMoL::Subsystem outputSubsystem, bool deep ) {

	ESMoL::Subsystem outputSubSubsystem = ESMoL::Subsystem::Create( outputSubsystem );
	UdmEngine::copyBlock( inputSubSubsystem, outputSubSubsystem );
	copyPorts( inputSubSubsystem, outputSubSubsystem );

	PrimitiveVector primitiveVector = inputSubSubsystem.Primitive_kind_children();
	for( PrimitiveVector::iterator pmvItr = primitiveVector.begin() ; pmvItr != primitiveVector.end() ; ++pmvItr ) {

		ESMoL::Primitive primitive = *pmvItr;
		ESMoL::Block block = UdmEngine::copy( primitive, outputSubSubsystem );
		if ( primitive.BlockType() == "S-Function" ) {
			ConnectorRefVector connectorRefVector = primitive.ConnectorRef_kind_children();
			if ( !connectorRefVector.empty() ) {
				ESMoL::ConnectorRef inputConnectorRef = connectorRefVector.back();
				ESMoL::ConnectorRef outputConnectorRef = ESMoL::ConnectorRef::Create( block );
				outputConnectorRef.name() = inputConnectorRef.name();
				ESMoL::TransConnector inputTransConnector = inputConnectorRef.ref();
				TransConnectorMap::iterator tcmItr = getTransConnectorMap().find( inputTransConnector );
				if ( tcmItr != getTransConnectorMap().end() ) outputConnectorRef.ref() = tcmItr->second;
			}
		}
		copyPorts( primitive, block );
	}

	SubsystemVector sub3systemVector = inputSubSubsystem.Subsystem_kind_children();
	for( SubsystemVector::iterator ssvItr = sub3systemVector.begin() ; ssvItr != sub3systemVector.end() ; ++ssvItr ) {

		ESMoL::Subsystem inputSub3system = *ssvItr;
		if ( deep ) copySubsystem( inputSub3system, outputSubSubsystem );
		else        flattenSubsystem( inputSub3system, outputSubSubsystem );
	}
}
bool isStateMachine( ESMoL::Subsystem subsystem ) {
	ESMoL::Primitive sFunction;

	PrimitiveVector primitiveVector = subsystem.Primitive_kind_children();
	for( PrimitiveVector::iterator pmvItr = primitiveVector.begin() ; pmvItr != primitiveVector.end() ; ++pmvItr ) {

		ESMoL::Primitive primitive = *pmvItr;
		if ( primitive.BlockType() == "S-Function" ) {
			sFunction = primitive;
			break;
		}
	}

	if ( sFunction == Udm::null ) return false;

	ConnectorRefVector connectorRefVector = sFunction.ConnectorRef_kind_children();
	return !connectorRefVector.empty();
}
void flattenSubsystem( ESMoL::Subsystem inputSubsystem, ESMoL::Subsystem outputSubsystem ) {
	
	PrimitiveVector primitiveVector = inputSubsystem.Primitive_kind_children();
	for( PrimitiveVector::iterator pmvItr = primitiveVector.begin() ; pmvItr != primitiveVector.end() ; ++pmvItr ) {

		ESMoL::Primitive primitive = *pmvItr;
		ESMoL::Block block = UdmEngine::copy( primitive, outputSubsystem );
		copyPorts( primitive, block );
	}

	SubsystemVector subSubsystemVector = inputSubsystem.Subsystem_kind_children();
	for( SubsystemVector::iterator ssvItr = subSubsystemVector.begin() ; ssvItr != subSubsystemVector.end() ; ++ssvItr ) {

		ESMoL::Subsystem inputSubSubsystem = *ssvItr;
		if (  isStateMachine( inputSubSubsystem )  )                  copySubsystem( inputSubSubsystem, outputSubsystem );
		else if (  isConditionActionSubsystem( inputSubSubsystem )  ) copySubsystem( inputSubSubsystem, outputSubsystem, false );
		else                                                          flattenSubsystem( inputSubSubsystem, outputSubsystem );
	}
}