Solution in the BII/Application

For complex data model differences (such as missing tables), a feature pack-independent BII can be created by handling the differences in hooks.

In general, you can use this approach:

  1. To reduce the efforts for implementing and maintaining BODs for LN feature packs, reuse as much as possible. Create a specific implementation only for those parts of the BII that require a specific implementation. Avoid duplicates of specific code. Do not copy a lot of code to adapt only a minor part.
  2. Use a single BID and BII for all feature packs. Generate the runtime in a separate package having a single version independent of the LN FP (but multiple versions for new BOD versions). Implement application version-specific code in the application package version.

    The specific DLLs in each feature pack will offer the same interface; only the implementation will be different.

    For any difference in data model (or used application DLL functions), a solution is already possible using the current LN Studio and LN implementation generator.

    Use an 'on get hook' for the field(s) that are not applicable in an older application version. In the hook, invoke a function from an application DLL. Implement that function differently depending on the application version.

    For example in FP2
    o.attribute = ""
    o.attribute.isSet = false
    return(0)
    
    In FP5
    select table.column:o.attribute
    from table
    where table.key = :i.key.attribute
    selectdo
    	o.attribute.isSet = true
    selectempty
    	...
    selecterror
    	...
    endselect
    return(0)
    

    If multiple columns are involved, an optimization can be implemented combining the selects for the same table.

    Pro: on BII for all LN FPs. No technology changes needed.

    Con: an additional query is executed on the same table.

    To be determined:

    • Using 'alternative implementations' may also help to reuse BII parts that are equal?
    • What about BID changes other than the addition of attributes, such as introduction of a new component?

    Example:

    In Baan IV, two columns exist (ppmmm123.date and ppmmm123.time). In LN , one column exists (ppmmm123.utcd).

    Assume the following generic functions exist in both versions:

    • tcabc.dll0001.date.and.time.to.utc(long i.date, long i.time, ref long o.utc)
    • tcabc.dll0001.utc.to.date.and.time(long i.utc, ref long i.date, ref long i.time)

    To deal with this in a version-independent manner, ensure the ppmmm123 table in LN Studio contains three columns: date, time and utcd.

    Use these attribute implementations:

    • date: maps to ppmmm123.date, uses an on set hook based on DateTime
    • time: maps to ppmmm123.time, uses an on set hook based on DateTime
    • utcd: maps to ppmmm123.utcd, uses an on set hook based on DateTime
    • DateTime: calculated using an on get hook based on date, time and utcd.
    On set date:
    long	dummy.time
    tcabc.dll0001.utc.to.date.and.time(i.DateTime, o.date, dummy.time)
    return(0) | OK
    
    On set time:
    long	dummy.date
    tcabc.dll0001.utc.to.date.and.time(i.DateTime, dummy.date, o.time)
    return(0) | OK
    
    On set utcd
    o.utcd = i.DateTime
    return(0) | OK
    
    On get DateTime
    if i.utcd.isSet then
    	o.DateTime = i.utcd
    else
    	tcabc.dll0001.date.and.time.to.utc(i.date, i.time, o.DateTime)
    endif
    return(0) | OK
    
    Alternatively you can delegate the logic to a version-dependent library function. For this example it can be a bit overdone, but in more complex situations this approach can be helpful. In that case the code is:
    ppmmm.dll0001.get.date.from.utc.if.applicable(i.DateTime, o.date, io.date.isSet)
    return(0) | OK
    
    On set date:
    ppmmm.dll0001.get.date.from.utc.if.applicable(i.DateTime, o.date, io.date.isSet)
    return(0) | OK
    
    On set time:
    ppmmm.dll0001.get.time.from.utc.if.applicable(i.DateTime, o.time, io.time.isSet)
    return(0) | OK
    
    On set utcd
    ppmmm.dll0001.get.utc.from.utc.if.applicable(i.DateTime, o.utcd, io.utcd.isSet)
    return(0) | OK
    
    On get DateTime
    ppmmm.dll0001.get.utc.from.utc.or.date.and.time(i.date, i.time, i.utcd, o.DateTime, io.DateTime.isSet)
    return(0) | OK
    
    Library ppmmmdll0001 in Baan IV
    function extern ppmmm.dll0001.get.date.from.utc.if.applicable(
    		long	i.utc,
    	ref	long	o.date,
    	ref	long	io.date.isSet)
    {
    	long	dummy.time
    	tcabc.dll0001.utc.to.date.and.time(i.utc, o.date, dummy.time)
    }
    
    function extern ppmmm.dll0001.get.time.from.utc.if.applicable(
    		long	i.utc,
    	ref	long	o.time,
    	ref	long	io.time.isSet)
    {
    	long	dummy.date
    	tcabc.dll0001.utc.to.date.and.time(i.utc, dummy.date, o.time)
    }
    
    ppmmm.dll0001.get.utc.from.utc.if.applicable(
    		long	i.utc,
    	ref	long	o.utc,
    	ref	long	io.utc.isSet)
    {
    	io.utc.isSet = false
    }
    
    ppmmm.dll0001.get.utc.from.utc.or.date.and.time(
    		long	i.date,
    		long	i.time,
    		long	i.utc,
    	ref	long	o.utc,
    	ref	long	io.utc.isSet)
    {
    	tcabc.dll0001.date.and.time.to.utc(i.date, i.time, o.utc)
    	| i.utc is unused in Baan IV
    }
    Library ppmmmdll0001 in ERP LN, same interface but a different implementation:
    
    function extern ppmmm.dll0001.get.date.from.utc.if.applicable(
    		long	i.utc,
    	ref	long	o.date,
    	ref	long	io.date.isSet)
    {
    	io.date.isSet = false
    }
    
    function extern ppmmm.dll0001.get.time.from.utc.if.applicable(
    		long	i.utc,
    	ref	long	o.time,
    	ref	long	io.time.isSet)
    {
    	io.time.isSet = false
    }
    
    ppmmm.dll0001.get.utc.from.utc.if.applicable(
    		long	i.utc,
    	ref	long	o.utc,
    	ref	long	io.utc.isSet)
    {
    	o.utc = i.utc
    }
    ppmmm.dll0001.get.utc.from.utc.or.date.and.time(
    		long	i.date,
    		long	i.time,
    		long	i.utc,
    	ref	long	o.utc,
    	ref	long	io.utc.isSet)
    {
    	o.utc = i.utc
    	| i.date and i.time are unused in ERP LN
    }