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

DROOLS-7475 Proposed feature for ['key'] accessor #56

Merged
merged 17 commits into from
Jun 22, 2023

Conversation

tarilabs
Copy link
Member

@tarilabs tarilabs commented Jun 20, 2023

this PR is actually merge-able without having to necessarily wait for ansible-side (ie: retrofit and backward compatible)

to review this PR, I believe will be easier at times to see each commit individually "as a step", maybe is more easier to digest that way 🙃
to avoid bloating further the PR, I've tried to minimize the refactor on existing code.

I remain available also via chat/quickcall if preferred.

JIRA: https://issues.redhat.com/browse/DROOLS-7475

referenced Pull Requests:

nesting the protoextractor into the maven build
Results :

Failed tests:   testWithSelectAttr(org.drools.ansible.rulebook.integration.api.NullTest): expected:<1> but was:<0>
  test(org.drools.ansible.rulebook.integration.api.NullTest): expected:<1> but was:<0>
  testRepeatedOnceWithin(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithOr(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithAnd(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testSelectOnNull(org.drools.ansible.rulebook.integration.api.SelectTest): expected:<1> but was:<0>

Tests in error:
  testOnceWithinInRule(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceWithinInCondition(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceAfterWithOr(org.drools.ansible.rulebook.integration.api.OnceAfterTest): Cannot invoke "Object.toString()" because the return value of "org.drools.base.facttemplates.Fact.get(String)" is null

Tests run: 138, Failures: 6, Errors: 3, Skipped: 0
Results :

Failed tests:   testRepeatedOnceWithin(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithOr(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithAnd(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>

Tests in error:
  testOnceWithinInRule(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceWithinInCondition(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceAfterWithOr(org.drools.ansible.rulebook.integration.api.OnceAfterTest): Cannot invoke "Object.toString()" because the return value of "org.drools.base.facttemplates.Fact.get(String)" is null

Tests run: 138, Failures: 3, Errors: 3, Skipped: 0
Failed tests:   testRepeatedOnceWithin(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinInRule(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithOr(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithAnd(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinInCondition(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceAfterWithOr(org.drools.ansible.rulebook.integration.api.OnceAfterTest): expected:<2> but was:<1>

Tests run: 138, Failures: 6, Errors: 0, Skipped: 0
Copy link
Collaborator

@tkobayas tkobayas left a comment

Choose a reason for hiding this comment

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

Thank you for the great work!

Btw, does it make sense to add a few integration tests (under drools-ansible-rulebook-integration-api) to demonstrate the new capability?

@tarilabs
Copy link
Member Author

Thank you for the great work!
Btw, does it make sense to add a few integration tests (under drools-ansible-rulebook-integration-api) to demonstrate the new capability?

thanks @tkobayas 🙇
That is correct observation and thank you for raising, nevertheless I believe would be helpful to do e2e test only after ansible-side approve of their related parser changes (I want to minimize the number of e2e tests which are not actually "requested").
In other words, I believe would make sense to enrich e2e testing in following PRs

@tkobayas
Copy link
Collaborator

In other words, I believe would make sense to enrich e2e testing in following PRs

Got it, thanks!

}

// TODO used for indexing, normalizing chunks.
public String getFieldName() {
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately this is breaking indexing, see https://github.com/kiegroup/drools/blob/main/drools-model/drools-canonical-model/src/main/java/org/drools/model/PrototypeDSL.java#L135 What I suggest is introducing an interface named something like FieldAccessingExpression declaring a getFieldName() method, making both this class and PrototypeFieldValue to implement it and changing the downcasts in PrototypeDSL to use it. The only problem is that this will of course require also a change in Drools, but this seems unavoidable (or at least I don't have any better idea).

Copy link
Member

Choose a reason for hiding this comment

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

Also it would be nice to add a few assertions in some tests, for instance here, to make sure that the alpha node is indexed as expected.

Copy link
Member Author

Choose a reason for hiding this comment

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

seems no other way indeed given PrototypeFieldValue cannot be instantiated (due to constructor visibility)

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

What about just adding the extractor method to the PrototypeExpression interface returning an Optional? Like
Optional<String> getIndexingKey();

In this way we can avoid the instanceof and the downcasting: each expression can be indexable returning a value or not with an empty option

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

@danielezonca I don't see any semantic difference between the method returning an Optional and the new interface and actually I still prefer to use the second to have clearer marker between which expression is indexable and which isn't.

Copy link
Member Author

Choose a reason for hiding this comment

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

@tarilabs tarilabs force-pushed the tarilabs-20230614-DROOLS-7475 branch from 3944ca7 to f6ccd37 Compare June 20, 2023 12:19
@@ -70,7 +71,7 @@ public void testExecuteRules() {
public void testExecuteRulesSet() {
RulesSet rulesSet = new RulesSet();
rulesSet.addRule().withCondition().all()
.addSingleCondition(prototypeField("nested.i"), Index.ConstraintType.EQUAL, prototypeField("nested.j").add(fixedValue(1)));
Copy link
Member

Choose a reason for hiding this comment

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

Just a note: when we will move the extractor module into Drools I think we could also deprecate (or completely remove) the old prototypeField.

Copy link
Member Author

Choose a reason for hiding this comment

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

one step at a time 🙃
the correct place to mark this would be another ticket 😉

Copy link
Member

@mariofusco mariofusco left a comment

Choose a reason for hiding this comment

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

Great job! Except for a few minor comments the only real problem is that this pull request as it is breaks indexing. Please fix it as discussed.

tarilabs added a commit to tarilabs/drools that referenced this pull request Jun 20, 2023
see also kiegroup/drools-ansible-rulebook-integration#56 (comment)

make IndexableExpression interface so downstream can leverage this rather than specific concrete class
@tarilabs tarilabs requested a review from mariofusco June 20, 2023 15:23
@tarilabs tarilabs requested a review from mariofusco June 21, 2023 10:25
@tarilabs
Copy link
Member Author

Copy link
Member

@danielezonca danielezonca left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, few comments but they are all minor or clarification, well done 👍

@@ -41,4 +42,6 @@ public interface RulesEvaluator {
static RulesEvaluator createRulesEvaluator( RulesExecutorSession rulesExecutorSession, boolean async ) {
return async ? new AsyncRulesEvaluator(rulesExecutorSession) : new SyncRulesEvaluator(rulesExecutorSession);
}

KieSession asKieSession();
Copy link
Member

Choose a reason for hiding this comment

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

I'm not familiar with this RulesEvaluator interface (even if we have probably similar concepts in Drools repo) but I guess it is a "facade" to hide the Session (a bit similar to the RuleEvaluator in Drools). I don't think we want to expose a asKieSession.

@mariofusco
Wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe is package-protected for testing puposes? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Yes, this is only for testing purpose and unfortunately unavoidable. In particular the need is to access the KieSession and then the KieBase and the Rete network to check that a node was indexed as expected. I don't see any other way to do this.

@@ -33,6 +34,7 @@
<version.assertj>3.20.2</version.assertj>
<version.jackson>2.13.1</version.jackson>
<version.json>20230227</version.json>
<version.org.antlr4>4.10.1</version.org.antlr4>
Copy link
Member

Choose a reason for hiding this comment

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

Do you think this version and Drools repo antlr versions can conflict or this is not possible?
In general if they must stay aligned it might be useful to create a followup ticket to introduce the usage of drools-parent or similar to centralise the declaration.
Wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

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

We could consider drools-ansible-rulebook-intergration to inherit the same parent (or even jboss-patent) in a subsequent task/pr ?

Copy link
Member

Choose a reason for hiding this comment

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

Yes I think something like that in another PR 👍

Comment on lines +19 to +24
/**
* This is okay for ansible-integration work as prototype do not define accessor programmatically,
* but having prototype definition ignored in {@link #asFunction(Prototype)} call, ought to be revised
* if porting this module into Drools and generalizing beyond usage in ansible-integration.
*/
public static final Prototype IGNORED = PrototypeDSL.prototype("IGNORED");
Copy link
Member

Choose a reason for hiding this comment

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

It should be ideal to have a tracking ticket and here the id/link

@@ -0,0 +1,26 @@
grammar Protoextractor;
Copy link
Member

Choose a reason for hiding this comment

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

@mariofusco
Is native compilation a requirement/nice to have/planned scenario for this integration module?
If so we should verify if this antlr part is compatible

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure why we would think this is unsupported at native-image? 🤔
To my knowledge, we are not codegen at parsing time, so this is just standard java code in some way, don't you agree?

Copy link
Member

Choose a reason for hiding this comment

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

Yes indeed, it might be necessary to list some classes for reflection but nothing more than that overall

mariofusco added a commit to apache/incubator-kie-drools that referenced this pull request Jun 22, 2023
* DROOLS-7475 Proposed feature for ['key'] accessor

see also kiegroup/drools-ansible-rulebook-integration#56 (comment)

make IndexableExpression interface so downstream can leverage this rather than specific concrete class

* fix PrototypeDSL

* implement code review feedback

---------

Co-authored-by: mariofusco <[email protected]>
@mariofusco mariofusco merged commit 28b41e5 into kiegroup:main Jun 22, 2023
tarilabs added a commit to tarilabs/drools-ansible-rulebook-integration that referenced this pull request Jul 25, 2023
mkanoor added a commit to ansible/ansible-rulebook that referenced this pull request Aug 3, 2023
work-in-progress as i'm volunteering to work on this e2e, so this is a
quite-complete draft for the ansible-rulebook side; i'll keep posted as
i will progress on drools-ansible-rulebook-integration side.

EDIT: demonstrate working locally and added e2e test as requested

**JIRA**: https://issues.redhat.com/browse/DROOLS-7475

**referenced Pull Requests**: 

* #539
* ansible/drools_jpy#50
*
kiegroup/drools-ansible-rulebook-integration#56
* https://github.com/kiegroup/drools/pull/5333
* https://issues.redhat.com/browse/AAP-10738
*
kiegroup/drools-ansible-rulebook-integration#65
* ansible/drools_jpy#51

---------

Co-authored-by: Madhu Kanoor <[email protected]>
Co-authored-by: Alex <[email protected]>
mariofusco pushed a commit that referenced this pull request Aug 21, 2023
* DROOLS-7475 Proposed feature for ['key'] accessor

nesting the protoextractor into the maven build

* WIP: broken but progressing

Results :

Failed tests:   testWithSelectAttr(org.drools.ansible.rulebook.integration.api.NullTest): expected:<1> but was:<0>
  test(org.drools.ansible.rulebook.integration.api.NullTest): expected:<1> but was:<0>
  testRepeatedOnceWithin(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithOr(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithAnd(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testSelectOnNull(org.drools.ansible.rulebook.integration.api.SelectTest): expected:<1> but was:<0>

Tests in error:
  testOnceWithinInRule(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceWithinInCondition(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceAfterWithOr(org.drools.ansible.rulebook.integration.api.OnceAfterTest): Cannot invoke "Object.toString()" because the return value of "org.drools.base.facttemplates.Fact.get(String)" is null

Tests run: 138, Failures: 6, Errors: 3, Skipped: 0

* WIP: broken but null != UNDEF

Results :

Failed tests:   testRepeatedOnceWithin(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithOr(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithAnd(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>

Tests in error:
  testOnceWithinInRule(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceWithinInCondition(org.drools.ansible.rulebook.integration.api.OnceWithinTest): Cannot invoke "java.util.Map.get(Object)" because "map" is null
  testOnceAfterWithOr(org.drools.ansible.rulebook.integration.api.OnceAfterTest): Cannot invoke "Object.toString()" because the return value of "org.drools.base.facttemplates.Fact.get(String)" is null

Tests run: 138, Failures: 3, Errors: 3, Skipped: 0

* WIP: broken but progressing

Failed tests:   testRepeatedOnceWithin(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinInRule(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithOr(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinWithAnd(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceWithinInCondition(org.drools.ansible.rulebook.integration.api.OnceWithinTest): expected:<0> but was:<1>
  testOnceAfterWithOr(org.drools.ansible.rulebook.integration.api.OnceAfterTest): expected:<2> but was:<1>

Tests run: 138, Failures: 6, Errors: 0, Skipped: 0

* ALL tests passing

* small refactor

* cleanup RulesModelUtil

* refactor, small fix for array access, tests

* fix grammar typo

* refactor ExistsField as discussed with Mario

* implement code review feedback

* implement code review feedback

* code review feedback impl about ORIGINAL_MAP_FIELD

* BREAKING to investigate indexing issue

* revert the disabled commit

* implement code review feedback

* code review feedback

(cherry picked from commit 28b41e5)
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