Do you know all the available rules ahead of time, even if you don't
necessarily want to pre-register them?

Perhaps we could have a lazy rule provider that registers all its tokens
ahead of time, but doesn't compile the rules until they're actually
requested?

-Darius

On Thu, Sep 1, 2011 at 11:50 AM, McKee, Steven Jay <[email protected]>wrote:

>  The pre-registration of rules is what we’re currently trying to get away
> from.  We basically want our rules to be found and loaded as needed.  The
> problem is the rules are executed at the OpenMRS level (created by the Arden
> translator).  We can’t directly register rules to our provider from there
> since the provider is down in a module.  We need something to call before we
> call eval on a rule to make sure it’s loaded (or it won’t be found): ****
>
> ** **
>
> Rule 1:****
>
>
> ///////////////////////////////////////////////////////////////////////////////////////
> ****
>
> Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”,
> parameters);****
>
>
> ///////////////////////////////////////////////////////////////////////////////////////
> ****
>
> ** **
>
> Rule 1 is calling the “ChicaAgeRule” from within it.  We need some
> mechanism to ensure the “ChicaAgeRule” is loaded (and load it if it’s not)
> before we call eval.  Since we’re trying to avoid pre-registering all the
> rules, there isn’t a good way to get them loaded.****
>
> ** **
>
> One possibility is to have the “getRule” method in a rule provider be dual
> purpose.  It can load and possibly register the rule if it’s not currently
> registered.  The rule provider would then have to be passed in parameters of
> the eval method.  The Arden translator could create something like this:**
> **
>
> ** **
>
> Rule 1:****
>
>
> ///////////////////////////////////////////////////////////////////////////////////////
> ****
>
> RuleProvider ruleProvider = (RuleProvider)parameters.get(“ruleProvider”);*
> ***
>
> If (ruleProvider != null) {****
>
> ruleProvider.getRule(“ChicaAgeRule”);****
>
> }****
>
> Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”,
> parameters);****
>
>
> ///////////////////////////////////////////////////////////////////////////////////////
> ****
>
> ** **
>
> This doesn’t seem the best way to do it, but I’m not sure of another way
> since we’re trying to avoid pre-registration.  This is basically why we were
> proposing to add a new “loadRule” method to the logicService interface so we
> could AOP around it and load our rules: ****
>
> ** **
>
> Rule 1:****
>
>
> ///////////////////////////////////////////////////////////////////////////////////////
> ****
>
> logService.loadRule(“ChicaAgeRule”, false);****
>
> Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”,
> parameters);****
>
>
> ///////////////////////////////////////////////////////////////////////////////////////
> ****
>
> ** **
>
> ** **
>
> Thanks,****
>
> Steve****
>
> ** **
>
> ** **
>
> *From:* Darius Jazayeri [mailto:[email protected]]
> *Sent:* Thursday, September 01, 2011 10:22 AM
> *To:* McKee, Steven Jay
> *Cc:* dev; Dugan, Tammy Marie
>
> *Subject:* Re: New LogicService method****
>
> ** **
>
> Yes, you could register your static rules in the afterStartup method on a
> RuleProvider. (That's exactly what that method is for.)****
>
> ** **
>
> E.g. the handler in the logic module that handles dynamically-defined rules
> in groovy or java does:****
>
> /**
> * @see org.openmrs.logic.rule.provider.AbstractRuleProvider#afterStartup()
> */
> @Override
> public void afterStartup() {
>     TokenService tokenService = Context.getService(TokenService.class);
>     RuleDefinitionService service =
> Context.getService(RuleDefinitionService.class);
>     for (RuleDefinition rd : service.getAllRuleDefinitions()) {
>         tokenService.registerToken(rd.getName(), this,
> rd.getId().toString());
>     }
> }****
>
> Also, do make sure you extend AbstractRuleProvider rather than just
> implementing RuleProvider, in case that interface ends up getting methods
> added later.****
>
> ** **
>
> -Darius****
>
> ** **
>
> On Thu, Sep 1, 2011 at 8:15 AM, McKee, Steven Jay <[email protected]>
> wrote:****
>
> I can see this approach working well for our dynamic class loading:****
>
>  ****
>
> 1.       The class loader task looks for new classes.****
>
> 2.       Once found, the rules get registered to our DSS rule provider.***
> *
>
> 3.       The DSS rule provider would use our compiling classloader to
> locate the file in the “getRule” method.****
>
>  ****
>
> We still, however, have the issue of our static rules in some of our
> modules.  We want to be able to use these on the fly, so how would be
> initially get these rules registered?  Would be have to write some sort of
> task to do this on startup?  Is there anything in logic that provides us a
> way of doing this?  I noticed there’s an “afterStartup” method in the
> RuleProvider interface.  What exactly is this used for?****
>
>  ****
>
> Thanks,****
>
> Steve****
>
>  ****
>
>  ****
>
> *From:* Darius Jazayeri [mailto:[email protected]]
> *Sent:* Wednesday, August 31, 2011 5:34 PM
> *To:* McKee, Steven Jay; dev****
>
>
> *Cc:* Dugan, Tammy Marie
> *Subject:* Re: New LogicService method****
>
>  ****
>
> Moving this to the developers list.****
>
>  ****
>
> The way this is supposed to work is that if you have a rule (YourRule.java)
> and you want it to be accessible as the token "Your Rule", then you need to
> do something like this:****
>
>     TokenService.registerToken("Your Rule", chicaRuleProvider,
> "InternalUniqueIdOfYourRule");****
>
>  ****
>
> Then when LogicService.getRule("Your Rule") is called, that will delegate
> to:****
>
>     chicaRuleProvider.getRule("InternalUniqueIdOfYourRule");****
>
>  ****
>
> Presumably you have a RuleProvider in your module already? (Even if you're
> bypassing LanguageHandler, I think RuleProvider is necessary...)****
>
>  ****
>
> The logic infrastructure will cache these rules (since they may be
> expensive to compile) so if you want it to forget a cached value, you'd do:
> ****
>
>     TokenService.notifyRuleDefinitionChanged("Your Rule");****
>
>  ****
>
> It seems like these methods should be sufficient for what you're trying to
> do.****
>
>  ****
>
> (Adding a method to LogicService is pretty significant to do, because
> that's a change to the core api, which requires simultaneous releases of new
> versions of 1.6.x, 1.7.x, and 1.8.x, to support the new logic module. It's
> possible that we end up doing this, but it can't happen quickly.)****
>
>  ****
>
> -Darius****
>
>  ****
>
> On Tue, Aug 30, 2011 at 2:42 PM, McKee, Steven Jay <[email protected]>
> wrote:****
>
> We are currently bypassing the dynamic rule code and language handlers.  We
> need the ability to load rules on the fly instead of pre-loading them.  It
> just gives us a lot of flexibility and the benefit of not loading rules we
> may not use.****
>
>  ****
>
> Thanks, Darius.****
>
>  ****
>
> Steve****
>
>  ****
>
> *From:* Darius Jazayeri [mailto:[email protected]]
> *Sent:* Tuesday, August 30, 2011 2:04 PM
> *To:* McKee, Steven Jay
> *Cc:* Dugan, Tammy Marie
> *Subject:* Re: New LogicService method****
>
>  ****
>
> Hi steve****
>
> I'm out and about at the moment, but will try to reply on the dev list
> today out tomorrow.****
>
> Isn't there already a workflow so your rule provider can update loaded
> rules though? Or have you ended up bypassing the dynamic rule code and
> language handlers I put in?****
>
> -Darius (by phone)****
>
> On Aug 30, 2011 1:17 PM, "McKee, Steven Jay" <[email protected]> wrote:***
> *
>
> Darius,****
>
>  ****
>
> CHICA is very close to finishing the upgrade to OpenMRS 1.7.x, but we’re
> needing an additional method added to the LogicService interface:****
>
>  ****
>
>       /******
>
>       * Loads a rule into memory so it can be used. It will also update the
> rule *metadata* if****
>
>       * required.****
>
>       * ****
>
>        * *@param* token the lookup key ("token") for the rule to be
> loaded.****
>
>       * *@param* updateRule Whether or not the rule *metadata* needs to be
> updated once loaded.****
>
>       * *@throws* LogicException if an error occurs loading a rule.****
>
>       */****
>
>       *public* *void* loadRule(String token, boolean updateRule) 
> *throws*LogicException;
> ****
>
>  ****
>
> CHICA currently has the same method in its DSS module which looks in
> various places to load a rule into memory.  We currently have hardcoded
> places in our code to load specific rules before any other rules are
> executed.  We want to be able to remove the hardcoded loading of the rules
> so we can be more dynamic about it.  ****
>
>  ****
>
> Here’s what we are proposing to do:****
>
> 1.       Add the new LogicService method.****
>
> 2.       Update the Arden parser to create Java calls that execute the
> loadRule method on an inner rule before calling “eval”.****
>
> logicService.loadRule("LocationAttributeLookup", false);****
>
> Result result = context.eval(patient.getPatientId(),
> "LocationAttributeLookup",parameters);****
>
> 3.       For the time being the implementation of the loadRule method in
> the logic module will do nothing.****
>
> 4.       We will set up an AOP call for the method in our DSS module so we
> can call our own loadRule to get the correct rule into memory.****
>
> 5.       The AOP call is a temporary fix until we can eventually get some
> of our DSS code moved into logic in the future.  But we’re very close to our
> upgrade deadline at the moment.****
>
>  ****
>
> The “updateRule” parameter for the method is used to tell the code whether
> or not the metadata about the rule should be updated.  Most of the time in
> normal operating conditions this will be false.  The case where we would
> supply true is when are class loading scheduled task is looking for new
> rules.  Once it finds a new rule, we want the newest metadata (and
> registration) for it.****
>
>  ****
>
> Thanks,****
>
>  ****
>
> Steve McKee****
>
> Children’s Health Services Research****
>
> Indiana University School of Medicine****
>
> Phone: 317-278-9660****
>
> Email: [email protected]****
>
>  ****
>
>     ****
>
> ** **
>

_________________________________________

To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to 
[email protected] with "SIGNOFF openmrs-devel-l" in the  body (not 
the subject) of your e-mail.

[mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

Reply via email to