How to extend ScreenRender - moqui

The ScreenRender is initialised with ScreenRenderImpl in ScreenFacadeImpl.makeRender, while ScreenFacade is initialised in ExcecutionContextFactoryImpl. In some cases, I would like to add more functions in ScreenRender that can be invoked in Macro templates. Instead of overriding the ExecutionContextFactoryImpl and down to ScreenRenderImpl as well s MoquiContextListener, is there a way to simply inject a sub class of ScreenRenderImpl when ScreenFacade.makeRender?
A real case to get support of sri in macro template is:
I am trying to populate the options of select via list-options or entity-options or via manual option which return by sri.getFieldOptions(). But it is kind of bound to form fields. I want to use in non-form context. So I kind of want to extend ScreenRender to have a function like sri.getOptions().

Related

How to specify when giving a generic parameter that it should implement some specific creation method?

How to specify when giving a generic parameter that it should implement some specific creation method? as LIST[G -> create make end] doesn't work :-(
In my particular case,
* SMA_INVERTER_MANAGER_CSV has inherited from CONSUMPTION_SECTOR_MODBUS_DEVICE_CSVa list of devices as devices: LINKED_SET[G] as G -> MEASURING_POINT_MODBUS_DEVICE create make_from_file_path end.
I'd like the SMA_INVERTER_MANAGER_CSV class to be able into devices: LINKED_SET[G] to be able to have either JANITZA_DEVICE, SUNSPEC_DEVICE, ABB_DEVICE, etc. Giving the generic parameter as MEASURING_POINT_MODBUS_DEVICE seems to come out of a sense, but how do I specify that I'd like the creation method to be make_from_file_path
Hope the description is sufficient to understand, refactoring I think this question is linked -> explicit creation type not conforming to type of target
The only workaround for the moment I found working for the moment is
class
SMA_INVERTER_MANAGER_CSV
inherit
CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV[SUNSPEC_DEVICE]
create
make
end
but I'd like it to be
class
SMA_INVERTER_MANAGER_CSV
inherit
CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV[MEASURING_POINT_MODBUS_DEVICE]
create
make
end
which would generate a conformance problem because MEASURING_POINT_MODBUS_DEVICE generic parameter doesn't specify make_from_file_path as creation procedure as its deferred
There is more than a conformance problem. MEASURING_POINT_MODBUS_DEVICE is deferred. Therefore, it cannot be used as an actual parameter for CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV. If it were allowed, how would CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV create an instance of a deferred class?
One possible solution — supplying an effective class — is mentioned in the question. Another solution is to add a formal generic parameter to SMA_INVERTER_MANAGER_CSV with the corresponding constraint and to use it for the actual generic of CONSUMPTION_SECTOR_MODBUS_DEVICE_CSV.

How to call remove_column on SALV table?

I want to execute the method remove_column on an instance of cl_salv_column_table but because of its visibility level, I am not able to do so.
Plan:
I already tried inheriting from cl_salv_columns_list and then perform the call inside the remove-method:
CLASS lcl_columns_list DEFINITION INHERITING FROM CL_SALV_COLUMNS_LIST.
PUBLIC SECTION.
METHODS:
remove IMPORTING iw_colname TYPE string.
ENDCLASS.
But apparently my casting knowledge got rusty as I'm not able to figure out an appropriate solution.
This is my current hierarchy - the red arrows show the way I would have to take:
My approach looks like this:
DATA lo_column_list TYPE REF TO lcl_columns_list.
lo_column_list ?= CAST cl_salv_columns_list( lo_columns ).
But it fails with:
CX_SY_MOVE_CAST_ERROR
Source type: \CLASS=CL_SALV_COLUMNS_TABLE
Target type: "\PROGRAM=XXX\CLASS=LCL_COLUMNS_LIST"
Background:
My task is to select all columns of 3 tables (which would be done like SELECT t1~*, t2~*, t3~* ...) as long as their names don't conflict (e.g. field MANDT should only be displayed once). This would require defining a very big structure and kick the size of the selection list to a maximum.
To avoid this, I wanted to make use of the type generated by my inline-declaration. Hiding the individual columns via set_visible( abap_false ) would still display them in the layout manager - which looks really ugly.
Is there any other way to accomplish my target?
Use set_technical( abap_true ) to hide the columns entirely. As for your approach - sorry, inheritance does not work that way - in no statically typed object oriented language that I know. You can't 'recast' an instantiated object to a different class. You would need to modify the framework extensively to support that.

Can define variables as references to local classes defined in another program?

I have a program ZPROG1_TEST where I define a local class LCL_PROG1_HELPER.
I have a second program ZPROG2_TEST where I'd like to define a variable reference to this class.
Isn't there a syntactic possibility for me to do this?
Or could this be in theory doable with the RTTI classes like CL_ABAP_CLASSDESCR ?
EXTRA
Why I'd like to do this is because I have a custom form ZMM_MEDRUCK that needs to know if the ME32N Document it's printing has been changed but not saved.
I've figures out the exact objects whose properties I need to interogate, but some of them are defined at design time as common interfaces, like IF_SERIALIZABLE_MM, and I need to cast them to the local classes whose instances I know these objects are going to be, like \FUNCTION-POOL=MEGUI\CLASS=LCL_APPLICATION.
I could of course try a dynamic method call and not care about anything, but since i'm here i thought i'd ask this thing first.
You could do it like that.
REPORT ZPROG1_TEST.
INTERFACE lif_prog1_helper.
METHODS:
test.
ENDINTERFACE.
CLASS LCL_PROG1_HELPER DEFINITION.
PUBLIC SECTION.
INTERFACES:
lif_prog1_helper.
ALIASES:
test FOR lif_prog1_helper~test.
ENDCLASS.
CLASS LCL_PROG1_HELPER IMPLEMENTATION.
METHOD test.
WRITE / sy-repid.
ENDMETHOD.
ENDCLASS.
REPORT ZPROG2_TEST.
DATA: g_test TYPE REF TO object.
START-OF-SELECTION.
CREATE OBJECT g_test TYPE ('\PROGRAM=ZPROG1_TEST\CLASS=LCL_PROG1_HELPER').
CALL METHOD g_test->('TEST').
CALL METHOD g_test->('LIF_PROG1_HELPER~TEST').
As far as I know, this is not possible. Accessing the local class dynamically is easy (well, relatively easy), but referring to it statically - not as far as I know. You'll probably have to call the methods dynamically.

Caller Contextual Binding NInject

I need to compose an instance conditionally depending on the caller.
In some cases I need a composite object instances with a "deep" type "NullService"
in other cases I instead inject a "ConcreteService"
I expect something like this:
Get<Root>.with(NullService)
or
Get<Root>.with(ConcreteService)
or better still if one could bind the construction so that it dated back to the calling context
Bind<IService>.to(ConcreteService).
Bind<IService>.to(NullService).only.whenCallerIsTypeOf(CallerWhosNeedsANullService)
is it possible?
There are two ways:
Use an own condition in case you can calculate which one should be used:
Bind<IService>.To(NullService)
.When(ctx => IsCallerWhosNeedsANullService(HttpContext.Current.Request));
Use Named bindings
Bind<Root>().ToSelf().Named("DefaultRoot");
Bind<Root>().ToSelf().Named("NullRoot");
Bind<IService>.To(ConcreteService);
Bind<IService>.To(NullService).WhenAnyAnchestorNamed("NullRoot");
Get<Root>("NullRoot");

naming a method - using set() when *not* setting a property?

Is setX() method name appropriate for only for setting class property X?
For instance, I have a class where the output is a string of an html table. Before you can you can call getTable, you have to call setTable(), which just looks at a other properties and decides how to construct the table. It doesn't actually directly set any class property -- only causes the property to be set. When it's called, the class will construct strHtmlTable, but you can't specify it.
So, calling it setTable breaks the convention of get and set being interfaces for class properties.
Is there another naming convention for this kind of method?
Edit: in this particular class, there are at least two ( and in total 8 optional ) other methods that must be called before the class knows everything it needs to to construct the table. I chose to have the data set as separate methods rather than clutter up the __construct() with 8 optional parameters which I'll never remember the order of.
I would recommend something like generateTable() instead of setTable(). This provides a situation where the name of the method clearly denotes what it does.
I would probably still use a setTable() method to actually set the property, though. Ideally, you could open the possibility of setting a previously defined table for further flexibility.
Yes, setX() is primarily used for setting a field X, though setX() may have some additional code that needs to run in addition to a direct assignment to a field. Using it for something else may be misleading to other developers.
I would definitely recommend against having a public setTable() and would say that setTable() could be omitted or just an unused private method depending upon your requirements.
It sounds like the activity to generate the table is more of a view of other properties on the object, so you might consider moving that to a private method on the object like generateHtmlTable(). This could be done during construction (and upon updates to the object) so that any subsequent calls to getTable() will return the the appropriate HTML.