/** * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.logic; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.openmrs.Cohort; import org.openmrs.Patient; import org.openmrs.logic.datasource.LogicDataSource; import org.openmrs.logic.result.Result; import org.openmrs.logic.result.Result.Datatype; import org.openmrs.logic.rule.RuleParameterInfo; import org.springframework.transaction.annotation.Transactional; /** * The Logic Service provides a mechanism for both registering and consuming business logic in the * form of logic <em>rules</em>. Rules may be run against a single patient or a set of patients. * Rules are registered under a unique string <em>token</em>. Later evaluation and/or retrieval of * the rule is done through the token. Tokens can be tagged with any number of string word/phrases * to simplify organization and lookup of tokens. Data source results can be obtained directly by * using a token in the form <em>@foo.bar</em>, where <em>foo</em> is the logic data source name and * <em>bar</em> is the key for that data source. For example, the token <em>@person.gender</em> is a * direct reference to the <em>gender</em> key of the <em>person</em> logic data source. <h3>Example * Usage</h3> * * <pre> * Patient myPatient = Context.getPatientService().getPatient(123); * LogicService logicService = Context.getLogicService(); * Result result = logicService.eval(myPatient, "HIV POSITIVE"); * if (result.toBoolean()) { * // patient is HIV positive * } * </pre> * * Results can be derived with specific criteria as well. For example, to fetch the maximum CD4 * count within the past six months: * * <pre> * Result result = logicService.eval(myPatient, new LogicCriteria("CD4 COUNT") * .within(Duration.months(6)).max(); * </pre> * * or within 6 months of 11-November-2006: * * <pre> * Calendar calendar = Calendar.getInstance(); * calendar.set(2006, 11, 11); * Date targetDate = calendar.getTime(); * Result result = logicService.eval(myPatient, new LogicCriteria("CD4 COUNT") * .asOf(targetDate).within(Duration.months(6)).max(); * </pre> * * @see org.openmrs.logic.Rule * @see org.openmrs.logic.LogicCriteria * @see org.openmrs.logic.datasource.LogicDataSource */ @Transactional public interface LogicService { /** * Fetch all known (registered) tokens * * @return all known (registered) tokens * @deprecated use {@link #getAllTokens()} */ @Deprecated public Set<String> getTokens(); /** * Fetch all known (registered) tokens * * @return all known (registered) tokens * @should return all registered token */ public List<String> getAllTokens(); /** * Fetch all known (registered) tokens matching a given string * * @param token full or partial token name * @return all tokens containing the given string * @deprecated use {@link #getTokens(String)} */ @Deprecated public Set<String> findToken(String token); /** * Fetch all known (registered) tokens matching a given string * * @param token full or partial token name * @return all tokens containing the given string * @should return all registered token matching the input fully * @should return all registered token matching the input partially * @should not fail when input is null */ public List<String> getTokens(String partialToken); /** * Registers a new rule with the logic service. * * @param token the lookup key ("token") for this rule * @param rule new rule to be registered * @throws LogicException * @see org.openmrs.logic.Rule * @should not fail when another rule is registered on the same token * @should persist the rule and associate it with the token */ public void addRule(String token, Rule rule) throws LogicException; /** * Registers a new rule with the logic service, associating the tags with the given token * * @param token the unique lookup key ("token") for this rule * @param tags words or phrases associated with this token (do not need to be unique) * @param rule new rule to be registered * @throws LogicException * @should not fail when no tags is specified * @should persist rule with the tags */ public void addRule(String token, String[] tags, Rule rule) throws LogicException; /** * Gets the rule registered under a given token * * @param token lookup key ("token") under which the rule is registered * @return rule registered under the given token * @throws LogicException if no rule by that name is found * @should return Rule associated with the input token * @should fail when no Rule is associated with the input token * @should return ReferenceRule */ public Rule getRule(String token) throws LogicException; /** * Update a rule that has previously been registered * * @param token lookup key ("token") for the rule to be updated * @param rule new version of rule (replaces existing rule) * @throws LogicException * @should update Rule when another Rule is registered under the same token */ public void updateRule(String token, Rule rule) throws LogicException; /** * Removes a rule from the logic service * * @param token lookup key ("token") under which rule to be removed is registered * @throws LogicException * @should remove rule */ public void removeRule(String token) throws LogicException; /** * Evaluates a rule for a given patient, given the token for the rule. * * @param patientId patient for whom the rule is to be calculated * @param expression expression to be parsed and evaluated * @return patient-specific result from given rule * @throws LogicException * @see {@link #parse(String)} * @since 1.6.3, 1.7.2, and 1.8 */ public Result eval(Integer patientId, String expression) throws LogicException; /** * Evaluates a rule for a given patient, given a token and parameters for the rule. * * @param patientId patient for whom the rule is to be calculated * @param expression expression to be parsed and evaluated * @param parameters parameters to be passed to the rule * @return patient-specific result from given rule * @throws LogicException * @see {@link #parse(String)} * @since 1.6.3, 1.7.2, and 1.8 */ public Result eval(Integer patientId, String expression, Map<String, Object> parameters) throws LogicException; /** * Evaluates a query for a given patient * * @param patientId patient for whom the query is to be run * @param criteria question to be answered (along with the token) for the given patient * @return result of query * @throws LogicException * @since 1.6.3, 1.7.2, and 1.8 */ public Result eval(Integer patientId, LogicCriteria criteria) throws LogicException; /** * Evaluates a query for a given patient * * @param patientId <code>Patient</code> for whom the query is to be run * @param criteria <code>Criteria</code> question to be answered (along with the token) for the * given patient * @param parameters <code>Map</code> of arguments to be passed to the rule * @return <code>Result</code> of query * @throws LogicException * @since 1.6.3, 1.7.2, and 1.8 */ public Result eval(Integer patientId, LogicCriteria criteria, Map<String, Object> parameters) throws LogicException; /** * Evaluates multiple logic expressions for a single patient. * (The expressions argument is an array and comes last because using a List would give this method * the same type erasure as the {@link LogicCriteria}... version.) * * @param patientId which patient to run the rules on * @param parameters global parameters to be passed to all rule evaluations * @param expressions expressions to be parsed and run * @return results of the rule evaluations * @throws LogicException * @see {@link #parse(String)} * @since 1.6.3, 1.7.2, and 1.8 */ public Map<String, Result> eval(Integer patientId, Map<String, Object> parameters, String... expressions) throws LogicException; /** * Evaluates multiple {@link LogicCriteria} for a single patient. * (The criteria argument is an array and comes last because using a List would give this method * the same type erasure as the {@link String}... version.) * * @param patientId which patient to run the rules on * @param parameters global parameters to be passed to all rule evaluations * @param criteria what criteria to run * @return results of the rule evaluations * @throws LogicException * @since 1.6.3, 1.7.2, and 1.8 */ public Map<LogicCriteria, Result> eval(Integer patientId, Map<String, Object> parameters, LogicCriteria... criteria) throws LogicException; /** * Evaluates a rule for a given patient, given the token for the rule. * * @param who patient for whom the rule is to be calculated * @param expression expression to be parsed and evaluated * @return patient-specific result from given rule * @throws LogicException * @deprecated use {@link #eval(Integer, String)} * @see {@link #parse(String)} */ @Deprecated public Result eval(Patient who, String expression) throws LogicException; /** * Evaluates a rule for a given patient, given a token and parameters for the rule. * * @param who patient for whom the rule is to be calculated * @param expression expression to be parsed and evaluated * @param parameters parameters to be passed to the rule * @return patient-specific result from given rule * @throws LogicException * @deprecated use {@link #eval(Integer, String, Map)} * @see {@link #parse(String)} */ @Deprecated public Result eval(Patient who, String expression, Map<String, Object> parameters) throws LogicException; /** * Evaluates a query for a given patient * * @param who patient for whom the query is to be run * @param criteria question to be answered (along with the token) for the given patient * @return result of query * @throws LogicException * @deprecated use {@link #eval(Integer, LogicCriteria)} */ @Deprecated public Result eval(Patient who, LogicCriteria criteria) throws LogicException; /** * Evaluates a query for a given patient * * @param who <code>Patient</code> for whom the query is to be run * @param criteria <code>Criteria</code> question to be answered (along with the token) for the * given patient * @param parameters <code>Map</code> of arguments to be passed to the rule * @return <code>Result</code> of query * @throws LogicException * @deprecated use {@link #eval(Integer, LogicCriteria, Map)} */ @Deprecated public Result eval(Patient who, LogicCriteria criteria, Map<String, Object> parameters) throws LogicException; /** * Evaluates a query over a list of patients * * @param who patients for whom the query is to be run * @param expression expression to be parsed and evaluated for each patient * @return result for each patient * @throws LogicException * @see {@link #parse(String)} */ public Map<Integer, Result> eval(Cohort who, String expression) throws LogicException; /** * Evaluates a query over a list of patients * * @param who patients for whom the query is to be run * @param expression expression to be parsed and evaluated for each patient * @param parameters parameters to be passed to the rule * @return result for each patient * @throws LogicException * @see {@link #parse(String)} */ public Map<Integer, Result> eval(Cohort who, String expression, Map<String, Object> parameters) throws LogicException; /** * Evaluates a query over a list of patients * * @param who patients for whom the query is to be run * @param criteria question to be answered (along with the token) for each patient * @return result for each patient * @throws LogicException */ public Map<Integer, Result> eval(Cohort who, LogicCriteria criteria) throws LogicException; /** * Evaluates a query over a list of patients * * @param who patients for whom the query is to run * @param criteria question to be answered (along with the token) for each patient * @param parameters arguments to be passed to the rule * @return result for each patient * @throws LogicException */ public Map<Integer, Result> eval(Cohort who, LogicCriteria criteria, Map<String, Object> parameters) throws LogicException; /** * Evaluates a collection of queries for a set of patients * * @param who patients for whom the queries are to be run * @param criterias parallel list of criteria to be evaluated on each patient * @return results for each patient * @throws LogicException */ public Map<LogicCriteria, Map<Integer, Result>> eval(Cohort who, List<LogicCriteria> criterias) throws LogicException; /** * Adds a tag to the given token. * * @param token * @param tag * @should add tag for a token */ public void addTokenTag(String token, String tag); /** * Removes a token's previously assigned tag. * * @param token * @param tag * @should remove tag from a token */ public void removeTokenTag(String token, String tag); /** * Gets all tags associated with this token. * * @param token token to look up by * @return collection of tags * @deprecated use {@link #getTokenTags(String)} */ @Deprecated public Collection<String> getTagsByToken(String token); /** * Gets all tags associated with this token. * * @param token token to look up by * @return collection of tags * @should return set of tags for a certain token */ public Set<String> getTokenTags(String token); /** * Gets all tokens associated with this tag. * * @param tag tag to look up by * @return collection of tokens * @deprecated use {@link #getTokensWithTag(String)} */ @Deprecated public Set<String> getTokensByTag(String tag); /** * Gets all tokens associated with this tag. * * @param tag tag to look up by * @return collection of tokens * @should return set of token associated with a tag */ public List<String> getTokensWithTag(String tag); /** * Performs a partial match search for token tags among all known tokens. * * @param partialTag partial match string * @return collection of tags * @deprecated use {@link #getTags(String)} */ @Deprecated public Set<String> findTags(String partialTag); /** * Performs a partial match search for token tags among all known tokens. * * @param partialTag partial match string * @return collection of tags * @should return set of tags matching input tag partially */ public List<String> getTags(String partialTag); /** * Fetches the default datatype this token will return when fed to an eval() call. Results * (returned by the logic service) are loosely typed by design; however, the default datatype * can be a useful hint for managing user interfaces or providing default behavior when working * with rules. * * @param token token to look the datatype up for * @return datatype of the given token */ public Datatype getDefaultDatatype(String token); /** * Fetches the parameters expected by a given rule * * @return list of parameters */ public Set<RuleParameterInfo> getParameterList(String token); /** * Adds a data source to the logic service. Data sources provide access to granular data that * can be combined by rules to derive higher level information. * * @param name name for the data source * @param logicDataSource the data source * @throws LogicException * @deprecated data sources are now auto-registered via Spring (since Logic module version 0.5) */ @Deprecated public void registerLogicDataSource(String name, LogicDataSource logicDataSource) throws LogicException; /** * Get all registered logic data sources * * @return all registered logic data sources */ public Map<String, LogicDataSource> getLogicDataSources(); /** * Adds the given logic data sources to the list of current data sources on this logic service * * @param logicDataSources * @deprecated data sources are now auto-registered via Spring (since Logic module version 0.5) */ @Deprecated public void setLogicDataSources(Map<String, LogicDataSource> logicDataSources) throws LogicException; /** * Get a logic data source by name * * @param name name of the desired logic data source * @return the logic data source with the given name or <code>null</code> if there is no data * source registered under the given name (must be an exact match) */ public LogicDataSource getLogicDataSource(String name); /** * Remove a logic data source by name * * @param name name of the logic data source to be unregistered * @deprecated data sources are now auto-registered via Spring (since Logic module version 0.5) */ @Deprecated public void removeLogicDataSource(String name); /** * Parse a criteria String to create a new LogicCriteria. <br /> * <br /> * Example: <br /> * <code>logicService.parseString("LAST 'CD4 COUNT' < 200");</code> * * @param inStr LogicCriteria expression in a plain String object. * @return LogicCriteria using all possible operand and operator from the String input * @deprecated use {@link LogicService#parse(String)} */ @Deprecated public LogicCriteria parseString(String inStr); /** * Parse a criteria String to create a new LogicCriteria. <br /> * <br /> * Example: <br /> * <code>logicService.parseString("LAST 'CD4 COUNT' < 200");</code> * * @param criteria LogicCriteria expression in a plain String object. * @return LogicCriteria using all possible operand and operator from the String input */ public LogicCriteria parse(String criteria); }