How to Identify "Calling Application"

DBohner-(db)

Legendary Poster
OK, I know this is well-beyond the normal...

I have a requirement to configure logic of a Child-App, based on the Parent App that calls it.

For example:
If AppX is called by App1, AppX does A, B, C...
If AppX is called by App2, AppX does C, D, X...
If AppX is called by App3, AppX does A, C, X...

What AppX does, based from the calling (Parent) app - is stored in a table...

Using a C-Function, I can usually identify the calling application based LPDS (I'll have to login to their system to confirm the structure)...

The function works 'most of the time', but when there are a cascade of parents calling down the line - the DS doesn't seem to populate correctly. Thus, I'm looking for an alternate suggestion.

In other words, What might be the Best way to identify 'what parent' called a Child App/Form?

Oh - Changing the FI Structure is not an option (that modification word comes into play, for some reason)...

(db)
 
Oh - Changing the FI Structure is not an option (that modification word comes into play, for some reason)...

I hate changing the FI structure as well and avoid it where ever possible. Are you allowed to modify anything in App1,2,3 and AppX?


If you can. I have passed through multiple params in a single FI before. It's a little... weird and kludgy. But it works. It kind of depends on what the existing FI looks like.

For example:
App1

AppX
- FI_mnAddressNumber

In App1 call a function SetCustomFI that has a list of all the custom params you want to pass to AppX including mnAddressNumber that you would normally pass in the FI variable.

Code:
App1
	SetCustomFI
		evt_mnHandle <- mnHandle
		FC_mnAddressNumber -> mnAddressNumber
		evt_MyCustomParm1 -> myCustomParam1
		evt_MyCustomParm2 -> myCustomParam2


You store this in memory (jdeAlloc or jdeCache.. doesn't matter). The return is a handle (mnHandle) to this memory passed back as a negative MATH_NUMERIC. Then pass this negative number in FI_mnAddressNumber to AppX. The negative number is the "flag" to AppX that custom FI are being passed since Address Number should always be positive.

Code:
Call AppX
	FI_mnAddressNumber = evt_mnHandle 		<<<< again this is a negative number, the negative is the "flag" to AppX that custom params are being passed


In AppX you have:

Code:
AppX.DialogInit
	if FI_mnAddressNumber < 0)
		evt_mnHandle = FI_mnAddressNumber
		GetCustomFI
			evt_mnHandle -> mnHandle
			FI_mnAddressNumber <- mnAddressNumber
			evt_MyCustomParm1 <- myCustomParam1
			evt_MyCustomParm2 <- myCustomParam2
	endif


The psudeo code for SetCustomFI and GetCutomFI is basically just this (jdeCache could also be used and is probably safer):

Code:
typedef struct tagDSD5900001
{
	mnHandle;
	mnAddressNumber;
	myCustomParam1
	myCustomParam2
} DSD5900001, *LPDSD5900001;

SetCustFI(LPDSD5900001 lpDS)
{
	ID handle;
	LPDSD5900001 pcustfi;
	
	pcustfi = jdeAlloc(COMMON_POOL, sizeof(DSD5900001), MEM_ZEROINIT);
	memcpy(pcustfi, lpDS, sizeof(DSD5900001));
	handle = jdeStoreDataPtr(hUser, pcustfi);
	LongToMathNumeric(handle, &lpDS->mnHandle);
	ReverseMathNumeric(&lpDS->mnHandle);
}

GetCustFI(LPDSD5900001 lpDS)
{
	ID handle;
	LPDSD5900001 pcustfi;

	ReverseMathNumeric(&lpDS->mnHandle);
	MathNumericToLong(&lpDS->mnHandle, &handle);
	pcustfi = jdeRemoveDataPtr(hUser, handle);
	memcpy(lpDS, pcustfi, sizeof(DSD5900001));
	jdeFree(pcustfi);
}
 
Thanks Brian...

New curveball... Now, instead of knowing what 'called' the App... they have a NER that is used in many applications. I guess the NER is supposed to react differently, based on what application it is being used in. If the NER is called by one app, do X. If called within another app, do Y...

So, if I embed a very simple C-Function, that just returns the App / Version - I should be able to control the behavior within the NER...

For simplicity - shouldn't this be the resolution to returning the Application Name and Version?


/************************************************************************
* Main Processing
************************************************************************/
lpObj = lpBhvrCom->lpObj;

memcpy( lpDS->szNameObject, lpObj->szApplication, sizeof( lpObj->szApplication ) );
memcpy( lpDS->szVersion, lpObj->szVersion, sizeof( lpObj->szVersion ) );

Never-ending engineering of how not to do things will always repeat itself...

(db)
 
Yes, you could probably do something like that. Are we talking all pristine objects? I know that we often have to mod pristine objects in less than ideal ways to make the mod as minimal as possible and to make retrofits as easy and seamless as possible. Having said that, I have always tried to avoid logic that branches based on which specific application is the caller. I can also be frustrating for the caller. We have created some custom apps that call pristine BSFNs and the BSFNs didn't behave the same way as when called from the pristine apps even though the exact same data was passed to them. You have to resort to debugging to find out why it behaves differently despite having identical inputs. I much rather have some sort of logic flag that can be passed and then mod each caller to pass a different flag. To me this makes the BSFN more reusable and self documenting in that if some new application needs to call it and have behavior like AppXYZ, you don't have to mod the BSFN for AppXYZ, AppXYZ just passes in the correct flag. If the NER is pristine and you (correctly IMO) do not want to modify the DSTR you can pass custom params to a BSFN through an existing DSTR using the same technique I outlined above for passing custom data through an existing FI - even easier if some sort of unique memory type handle is all ready being used in the NER (mnJobnumber, szSessionKey, etc.).

However, if you are operating under some modification guideline constraints and you are prohibited from modifying the callers, you may have to resort to what you proposed, i.e. using lpBhvrCom->lpObj->szApplication.
 
Back
Top