content.txt 5.63 KB
!1 Création d'un nouveau type d'output
!2 Objectif
L'objectif de cette page est de créer un nouveau type de sortie. 
Cela permettra de gérer un fichier xml décrivant une requête contenant une balise output du type 
{{{
  <outputs>
    <OutputName>
      <param id="density_boxcar" /> 
      ...
    </OutputName>
  </outputs>
}}}
!2 Procédure
 * Il faut créer un plugin [[cf. AMDA plugin][.HelpDev.AmdaPlugin]] enregistrant le nouveau '''Output''' * 
 * Il faut créer au moins une class dérivant de '''!-AMDA::Parameters::ParamOutput-!'''.
 * Il faut créer une classe dérivant de '''!-AMDA::XMLConfigurator::NodeGrpCfg-!'''.
 * Il faut mettre à jour les schémas XSD permettant de valider les fichier XML de requête

!2 Exemple:
!3 Création d'une nouvelle sortie: '''intervalTrue'''
Cette sortie écrit toutes les valeurs d'un paramètre sur une ligne.
Le fichier xml de requête contiendra la balise output suivante (pamarmName)
{{{
  <outputs>
    <intervalTrue>
      <param id="pamarmName" /> 
    </intervalTrue>
  </outputs>
}}}
!4 1 - Suivre la procédure de création de plugin
[[cf. AMDA plugin][.HelpDev.AmdaPlugin]]
!5 La fonction registerPlugin doit contenir les lignes suivantes:
{{{
extern "C" void registerPlugin(AMDA::Plugins::PluginManager & pm) {
	AMDA::XMLRequest::XMLRequestParser* lXMLRequestParser = ServicesServer::getInstance()->getService<AMDA::XMLRequest::XMLRequestParser*>();
	if (lXMLRequestParser) {
		XMLRequestParser->addNodeParser("request/outputs/IntervalTrue",AMDA::XMLConfigurator::NodeCfgSPtr(new OutputIntervalTrueNode));
	}
}
}}}
!4 2 - Créer la classe !-OutputIntervalTrueNode-! 

Il faut dériver de '''!-AMDA::XMLConfigurator::NodeGrpCfg-!''' et implémenter la méthode:
 * !-void process()-! : permet de lire le nœud intervalTrue du fichier de requête.
Ce nœud comporte seulement un noeud param (qui est le paramètre qui sera affiché), il peut en comporter d'autre si besoin.
{{{
OutputIntervalTrueNode::OutputIntervalTrueNode() : NodeGrpCfg() {
	getChildList()["param"]=NodeCfgSPtr(new ParamNode<ParamOutputIntervalTrueFile>());
}
void OutputIntervalTrueNode::proceed(xmlNodePtr pNode,
	const AMDA::Parameters::CfgContext& pContext) {

	LOG4CXX_DEBUG(gLogger,
		"OutputIntervalTrueNode::proceed: '" << pNode->name << "' node")

	ParameterManager* lParameterManager = pContext.get<ParameterManager*>();
	CfgContext lContext;

	ParamOutput* lParamOutputIntervalTrueFile = new ParamOutputIntervalTrueFile(
			*lParameterManager);
	ParamOutputSPtr  lParamOutput(lParamOutputIntervalTrueFile);
	lContext.push<ParamOutputIntervalTrueFile*>(dynamic_cast<ParamOutputIntervalTrueFile *>(lParamOutputIntervalTrueFile));
	NodeGrpCfg::proceed(pNode, lContext);
	lParameterManager->getParamOutputList().push_back(lParamOutput);

}
}}}

!4 3 - Créer la classe !-ParamOutputIntervalTrueFile-! 	 
Il faut dériver de '''!-AMDA::Parameters::ParamOutput-!''' et implémenter au minimum les méthodes:
 * '''!-void apply()-!''' : permet de générer la sortie, c'est le cœur du métier d'output, get data avec _parameter->getAsync() 
et utilise le design pattern visiteur pour lire les valeur du paramètre.
{{{
void ParamOutputIntervalTrueFile::apply() {

	_paramDataIndexInfo = _parameter->getAsync(this).get();

	initOutput(); //create file
	_printIntervalTrueVisitor->setParamDataIndexInfo(_paramDataIndexInfo);

	while ( _paramDataIndexInfo._nbDataToProcess > 0) {
		try {
			_parameter->getParamData(this)->accept(*_printIntervalTrueVisitor); //visitor pattern
			_paramDataIndexInfo = _parameter->getAsync(this).get();
			_printIntervalTrueVisitor->setParamDataIndexInfo(_paramDataIndexInfo);
		} catch(AMDA::AMDA_exception & e) {
			e << AMDA::errno_code(AMDA_PARAM_OUTPUT_ERR);
			throw;
		}
	}
	endOutput(); //close file
}
}}}
 * '''!-void init()-!''' : permet d'initialiser les paramètres à traiter 
{{{
void ParamOutputIntervalTrueFile::init() {
	getParameter()->init(this,getStartTime(),getTimeInt());
}
}}}
  * '''!-void DataClient::establishConnection()-!''' : permet de calculer des informations static (comme parser la formule de process) et doit ouvrir les connections avec son _parameterInput 
{{{
void ParamOutputIntervalTrueFile::establishConnection() {
	_parameter = _parameterManager.getSampledParameter(_paramName, _samplingMode, _samplingValue, _gabsThreshold).get();
	if(_parameter == NULL)  {
		LOG4CXX_ERROR(_logger,"ParamOutput::init parameter : \""<< _paramName <<"\" Not Exist" );
		BOOST_THROW_EXCEPTION( ParamOutput_exception());
	}
	getParameter()->openConnection(this);
}
}}}
  * '''!-double  DataClient::timeOfDataPreserve()-!''' : doit retourner l’intervalle temps nécessaire pour assurer l'intégrité des calculs, ici la taille du boxcar: 1200


!4 4 -  Mettre à jour le XSD
 * Modifier le fichier request/all.xsd:
Y ajouter une ligne du type:   !- <xs:include schemaLocation="intervalTrue.xsd" />-!
 * Créer un fichier intervalTrue.xsd (voir nom du fichier référencer dans la ligne ajouté au fichier all.xsd)

{{{
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:include schemaLocation="request.xsd" />
	<xs:element name="intervalTrue" substitutionGroup="OutputElement" >
		<xs:complexType>
			<xs:sequence>
				<xs:element name="param" minOccurs="1" maxOccurs="1">
					<xs:complexType>
						<xs:sequence>
							<xs:element name="index" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
							<xs:element name="calibration_info" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
						</xs:sequence>
						<xs:attribute name="id" type="xs:string"  use="required"/>
					</xs:complexType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>
}}}




!contents -R2 -g -p -f -h