Kbase P47676: ADM2: How to achieve a passthrough link with a custom link?
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  17/10/2003 |
|
Status: Unverified
GOAL:
How to achieve a passthrough link with a custom link?
FIX:
The following solution has been successfully tested with Dynamics 2.0A02, and might work the same with simple ADM2.
Says we want to achieve a passthrough link 'MyLink' between ObjA and ObjB respectively contained in ContainerA and ContainerB.
We already have the 2 following links:
Source link Target
ObjA MyLink ContainerA
ContainerB MyLink ObjB
Normally, doing the following:
RUN addLink(hContainerA,'MyLink',hContainerB).
Should result in:
Source link Target
ObjA MyLink ContainerA
ContainerA MyLink ContainerB
ContainerB MyLink ObjB
Which the ADM2 will resolve into one single link 'MyLink' between ObjA and ObjB. We call this mechanism passThrough link. Note that this case is about resolving the most sophisticated situation with 3 links into one. But the same applies with simpler case of 2 links resolved in one, with only one involved container in the chain such as SDOa + SmartFrameB + SDOb resulting in SDOa + SDOb
Now, the 3 following steps will have to be achieved to make a passThrough link really work, because smart.p/addLink was designed to manage passThrough links only for standard links:
1) Make sure that the ADM2 considers 'MyLink' as a possible passThrough link:
DEFINE VARIABLE cPassThroughLinks AS CHARACTER NO-UNDO.
cPassThroughLinks = DYNAMIC-FUNCTION('getPassThroughLinks':U).
IF LOOKUP('myLink;Single',cPassThroughLinks) = 0 THEN
DYNAMIC-FUNCTION('setPassThroughLinks':U, cPassThroughLinks + ",myLink;Single").
You might run the above code at the beginning of your session, or customize the smart.p class. Note that all the smart objects inherit from the passThroughLinks property, which is stored in smart.p. See note a the bottom about using ';multiple' instead of ';single'
2) Add the following function into ContainerA (or its super procedure):
FUNCTION getMyLinkSource RETURNS CHAR
( /* parameter-definitions */ ) :
/* The following is needed to avoid a infinite loop:
The normal way to find out the list of handles at one side of a link is to
call linkHandles. Now smart.p/linkHandles first calls getMyLinkSource again
because it usual exist only for the standard links (SupportedLinks).
If we first returns ? to linkHandles then we will force linkHandles to
work out the targets from Object:ADM-DATA.
So calling getMyLinkSource from ProcedureA will result in calling
linkHandles, which calls again getMyLinkSource which return ? to linkHandles,
so linkHandles works out the info from ADM-DATA and returns it to the first
call of getMyLinkSource, which can at last return it to ProcedureA*/
IF PROGRAM-NAME(2) BEGINS "linkHandles" THEN RETURN ?.
RETURN DYNAMIC-FUNCTION('linkHandles':U IN TARGET-PROCEDURE, 'MyLink-source').
END FUNCTION.
3) Add the following function into ContainerB (or its super procedure):
FUNCTION getMyLinkTarget RETURNS CHAR
( /* parameter-definitions */ ) :
/* The following is needed to avoid a infinite loop:
The normal way to find out the list of handles at one side of a link is to
call linkHandles. Now smart.p/linkHandles first calls getMyLinkTarget again
because it usual exist only for the standard links (SupportedLinks).
If we first returns ? to linkHandles then we will force linkHandles to
work out the targets from Object:ADM-DATA.
So calling getMyLinkTarget from ProcedureA will result in calling
linkHandles, which calls again getMyLinkTarget which return ? to linkHandles,
so linkHandles works out the info from ADM-DATA and returns it to the first
call of getMyLinkTarget, which can at last return it to ProcedureA*/
IF PROGRAM-NAME(2) BEGINS "linkHandles" THEN RETURN ?.
ELSE RETURN DYNAMIC-FUNCTION('linkHandles':U IN TARGET-PROCEDURE, 'MyLink-target').
END FUNCTION.
By enabling multiple targets for mylink (use 'My.link;multiple' instead of 'Mylink;single' in setPassThroughLinks) the situation will end up with the expected following links:
Source link Target
ObjA MyLink ContainerA
ObjA MyLink ContainerB
ObjA MyLink ObjB
Note: Replace 'myLink' by 'yourLink' everywhere in the code, including in the function names..