IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XMLRAD Discussion :

XMLGRAM


Sujet :

XMLRAD

  1. #1
    Membre habitué
    Inscrit en
    Janvier 2003
    Messages
    214
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 214
    Points : 132
    Points
    132
    Par défaut XMLGRAM
    Bonjour,

    Voici mon problème : j'ai une base qui a des intégrités référentielles. Je dois faire des inserts et updates sur ces bases mais le pb est le suivant.

    Si je ne renseigne rien dans mon champ avec intégrité, le DAC va mettre '' lors de l'insertion et boum!! ma bdd me renvoie une erreur d'intégrité, ce qui est normal car je n'ai pas d'enreg avec comme clé '' (qui plus est, il est impossible d'en créer une car une contrainte not null est sur le champ référent).

    Quelqu'un a-t-il déjà eu ce cas ???

    J'ai essayé un truc, c'est d'envoyer une fonction dans mon BeforeXmlGram qui va modifier le :CHAMP par NULL. Ca marche, mais evidemment comme la requête est gardée en mémoire, lors de mon prochain appel à cette requête, le NULL va rester... y a-t-il un moyen de recharger la requête du fichier xml ???

    pour info, voici ma petite fonction :
    procedure VerifChamp(const Context : IXMLContext; var XmlGram : IXmlGram ; MyRequete,sChamp: string);
    var
    MyXMLInstruction : IXMLInstruction;
    MyDBExtract : TDBBatch;
    begin
    MyXMLInstruction := XMLGram.GetXMLInstruction('MyRequete');
    MyDBExtract := TDBBatch(MyXMLInstruction.Get_ObjectReference);
    if Context.Values[MyChamp]= '' then
    begin
    MyDBExtract.Statement := StringReplace(MyDBExtract.Statement,':'+MyChamp,'NULL',[rfReplaceAll]);
    end;

    Merci d'avance

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 42
    Points : 31
    Points
    31
    Par défaut Re: XMLGRAM
    Je ne comprends pas bien ton pb, mais tu as dû le règler de puis le 29/01.

    Il est toujours préférable de vérifier l'intégrité des données côté serveur, cad après envoi de la Form et dans dans un beforexmlgram. En cas de non intégrité tu renvoies sur la form mal renseignée avec un msg d'erreur...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function InsertOPERATION_BeforeXMLService(XMLService)
    {
     
      if (Context.GetValue("ID_IMPUTATION")== '0') 
        throw (Error("Vous devez choisir une imputation"));
      if (Context.GetValue("ID_NATURE_MISSION")== '0') 
        throw (Error("Vous devez choisir un type de mission"));
      if (Context.GetValue("PROTOCOLE_OP")== '') 
        throw (Error("Vous devez choisir un type de protocole"));
      if (Context.GetValue("ID_AVANCE")== '0') 
        throw (Error("Vous devez choisir un état d'avancement"));
      if (Context.GetValue("MONTANT_OP")== '0') 
        throw (Error("Le Montant ne peut être"));
      if (Context.GetValue("MONTANT_DEVIS")== '0') 
        throw (Error("Le Montant du devis ne peut être nul"));
     
    }

  3. #3
    Membre habitué
    Inscrit en
    Janvier 2003
    Messages
    214
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 214
    Points : 132
    Points
    132
    Par défaut
    En fait, j'ai depuis contourné le pb, mais il reste cependant d'actualité.

    Le pb est que le DAC ne gère pas les NULL, cad que si la valeur du context ID_LIEN (qui est soumise à intégrité dans une autre table) est égale à '', c'est correct dans ma table car ce champ n'est pas obligatoire.

    ce que je voudrais, c'est que lors de mon insert, je puisse mettre NULL au lieu de '' car '' n'existe pas dans ma table de référence.

    P.S. : EN fait j'utilise maintenant le {$Valeur} dans mes requêtes qui me permettent dans le beforexmlgram de l'initialiser soit à :ID_LIEN, soit à NULL et ça marche bien. (mais c'est pas automatique ...

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    520
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 520
    Points : 1 446
    Points
    1 446
    Par défaut
    Citation Envoyé par rgarnier
    En fait, j'ai depuis contourné le pb, mais il reste cependant d'actualité.

    ce que je voudrais, c'est que lors de mon insert, je puisse mettre NULL au lieu de '' car '' n'existe pas dans ma table de référence.

    P.S. : EN fait j'utilise maintenant le {$Valeur} dans mes requêtes qui me permettent dans le beforexmlgram de l'initialiser soit à :ID_LIEN, soit à NULL et ça marche bien. (mais c'est pas automatique ...
    Presque 4 ans après...

    Et tu affectes quoi comme valeur dans SetValue pour que ce soit NULL ?

    Je me trouve dans le même cas.
    La soluce de trafiquer les NULL me dérange un peu.
    L'autre soluce c'est d'ajouter un enregistrement vide dans la table de référence et dont l' ID = 0. La seule contrainte, c'est lorsqu'on présente dans une grille par exemple, la liste de ces données de référence, il faut ajouter une restriction SQL : Where ID > 0
    Dans le cas d'une balise HTML Select, si on veut permettre un choix null à l'utilisateur, on lui propose tous les enregistrements, dont le vide.

    Sylvain

  5. #5
    Membre habitué
    Inscrit en
    Janvier 2003
    Messages
    214
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 214
    Points : 132
    Points
    132
    Par défaut
    oulà, je me demandais bien pourquoi ce post était de retour ....

    En fait, j'ai la chance d'avoir des normes de nommage de champs de ma BD qui font que je sais identifier en fonction de son nom, un champ avec intégrité référentielle. Du coup, je modifie le dacado.pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    procedure TDacAdoQuery.InternalSetParamAsString
    var
      ...
    begin
      ...
      if (Value = '') and (Copy(Parameter.Name,1,1) = 'K')then
      begin
        Parameter.Value := null;
      end;
    ...
    end;
    Ok, c'est pas très propre, mais robuste
    (en fonction de la bd, tu pourrais aller regarder dans les tables systèmes la liste des champs avec intégrité, c'est peut-être une piste)

    Ta solution d'ajouter un enreg 0 est à mon avis mon bonne, car d'un côté tu annonce que ta BD respecte les (bonnes) règles d'une BD relationnelle, et puis tu bidouille un enregistrement qui n'en n'est pas un.
    Si un architecte voit ça, j'imagine qu'il va faire des bonds à se cogner la tête au plafond.

    Tiens-moi au courant de tes investigations, je suis preneur de tout avis sur la question (très sensible chez pas mal de nos clients)

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    520
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 520
    Points : 1 446
    Points
    1 446
    Par défaut
    Citation Envoyé par rgarnier
    oulà, je me demandais bien pourquoi ce post était de retour ....
    Si un architecte voit ça, j'imagine qu'il va faire des bonds à se cogner la tête au plafond.
    hé hé c'est pas faux :-)
    On est devant une réalité embarassante. D'un côté Delos qui préconise l'abandon des NULL et d'un autre côté un héritage de technologies et de techniques qui impliquent la prise en compte des null.
    Le fait est qu'en SQL, 0 est différent de NULL et est susceptible d'avoir une signification sémantique complètement différente.

    Ma soluce est loin d'être idéale puisqu'elle implique des adaptations - voire une certaine complexification - au niveau de la gestion des données et de la présentation.
    Ta solution est restrictive puisqu'elle implique d'avoir un modèle de données respectant une norme de nommage. Malgré tout c'est une bonne idée.

    Alors je me dis qu'on pourrait adapter ta solution de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TDacAdoQuery.InternalSetParamAsString
    var
      ...
    begin
      ...
      if (Value = '') and (XMLApplication.InitParams.Values['XMLC_AllowNULLValue'] = '1') then
      begin
    // tester aussi si le type du champ n'est pas string par ex.
        Parameter.Value := null;
      end;
    ...
    end;
    Ca permettrait de travailler avec des "NULL" quand les champs sont vides pour peu qu'on l'ait indiqué dans les InitParams. Il reste quelques inconvénients cependant.

    Par exemple comment déterminer qu'une chaine est NULL ou vide ? Il faudrait que cette règle ne s'applique que sur certains types de champs, ou bien tu as raison, uniquement sur ceux qui font l'objet d'un intégrité référentielle.

    Et ne s'éloigne-t-on pas de la philosophie d'XMLRAD qui consiste à encadrer le développeur au maximum ? En permettant les écarts (si on accepte que c'en est un), ne brise-t-on pas ce bénéfice de l'encadrement...

    à discuter, mais il faut bien admettre que l'absence de NULL introduit aussi des difficultés.

    PS : J'avais envie de battre un record : l'attente maxi avant de répondre à une question

  7. #7
    Membre actif Avatar de Jeweller
    Inscrit en
    Août 2003
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 357
    Points : 278
    Points
    278
    Par défaut
    Si il y en a que ca interesse, voici comment je contourne ce pb:

    Les requetes sont ecrites alors comme ca (un parametre NU_PRIACH est déclaré de type FLOAT):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    UPDATE TABLE
    SET
    NU_PRIACH = {$NU_PRIACH_PAR},
    ....
    WHERE CLE = :CLE
    Et du code par code, on peut faire un truc comme ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      if Context.GetValue('NU_PRIACH') <> '' then
      begin
        s :=  Job.GetStrFloat(Context.GetValue('NU_PRIACH')); //gestion des formats
        if s = ''
        then //raise d'une erreur de saisie
        else Context.SetValue('NU_PRIACH',s);
        Context.SetValue('NU_PRIACH_PAR',':NU_PRIACH');
      end else
      begin
        Context.SetValue('NU_PRIACH_PAR','NULL');
        Context.SetValue('NU_PRIACH','0'); // pour tests ultérieurs
      end;
    L'avantage, cest qu'on touche pas au framework, mais le gros inconvinient c'est qu'il faut coder à chaque fois (même si c'est factorisable), mais pour les champs float, dates ou meme string, on maitrise vraiment ce qui est inséré ou mis à jour!
    Bonne vacances (j'ai pas résisté!) ;-)
    Michael

  8. #8
    Membre expérimenté

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    520
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 520
    Points : 1 446
    Points
    1 446
    Par défaut
    Citation Envoyé par Jeweller
    L'avantage, cest qu'on touche pas au framework, mais le gros inconvinient c'est qu'il faut coder à chaque fois (même si c'est factorisable), mais pour les champs float, dates ou meme string, on maitrise vraiment ce qui est inséré ou mis à jour!
    Bonne vacances (j'ai pas résisté!) ;-)
    Michael
    Les vacances ! ... ah ah
    Comme tu dis, en factorisant un minimum, ça serait aussi une solution intéressante.
    Cependant, factoriser reviendrait presque à se substituer au framework.

    Le constat que je fait, c'est que la plupart d'entre nous tente de contourner - tant bien que mal - cette absence de gestion des NULL.
    Ca veut dire que personne n'a été convaincu de l'intérêt de ce choix, ou ne l'a pas compris ? La question mérite d'être débattue :-)

  9. #9
    Membre habitué
    Inscrit en
    Janvier 2003
    Messages
    214
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 214
    Points : 132
    Points
    132
    Par défaut
    Les personnes de Delos pourraient mieux donner la 'politique' Delos, mais vu :
    - la conception de la BD Delos,
    - leur intention de distribuer une BD 'propriétaire',
    - que XMLRAD découle de Delos,
    ==> la gestion des NULL ne sont pas dans les cartons (ou alors dans les cartons de la cave )

  10. #10
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    Il y a un problème de fond que vous avez aborder mais rapidement:
    pour une chaine de caractère en paramètre il n'est pas possible de passer une valeur qui serait équivalente à NULL du fait du protocole HTTP !

    on pourrait considérer que '' implique une insertion de NULL
    sauf que dans d'autres cas, pour un champ acceptant les NULL, une chaine vide aurait aussi une signification.

    On est d'accord que pour tous les autres type autres que VARCHAR, une chaine vide peut signifier NULL sans ambiguité, mais du coup ce n'est pas cohérent avec le reste.

    Regardez comment les autres technologies Web font pour gérer les NULL. il le font en dur dans leur requête (pas de paramètre/prépartion) ou par code.

    On peut envisager une option comme le suggère sylvain pour considérer les chaines vides comme des NULL même pour les VARCHAR, sauf que ca ne vas pas autoriser d'insérer une chaine vide.
    Si le champ n'accepte pas les NULL il faudrait le typé avec un VARCHAR NOT NULL pour que le framework puisse mettre chaine vide à la place

    ou/et bien on décrit champ par champ NULLABLE ou NOT NULLABLE

    est-ce que cela régèlerais tous vos problèmes ?

  11. #11
    Membre expérimenté

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    520
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 520
    Points : 1 446
    Points
    1 446
    Par défaut
    Citation Envoyé par RDM
    On peut envisager une option comme le suggère sylvain pour considérer les chaines vides comme des NULL même pour les VARCHAR, sauf que ca ne vas pas autoriser d'insérer une chaine vide.
    Si le champ n'accepte pas les NULL il faudrait le typé avec un VARCHAR NOT NULL pour que le framework puisse mettre chaine vide à la place

    ou/et bien on décrit champ par champ NULLABLE ou NOT NULLABLE

    est-ce que cela régèlerais tous vos problèmes ?
    Comme tu dis, il n'est pas certain que ça n'introduise pas autant de contraintes que ça n'en enlève.
    En y réfléchissant de plus en plus, je me dis qu'il n'y a pas de solution globale au problème, qui si elle existait ne ferait que déplacer le problème (que tu évoques ci dessus).

    Pour la question des Selections (DBExtract) il ne me semble pas trop compliqué d'indiquer si une donnée a été récupérée NULL ou vide, selon l'exemple suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <ETAB>
       <ID_ETAB>2</ID_ETAB>
       <SIGLE_ETAB>AMUE</SIGLE_ETAB>
       <NOM_ETAB IsNull="1"></NOM_ETAB>
    </ETAB>
    , ce qui offrirait un élément d'interprétation supplémentaire, d'autant que la valeur NULL peut refléter une sémantique particulière dans le modèle de donnée.

    En revanche, la question des insertions et mises à jour est plus délicate.
    on pourrait étudier une approche localisée au niveau du XMLGram qui pourraient switcher la gestion des NULL ou non selon certaines conditions :

    On a vu avec l'expérience que seulement dans certains cas on a besoin d'injecter des NULL quand certaines valeurs sont vides.
    On pourrait indiquer ces cas particuliers au niveau des "propriétés" de paramètres. Par exemple on est aujourd'hui capable de spécifier un format dans lequel un champ doit être rendu par le framework.
    Et mieux, on sait aussi décrire des contraintes sur paramètres (expressions régulières et rules) en fonction desquelles une exception est déclenchée.

    Ne pourrait-on pas imaginer une nouvelle "propriété" de paramètre qui permettrait de décrire les conditions dans lesquelles on affecte NULL à un paramètre ?
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <DBBatch Name="DBUpd_AGENT">
       <DataSource>DBCAMEL_ORA</DataSource>
       <Params>
          <Param>
             <Name>ID_ETAB_AFFECTE</Name>
             <Type>INTEGER</Type>
             <Value>0</Value>
             <CheckConstraint></CheckConstraint>
             <Exception></Exception>
             <UpdateMode></UpdateMode>
             <Statement><![CDATA[]]></Statement>
             <Fields/>
             <Fragments/>
             <SetNULLWhenRule>Context.ID_ETAB=''></SetNULLWhenRule>
             </Param>
    ....
    Je suis convaincu que l'absence de gestion des NULL dans XMLRAD apporte plus d'avantages que d'inconvénients, mais avec une solution de ce genre on ne serait pas devant une impasse face à certains modèles de données utilisant explicitement les NULLs.
    Cela resterait du cas particulier, mais gérable. On n'est plus si loin de ta proposition de NULLABLE / NOT NULLABLE Champ par Champ :-)

  12. #12
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    interessante ton idée d'utiliser les rules...

  13. #13
    Membre habitué
    Inscrit en
    Janvier 2003
    Messages
    214
    Détails du profil
    Informations forums :
    Inscription : Janvier 2003
    Messages : 214
    Points : 132
    Points
    132
    Par défaut
    Ce qui me gène dans la solution de Sylvain, c'est qu'on déporte le pb de gestion de bd au niveau du développeur, alors que celui qui a pensé la base a déjà mis en place les contraintes de maj. (les intégrités référentielles et NULL/NOT NULL), et en plus, le comportement de gestion d'un champ pourrait être différent en fonction des écrans.


    Un exemple tout bête :
    SELECT * FROM CLIENTS WHERE VILLE = ''
    Si des enregistrements ont '' dans VILLE et d'autres NULL, cette requete ne renverra pas les mêmes enregistrements en fonction du moteur de bd utilisé


    Plusieurs idées (combinables) :
    - Un paramètre général du style XMLC_NULL qui indiquerait au xmlgram d'insérer NULL dans les champs VARCHAR dont la valeur du paramètre = ''
    ==> Cela aurait pour effet de figer un comportement standard.
    - Une variable mémoire créée au demarrage qui serait remplie avec les données des tables systèmes + paramétrage spécifique éventuel.
    - Un concept de construction dynamique de requete en fonction des valeurs modifiées (on a la valeur de chaque champ lors de l'ouverture de l'écran, puis sa valeur lors de la validation, et si les 2 valeurs sont identiques, on ne met même pas ce champ dans la requete)

  14. #14
    Membre expérimenté

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    520
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 520
    Points : 1 446
    Points
    1 446
    Par défaut
    Citation Envoyé par rgarnier
    Ce qui me gène dans la solution de Sylvain, c'est qu'on déporte le pb de gestion de bd au niveau du développeur, alors que celui qui a pensé la base a déjà mis en place les contraintes de maj. (les intégrités référentielles et NULL/NOT NULL), et en plus, le comportement de gestion d'un champ pourrait être différent en fonction des écrans.

    Un exemple tout bête :
    SELECT * FROM CLIENTS WHERE VILLE = ''
    Si des enregistrements ont '' dans VILLE et d'autres NULL, cette requete ne renverra pas les mêmes enregistrements en fonction du moteur de bd utilisé
    Je suis d'accord avec ta première remarque. Ceci dit il ne serait pas impossible de générer automatiquement les <Param> gérant les null, pour peu qu'on se repose sur les metadonnées de la base SQL. Le travail du développeur consisterait à vérifier la pertinence de ce qui a été généré. Aujourd'hui par ex, les <param> de type date sont aussi générés automatiquement.
    L'important est de pouvoir continuer à gérer les NULL au cas par cas.

    Pour les Selections SQL, il suffirait comme je l'ai indiqué dans mon thread précédent, d'ajouter un attribut dans l'output XML qui indiquerait si la donnée est NULL, permettant ainsi de bien distinguer NULL et vide.

    Plusieurs idées (combinables) :
    - Un paramètre général du style XMLC_NULL qui indiquerait au xmlgram d'insérer NULL dans les champs VARCHAR dont la valeur du paramètre = ''
    ==> Cela aurait pour effet de figer un comportement standard.
    - Une variable mémoire créée au demarrage qui serait remplie avec les données des tables systèmes + paramétrage spécifique éventuel.
    - Un concept de construction dynamique de requete en fonction des valeurs modifiées (on a la valeur de chaque champ lors de l'ouverture de l'écran, puis sa valeur lors de la validation, et si les 2 valeurs sont identiques, on ne met même pas ce champ dans la requete)
    Je ne crois pas trop aux vertus d'un paramètre général car je pense qu'en résolvant les problèmes d'un côté, on les déplacerait d'un autre côté.
    Pour la variable mémoire, pourquoi pas mais je ne vois pas trop comment tu voudrais l'utiliser et si ça ne serait pas trop complexifier le pb ?
    Concernant le concept de construction dynamique de requête, ca peut être complémentaire au concept d'utilisation des rules pour assigner NULL à un champ. En effet, on pourrait imaginer une propriété type "IgnoreParam", décrite avec une Rule, en fonction de laquelle le middleware enverrai ou non le champ respectif au sein de la requête SQL.

    Intéressant tout ça :-)

Discussions similaires

  1. XMLGram, Import et cache
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 13
    Dernier message: 05/03/2003, 17h09
  2. C'est quoi "Profile" dans le assign du XMLGram ?
    Par Lux interior dans le forum XMLRAD
    Réponses: 2
    Dernier message: 28/02/2003, 11h37
  3. XMLGram et nombre d'enregistrements par page
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 7
    Dernier message: 26/02/2003, 12h35
  4. {$PARAM} dans XMLGRAM
    Par rgarnier dans le forum XMLRAD
    Réponses: 3
    Dernier message: 31/01/2003, 12h42
  5. [XMLRAD] Version 7RC et XMLGRAM
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 2
    Dernier message: 24/12/2002, 10h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo