1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : DataIdFilter.hxx
24 // Author : Eric Fayolle (EDF)
30 * Implemente les fonctions de filtrage et conversion d'un port de DATASTREAM
32 * Rappel des fonctions du Filtrage:
33 * --------------------------------
35 * Dans une communication de type DATASTREAM, le destinataire indique à l'avance la liste
36 * des instances qu'il veut recevoir, c'est à dire celles qui lui sont nécessaires.
37 * Il indique pour cela la liste des 'times' et la liste des 'tags' qui
38 * caractérisent les instances désirées.
39 * Ces deux listes sont indépendantes. Toute instance dont les paramètres 'time' et
40 * 'tag' figurent dans la liste des 'times' et respectivement dans la liste des
41 * 'tags' est désirée par le destinataire.
42 * Par la suite, une telle instance sera acceptée par le port-DATASTREAM. Les autres
45 * Le filtrage consiste à limiter les valeurs possibles du paramètre TIME ou TAG (un
46 * entier). La liste des valeurs possibles est décrite sous la forme d'une liste de
47 * valeurs ou de séquences arithmétiques de valeurs.
49 * La liste 1; 3; 30:34; 40:50:2 autorise les valeurs 1 et 3 et toutes les valeurs
50 * comprises entre 30 et 34 inclus et toutes les valeurs de la séquence 40 à 50
51 * inclus par pas de 2, c'est à dire 40, 42, ... 50.
52 * On appelle règle élémentaire de filtrage celle spécifiant un élément de la liste
53 * des valeurs autorisées: soit une seule valeur, soit une séquence de valeurs. Une
54 * séquence de valeurs est spécifiée par sa valeur de départ, sa valeur de fin et
55 * son pas. Le filtrage est donc défini par une suite de règles de filtrage.
56 * La fonction élémentaire de configuration du filtrage sert à spécifier une règle
59 * Rappels des fonctions de conversion:
60 * -----------------------------------
62 * La conversion est intimement liée au filtrage car seules les valeurs passant le
63 * filtre sont converties. La conversion n'est pas obligatoire. Une valeur de TIME ou TAG
64 * entrante peut ne pas être convertie. Elle garde alors sa valeur et est gardée
65 * telle quelle pour l'objet destinataire.
66 * DATASTREAM peut associer une règle de conversion à chaque règle élémentaire de
68 * La conversion consiste à changer:
69 * - un valeur de TIME ou TAG en une valeur différente
70 * - une séquence de valeurs en une autre séquence de valeurs de même taille
71 * (ex: 30:40 en 300:400:10)
72 * Mais la conversion permet aussi de transformer:
73 * - une valeur de TIME ou TAG unique en une séquence de valeurs (les données entrantes sont
74 * alors duppliquées et à chaque fois que l'objet destinataire réclame une donnée
75 * de la séquence, il reçoit en fait une copie de la donnée reçue une seule fois)
77 * - une séquence de valeurs en une valeur unique (alors, chaque donnée entrante
78 * associée à un TIME ou TAG de la séquence correspond à une donnée unique pour le
79 * destinataire: seule la dernière reçue est la donnée valide)
86 // Pour l'utilisation de "vector" de la STL
87 // Classe filtre_elementaire
89 // Implémente une structure de donnée décrivant un filtre élémentaire
90 // sur le paramètre TIME ou TAG; c'est
91 // - soit une valeur entière unique
92 // - soit une séquence arithmétique de valeurs
94 class filtre_elementaire
97 int len; // Longueur de séquence ou 1 pour une valeur unique
98 int debut; // Début de la séquence ou valeur pour une valeur unique
99 int fin; // Fin de la séquence
100 int pas; // Pas de la séquence
102 // Constructeur par défaut
103 filtre_elementaire() {}
105 // Création d'un filtre élémentaire pour une valeur unique
106 filtre_elementaire(int valeur)
109 this->debut = valeur;
112 // Création d'un filtre élémentaire pour une séquence de valeurs entières
113 // Le pas par défaut est 1
114 filtre_elementaire (int _debut, int _fin, int _pas=1)
116 this->debut = _debut;
117 this->len = (_fin - _debut) / _pas;
120 this->fin = _debut + _pas * this->len; // Calcule la vrai borne de fin
122 this->len += 1; // Compte les bornes et non les intervalles
124 else // erreur de spécification: on ne prend que la première valeur
128 // Constructeur par copie
129 filtre_elementaire (filtre_elementaire &_f)
132 this->debut = _f.debut;
138 // Classe filtre_conversion
140 // Implémente le filtrage et la conversion du paramètre TIME ou TAG
141 // des données reçues par un port DATASTREAM.
144 // 1) Création d'un objet
145 // 2) Configuration de cet objet par passage de paramètres
146 // de filtage et de conversion
147 // 3) A la création d'un port DATASTREAM, on passe au constructeur
148 // deux objets 'filtre_conversion', l'un pour le TIME, l'autre pour le TAG.
149 // 4) A l'utilisation du port DATASTREAM, celui-ci appelle la méthode
150 // "applique_filtre_conversion" pour opérer
152 class filtre_conversion
155 // Structure de données décrivant une conversion élémentaire:
156 // un filtre élementaire
157 // et un pointeur éventuel vers les paramètres de conversion associés
158 class conversion_elementaire
162 filtre_elementaire filtre;
163 filtre_elementaire * p_convers;
166 conversion_elementaire() {}
168 // Constructeur par copie d'un objet non modifie (const)
169 conversion_elementaire (const conversion_elementaire& _ce)
173 // Remarque: le Constructeur par copie d'un objet existe par defaut mais sans le modificateur 'const'
174 // et l'emploi d'un objet comme element dans un vecteur oblige d'avoir un tel const-copy-constructor.
177 // Données de configuration de filtrage et conversion:
178 // une table de filtres élémentaires
179 // avec leurs données de conversion associées éventuelles
180 std::vector<conversion_elementaire> config;
183 // Constructeur: juste une allocation mémoire initiale
184 filtre_conversion() {}
187 // réclamer la mémoire utilisée par tous les éléments du vecteur config
190 std::vector<conversion_elementaire>::iterator i;
191 for (i = this->config.begin(); i != this->config.end(); i ++)
193 delete (*i).p_convers;
197 // Configuration partielle par ajout d'un filtre élémentaire
198 bool config_elementaire (filtre_elementaire& _f)
200 // cout << "ajout config_elementaire 1 " << this << endl;
201 conversion_elementaire conv_elem;
203 conv_elem.filtre = _f;
204 conv_elem.p_convers = NULL;
206 // Ajoute cette conversion/filtrage elementaire a la liste
207 this->config.push_back (conv_elem);
209 // vector<conversion_elementaire>::iterator i;
210 // cout << "liste apres ajout:" << endl;
211 // for (i = this->config.begin(); i != this->config.end(); i ++)
213 // cout << "config elem " << endl;
214 // cout << "filtre: len, debut, fin, pas " << (*i).filtre.len << " " << (*i).filtre.debut << " " << (*i).filtre.fin << " " << (*i).filtre.pas << endl;
220 // Configuration partielle par ajout d'un filtre élémentaire
221 // et sa conversion associée
223 // Retourne false si les param de conversion sont incompatibles avec le filtre élémentaire.
224 // La configuration partielle est alors refusée.
226 bool config_elementaire (filtre_elementaire& _f, filtre_elementaire& _conv)
228 // cout << "ajout config_elementaire 2 " << this << endl;
230 if (_f.len == 1 || _conv.len == 1 || _f.len == _conv.len)
232 conversion_elementaire conv_elem;
233 conv_elem.filtre = _f;
234 conv_elem.p_convers = new filtre_elementaire(_conv);
236 // Ajoute cette conversion/filtrage elementaire a la liste
237 this->config.push_back (conv_elem);
239 // vector<conversion_elementaire>::iterator i;
240 // cout << "liste apres ajout:" << endl;
241 // for (i = this->config.begin(); i != this->config.end(); i ++)
243 // cout << "config elem " << endl;
244 // cout << "filtre: len, debut, fin, pas " << (*i).filtre.len << " " << (*i).filtre.debut << " " << (*i).filtre.fin << " " << (*i).filtre.pas << endl;
251 // Filtre et conversion incompatibles
256 // applique_filtre_conversion: Opération du filtre et de la conversion
257 template <typename T > T applique_filtre_conversion (T valeur_initiale, std::vector<T>& liste_conversions) const;
262 // filtre_conversion::applique_filtre_conversion: Opération du filtre et de la conversion
264 // Etant donné une valeur entière (de TIME ou de TAG), cette méthode détermine :
265 // - si cette valeur passe le filtre
266 // - dans le cas où une conversion existe, la liste des valeurs de conversion
267 // qui correspondent à la valeur initiale
269 // Dans tous les cas, cette méthode retourne une liste de valeurs.
270 // Dans le cas où il n'y a pas de conversion, cette liste a une longueur 1
271 // et ne contient que la valeur initiale.
273 // Paramètre d'entrée : la valeur initiale (integer)
275 // Paramètre de sortie : la liste des valeurs après conversion (vector<int>)
277 // Valeur de retour : la longueur de la liste
278 // si cette longueur est 0, c'est que la valeur initiale ne passe pas le filtre
280 template <typename T>
281 T filtre_conversion::applique_filtre_conversion (T valeur_initiale, std::vector<T>& liste_conversions) const
283 // Part d'une liste vierge
284 liste_conversions.clear();
286 // cout << "config applique_filtre_conversion " << this << endl;
288 // Balaye tous les éléments de configuration
289 // et cherche pour chacun d'eux si la valeur initiale est présente parmi les valeurs filtrées
291 // Pour tous les éléments de configuration du filtrage/conversion
292 std::vector<conversion_elementaire>::const_iterator i;
293 for (i = config.begin(); i != config.end(); i ++)
296 // cout << "config elem " << endl;
297 // cout << "filtre: len, debut, fin, pas " << (*i).filtre.len << " " << (*i).filtre.debut << " " << (*i).filtre.fin << " " << (*i).filtre.pas << endl;
299 bool si_passe_filtre = false;
301 // Si la longueur du filtre est 1
302 if ((*i).filtre.len == 1) {
303 // Si la valeur initiale correspond à la valeur du filtre
304 if ((*i).filtre.debut == valeur_initiale)
305 si_passe_filtre = true;
307 // Si la valeur initiale est dans la séquence des valeurs du filtre
308 // la valeur est comprise dans les bornes [debut,fin]
309 // et sa distance du début de la séquence est modulo le pas
310 if ( ((*i).filtre.fin - valeur_initiale >= 0) == (valeur_initiale - (*i).filtre.debut >= 0)
311 && (valeur_initiale - (*i).filtre.debut) % (*i).filtre.pas == 0 ) {
312 si_passe_filtre = true;
316 // Si la valeur initiale passe le filtre
317 if (si_passe_filtre) {
318 // cout << "config: filtre passe " << endl;
320 // Si il y a une conversion à effectuer
321 if ((*i).p_convers != NULL) {
323 // Si la longueur du filtre est 1
324 if ((*i).filtre.len == 1) {
326 // Si la longueur des paramètres de conversion est aussi 1
327 if ((*i).p_convers->len == 1) {
328 // Ajoute la valeur de conversion à la liste des valeurs après conversion
329 liste_conversions.push_back ((*i).p_convers->debut);
331 // Ajoute la séquence de conversion à la liste des valeurs après conversion
332 for (int s = (*i).p_convers->debut; s != (*i).p_convers->fin; s += (*i).p_convers->pas) {
333 liste_conversions.push_back (s);
335 liste_conversions.push_back ((*i).p_convers->fin);
339 // Le filtre est une séquence qui est convertie en une autre séquence de même longueur
340 // Choisit la valeur au rang désiré dans la séquence de conversion
341 int rang = (valeur_initiale - (*i).filtre.debut) / (*i).filtre.pas;
343 int valeur_convertie = (*i).p_convers->debut + rang * (*i).p_convers->pas;
345 // Ajoute cette valeur à la liste des valeurs après conversion
346 liste_conversions.push_back (valeur_convertie);
349 // Ajoute la valeur initiale telle-quelle à la liste des valeurs après conversion
350 liste_conversions.push_back (valeur_initiale);
355 return liste_conversions.size();