Hi Mario,
this looks very nice. Although I've learned to live without slot-specifc,
this should simplify certain rule patterns. OTOH, I expect some fallout
when this hits the user community ;-)
See inline for several remarks and questions.
On 17/01/2012, Mario Fusco <mario.fusco(a)gmail.com> wrote:
The property specific feature is off by default in order to make the
behavior of the rule engine backward compatible with the former releases.
If you want to activate it on a specific bean you have to annotate it with
@propSpecific.
OK, but will there be a PackageBuilder option as well? If so,
@propSpecifc and @PropSpecific might need an optional element for
inverting its meaning.
This annotation works both on drl type declarations:
declare Person
@propSpecific
firstName : String
lastName : String
end
and on Java classes:
@PropSpecific
public static class Person {
private String firstName;
private String lastName;
}
Moreover on Java classes you can also annotate any method to say that its
invocation actually modifies other properties. For instance in the former
Person class you could have a method like:
@Modifies( "firstName, lastName" )
public void setName(String name) {
String[] names = name.split("\\s");
this.firstName = names[0];
this.lastName = names[1];
}
(1) Given that similar annotations (e.g. JAXB) have established the
usage pattern of
defining a set of field names as a String[] I'd very much prefer to have
it here, too:
public abstract String[] value
The small extra punctuation effort is balanced by compile-time diagnostics. (But
within a single string, what's the purpose of the comma?)
(2) Is this transitive?
@Modifies( { "name" } )
public void setLastName(String name) {...}
@Modifies( { "letterhead" } )
public void setName(String name) {...}
Does setLastName propagate to a change of "letterhead"?
(3) I suppose you've realized that there could be circular references,
@Modifies( { "name" } )
public void setLastName(String name) {...}
@Modifies( { "firstName", "lastName" } )
public void setName(String name) {...}
Is it permitted? Detected at runtime?
(4) Make sure to document that the propagation is limited to the fact
being modified. Given
@PropSpecific
public class SomeClass {
private Foo foo;
@Modifies( { "foo", "bar" } )
public void setBlech( String blech ){
this.blech = blech;
this.foo.setThingummy( blech );
}
a re-evaluation of rules with SomeClass patterns referencing blech and
foo is to be expecte, but NOT of rules containing a Foo pattern.
(5) It might be useful to permit annotations on the fields, too. You'd
see more, or even all, annotations on a single screen.
That means that if a rule has a RHS like the following:
modify($person) { setName("Mario Fusco") }
it will correctly recognize that both the firstName and lastName have been
modified and act accordingly. Of course the @Modifies annotation on a
method has no effect if the declaring class isn't annotated with
@PropSpecific.
The third annotation I have introduced is on patterns and allows you to
modify the inferred set of properties "listened" by it. So, for example,
you can annotate a pattern in the LHS of a rule like:
Person( firstName == $expectedFirstName ) @watch( lastName ) // --> listens
for changes on both firstName (inferred) and lastName
Person( firstName == $expectedFirstName ) @watch( * ) // --> listens for
all the properties of the Person bean
Person( firstName == $expectedFirstName ) @watch( lastName, !firstName ) //
--> listens for changes on lastName and explicitly exclude firstName
Person( firstName == $expectedFirstName ) @watch( *, !age ) // --> listens
for changes on all the properties except the age one
(a) Please document whether a mere binding occurrence as in
Person( $ln: lastName )
does or does not imply "listening".
(b) What happens here?
Person( firstName == $efn ) @watch( firstName, ! firstName )
(c) And here? Will the rule with the $px:Person pattern fire due to the modify?
@PropSpecific
class Person {
private String name, lastName;
@Modifies( { "name" } )
public void setLastName(String name) {...}
//---
when
$px: Person( ... ) @watch( ! lastName )
//---
modify( $person ){ setLastName( "Smith" ) }
Once again this annotation has no effect if the corresponding
pattern's
type hasn't been annotated with @PropSpecific.
(d) Is there a diagnostic or is it silently ignored?
(e) Other good verbs besides "watch" would be "sense",
"note" an "observe". But
"watch" is certainly better than "onChange".
(f) Does this rule ever fire? (Plenty of Smiths have been inserted.)
when
Person( $name: name == "Smith") @watch()
(g) Does this rule ever fire? (Plenty of Smiths have been inserted.)
when
Person( $name: name == "Smith") @watch( ! name )
Thenks
Wolfgang