Back to index

salome-kernel  6.5.0
DataIdFilter.hxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  File   : DataIdFilter.hxx
00024 //  Author : Eric Fayolle (EDF)
00025 //  Module : KERNEL
00026 //
00027 /*   Module Filtre
00028  *   -------------
00029  *
00030  *   Implemente les fonctions de filtrage et conversion d'un port de DATASTREAM
00031  *
00032  *   Rappel des fonctions du Filtrage:
00033  *   --------------------------------
00034  *
00035  *   Dans une communication de type DATASTREAM, le destinataire indique à l'avance la liste
00036  *   des instances qu'il veut recevoir, c'est à dire celles qui lui sont nécessaires.
00037  *   Il indique pour cela la liste des 'times' et la liste des 'tags' qui
00038  *   caractérisent les instances désirées.
00039  *   Ces deux listes sont indépendantes. Toute instance dont les paramètres 'time' et
00040  *   'tag' figurent dans la liste des 'times' et respectivement dans la liste des
00041  *   'tags' est désirée par le destinataire.
00042  *   Par la suite, une telle instance sera acceptée par le port-DATASTREAM. Les autres
00043  *   seront rejetées.
00044  *
00045  *   Le filtrage consiste à limiter les valeurs possibles du paramètre TIME ou TAG (un
00046  *   entier). La liste des valeurs possibles est décrite sous la forme d'une liste de
00047  *   valeurs ou de séquences arithmétiques de valeurs.
00048  *   Exemple: 
00049  *     La liste 1; 3; 30:34; 40:50:2 autorise les valeurs 1 et 3 et toutes les valeurs
00050  *     comprises entre 30 et 34 inclus et toutes les valeurs de la séquence 40 à 50
00051  *     inclus par pas de 2, c'est à dire 40, 42, ... 50.
00052  *   On appelle règle élémentaire de filtrage celle spécifiant un élément de la liste
00053  *   des valeurs autorisées: soit une seule valeur, soit une séquence de valeurs. Une
00054  *   séquence de valeurs est spécifiée par sa valeur de départ, sa valeur de fin et
00055  *   son pas. Le filtrage est donc défini par une suite de règles de filtrage.
00056  *   La fonction élémentaire de configuration du filtrage sert à spécifier une règle
00057  *   de filtrage.
00058  *
00059  *   Rappels des fonctions de conversion:
00060  *   -----------------------------------
00061  *
00062  *   La conversion est intimement liée au filtrage car seules les valeurs passant le
00063  *   filtre sont converties. La conversion n'est pas obligatoire. Une valeur de TIME ou TAG
00064  *   entrante peut ne pas être convertie. Elle garde alors sa valeur et est gardée
00065  *   telle quelle pour l'objet destinataire.
00066  *   DATASTREAM peut associer une règle de conversion à chaque règle élémentaire de
00067  *   filtrage.
00068  *   La conversion consiste à changer:
00069  *     - un valeur de TIME ou TAG en une valeur différente
00070  *     - une séquence de valeurs en une autre séquence de valeurs de même taille
00071  *       (ex: 30:40 en 300:400:10)
00072  *   Mais la conversion permet aussi de transformer:
00073  *     - une valeur de TIME ou TAG unique en une séquence de valeurs (les données entrantes sont
00074  *       alors duppliquées et à chaque fois que l'objet destinataire réclame une donnée
00075  *       de la séquence, il reçoit en fait une copie de la donnée reçue une seule fois)
00076  *
00077  *     - une séquence de valeurs en une valeur unique (alors, chaque donnée entrante
00078  *       associée à un TIME ou TAG de la séquence correspond à une donnée unique pour le
00079  *       destinataire: seule la dernière reçue est la donnée valide)
00080  *
00081  */
00082 
00083 #include <vector>
00084 #include <iostream>
00085 
00086 // Pour l'utilisation de "vector" de la STL
00087 // Classe filtre_elementaire
00088 //
00089 // Implémente une structure de donnée décrivant un filtre élémentaire
00090 // sur le paramètre TIME ou TAG; c'est
00091 //    - soit une valeur entière unique
00092 //    - soit une séquence arithmétique de valeurs
00093 //
00094 class filtre_elementaire
00095 {
00096 public:
00097     int len;    // Longueur de séquence ou 1 pour une valeur unique
00098     int debut;  // Début de la séquence ou valeur pour une valeur unique
00099     int fin;    // Fin de la séquence
00100     int pas;    // Pas de la séquence
00101 
00102     // Constructeur par défaut
00103     filtre_elementaire() {}
00104     
00105     // Création d'un filtre élémentaire pour une valeur unique
00106     filtre_elementaire(int valeur)
00107     {
00108         this->len = 1;
00109         this->debut = valeur;
00110     }
00111 
00112     // Création d'un filtre élémentaire pour une séquence de valeurs entières
00113     // Le pas par défaut est 1
00114     filtre_elementaire (int _debut, int _fin, int _pas=1)
00115     {
00116         this->debut = _debut;
00117         this->len = (_fin - _debut) / _pas;
00118         if (this->len > 0)
00119         {
00120             this->fin = _debut + _pas * this->len;  // Calcule la vrai borne de fin
00121             this->pas = _pas;
00122             this->len += 1;   // Compte les bornes et non les intervalles
00123         }
00124         else  // erreur de spécification: on ne prend que la première valeur
00125             this->len = 1;
00126     }
00127 
00128     // Constructeur par copie
00129     filtre_elementaire (filtre_elementaire &_f)
00130     {
00131       this->len = _f.len;
00132       this->debut = _f.debut;
00133       this->fin = _f.fin;
00134       this->pas = _f.pas;
00135     }
00136 };
00137 
00138 // Classe filtre_conversion
00139 //
00140 // Implémente le filtrage et la conversion du paramètre TIME ou TAG
00141 // des données reçues par un port DATASTREAM.
00142 //
00143 // Mode d'emploi:
00144 //      1) Création d'un objet
00145 //      2) Configuration de cet objet par passage de paramètres
00146 //         de filtage et de conversion
00147 //      3) A la création d'un port DATASTREAM, on passe au constructeur
00148 //         deux objets 'filtre_conversion', l'un pour le TIME, l'autre pour le TAG.
00149 //      4) A l'utilisation du port DATASTREAM, celui-ci appelle la méthode
00150 //         "applique_filtre_conversion" pour opérer
00151 //
00152 class filtre_conversion
00153 {
00154 private:
00155     // Structure de données décrivant une conversion élémentaire:
00156     // un filtre élementaire
00157     // et un pointeur éventuel vers les paramètres de conversion associés
00158     class conversion_elementaire
00159     {
00160     public :
00161         // Data
00162         filtre_elementaire filtre;
00163         filtre_elementaire * p_convers;
00164 
00165         // Constructeur
00166         conversion_elementaire() {}
00167 
00168         // Constructeur par copie d'un objet non modifie (const)
00169         conversion_elementaire (const conversion_elementaire& _ce)
00170         {
00171             *this = _ce;
00172         }
00173         // Remarque: le Constructeur par copie d'un objet existe par defaut mais sans le modificateur 'const'
00174         //           et l'emploi d'un objet comme element dans un vecteur oblige d'avoir un tel const-copy-constructor.
00175     };
00176 
00177     // Données de configuration de filtrage et conversion:
00178     //    une table de filtres élémentaires
00179     //    avec leurs données de conversion associées éventuelles
00180     std::vector<conversion_elementaire> config;
00181 
00182 public:
00183     // Constructeur: juste une allocation mémoire initiale
00184     filtre_conversion() {}
00185 
00186     // Destructeur:
00187     // réclamer la mémoire utilisée par tous les éléments du vecteur config
00188     ~filtre_conversion()
00189     {
00190         std::vector<conversion_elementaire>::iterator i;
00191         for (i = this->config.begin(); i != this->config.end(); i ++)
00192         {
00193             delete (*i).p_convers;
00194         }
00195     }
00196 
00197     // Configuration partielle par ajout d'un filtre élémentaire
00198     bool config_elementaire (filtre_elementaire& _f)
00199     {
00200 //    cout << "ajout config_elementaire 1  " << this << endl;
00201         conversion_elementaire conv_elem;
00202         
00203         conv_elem.filtre = _f;
00204         conv_elem.p_convers = NULL;
00205 
00206         // Ajoute cette conversion/filtrage elementaire a la liste
00207         this->config.push_back (conv_elem);
00208     
00209 //    vector<conversion_elementaire>::iterator i;
00210 //    cout << "liste apres ajout:" << endl;
00211 //    for (i = this->config.begin(); i != this->config.end(); i ++)
00212 //    {
00213 //        cout << "config elem   " << endl;
00214 //        cout << "filtre: len, debut, fin, pas " << (*i).filtre.len << " " << (*i).filtre.debut << " " << (*i).filtre.fin << " " << (*i).filtre.pas << endl;
00215 //    }
00216         
00217         return true;
00218     }
00219     
00220     // Configuration partielle par ajout d'un filtre élémentaire
00221     // et sa conversion associée
00222     //
00223     // Retourne false si les param de conversion sont incompatibles avec le filtre élémentaire.
00224     // La configuration partielle est alors refusée.
00225     //
00226     bool config_elementaire (filtre_elementaire& _f, filtre_elementaire& _conv)
00227     {
00228 //    cout << "ajout config_elementaire 2  " << this << endl;
00229     
00230         if (_f.len == 1 || _conv.len == 1 || _f.len == _conv.len)
00231         {
00232             conversion_elementaire conv_elem;
00233             conv_elem.filtre = _f;
00234             conv_elem.p_convers = new filtre_elementaire(_conv);
00235 
00236             // Ajoute cette conversion/filtrage elementaire a la liste
00237             this->config.push_back (conv_elem);
00238     
00239 //    vector<conversion_elementaire>::iterator i;
00240 //    cout << "liste apres ajout:" << endl;
00241 //    for (i = this->config.begin(); i != this->config.end(); i ++)
00242 //    {
00243 //        cout << "config elem   " << endl;
00244 //        cout << "filtre: len, debut, fin, pas " << (*i).filtre.len << " " << (*i).filtre.debut << " " << (*i).filtre.fin << " " << (*i).filtre.pas << endl;
00245 //    }
00246         
00247             return true;
00248         }
00249         else
00250         {
00251             // Filtre et conversion incompatibles
00252             return false;
00253         }
00254     }
00255 
00256     // applique_filtre_conversion: Opération du filtre et de la conversion
00257     template <typename T > T applique_filtre_conversion (T valeur_initiale, std::vector<T>& liste_conversions) const;
00258 };
00259 
00260 
00261 
00262 // filtre_conversion::applique_filtre_conversion: Opération du filtre et de la conversion
00263 //
00264 // Etant donné une valeur entière (de TIME ou de TAG), cette méthode détermine :
00265 //   - si cette valeur passe le filtre
00266 //   - dans le cas où une conversion existe, la liste des valeurs de conversion
00267 //     qui correspondent à la valeur initiale
00268 //
00269 // Dans tous les cas, cette méthode retourne une liste de valeurs.
00270 // Dans le cas où il n'y a pas de conversion, cette liste a une longueur 1
00271 // et ne contient que la valeur initiale.
00272 //
00273 // Paramètre d'entrée :         la valeur initiale (integer)
00274 //
00275 // Paramètre de sortie :        la liste des valeurs après conversion (vector<int>)
00276 //
00277 // Valeur de retour :           la longueur de la liste
00278 //     si cette longueur est 0, c'est que la valeur initiale ne passe pas le filtre
00279 //
00280 template <typename T>
00281 T filtre_conversion::applique_filtre_conversion (T valeur_initiale, std::vector<T>& liste_conversions) const
00282 {
00283     // Part d'une liste vierge
00284     liste_conversions.clear();
00285 
00286 //    cout << "config applique_filtre_conversion " << this << endl;
00287     
00288     // Balaye tous les éléments de configuration
00289     // et cherche pour chacun d'eux si la valeur initiale est présente parmi les valeurs filtrées
00290 
00291     // Pour tous les éléments de configuration du filtrage/conversion
00292     std::vector<conversion_elementaire>::const_iterator i;
00293     for (i = config.begin(); i != config.end(); i ++)
00294     {
00295 
00296 //    cout << "config elem   " << endl;
00297 //    cout << "filtre: len, debut, fin, pas " << (*i).filtre.len << " " << (*i).filtre.debut << " " << (*i).filtre.fin << " " << (*i).filtre.pas << endl;
00298     
00299         bool si_passe_filtre = false;
00300 
00301         // Si la longueur du filtre est 1
00302         if ((*i).filtre.len == 1) {
00303           // Si la valeur initiale correspond à la valeur du filtre
00304           if ((*i).filtre.debut == valeur_initiale)
00305             si_passe_filtre = true;
00306         } else  {
00307           // Si la valeur initiale est dans la séquence des valeurs du filtre
00308           //   la valeur est comprise dans les bornes [debut,fin]
00309           //   et sa distance du début de la séquence est modulo le pas
00310           if (  ((*i).filtre.fin - valeur_initiale >= 0) == (valeur_initiale - (*i).filtre.debut >= 0)
00311                 &&  (valeur_initiale - (*i).filtre.debut) % (*i).filtre.pas == 0  ) {
00312             si_passe_filtre = true;
00313           }
00314         }
00315 
00316         // Si la valeur initiale passe le filtre
00317         if (si_passe_filtre) {
00318           //    cout << "config: filtre passe    " << endl;
00319             
00320           // Si il y a une conversion à effectuer
00321           if ((*i).p_convers != NULL) {
00322 
00323             // Si la longueur du filtre est 1
00324             if ((*i).filtre.len == 1) {
00325 
00326               // Si la longueur des paramètres de conversion est aussi 1
00327               if ((*i).p_convers->len == 1) {
00328                 // Ajoute la valeur de conversion à la liste des valeurs après conversion
00329                 liste_conversions.push_back ((*i).p_convers->debut);
00330               } else {
00331                 // Ajoute la séquence de conversion à la liste des valeurs après conversion
00332                 for (int s = (*i).p_convers->debut; s != (*i).p_convers->fin; s += (*i).p_convers->pas) {
00333                   liste_conversions.push_back (s);
00334                 }
00335                 liste_conversions.push_back ((*i).p_convers->fin);
00336               }
00337 
00338             } else {
00339               // Le filtre est une séquence qui est convertie en une autre séquence de même longueur
00340               // Choisit la valeur au rang désiré dans la séquence de conversion
00341               int rang = (valeur_initiale - (*i).filtre.debut) / (*i).filtre.pas;
00342 
00343               int valeur_convertie = (*i).p_convers->debut + rang * (*i).p_convers->pas;
00344 
00345               // Ajoute cette valeur à la liste des valeurs après conversion
00346               liste_conversions.push_back (valeur_convertie);
00347             }
00348           } else {
00349             // Ajoute la valeur initiale telle-quelle à la liste des valeurs après conversion
00350             liste_conversions.push_back (valeur_initiale);
00351           }
00352         }
00353     }
00354 
00355     return liste_conversions.size();
00356 }