I am creating rules using Ruta as implemented in CLAMP ( https://clamp.uth.edu/ ). As one of the steps, I would like to identify all sentences that contain Temperature annotations.
So I would like to be able to specify attribute values for the annotation in CONTAINS function like this:
Sentence{CONTAINS(ClampNameEntityUIMA{"semanticTag", "Temperature"})
-> CREATE( ClampNameEntityUIMA , "semanticTag" = "TemperatureSentence")};
The statement that works is:
Sentence{CONTAINS(ClampNameEntityUIMA)
-> CREATE( ClampNameEntityUIMA , "semanticTag" = "TemperatureSentence")};
but that marks all sentences regardless of the contained annotation's feature value.
CLAMP does not allow creating types on the fly so I cannot declare a new type as a placeholder for annotations that meet conditions. So I have to use only the existing type - ClampNameEntityUIMA - and I can only check the feature values to differentiate the annotation classes.
Is there a way to include additional conditions in CONTAINS function? Or can I manipulate annotations without having to declare a new type?
The CONTAINS condition does not support what you need. If more complex condition are required as in your example, you need to switch to inlined rules as condition. A rule like the following could solve your problem:
Sentence{-> CREATE(ClampNameEntityUIMA, "semanticTag" = "TemperatureSentence")}
<- {e:ClampNameEntityUIMA{e.semanticTag == "Temperature"};};
DISCLAIMER: I am a developer of UIMA Ruta
Related
I am new to Drools, we are trying to create basic validation rules like a NULL check, etc. using the Drools n Scala framework.
I have a source file which has 200 attributes, need to apply NULL-check rule on all these attributes,
is there any easy way to do this? or do I need to create 200 rules for each attribute?
Thanks in advance.
Assuming you have a POJO ("plain old java object", getters/setters and some private variables to hold values) or modern java Records (effectively the same thing), then the answer is no: you need separate rules. For this scenario, the only way to check that field "name" is null is to actually assert against that field like this:
rule "example - name is null"
when
ExampleObject( name == null )
then
System.out.println("Name is null.");
end
However there exist other data structures -- for example, Map and its sibling types -- where you can reference the fields by name. In this case you could theoretically iterate through all of the field names and find the one whose value is empty.
So, for example, Map has a keySet() method which returns a set of fields -- you could iterate through this keyset and for each key check that there is a non-null value present in the map.
rule "example with map"
when
$map: Map()
$keys: Set() from $map.keySet()
$key: String() from $keys
String( this == null ) from $map.get($key)
// or this might work, not sure if the "this" keyword allows this syntax:
// Map( this[$key] == null ) from $map
then
System.out.println($key + " is missing/null");
end
This would require converting your Java object into a Map before passing into the rules.
However I DO NOT RECOMMEND this approach. Maps are extremely un-performant in rules because of how they serialize/deserialize. You will use a ton of unnecessary heap when firing them. If you look at how a HashMap serializes, for example, by peeking at its source code you'll see that it actually contains a bunch of "child" data structures like entryset and keyset and things like that. When using "new", those child structures are only initialized if and when you need them; but when serializing/deserializing, they're created immediately even if you don't need them.
Another solution would be to use Java reflection to get the list of declared field names, and then iterate through those names using reflection to get the value out for that field. In your place I'd do this in Java (reflection is problematic enough without trying to do it in Drools) and then if necessary invoke such a utility function from Drools.
I have a parameter under section protected that is needed for further calculations:
parameter Integer Ns = integer(ceil(L / dx))
It shouldn't be modified that's why I placed it there.
However, I want to access this parameter while building my general model. Particularly to access it in the other component that I could do something like:
Ns = componentName.Ns
But as it is under protected section it is not possible. I did a work around by simply adding another parameter in general section:
parameter Integer N=Ns
However, this parameter appears in the GUI and can be modified, which I would like to avoid by all means.
Is there any solution for this? I hope it is clear what I mean.
Converting my comments into an answer:
If you want a parameter to be visible and accessible from outside of the model class, but no longer changeable, then you should mark it final, like this:
final parameter Integer Ns = integer(ceil(L / dx))
As you can see in the example, the parameter can be calculated and becomes final afterwards.
Is it possible to make a rule to match the value of a FEATURE in an annotation that is a child of another Annotation?
Example:
Annotation Person
Annotation Doctor
Feature TYPE: xyz
something like Person.Doctor{FEATURE("TYPE","xyz")}
Also is it possible to create a rule that matches a FEATURE in an annotation that is PARTOF another annotation?
|-----------A1------------|
|-----A2-----| |---A3----|
Make a rule where
A3{FEATURE("X","1")} but also A3{PARTOF(A1)}
Thank you!
Assuming that there is a type Doctor and its parent type called Person which defined a feature kind of type uima.cas.String, you can simply write:
Doctor.kind=="xyz";
Doctor{Doctor.kind=="xyz"};
d:Doctor{d.kind=="xyz"};
Doctor<-{Person.kind=="xyz";};
Some short explanation of the label expression d: and the inlined rule as condition (<-{}). The label expression introduces a local annotation variable within the scope of the rule. In the above example d:Doctor matches on a annotation of the type Doctor and assigns it to a new variable called d. This variables can then be used in other parts of the rule in order to refer to this specific annotation. In the second rule, no label expression is used and the annotation is refered to by using the type (Doctor.kind). Here, the annotation is resolved anew in the context of the match of the rule, which could lead to a different one in case there are several annotations of the type Doctorwith the same offsets.
The inlined rule as condition works as a complex condition. The rule element Doctor matches only if the rule Person.kind=="xyz"; is able to match within the context/offsets/span of the matched Doctor annotation.
Concerning the second part of the question:
You cannot directly access the annotation which is used in a PARTOF condition because none is used actually. You need to match on the annotation in order to access its features. It depends on which annotation coveres which one, and which annotation should be checked for the feature value. Here are some examples:
a:A3{PARTOF(A1),a.x==1};
A1.x=="1"{CONTAINS(A3)};
A1<-{a:A3{a.x=="1"};};
DISCLAIMER: I am a developer of UIMA Ruta
I'm trying to modify an existing JasperReports template for an invoice. I would like to do some simple math in one field, i.e. calcultate the tax from an existing gross value. The gross value is represented by a parameter $P{prevAdvanceLine1Sum} and in the next field I would like to simply divide this value by a number (in my case 1.23).
Can you give me the expression I should use and what expression class to set?
You can either use simple arithmetic operators (like " / " in this case. See example here: EL Basic Arithmetic), or use the pre-defined methods provided by iReports. Which means, right-click upon the TextField and select Edit Expression. Then select the divide() method.
So the two methods would be:
1. $P{prevAdvanceLine1Sum / 1.23}
2. $P{prevAdvanceLine1Sum}.divide( 1.23 )
I need to fill a field in a report based on the end result of a complex branching statement. How do I do this in iReport? The report needs to show a different string depending on what is in different fields in the database. Do I make a really complex SQL statement? Do I use variables?
So, for instance,
If field x=1
IF y=1
IF z=1
Field should read A
If x=1
IF y=1
IF z=2
Field should read B
You could do something similar to the following:
( $F{staff_type} == null ? new String("") :
( $F{staff_type}.equalsIgnoreCase("Permanent") ? new String("1") :
( $F{staff_type}.equalsIgnoreCase("Non-permanent") ? new String("2") : new String("")
)))
Basically, you need to use nested condition expressions.
in the textfieldexpression write an expression like this
(($F{PAYMENTMODE}.equals("CS")) ? "Cash":($F{PAYMENTMODE}.equals("CQ"))? "Cheque":"Bank")e
I think the easiest way to do this would be to have the field(s) filled by a parameter passed from the backing bean. The jdbc connection is created in the bean and passed to the report, it should be relatively easy to access the field or fields you need and run the data through a method which determines the branching outcome. Assign the outcome to the parameter and pass it to the report in the jasperParameter variable of JasperFillManager.fillReport(file, parameters, jdbcConnection).
Usually, I handle all the programming logic before passing the data to the Jasper Report Engine, but in some cases, post-processing or post-checking is required. If it is that scenario and If I had MANY cases (strings) to check, I would code a 'Jasper Report Scriptlet' and handle that logic there (so that the code/report is readable and maintainable and also for code reuse). If it is just 2 or 3 strings to check, I would use the 'Ternary' operator.
If you want to use report scriptlet, create a scriptlet class (or use an existing one), code a method to handle this logic (Ex: 'checkString' method) and put $P{REPORT_SCRIPTLET}.checkString(someString) in the TextField's expression.