Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KOGITO-590: Rules should "see" process variables #269

Merged
merged 9 commits into from
Jan 13, 2020

Conversation

evacchi
Copy link
Contributor

@evacchi evacchi commented Dec 23, 2019

It is now possible to declare RuleUnits implicitly. The DataSources (DataStores actually) are inferred from the process variables. e.g. if process variables are

String foo;
Person bar;

the rule unit will declare:

DataStore<String> foo;
DataStore<Person> bar;

mutation occurs in-place on the reference that is shared with the process variable.
Future work:

  • explicitly (possibly automatically) copy back and forth (useful especially when the rule service is a remote service)
  • improve codegen: right now a DataStore is always used

}
RuleUnitComponentFactoryImpl impl = (RuleUnitComponentFactoryImpl) RuleUnitComponentFactory.get();
impl.registerRuleUnitDescription(generatedRuleUnitDescription);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this cast, but at the same time, I did not want to expose this in the public API. Maybe we can introduce some other interface

@@ -30,6 +30,8 @@ static RuleUnitComponentFactory get() {

RuleUnitDescription createRuleUnitDescription( KiePackage pkg, Class<?> ruleUnitClass );

RuleUnitDescription createRuleUnitDescription( KiePackage pkg, String ruleUnitSimpleName );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we should backport this, although it will be a no-op

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return null;
} else {
return ruleUnitDescription;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this change should be backported, There is no way createRuleUnitDescription(pkg, String) != null in the 7 series

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.ifPresent(m -> m.setBody(unit(unitName)));
// factory.findFirst(MethodDeclaration.class, m -> m.getNameAsString().equals("unbind"))
// .ifPresent(m -> m.setBody());
});
Copy link
Contributor Author

@evacchi evacchi Dec 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is duplicated code, really. We should schedule a refactoring later KOGITO-828

Copy link
Contributor Author

@evacchi evacchi Dec 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(the comment is there to show that the entire snippet is duplicated)

unitKieBaseModel.setEventProcessingMode( EventProcessingOption.STREAM );
unitKieBaseModel.addPackage(ruleUnitDescription.getPackageName());

// fixme config should go in the description as well
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these fixmes are now captured in KOGITO-827

Files.write(fpath, entry.contents());
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added this utility: when DEBUG mode is on, the files are also dumped to a temp directory

@evacchi evacchi requested review from mswiderski and mariofusco and removed request for mswiderski December 23, 2019 13:18
<bpmn2:endEvent id="_B89C98A9-F577-4B07-BB72-52283EE38A77">
<bpmn2:incoming>_D8A8D35C-3BBE-461E-8C67-682A3CEE6ACD</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:businessRuleTask id="_5293F325-A06A-469B-8C31-1E79EE36A3E2" drools:ruleFlowGroup="unit:ruletask.Generated" name="Rule2" implementation="http://www.jboss.org/drools/rule">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this rule flow group value has to map to package and unit name defined in DRL or?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is not actually a ruleFlowGroup that's just special syntax that's interpreted as a rule unit identifier. I chose this so that it can be retrofitted for the designer without changes. However, an alternative syntax is to just use implemenation="ruletask.Generated" and language="http://.../rule-unit" (don't remember the URI right now) but that requires a change in the designer UI

import org.kie.kogito.codegen.data.Person;

rule singlePerson when
p: /singlePerson[ age >= 18 ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use standard (no oopath) syntax? I tried it with just Person(age >= 18) and it didn't work...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mswiderski
DS are named entry point so you can rewrite that OOPath expression as
p: Person( age >= 18 ) from singlePerson

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @danielezonca

rule singlePerson when
p: /singlePerson[ age >= 18 ]
then
p.setAdult(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also add or remove data which would result in setting or removing process variables?

Copy link
Contributor Author

@evacchi evacchi Jan 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can "clear" a process variable like this

singlePerson.remove(p)

if you mean declaring a new process variable or deleting... I don't think you can, but then again, you can't with processes either, as the model is now code-generated ahead of time, right? you can of course add new values to collections (e.g. collection.add(...)). The process variable declarations become the source of truth here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think you can also use remove(p))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

singlePerson.remove(p) does not seem to remove the value from process.

what I had in mind is that we should allow to set one process variable based on others that are evaluated as rules. So we have the person and string here so based on person we should be able to set the string - like if there is adult person then we should set "you can drink" as string.

similar we should be able to remove given value like if person is not adult we should set the string to null.

so it's not about adding new variables but more of changing values of defined variables.

Copy link
Contributor Author

@evacchi evacchi Jan 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh in that case, you can refer to any variable (as long as the process declares it), but it's turned into a data source so you always have to use this dot notation (variables are always wrapped in a data source of some kind). We may refine this further with syntactic sugar, though

e.g. if you have a variable string of type String

you may (currently) write string.add("you can drink")

we could iteratively refine this by allowing "singleton" values and add syntactic sugar so that you can effectively write

string = "you can drink"

or something like that. Currently we only have "collection-like" data sources but we were already thinking about adding a "singleton" data source type

Copy link
Contributor Author

@evacchi evacchi Jan 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reason why the process is not updated when you remove/add is probably because the unbind part of the rule node is not implemented yet (the lines that were commented away), so that's why some changes are not reflected. That piece of code gets called when control is returned from the rule engine to the process engine

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, made some implementation to provide support for it, sent PR to your branch evacchi#1 please have a look and see if it is of any use

@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 13 Code Smells

0.0% 0.0% Coverage
0.0% 0.0% Duplication

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants