Edson,

Thank you very match. I've found a lot of ideas from your response. I didn't 
think about moving all conditions to LHS first and planned to use LHS only as a 
filter to find object to validate in RHS. I'll try to implement prototype and 
share experience in a list if you don't mind.

Oleg.

Edson Tirelli <[EMAIL PROTECTED]> wrote: 
   Oleg,

   As I mentioned to you, it is perfectly fine and easy to use the rules engine 
to validate your object tree as long as you instruct your users that they must 
write structured rules. What I mean is: as much as DSL templates allow you to 
write rules that resemble natural language, it is not really natural language. 
The main advice is to group objects and attributes together. So, instead of 
writing the rule as: 

3. "ServiceDescription" contained inside "ClientService" with type "BRONZE" 
should has status "ACCEPTED"

   They need to write the rule as:

3. If there is a ClientService whose type is "BRONZE" and a ServiceDescription 
contained inside it whose status is different of "ACCEPTED" then report error 

   As you can see, all the constraints/attributes are listed right after each 
object type. The above rule can be translated to:

rule "3. Validate status for BRONZE"
when
    There is a ClientService 
    - whose type is "BRONZE"
    There is a ServiceDescription
    - contained inside it
    - whose status is different of "ACCEPTED"
then
    report error
end

   As you can see, the rule definition is very close to the actual rule, if you 
take the appropriate care when writing it, having the attribute/constraints 
right after each object type. 
   Now, the DSL mapping will transform the above rule into:

rule "3. Validate status for BRONZE"
 when
     cs : ClientService( type == "BRONZE" )
    sd : ServiceDescription( this memberOf cs.children, status != "ACCEPTED" )
then
     # report error
 end
 
   When you try to extrapolate the above example to your real business example, 
to make your DSL template completely  generic, you may find the need to explain 
to your users the concept of "variable" though.  
   So, what he would do is actually name each of your objects. Example (replace 
X and Y for any identifier that makes sense for the user):

3. If there is a ClientService named X whose type is "BRONZE" and a 
ServiceDescription name Y contained inside X whose status is different of 
"ACCEPTED" then report error
 
   If the user names each object, it will be much easier to write generic 
templates, since your rule would become:

rule "3. Validate status for BRONZE"
 when
     There is a ClientService named X
     - whose type is "BRONZE"
     There is a ServiceDescription named Y
     - contained inside X
     - whose status is different of "ACCEPTED"
 then
     report error
 end
 
   And the DSL would translate that to:

rule "3. Validate status for BRONZE"
  when
      X : ClientService( type == "BRONZE" )
     Y : ServiceDescription( this memberOf X.children, status != "ACCEPTED" )
 then
      # report error
  end
  
   I don't think that it is too hard to explain to users that they need to name 
each of his objects and this adds a great flexibility to the rules when adding 
constraints between objects of the same type.

    The final (and hardest) problem you will face is that you mentioned that 
your objects may be any level deep inside each other and you want to abstract 
that from users. In this case I see only 2 options:

1. The first option is do what you are already doing and create a helper 
function that goes deep a hierarchy checking for the existence of the 
relationship.  

2. The second option is to create a relationship object that will flatten your 
tree structure transforming it in a pure relational structure. This is a very 
common solution used in databases that do not support hierarchy queries. The 
idea is that you create an object with attributes parent, child and optionally 
the level (distance) between each other, and you assert a copy of it for each 
related object in your object hierarchy (in computational theory we call this 
set of objects the result of the transitive closure calculation). The result is 
really a trade-off between memory and query time. You need to check if for your 
use case, the performance gains and expressiveness flexibility pays off the 
memory cost. 

    Hope it helps.

    []s
    Edson
 
2007/7/12, Oleg Yavorsky <[EMAIL PROTECTED]>: Hi.

I've got a lot of domain objects represented as instances of classes generated 
from XSD using Castor. My goal is to implement validation framework for whole 
tree which contains complex "when"  conditions (see bellow). Furthermore, rules 
definitions should be very easy for unexperienced user to change so I need DSL. 

Now I use reflection to assert whole tree of objects to working memory along 
with additional context information (like stack of parents associated with 
particular object). Then I use eval() in LHS to call boolean functions which 
performs checks in plain Java to see if object in particular context. But I 
think that this is ugly approach and it doesn't solve other cases. I'm new to 
Drools but something tells me that  it can give me more elegant solution for 
such problems. 

Here is an example of possible hierarchy (used XSD to better represent it). 
Make note that in production case similar hierarchy is more complex and has a 
lot of  objects. Sorry, but I don't know how to format it in email.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns=" http://www.w3.org/2001/XMLSchema";
    targetNamespace="http://www.example.org/ClientService "
    xmlns:tns="http://www.example.org/ClientService";
    elementFormDefault="qualified"> 

    <complexType name="ClientService">
        <sequence minOccurs="0" maxOccurs="1">
            <element name="ClientInfo">
                <complexType> 
                    <sequence>
                        <element name="Name"  type="string"/>
                        <element name="AccountID" type="string" minOccurs="0" 
maxOccurs="1"/>
                    </sequence>
                </complexType> 
            </element>
            <element name="ServiceDescription" minOccurs="0">
                <complexType>
                    <sequence>
                        <element name="Name"  type="string"/>
                        <element name="Status">
                            <simpleType>
                                <restriction base="string"> 
                                    <enumeration value="VERIFIED"/>
                                    <enumeration value="ACCEPTED"/>
                                     <enumeration value="DENIED"/>
                                </restriction>
                            </simpleType>
                        </element> 
                    </sequence>
                </complexType>
            </element>
         </sequence>
        <attribute name="Type">
            <simpleType>
                <restriction base="string">
                    <enumeration value="BRONZE" /> 
                    <enumeration value="SILVER"/>
                    <enumeration value="GOLD"/>
                </restriction>
            </simpleType>
        </attribute> 
     </complexType>
</schema>

And here are possible validation cases:

1. "ClientInfo" contained inside "ClientService" with type "GOLD" should have 
"AccountID" assigned. 
2. "ClientService" with type "BRONZE" could have up to 3 "ServiceDescription"
3. "ServiceDescription" contained inside "ClientService" with type "BRONZE" 
should has status "ACCEPTED" 
4. "ClientInfo" should have "AccountID" assigned if there is 
"ServiceDescription" with name "SUBSCRIPTION"

I'd like to come up with rules definition that looks like this (for 3-d 
example): 
rule "Validate status for BRONZE"
when
    Validating ServiceDescription
    Contained in ClientService having
        type equals to "BRONZE"
then
    # Validate status
end
 
In this rule  ServiceDescription, ClientService and type literals could be 
anything else (so I don't need to create DSL for each  object in domain). But 
this could be easily done through  reflection.

Any help with possible approach will  be highly appreciated.

Oleg.
           

---------------------------------

Вы уже с Yahoo!?  Испытайте обновленную и улучшенную. Yahoo! Почту!

_______________________________________________ 
rules-users mailing list
[email protected]
 https://lists.jboss.org/mailman/listinfo/rules-users





-- 
  Edson Tirelli
  Software Engineer - JBoss Rules Core Developer
  Office: +55 11 3529-6000
  Mobile: +55 11 9287-5646 
  JBoss, a division of Red Hat @ www.jboss.com 
_______________________________________________
rules-users mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/rules-users


                
---------------------------------
 Вы уже с Yahoo!?
 Испытайте обновленную и улучшенную Yahoo! Почту!
_______________________________________________
rules-users mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/rules-users

Reply via email to