@Burke: Logic, as currently written, has the idea of providers under the hood. What a logic token does is map a public-facing name to a String providerClassName + String configuration. The idea is that each provider has a universe of rules it could expose, and at module startup it tries to register each of those rules with a token. However all of our historic implementations of token registration-at-startup have been buggy. (E.g. if I look at my 1.8.x database, I only have 18 tokens registered, because all the reference rules from the concept datasource seem to have failed to register.) I would imagine that there are probably 2 OpenMRS installations out there with logic tokens registered correctly: AMPATH and Chica.
So yeah, one option would be for the LogicCalculationProvider to expose all its known logic tokens as calculation tokens. But since logic tokens have never really worked, I propose that instead we let logic expose its under-the-hood machinery, at least potentially. (For what it's worth, we have not yet defined a mechanism for CalculationProviders to register tokens at startup. We should do that, and hopefully one arises naturally from this sprint.) Assuming we define that mechanism, and the logic module were to register a token for "WEIGHT (KG)", I'd prefer that token registration to point to "org.openrms.logic.LogicObsDataSource" + "5089", rather than have it just point to "WEIGHT (KG)". (Data Sources are actually also RuleProviders that return ReferenceRules, btw.) -Darius On Wed, Mar 14, 2012 at 9:01 PM, Burke Mamlin <[email protected]>wrote: > I don't quite follow. I thought the purpose of Calculation was to be the > next great Logic 2.0 that would allow various & more nimble implementations > of logic. In this case, logic is the implementation, so isn't the goal > that all the tokens exposed by logic would continue to be exposed? For > example, if I was running the logic module in a pre-Calculation-sprint > world and could evaluate "WEIGHT (KG)" for a patient to get a result > containing the patient's weights, then I'd expect to be able to call the > CalculationService in the new world to evaluate "WEIGHT (KG)" for a patient > and get a result containing weights. To support this, I would make a > single CalculationProvider for Logic that ensured that all of the various > ways that tokens could be registered within the logic service would now get > registered in the new Calculation service. Wasn't that the goal? > > -Burke > > On Wed, Mar 14, 2012 at 8:17 PM, Darius Jazayeri > <[email protected]>wrote: > >> Hi Wyclif, >> >> This is an interesting question, and I'm not sure what the right approach >> is. >> >> I don't think your options are phrased quite right--I think it should be: >> >> Option A: implement one single LogicCalculationProvider which is capable >> of fetching all logic rules. >> If we went this route, I'd suggest: >> >> - calculation's TokenRegistration.ruleName would be the classname of >> the logic RuleProvider >> - calculation's TokenRegistration.configuration would be directly the >> configuration string for the logic RuleProvider >> - we would completely ignore tokens registered in the logic module. >> It would be perfectly fine for the same underlying rule to be exposed as >> the calculation token "Chica A12", whereas it might be "A12" in logic, or >> not even have a token registered in logic. >> >> An alternate single provider approach would be to only expose as >> Calculations, rules that have tokens registered in logic. E.g. the >> calculation's TokenRegistration with ruleName="WEIGHT (KG)" and >> configuration=null would ultimately end up calling LogicService's >> eval("WEIGHT (KG)"). Personally I like this approach less, but I haven't >> thought it through much. >> >> Option B: one CalculationProvider per RuleProvider in logic. If we're >> doing this: >> >> - expose *all* the logic RuleProviders (including the data source >> ones) as CalculationProviders >> - but you don't need to care about how the data sources work. Just >> get all of them, and delegate to their getRule(String config) method. >> >> And actually, having written this email, I now favor Option A (my first >> variant). >> >> Off the top of my head the code would look something like this: >> >> class LogicCalculationProvider implements CalculationProvider { >> public Calculation getCalculation(String calculationName, String >> configuration) { >> // treat calculationName as the fully-qualified classname of the >> logic RuleProvider >> RuleProvider p = >> TokenRegistrationService.getRuleProvider(calculationName); // need to write >> this method >> if (p == null) throw new Exception(); >> // pass configuration straight through to the logic RuleProvider >> Rule rule = p.getRule(configuration); >> return new RuleAsCalculationWrapper(rule); >> } >> } >> >> The bulk of the code would actually be around converting logic's results >> to calculation's results. >> >> Also, looking at this, I think we should add a *checked* exception to >> CalculationProvider.getCalculation, like >> InvalidCalculationConfigurationException or something. Given that we're >> counting on two String being interpreted correctly, I'd much rather have a >> compile-time exception than a runtime one. >> >> -Darius >> >> >> On Wed, Mar 14, 2012 at 2:20 PM, Wyclif Luyima <[email protected]>wrote: >> >>> Hello, >>> >>> In the effort of refactoring logic to expose itself in a way based on >>> the calculation module i'm trying to figure out how to handle the >>> LogicCalculationProvider(s) and i need your views on this. The current >>> logic module has 2 main rule providers, the ClassRuleProvider and >>> RuleDefinitionRuleProvider(I'm trying to ignore the DataSourceRuleProvider >>> since i'm not yet sure how this is going to be incorporated). 2 questions >>> come to my mind, >>> >>> 1. Should we have 2 separate LogicCalculationProviders equivalents >>> for these? >>> 2. If yes, RuleDefinitionRuleProvider looks up Rules stored as >>> tokens in the database which is the equivalent of TokenRegistrations in >>> the >>> calculation module, does it mean that the CalculationProvider equivalent >>> for it should instead go through the TokenRegistrationService and the >>> equivalent for ClassRuleProvider goes through the >>> ClasspathCalculationProvider? >>> 3. If no, What are your suggestions? >>> >>> >>> Wyclif >>> >>> >>> >>> ------------------------------ >>> Click here to >>> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >>> OpenMRS Developers' mailing list >> >> >> ------------------------------ >> Click here to >> unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from >> OpenMRS Developers' mailing list >> > > ------------------------------ > Click here to > unsubscribe<[email protected]?body=SIGNOFF%20openmrs-devel-l>from > OpenMRS Developers' mailing list > _________________________________________ 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]

