diff --git a/opensrp-anc/build.gradle b/opensrp-anc/build.gradle index 88bcf7a00..61c724c4a 100644 --- a/opensrp-anc/build.gradle +++ b/opensrp-anc/build.gradle @@ -181,7 +181,7 @@ tasks.withType(Test) { dependencies { implementation 'androidx.appcompat:appcompat:1.3.1' - implementation('org.smartregister:opensrp-client-native-form:3.1.1-SNAPSHOT@aar') { + implementation('org.smartregister:opensrp-client-native-form:3.1.5-LOCAL-SNAPSHOT@aar') { transitive = true exclude group: 'com.android.support', module: 'recyclerview-v7' exclude group: 'com.android.support', module: 'appcompat-v7' @@ -226,13 +226,13 @@ dependencies { exclude group: 'com.android.support', module: 'cardview-v7' exclude group: 'com.android.support', module: 'support-v4' } - implementation group: 'org.apache.commons', name: 'commons-text', version: '1.9' + implementation group: 'org.apache.commons', name: 'commons-text', version: '1.10.0' implementation 'junit:junit:4.12' implementation 'androidx.test:core:1.4.0' annotationProcessor 'com.jakewharton:butterknife:10.2.3' implementation 'net.zetetic:android-database-sqlcipher:4.4.0@aar' implementation 'commons-validator:commons-validator:1.7' - implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.google.code.gson:gson:2.8.9' implementation 'org.greenrobot:eventbus:3.2.0' annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.2.0' implementation 'com.google.guava:guava:30.0-jre' @@ -251,17 +251,18 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.0' - implementation group: 'org.yaml', name: 'snakeyaml', version: '1.27' + implementation group: 'org.yaml', name: 'snakeyaml', version: '1.31' implementation 'de.hdodenhof:circleimageview:3.1.0' - implementation 'org.jeasy:easy-rules-core:3.3.0' - implementation 'org.jeasy:easy-rules-mvel:3.3.0' - implementation("com.itextpdf:itext7-core:7.1.12") + implementation("com.itextpdf:itext7-core:7.2.4") implementation 'org.jacoco:org.jacoco.agent:0.7.9:runtime' testImplementation 'org.jacoco:org.jacoco.agent:0.7.9:runtime' implementation 'com.android.volley:volley:1.2.1' implementation 'org.jacoco:org.jacoco.agent:0.8.7:runtime' testImplementation 'org.jacoco:org.jacoco.agent:0.8.7:runtime' + // FIX SECURITY VULNERABILITIES + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.0' + testImplementation 'junit:junit:4.13.1' testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3' testImplementation('com.squareup:fest-android:1.0.8') { diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/YamlRuleDefinitionReaderExt.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/YamlRuleDefinitionReaderExt.java new file mode 100644 index 000000000..22955eff2 --- /dev/null +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/YamlRuleDefinitionReaderExt.java @@ -0,0 +1,32 @@ +package org.smartregister.anc.library; + +import org.jeasy.rules.support.RuleDefinition; +import org.jeasy.rules.support.reader.YamlRuleDefinitionReader; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by Ephraim Kigamba - nek.eam@gmail.com on 22-11-2022. + */ +public class YamlRuleDefinitionReaderExt extends YamlRuleDefinitionReader { + + + @Override + protected RuleDefinition createRuleDefinition(Map map) { + RuleDefinition ruleDefinition = super.createRuleDefinition(map); + + List actionList = ruleDefinition.getActions(); + List newActionList = new ArrayList<>(); + + for (int i = 0; i < actionList.size(); i++) { + newActionList.add("facts." + actionList.get(i)); + } + + actionList.clear(); + actionList.addAll(newActionList); + + return ruleDefinition; + } +} diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineFactory.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineFactory.java index 704c55a5f..c95ff3c48 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineFactory.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineFactory.java @@ -9,8 +9,11 @@ import org.jeasy.rules.api.Rule; import org.json.JSONObject; +import java.util.HashMap; import java.util.Map; +import timber.log.Timber; + public class AncRulesEngineFactory extends RulesEngineFactory { private Map globalValues; private AncRulesEngineHelper ancRulesEngineHelper; @@ -22,7 +25,6 @@ public AncRulesEngineFactory(Context context, Map globalValues, this.ancRulesEngineHelper = new AncRulesEngineHelper(context); this.ancRulesEngineHelper.setJsonObject(mJSONObject); this.globalValues = globalValues; - } @Override @@ -45,4 +47,36 @@ protected Facts initializeFacts(Facts facts) { public boolean beforeEvaluate(Rule rule, Facts facts) { return selectedRuleName != null && selectedRuleName.equals(rule.getName()); } + + @Override + public void beforeExecute(Rule rule, Facts facts) { + super.beforeExecute(rule, facts); + + Timber.e("Putting facts in beforeExecute"); + HashMap myMap = new HashMap<>(); + facts.put("facts", myMap); + } + + @Override + public void onSuccess(Rule rule, Facts facts) { + super.onSuccess(rule, facts); + + Timber.e("Putting facts in onSuccess "); + HashMap myMap = facts.get("facts"); + + for (String key : + myMap.keySet()) { + facts.put(key, myMap.get(key)); + } + + facts.remove("facts"); + } + + @Override + public void onFailure(Rule rule, Facts facts, Exception exception) { + super.onFailure(rule, facts, exception); + + Timber.e("Putting facts in onFailure"); + facts.remove("facts"); + } } diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineHelper.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineHelper.java index b39cd5b15..6d42a6acc 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineHelper.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/helper/AncRulesEngineHelper.java @@ -10,18 +10,22 @@ import org.jeasy.rules.api.Facts; import org.jeasy.rules.api.Rule; +import org.jeasy.rules.api.RuleListener; import org.jeasy.rules.api.Rules; import org.jeasy.rules.api.RulesEngine; +import org.jeasy.rules.api.RulesEngineParameters; import org.jeasy.rules.core.DefaultRulesEngine; import org.jeasy.rules.core.InferenceRulesEngine; -import org.jeasy.rules.core.RulesEngineParameters; + import org.jeasy.rules.mvel.MVELRule; import org.jeasy.rules.mvel.MVELRuleFactory; -import org.jeasy.rules.support.YamlRuleDefinitionReader; + +import org.jeasy.rules.support.reader.YamlRuleDefinitionReader; import org.joda.time.LocalDate; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.smartregister.anc.library.YamlRuleDefinitionReaderExt; import org.smartregister.anc.library.rule.AlertRule; import org.smartregister.anc.library.rule.ContactRule; import org.smartregister.anc.library.util.ANCFormUtils; @@ -51,14 +55,92 @@ public class AncRulesEngineHelper extends RulesEngineHelper { private final RulesEngine defaultRulesEngine; private final Map ruleMap; private JSONObject mJsonObject = new JSONObject(); - private final YamlRuleDefinitionReader yamlRuleDefinitionReader = new YamlRuleDefinitionReader(); + private final YamlRuleDefinitionReaderExt yamlRuleDefinitionReader = new YamlRuleDefinitionReaderExt(); private final MVELRuleFactory mvelRuleFactory = new MVELRuleFactory(yamlRuleDefinitionReader); public AncRulesEngineHelper(Context context) { this.context = context; - this.inferentialRulesEngine = new InferenceRulesEngine(); + + InferenceRulesEngine rulesEngine = new InferenceRulesEngine(); + rulesEngine.registerRuleListener(new RuleListener() { + @Override + public boolean beforeEvaluate(Rule rule, Facts facts) { + Timber.e("Putting facts in beforeExecute"); + HashMap myMap = new HashMap<>(); + Map iterationFacts = facts.asMap(); + for(String key: iterationFacts.keySet() ) + { + myMap.put(key, iterationFacts.get(key)); + } + + facts.put("facts", myMap); + return true; + } + + @Override + public void onSuccess(Rule rule, Facts facts) { + Timber.e("Putting facts in onSuccess"); + HashMap myMap = facts.get("facts"); + + for (String key : + myMap.keySet()) { + facts.put(key, myMap.get(key)); + } + + facts.remove("facts"); + + + } + + @Override + public void onFailure(Rule rule, Facts facts, Exception exception) { + + Timber.e("Putting facts in onFailure"); + facts.remove("facts"); + + } + }); + + this.inferentialRulesEngine = rulesEngine; RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true); this.defaultRulesEngine = new DefaultRulesEngine(parameters); + + ((DefaultRulesEngine) this.defaultRulesEngine).registerRuleListener(new RuleListener() { + @Override + public void beforeExecute(Rule rule, Facts facts) { +// Timber.e("Putting facts in beforeExecute"); +// facts.put("facts", facts); + + Timber.e("Putting facts in beforeExecute"); + HashMap myMap = new HashMap<>(); + Map iterationFacts = facts.asMap(); + for(String key: iterationFacts.keySet() ) + { + myMap.put(key, iterationFacts.get(key)); + } + + facts.put("facts", myMap); + } + + @Override + public void onSuccess(Rule rule, Facts facts) { + Timber.e("Putting facts in onSuccess"); + HashMap myMap = facts.get("facts"); + + for (String key : + myMap.keySet()) { + facts.put(key, myMap.get(key)); + } + + facts.remove("facts"); + } + + @Override + public void onFailure(Rule rule, Facts facts, Exception exception) { + Timber.e("Putting facts in onFailure"); + facts.remove("facts"); + } + }); this.ruleMap = new HashMap<>(); } @@ -129,7 +211,8 @@ public boolean getRelevance(Facts relevanceFacts, String rule) { relevanceFacts.put(RuleConstant.IS_RELEVANT, false); Rules rules = new Rules(); - Rule mvelRule = new MVELRule().name(UUID.randomUUID().toString()).when(rule).then("isRelevant = true;"); + Rule mvelRule = new MVELRule().name(UUID.randomUUID().toString()).when(rule) + .then("facts.isRelevant = true;"); rules.register(mvelRule); processDefaultRules(rules, relevanceFacts); diff --git a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java index b60836396..f3bcdd7b3 100644 --- a/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java +++ b/opensrp-anc/src/main/java/org/smartregister/anc/library/util/Utils.java @@ -24,8 +24,8 @@ import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; -import com.itextpdf.layout.property.HorizontalAlignment; -import com.itextpdf.layout.property.TextAlignment; +import com.itextpdf.layout.properties.HorizontalAlignment; +import com.itextpdf.layout.properties.TextAlignment; import com.vijay.jsonwizard.activities.JsonFormActivity; import com.vijay.jsonwizard.constants.JsonFormConstants; import com.vijay.jsonwizard.rules.RuleConstant; diff --git a/reference-app/build.gradle b/reference-app/build.gradle index 392b5b4a6..a5c01dc37 100644 --- a/reference-app/build.gradle +++ b/reference-app/build.gradle @@ -28,7 +28,7 @@ jacoco { // This variables are used by the version code & name generators ext.versionMajor = 1 ext.versionMinor = 6 -ext.versionPatch = 15 +ext.versionPatch = 16 ext.versionClassifier = null ext.isSnapshot = false ext.minimumSdkVersion = androidMinSdkVersion @@ -233,7 +233,8 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' def powerMockVersion = '2.0.7' implementation project(":opensrp-anc") - implementation('org.smartregister:opensrp-client-native-form:3.1.1-SNAPSHOT@aar') { + implementation 'com.jakewharton.timber:timber:4.7.1' + implementation('org.smartregister:opensrp-client-native-form:3.1.5-LOCAL-SNAPSHOT@aar') { transitive = true exclude group: 'com.android.support', module: 'recyclerview-v7' exclude group: 'com.android.support', module: 'appcompat-v7' @@ -281,11 +282,11 @@ dependencies { exclude group: 'com.android.support', module: 'cardview-v7' exclude group: 'com.android.support', module: 'support-v4' } - implementation group: 'org.apache.commons', name: 'commons-text', version: '1.9' + implementation group: 'org.apache.commons', name: 'commons-text', version: '1.10.0' annotationProcessor 'com.jakewharton:butterknife:10.2.3' implementation 'net.zetetic:android-database-sqlcipher:4.4.0@aar' implementation 'commons-validator:commons-validator:1.7' - implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.google.code.gson:gson:2.8.9' implementation 'org.greenrobot:eventbus:3.2.0' annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.2.0' implementation 'com.google.guava:guava:30.0-jre' @@ -301,10 +302,8 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.0' - implementation group: 'org.yaml', name: 'snakeyaml', version: '1.27' + implementation group: 'org.yaml', name: 'snakeyaml', version: '1.31' implementation 'de.hdodenhof:circleimageview:3.1.0' - implementation 'org.jeasy:easy-rules-core:3.3.0' - implementation 'org.jeasy:easy-rules-mvel:3.3.0' implementation 'com.flurry.android:analytics:11.6.0@aar' implementation 'com.flurry.android:analytics:11.6.0@aar' implementation 'androidx.multidex:multidex:2.0.1' diff --git a/reference-app/src/main/assets/app.properties b/reference-app/src/main/assets/app.properties index e523b6aaa..4187ec63e 100644 --- a/reference-app/src/main/assets/app.properties +++ b/reference-app/src/main/assets/app.properties @@ -6,4 +6,5 @@ CAN_SAVE_INITIAL_SITE_SETTING=true MAX_CONTACT_SCHEDULE_DISPLAYED=5 language.switching.enabled=true widget.value.translated=true +easy_rule.v3.compatibility=true DEFAULT_COUNTRY_ID=02ebbc84-5e29-4cd5-9b79-c594058923e9 diff --git a/reference-app/src/main/java/org/smartregister/anc/application/AncApplication.java b/reference-app/src/main/java/org/smartregister/anc/application/AncApplication.java index 85dd5281c..14e17df24 100644 --- a/reference-app/src/main/java/org/smartregister/anc/application/AncApplication.java +++ b/reference-app/src/main/java/org/smartregister/anc/application/AncApplication.java @@ -13,6 +13,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics; import com.vijay.jsonwizard.NativeFormLibrary; +import org.slf4j.LoggerFactory; import org.smartregister.Context; import org.smartregister.CoreLibrary; import org.smartregister.P2POptions; @@ -37,6 +38,8 @@ import org.smartregister.view.activity.DrishtiApplication; import org.smartregister.view.receiver.TimeChangedBroadcastReceiver; +import java.util.logging.Logger; + import timber.log.Timber; /** @@ -128,6 +131,11 @@ public void onCreate() { } + @Override + public void initializeCrashLyticsTree() { + Timber.plant((timber.log.Timber.Tree) new Timber.DebugTree()); + } + private void setDefaultLanguage() { try { Utils.saveLanguage("en");