How can I achieve IF ALL ELSE, in Decision Table? - drools

Drools 5.4
I have a decision table that sets values in the BlueReport object based on Channel Name attribute. Everything works, except if a Channel name contains an unknown channel for which we don't have mappings, we need to set the values to indicate this condition. The picture below should illustrate this more clearly, I'm sure. Here is what we want:
How can we achieve the "ALL OTHERS" default condition?!
I've evolved my spreadsheet rules to this now:
In this version of DT above, I have left B15 blank, and then I have added a new condition on C15 which checks the auditRule field for presence of string variable "DIV". I don't know if I have the right syntax for it in C9?! The ruleAudit field is update everytime there is a match for Channel Name (F11 - F15). Therefore, absence of DIV rule name, would indicate that there is no match to any of the patterns on B11 - B14. What do you think?!

Add a new condition column again with declaration for blueReport and set this condition
channel_name!=$1 || channel_name!=$2 ||channel_name!=$3 || channel_name!=$4
New Condition's value field must be empty for the first four records except these values like ChannelName1,ChannelName2,ChannelName3,ChannelName4 in "ALL OTHERS" row. Though this isn't the standard solution try this workaround to check

I think the post can help you. It means you should not only declare sequential in the RuleSet, but also declare PRIORITY in RuleTable that the rules will be called according to the value of PRIORITY.

Related

Getting value from WHEN part while a condition meets using EXISTS keyword in drools

rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av:AttackVector()
exists $threat:Application.Threats(impact == "Disclose Information")from $threatList
exists AttackVector($av == AttackVector.REQUEST_MANIPULATION)
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
I am working on getting the object $threat in THEN part of the above-mentioned rule. If I run the above rule, it says:
Rule Compilation error : [Rule name='attaching AV and impact rating']
referee/security/attack/Rule_attaching_AV_and_impact_rating1426933818.java (7:1053) : $threat cannot be resolved
If I loop through it and get the value in the THEN part, it causes a CARTESIAN product and inserts the values a number of times in the session. My rule looks like this when I get the cartesian product.
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av:AttackVector()
exists $threat:Application.Threats(impact == "Disclose Information")from $threatList
$threat:Application.Threats(impact == "Disclose Information")from $threatList
exists AttackVector($av == AttackVector.REQUEST_MANIPULATION)
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
How do I get the value of $threat in THEN part without having the cartesian product?
Remove the exists operation entirely.
rule "attaching AV and impact rating"
agenda-group "evaluate likelihood"
dialect "java"
when
Application($threatList:getThreatList())
$av: AttackVector()
$threat: Application.Threats(impact == "Disclose Information")from $threatList
exists(AttackVector($av == AttackVector.REQUEST_MANIPULATION))
then
RiskRating riskRating=new RiskRating($threat.getImpactRating(),$av.getLikelihood(),$av.getName());
insertLogical(riskRating);
end
exists means "there is a thing in working memory that matches these conditions/looks like this". It's not used to actually extract or provide a reference to that matching instance. Simply remove the operator and it works as you need -- if there is an Application.Threats that matches your conditions, the rule triggers and the matching value is assigned to the $threat variable.
What you're running into is the fact that you have multiple threats that mean your condition, which is why you're having multiple triggers of the rule -- it will trigger once per matching Application.Threats. The exists keyword mitigates this because it only cares that at least one match exists, but you don't get a reference (because if there's four matches which one will be assigned to the variable? it doesn't make sense, logically.)
So you need to change your rule so that it won't fire multiple times and will instead only fire once when it finds a match. Usually you'd do this by making the consequences do something to working memory that makes the rule no longer eligible to be fired. In your example, you insert a RiskRating object; you could, then, check that no risk rating exists in your conditions:
not( RiskRating( /* insert criteria here or leave empty */ ) )
Alternatively you could retract something from working memory that your rule relies on to be present or a match. For example, if you don't need it for anything later on, you could retract the attack vector:
retract( $av )
Yet another option might be to try and update your getThreatList() implementation to return a Set instead so you don't have duplicates (assuming threats are considered duplicates based on the 'impact' field.) Or you could try to remove all Application.Threats instances that match the criteria from the threatlist being returned.
We simply don't know enough about your use case or rule set to know what data you need or what it looks like, but at the end of the day you simply need the rule to fire once and only once, so to do this you need to somehow update the rule to know that it's no longer valid.

Can Watson trigger a dialog based on 12 digits pattern?

I try to display a message that contains the number inserted in the question, for example when user inserts a number of 12 digits I want to display that 12 digits and a text.
Until now:
I created an Entity with pattern (/d{12}) named #ticket_number
An Intent named #myTicket that has as example #ticket_number
Dialog that triggers when #myTicket | #ticket_number and has on context TicketNumer "<?#ticket_number.literal?>" and display a message as follows "Do you want to get info for ticket $ticketnumber ?".
The problem is that when I try it the Intent result is irrelevant, the message looks ok but I need to match the Intent. What could I do?
Can you share a picture of your node? There is no need that you match the intent; as indicating the ticket number alone, should not be an intent itself, but the entity. I'd remove the #myTicket | part of the node. And the condition should not include an OR; otherwise, if #myTicket triggers the node, and there is no ticket number, the response would fail.
As mentioned in the IBM documentation
it is not yet possible to use pattern entity in Intents.
Currently, you can only directly reference synonym entities that you
define (pattern values are ignored). You cannot use system entities.

How to update JSON node that matches criteria based on attribute value (instead of index)?

Postgresql 10+
Example from the documentation...
jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}','[2,3,4]', false)
results in...
[{"f1":[2,3,4],"f2":null},2,null,3]
Fair enough. But I need to find my target node by attribute value, not index. For the life of me, I cannot figure out how do something like...
jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{(where f1 = 1),f1}','[2,3,4]', false)
Any advice on how to accomplish this?
Thanks!
You can split the steps into two jobs:
Split in elements (jsonb_arral_elements)
Indentify wich elements must change (case when...)
Update that element (jsonb_set)
Join all together (jsonb_agg)
solution
select jsonb_agg(case when element->>'f1'='1' then jsonb_set(element, '{f1}', '[2,3,4]') else element end)
from jsonb_array_elements('[{"f1":1,"f2":null},2,null,3,{"f1":3},{"f1":1,"f2":2}]'::jsonb) element
note
I changed the input adding two more elements with "f1" key

BIRT report parameter multiple selection value "All"

I have a problem with creating default value of 'All values' for a cascading parameter group last parameter. Actually I don't neccesary need that value to be default, but that would be preferable.
I have tried where I create additional data set with the needed value and additional data set with value All which uses different scripted data source, and another data set with computed column with full outer join, that column uses this code
if(row["userName"]==null ){
row["All"];
}else{
row["userName"];
}
and in the last cascaded parameter JDSuser which I need that All value I have added default value (All users).
In the data set with one value All in open I have script
ii=0;
in fetch
if( ii > 0 ){
return false;
}else{
row["All"] = "(All Users)";
ii++
return true;
}
and in the query data set, in beforeOpen script in if statement I have
if( params["JDSuser"].value!=null && params["JDSuser"].value[0] != "(All Users)" ){
This is used if I haven't selected All users value, and this works, though if I select All Users, it retrieves me no data.
I'm creating from this source example actuate link for example rptdesign download
If someone could give me some help, I would be very grateful.
The way you generate "(All values)" item in your selection list seems to me over complicated but if i understood correctly your case this part is working fine, the problem is not in the definition of the cascading parameter but the way it is used in the main dataset of the report.
Furthermore we have to assume we speak about the same query & beforeOpen script involved in this topic. No data are returned because if we don't do anything special when this item "All values" has been selected, then those filters are still active:
and role.name in ( 'sample grupa' )
and userbase.userName in ( 'sample' )
There are a couple of options to handle this. An elegant one is to declare a dataset parameter linked to your report parameter "JDSuser", and use a clause "OR" such:
and role.name in ( 'sample grupa' )
and (?='(All users)' OR userbase.userName in ( 'sample' ))
Notice this question mark, which represents a dataset parameter in your query. It is not intrusive: the beforeOpen script doesn't have to be changed. You probably need to do something similar with the other filter role.name, but you don't provide any information related to this. One more thing, in order to avoid bad surpises may be you should choose as value something more simple without brackets such "_allitems", and set "(All items)" as label.
Please refer to this topic for more informations about handling optional parameters. See a live example of optional parameters in a cascading group here.

Word 2010 can Field added via QuickParts be given an ID and later referenced in document.Fields collection

I need to add a few fields to a Word 2010 DOTX template which are to be populated automatically with custom content at "run time" when the document is opened in a C# program using Word Interop services. I don't see any way to assign a unique name to "Ask" or "Fill-In" fields when adding them to the template via the QuickParts ribbon-menu option.
When I iterate the document.Fields collection in the C# program, I must know which field I'm referencing, so it can be assigned the correct value.
It seems things have changed between previous versions of Word and Word 2010. So, if you answer please make sure your answer applies to 2010. Don't assume that what used to work in previous versions works in 2010. Much appreciated, since I rarely work with Word and feel like a dolt when trying to figure out the ribbon menuing in 2010.
You are correct in that fields don't necessarily have a built-in way to uniquely distinguish themselves from other field instances (other than its index in the Fields collection). However, you can use the Field.Type property to test for wdFieldAsk or wdFieldFillIn . If this is not narrow enough to ID then you will need to parse your own unique identifier from the Field.Code. For example, you can construct your FILLIN field as:
{ FILLIN "Hello, World!" MYIDENTIFER }
when you iterate through your document.Fields collection just have a test for the identifier being in the string. EDIT: example:
For Each fld In ActiveDocument.Fields
If InStr("CARMODEL", fld.Code) <> 0 Then
''this is the carmodel field
End If
Next
Another alternative - seek your specific field with a Find.Text for "^d MYIDENTIFIER" (where ^d is expression for 'field code')
Let me know if this helps and expand on your question if any gaps.