En revanche, si je copie le parent de mon objet, ce dernier se duplique bien avec ses liens.
Je n’ai rien de particulier dans les logs (même en debug), et j’ai désactivé tous les hook sans résultat.
Je n’ai pas le souci sur d’autres objets, donc il y a quelque chose de spécifique à celui ci que je n’arrive pas à identifier.
Auriez vous d’autres pistes d’analyse à me conseiller ? Des traces à mettre quelque part ?
Merci d’avance pour votre aide car je sèche …
Emmanuelle
Il faudrait clarifier le modèle logique et les clés foncitonnelles.
C’est l’idée.
La copie cascade des liens est une recopie des objets liées ayant l’objet parent en clé fonctionnelle. Sinon c’est impossible de copier N objets qui serait en doublon.
Pour copier un objet enfant, c’est juste la FK vers le parent qui doit être recopiable. La notion de copie cascade ne sert pas.
Si la clé fonctionnelle de l’objet lié n’est que la FK du parent, tu ne peux avoir qu’un seul objet rattaché au parent. Il doit manquer un autre champ en clé pour avoir une relation 0,n en plus de la FK au parent.
Ensuite tu peux debugger :
les links définis sur la parent initUpdate : getLinks() / link.isCascadeCopy()
les pre/postSelect(id, copy) for copy=true sur les enfants (panel instance) + setValue de la FK au parent + validate/save
Si la FK n’est pas clé fonctionnelle il y a un warning dans les logs.
Oui à l’affichage, ce n’est pas une copie, mais ça passe par les hooks
preSearch / preSelect/postSelect… par ligne / et postSearch final
Si “le select for copy” n’est pas appelé, il faut regarder le search de l’instance panel fille qui précède les select et qui a surement une search-spec ou un filtrage (LOG_SQL_USER=yes si pas clair dans le code).
preValidate/postSave… si le select for copy est ok, Simplicité lui change de parent et enregistre/create. Bref rien de nouveau, Simplicité passe par la couche logique comme tout le monde pour manipuler les objets en copie.
Tu peux ajouter des parent.isCopied() pour bypasser des règles de filtrage dans ton code lors d’une recopie d’un objet fils.
En fait j’ai l’impression qu’il n’y a aucun search sur les liens de mon objet source, on dirait qu’il ne détecte pas qu’ils sont en cascade copie.
J’ai mis des traces dans le preSearch et je n’ai rien, avec ou sans search spec. Ca s’arrête après le postCreate de mon objet copié.
Est-ce que je peux tracer la façon dont il sélectionne les liens en cascade copie ?
Merci pour ton aide, je suis à cours d’idées !
Emmanuelle
// Already copied (thru recursion) ?
if (h.containsKey(key))
return;
// All links
for (Link link : obj.getLinks()) {
// Hook copiable ?
if (!link.isCascadeCopy())
continue;
ObjectDB child = g.getPanelObject(link.getObjectName(), link.getFieldName());
child.resetFilters();
ObjectField fk = child.getField(link.getFieldName());
// Belongs to functional key ?
if (!fk.isFunctId())
// warning
continue;
// List all children with the parent context
fk.setFilter(parentId);
child.setParentObject(obj);
child.setParentObjectRefField(link.getFieldName());
List<String[]> rows = child.search(false);
for (String[] row : rows) {
// Select for copy
if (!child.select(row[0], true))
continue;
// Update the foreign key to copied item
fk.setValue(newId);
// populate FK
// reset non copiable fields
// copy documents...
// Validate and save
// Recursion
copyCascad(child, child.getRowId(), row[0], h);
}
}
Si le search n’est pas appelé c’est à priori :
le getLinks de l’objet qui ne contient pas ce lien ? pb héritage, droits ?
J’ai peut-être une piste, j’ai mis cette trace dans le preCreate de la classe commune à tous les objets.
AppLog.info("Entering precreate for " + getName() + " can copy " + canCopy() + " is copy " + isCopied(), getGrant());
Sur un objet où le cascade copy fonctionne, j’ai isCopied = true, mais sur mon objet qui pose problème, j’ai isCopied = false.
Est-ce possible que je fasse quelque chose qui change le contexte ? Est-ce que ça peut influer sur le cascade copy ?
canCopy est true dans tous les cas et j’ai bien mes links avec isCascade copy = true donc pas de souci de ce côté.
Je me demandais plutôt si je pouvais voir les logs système, c’est à dire les SELECT sur m_objfield etc … car même en activant les LOG_SQL_SYSTEM j’ai l’impression que je n’ai pas ce niveau de détail.
Non pas de getTargetObject sur cet objet.
isCopied change entre initCopy et initUpdate mais je ne vois rien d’intéressant dans les traces entre les deux :-/
RciAppSub|initCopy for RciAppSub is copy true
RciAppSub|initUpdate||Event: Entering initUpdate for RciAppSub is copy false
Et même sur l’objet ascendant ? en général c’est lui qui pilote quel héritier afficher.
c’est normal.
Une copy ou une création ne passe jamais par initUpdate. mais par l’initCopy et initCreate. on appelle souvent l’initCreate dans l’initCopy pour appliquer les mêmes règles.
Tu peux forcer l’id à copier par code setCopyId(id) mais ça c’est déjà fait par le “select for copy” select(id, true) sauf si tu travailles sur une instance à part qui fait autre chose.
As-tu du code pour pré-créer le record, puis qui ouvre le formulaire en mise à jour sans passer par l’écran de recopie ?
Et peut-être une révélation, je perds le copy ID entre le initCopy et le preSave.
J’ai codé en dur un setCopyId avec mon ID d’origine et cette fois j’ai bien les objets liés.
Plus qu’à trouver où je perds cet ID en route …
RciAppSub|initCopy for RciAppSub isCOpied true rowid 0 copy id 3151||Event: BEGIN
RciAppSub|initUpdate||Event: Entering initUpdate for RciAppSub can copy true is copy false
RciAppSub|preSave||Event: Entering preSave for RciAppSub rowid 0
RciAppSub|preSave||Event: Entering preSave for RciAppSub can copy true is copy false copy id null
PS : il semble en revanche que je passe dans le initUpdate alors que ce n’est pas sensé être le cas ?
Il y a peut-être du code qui refait un select(id) simple quelque part sur l’instance et qui du coup retire le copyId ? Il faut mettre le plus de code en commentaire et voir si ça corrige, puis décommenter progressivement pour identifier ce qui fait ce reset.
Ou sinon un effet indésirable du lien N,N présenté en pillbox ? Essaye de le remettre en affichage de liste temporairement pour voir.
J’ai commenté tout le code sans résultat, en revanche j’ai identifié le moment où je perds le copy ID, c’est quand je change une clé fonctionnelle de mon objet avant d’enregistrer (pour ne pas avoir de duplicate).
J’ai fait un setValue de cette valeur dans le preValidate pour ne pas avoir à cliquer sur la loupe et select la clé, mon cascade copy fonctionne.
Maintenant je debug pour comprendre ce qui fait disparaître mon copy ID au moment du Select.