6525036

Commodore
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-07-30
15:02
989 views
Dynamic namespace execution - is it possible?
Hi,
In my driver, I would like to call different java methods(or different ecma functions), dynamically, based on GCVs, because that way, I would only need one rule (to rule them all, and in the darkness bind them)
That means, that I iterate over a nodeset, and TRY to execute xpath("nexus:$lMethod").
$lMethod is in this instance GetActiveRoles().
The issue with this approach seems to be, that once a namespace is in use (be it java or excma script for example), I get errors like this:
Code(-9130) Error in vnd.nds.stream://META/dk/services/idm/Driver+Set/LB-NXRoles01/itp-GetActiveRoles#XmlData:239 : An invalid XPATH expression 'nexus:$lMethod' is specified: java.lang.IllegalArgumentException: DOMEvaluator parser error: ':' was unexpected
In other words, this works:
<token-xpath expression="nexus:GetActiveRoles()"/>
This does not work:
<token-xpath expression="nexus:$lMethod"/>
And $lMethod = "GetActiveRoles()"
Can anyone figure out a way to get this to work?
In my driver, I would like to call different java methods(or different ecma functions), dynamically, based on GCVs, because that way, I would only need one rule (to rule them all, and in the darkness bind them)
That means, that I iterate over a nodeset, and TRY to execute xpath("nexus:$lMethod").
$lMethod is in this instance GetActiveRoles().
The issue with this approach seems to be, that once a namespace is in use (be it java or excma script for example), I get errors like this:
Code(-9130) Error in vnd.nds.stream://META/dk/services/idm/Driver+Set/LB-NXRoles01/itp-GetActiveRoles#XmlData:239 : An invalid XPATH expression 'nexus:$lMethod' is specified: java.lang.IllegalArgumentException: DOMEvaluator parser error: ':' was unexpected
In other words, this works:
<token-xpath expression="nexus:GetActiveRoles()"/>
This does not work:
<token-xpath expression="nexus:$lMethod"/>
And $lMethod = "GetActiveRoles()"
Can anyone figure out a way to get this to work?
12 Replies


Knowledge Partner
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-07-30
15:41
6525036;2484880 wrote:
Hi,
In my driver, I would like to call different java methods(or different ecma functions), dynamically, based on GCVs, because that way, I would only need one rule (to rule them all, and in the darkness bind them)
That means, that I iterate over a nodeset, and TRY to execute xpath("nexus:$lMethod").
$lMethod is in this instance GetActiveRoles().
The issue with this approach seems to be, that once a namespace is in use (be it java or excma script for example), I get errors like this:
Code(-9130) Error in vnd.nds.stream://META/dk/services/idm/Driver+Set/LB-NXRoles01/itp-GetActiveRoles#XmlData:239 : An invalid XPATH expression 'nexus:$lMethod' is specified: java.lang.IllegalArgumentException: DOMEvaluator parser error: ':' was unexpected
In other words, this works:
<token-xpath expression="nexus:GetActiveRoles()"/>
This does not work:
<token-xpath expression="nexus:$lMethod"/>
And $lMethod = "GetActiveRoles()"
Can anyone figure out a way to get this to work?
What happens if you use ~ to reference the GCV?
6525036

Commodore
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-07-31
19:29
dgersic;2484881 wrote:
What happens if you use ~ to reference the GCV?
Aha, a ~ gcv expression actually works in xpath java calls.
Now the issue is, that what I want to execute is based on what is in a list. It is a series of calls to be executed based on a structured GCV.
One instance looks like this:
<definition display-name="Entity Name" name="name" type="string">
<description/>
<value>Active Roles</value>
</definition>
<definition display-name="Object Class" name="objclass" type="string">
<description>eDir object class</description>
<value>NEXUSRole</value>
</definition>
<definition display-name="GCV Name" name="gcv" type="string">
<description>Points to the "map" GCV to be used</description>
<value>map.nexus.attr</value>
</definition>
<definition display-name="Java Method to call" name="method" type="string">
<description/>
<value>GetActiveRoles()</value>
</definition>
<definition display-name="Do we want to process this one?" name="process" type="boolean">
<description/>
<value>true</value>
</definition>
</instance>
There are several of those, each with their own set of definitions.
Each definition set is looped over, and each definition is retrieved into local variables using xpath, like: $current-node/definition[@name='method']/value/text()
I tried to make the GCV refer to the local variable containing the value I want to call, that did of course not work.
I tried to redefine the GCV at runtime, and that was a bit to optimistic it seems.
So I wonder if there is any way that I can redefine the GCV at runtime, so I can use ~ notation to call my java method (since using $ notation does not work).


Knowledge Partner
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-07-31
19:42
6525036;2484955 wrote:
Aha, a ~ gcv expression actually works in xpath java calls.
Now the issue is, that what I want to execute is based on what is in a list. It is a series of calls to be executed based on a structured GCV.
One instance looks like this:<definition display-name="Entity Name" name="name" type="string">
<description/>
<value>Active Roles</value>
</definition>
<definition display-name="Object Class" name="objclass" type="string">
<description>eDir object class</description>
<value>NEXUSRole</value>
</definition>
<definition display-name="GCV Name" name="gcv" type="string">
<description>Points to the "map" GCV to be used</description>
<value>map.nexus.attr</value>
</definition>
<definition display-name="Java Method to call" name="method" type="string">
<description/>
<value>GetActiveRoles()</value>
</definition>
<definition display-name="Do we want to process this one?" name="process" type="boolean">
<description/>
<value>true</value>
</definition>
</instance>
There are several of those, each with their own set of definitions.
Each definition set is looped over, and each definition is retrieved into local variables using xpath, like: $current-node/definition[@name='method']/value/text()
I tried to make the GCV refer to the local variable containing the value I want to call, that did of course not work.
I tried to redefine the GCV at runtime, and that was a bit to optimistic it seems.
So I wonder if there is any way that I can redefine the GCV at runtime, so I can use ~ notation to call my java method (since using $ notation does not work).
GCVs are, by their nature, not redefineable at runtime. You'd have to do this with local variables if you're going to change their values.


Knowledge Partner
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-07-31
20:25
>> I tried to make the GCV refer to the local variable containing the
>> value I want to call, that did of course not work.
>> I tried to redefine the GCV at runtime, and that was a bit to
>> optimistic it seems.
>>
>> So I wonder if there is any way that I can redefine the GCV at
>> runtime, so I can use ~ notation to call my java method (since using $
>> notation does not work).
>
> GCVs are, by their nature, not redefineable at runtime. You'd have to do
> this with local variables if you're going to change their values.
Which is how he started and it did not work. 🙂
6525036

Commodore
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-07-31
22:30
Indeed so.
Wonder how.
Wonder how.
ffreitas

Captain
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-08-01
00:12
add to your ECMA library:
function routecall( imethod ) {
var whattocall;
switch( String(imethod).toLowerCase() ) {
case 'getactiveroles':
whattocall = GetActiveRoles;
break;
case 'getotherstuff':
whattocall = GetOtherFunThings;
break;
// add more cases here as desired
default:
whattocall = function() {}; // default noop function
}
return whattocall();
}
call your router code from the DirXML-Script:
<token-xpath expression="nexus:routecall( $lMethod )"/>
$lMethod = "GetActiveRoles" <--- note that we don't add the ()
That should get you by. Bonus points that you could send more parameters and pass them to the next function, things can get pretty interesting at that point...
function routecall( imethod ) {
var whattocall;
switch( String(imethod).toLowerCase() ) {
case 'getactiveroles':
whattocall = GetActiveRoles;
break;
case 'getotherstuff':
whattocall = GetOtherFunThings;
break;
// add more cases here as desired
default:
whattocall = function() {}; // default noop function
}
return whattocall();
}
call your router code from the DirXML-Script:
<token-xpath expression="nexus:routecall( $lMethod )"/>
$lMethod = "GetActiveRoles" <--- note that we don't add the ()
That should get you by. Bonus points that you could send more parameters and pass them to the next function, things can get pretty interesting at that point...


Knowledge Partner
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-08-01
01:15
On 7/31/2018 7:14 PM, ffreitas wrote:
>
> add to your ECMA library:
>
> function routecall( imethod ) {
> var whattocall;
> switch( String(imethod).toLowerCase() ) {
> case 'getactiveroles':
> whattocall = GetActiveRoles;
> break;
> case 'getotherstuff':
> whattocall = GetOtherFunThings;
> break;
> // add more cases here as desired
> default:
> whattocall = function() {}; // default noop function
> }
> return whattocall();
> }
>
> call your router code from the DirXML-Script:
>
> <token-xpath expression="nexus:routecall( $lMethod )"/>
>
> $lMethod = "GetActiveRoles" <--- note that we don't add the ()
>
> That should get you by. Bonus points that you could send more parameters
> and pass them to the next function, things can get pretty interesting at
> that point...
That is fairly clever. Just requires predefining the functions in
advance. I think the OP was to define it in the policy itself, but I
think is probably the best he is going to get
>
> add to your ECMA library:
>
> function routecall( imethod ) {
> var whattocall;
> switch( String(imethod).toLowerCase() ) {
> case 'getactiveroles':
> whattocall = GetActiveRoles;
> break;
> case 'getotherstuff':
> whattocall = GetOtherFunThings;
> break;
> // add more cases here as desired
> default:
> whattocall = function() {}; // default noop function
> }
> return whattocall();
> }
>
> call your router code from the DirXML-Script:
>
> <token-xpath expression="nexus:routecall( $lMethod )"/>
>
> $lMethod = "GetActiveRoles" <--- note that we don't add the ()
>
> That should get you by. Bonus points that you could send more parameters
> and pass them to the next function, things can get pretty interesting at
> that point...
That is fairly clever. Just requires predefining the functions in
advance. I think the OP was to define it in the policy itself, but I
think is probably the best he is going to get
6525036

Commodore
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-08-01
15:15
Sweet, I'll try that ASAP.
Thanks a lot.
Thanks a lot.
6525036

Commodore
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-08-01
15:41
Hmmm..... nexus is a java namespace declaration. And this I cannot call an ecma script via the java namespace (nexus).
But following the idea you laid out.....
What I could do (and will try), is to make a java wrapper method, which I can call with parameters to call the other java methods.
That should work.
Anyway, I had never seen anything returned as what I suppose is a function call like this "return whattocall()"
Wonder if the same ecma routing could be done like this?
function routecall2( imethod ) {
return imethod();
}
And then just be called with parameters, that would be passed on and executed?
But following the idea you laid out.....
What I could do (and will try), is to make a java wrapper method, which I can call with parameters to call the other java methods.
That should work.
Anyway, I had never seen anything returned as what I suppose is a function call like this "return whattocall()"
Wonder if the same ecma routing could be done like this?
function routecall2( imethod ) {
return imethod();
}
And then just be called with parameters, that would be passed on and executed?
ffreitas

Captain
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-08-01
16:19
apologies for the misread, assumed it was ECMA code. Two options then:
1 - make your routecall be a Java function that call other Java functions based on what you pass in as a string input
2 - Still use ECMA as the router, using the es: namespace to access, and call the java classes from it. Look at https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java for some details on how to do so (by default IDM uses Rhino as the ECMA engine). Be mindful that since Java is strongly typed and Javascript/ECMAscript is not, only base primitive that can be safely passed is string. You may end up having to check input types and wrap them in their Java counterparts before passing them along.
on ECMA you cannot pass an name and run it, you have to pass a function reference for that to work. that is why I used a switch statement in my example so that we could map the Strings to actual function names.
1 - make your routecall be a Java function that call other Java functions based on what you pass in as a string input
2 - Still use ECMA as the router, using the es: namespace to access, and call the java classes from it. Look at https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java for some details on how to do so (by default IDM uses Rhino as the ECMA engine). Be mindful that since Java is strongly typed and Javascript/ECMAscript is not, only base primitive that can be safely passed is string. You may end up having to check input types and wrap them in their Java counterparts before passing them along.
on ECMA you cannot pass an name and run it, you have to pass a function reference for that to work. that is why I used a switch statement in my example so that we could map the Strings to actual function names.
6525036

Commodore
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-08-03
12:09
ffreitas;2485026 wrote:
apologies for the misread, assumed it was ECMA code. Two options then:
1 - make your routecall be a Java function that call other Java functions based on what you pass in as a string input
2 - Still use ECMA as the router, using the es: namespace to access, and call the java classes from it. Look at https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java for some details on how to do so (by default IDM uses Rhino as the ECMA engine). Be mindful that since Java is strongly typed and Javascript/ECMAscript is not, only base primitive that can be safely passed is string. You may end up having to check input types and wrap them in their Java counterparts before passing them along.
on ECMA you cannot pass an name and run it, you have to pass a function reference for that to work. that is why I used a switch statement in my example so that we could map the Strings to actual function names.
Thank you very much. Since I did not ever manage to convert a string to a java function, I ended up with this. It is not entirely as dynamic as I would like, but since it is in ecma, it will be adequate (read: I wont need to recompile java classes to change stuff).
function routecall( imethod ) {
var res;
var myObj = new Packages.pwc.KMDNexusPlugin();
switch( String(imethod).toLowerCase() ) {
case 'getactiveroles':
res = myObj.GetActiveRoles();
break;
case 'getinactiveroles':
res = myObj.GetInactiveRoles();
break;
case 'getorganisationalhierarchy':
res = myObj.GetOrganisationalHeirarchy();
break;
case 'getinactiveorganisations':
res = myObj.GetInactiveOrganisations();
break;
case 'getprofessional':
res = myObj.GetProfessional();
break;
case 'getprofessionals':
res = myObj.GetProfessionals();
break;
}
return res;
}