Skip to content

Commit

Permalink
Merge pull request #373 from OpenSRP/367-add-mls-support-to-native-forms
Browse files Browse the repository at this point in the history
Add MLS to native forms
  • Loading branch information
vincent-karuri authored Mar 13, 2020
2 parents 0895e9c + 4c152c3 commit 5011d67
Show file tree
Hide file tree
Showing 21 changed files with 1,066 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import java.util.List;
import java.util.Map;

import static com.vijay.jsonwizard.utils.NativeFormLangUtils.getTranslatedString;

abstract class JsonFormBaseActivity extends MultiLanguageActivity implements OnFieldsInvalid {
protected static final String TAG = JsonFormActivity.class.getSimpleName();
protected static final String JSON_STATE = "jsonState";
Expand Down Expand Up @@ -69,7 +71,7 @@ protected void onCreate(Bundle savedInstanceState) {
lifeCycleListeners = new ArrayList<>();
isFormFragmentInitialized = false;
if (savedInstanceState == null) {
init(getIntent().getStringExtra(JsonFormConstants.JSON_FORM_KEY.JSON));
init(getForm());
initializeFormFragment();
onFormStart();
this.form = extractForm(getIntent().getSerializableExtra(JsonFormConstants.JSON_FORM_KEY.FORM));
Expand All @@ -82,6 +84,14 @@ protected void onCreate(Bundle savedInstanceState) {
}
}

private String getForm() {
String jsonForm = getIntent().getStringExtra(JsonFormConstants.JSON_FORM_KEY.JSON);
if (getIntent().getBooleanExtra(JsonFormConstants.PERFORM_FORM_TRANSLATION, false)) {
jsonForm = getTranslatedString(jsonForm);
}
return jsonForm;
}

public void init(String json) {
try {
setmJSONObject(new JSONObject(json));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,14 @@ public class JsonFormConstants {
public static final String FALSE = "false";
public static final String DISPLAY_SCROLL_BARS = "display_scroll_bars";
public static final String SKIP_BLANK_STEPS = "skip_blank_steps";
public static final String MULTI_SELECT_LIST ="multi_select_list" ;
public static final String MULTI_SELECT_LIST = "multi_select_list";
public static final String FORM_VERSION = "form_version";
public static final String LABEL_CONSTRAINT_LAYOUT = "label_constraint_layout";
public static final String STEP = "step";
public static final String RULE = "rule/";
public static final String REFERENCE_EDIT_TEXT = "reference_edit_text";
public static final String DISPLAY_LABEL = "display_label";
public static final String PERFORM_FORM_TRANSLATION = "perform_form_translation";

public interface MultiSelectUtils {
String IS_HEADER = "isHeader";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public JsonFormInteractor(@Nullable Map<String, FormWidgetFactory> additionalWid
}
}


public static JsonFormInteractor getInstance(@Nullable Map<String, FormWidgetFactory> additionalWidgetsMap) {
if (INSTANCE == null) {
INSTANCE = new JsonFormInteractor(additionalWidgetsMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* Created by vijay on 24-05-2015.
*/
public interface FormWidgetFactory {

List<View> getViewsFromJson(String stepName, Context context, JsonFormFragment formFragment, JSONObject jsonObject, CommonListener listener, boolean popup) throws Exception;

List<View> getViewsFromJson(String stepName, Context context, JsonFormFragment formFragment, JSONObject jsonObject, CommonListener listener) throws Exception;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
import android.util.Log;

import java.util.Locale;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import timber.log.Timber;

public class NativeFormLangUtils {

Expand All @@ -31,4 +36,44 @@ public static Context setAppLocale(Context ctx, String language) {

return context;
}

/**
* Performs translation on an interpolated {@param str}
* i.e. a String containing tokens in the format {{string_name}},
* replacing these tokens with their corresponding values for the current Locale
*
* @param str
* @return
*/
public static String getTranslatedString(String str) {
String translationsFileName = getTranslationsFileName(str);
if (translationsFileName.isEmpty()) {
Timber.e("Could not translate the String. Translation file name is not specified!");
return str;
}

ResourceBundle mlsResourceBundle = ResourceBundle.getBundle(getTranslationsFileName(str));

StringBuffer stringBuffer = new StringBuffer();
Pattern interpolatedStringPattern = Pattern.compile("\\{\\{([a-zA-Z_0-9\\.]+)\\}\\}");
Matcher matcher = interpolatedStringPattern.matcher(str);
while (matcher.find()) {
matcher.appendReplacement(stringBuffer, mlsResourceBundle.getString(matcher.group(1)));
}
matcher.appendTail(stringBuffer);

return stringBuffer.toString();
}

/**
* Gets the name of the translation file to be applied to the {@param str}
*
* @param str
* @return
*/
public static String getTranslationsFileName(String str) {
Pattern propertiesFileNamePattern = Pattern.compile("\"?properties_file_name\"?: ?\"([a-zA-Z_0-9\\.]+)\"");
Matcher matcher = propertiesFileNamePattern.matcher(str);
return matcher.find() ? matcher.group(1) : "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -52,12 +51,14 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import timber.log.Timber;

import static com.vijay.jsonwizard.constants.JsonFormConstants.KEY;
import static com.vijay.jsonwizard.utils.NativeFormLangUtils.getTranslatedString;

public class Utils {
private static ProgressDialog progressDialog;
Expand Down Expand Up @@ -482,18 +483,59 @@ private static String cleanConditionString(String conditionStringRaw) {

public static Iterable<Object> readYamlFile(String fileName, Context context) {
Yaml yaml = new Yaml();
InputStreamReader inputStreamReader;
Iterable<Object> objectIterable = null;
try {
inputStreamReader = new InputStreamReader(context.getAssets().open(fileName));
objectIterable = yaml.loadAll(inputStreamReader);
String translatedYamlStr = getTranslatedYamlFile(fileName, context);
objectIterable = yaml.loadAll(translatedYamlStr);
} catch (IOException e) {
Timber.e(e);
}

return objectIterable;
}

/**
* Translates a yaml file specified by {@param fileName} and returns its String representation
*
* @param fileName
* @param context
*
* @return Translated Yaml file in its String representation
*
* @throws IOException
*/
public static String getTranslatedYamlFile(String fileName, Context context) throws IOException {
return getTranslatedString(getAssetFileAsString(fileName, context));
}

/**
*
* Gets a file specified by {@param fileName} from the assets folder as a String
*
* @param fileName
* @param context
*
* @return A file from the assets folder as a String
*
* @throws IOException
*/
public static String getAssetFileAsString(String fileName, Context context) throws IOException {
InputStream inputStream = context.getAssets().open(fileName);
return convertStreamToString(inputStream);
}

/**
* Converts an {@link InputStream} into a String
*
* @param inputStream
*
* @return String representation of an {@link InputStream}
*/
public static String convertStreamToString(InputStream inputStream) {
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}

public static void buildRulesWithUniqueId(JSONObject element, String uniqueId, String ruleType, WidgetArgs widgetArgs, Map<String, List<Map<String, Object>>> rulesFileMap) throws JSONException {
JSONObject rules = element.optJSONObject(ruleType);
if (rules != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.vijay.jsonwizard.utils;

import android.content.Context;
import android.content.res.AssetManager;

import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;

import static com.vijay.jsonwizard.utils.Utils.convertStreamToString;
import static com.vijay.jsonwizard.utils.Utils.getTranslatedYamlFile;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

/**
* Created by Vincent Karuri on 20/02/2020
*/
public class NativeFormLangUtilsTest {

@Test
public void testJsonFormTranslationShouldTranslateForm() {
Locale.setDefault(new Locale("id"));
String expectedJsonForm = getFileContentsAsString("test_form_translation_in");
String interpolatedJsonForm = getFileContentsAsString("test_form_translation_interpolated");
assertEquals(expectedJsonForm, NativeFormLangUtils.getTranslatedString(interpolatedJsonForm));

Locale.setDefault(new Locale("en", "US"));
expectedJsonForm = getFileContentsAsString("test_form_translation_en_US");
assertEquals(expectedJsonForm, NativeFormLangUtils.getTranslatedString(interpolatedJsonForm));
}

@Test
public void testYamlFileTranslationShouldTranslateYamlFile() throws IOException {
Context context = mockAssetManager("test_yaml_translation_interpolated");
Locale.setDefault(new Locale("en", "US"));
String translatedYamlStr = getTranslatedYamlFile("file_name", context);
assertEquals(getFileContentsAsString("test_yaml_translation_en_US"), translatedYamlStr);
}

@Test
public void testJsonFormTranslationShouldReturnUntranslatedForm() {
Locale.setDefault(new Locale("id"));
String interpolatedJsonForm = getFileContentsAsString("test_form_translation_interpolated_missing_translations");
assertEquals(interpolatedJsonForm, NativeFormLangUtils.getTranslatedString(interpolatedJsonForm));
}

@Test
public void testYamlFileTranslationShouldReturnUntranslatedYamlFile() throws IOException {
Context context = mockAssetManager("test_yaml_translation_interpolated_missing_translations");
Locale.setDefault(new Locale("en", "US"));
String translatedYamlStr = getTranslatedYamlFile("file_name", context);
assertEquals(getFileContentsAsString("test_yaml_translation_interpolated_missing_translations"), translatedYamlStr);
}

private Context mockAssetManager(String yamlFilePath) throws IOException {
Context context = mock(Context.class);
AssetManager assetManager = mock(AssetManager.class);
doReturn(getTestResource(yamlFilePath))
.when(assetManager)
.open(eq("file_name"));
doReturn(assetManager).when(context).getAssets();
return context;
}

private InputStream getTestResource(String filePath) {
return getClass().getClassLoader().getResourceAsStream(filePath);
}

private String getFileContentsAsString(String filePath) {
return convertStreamToString(getTestResource(filePath));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
step1.title = New client record
step1.previous_label = SAVE AND EXIT
step1.submit_label = SAVE
step1.patient_name_label.text = Name
step1.sex.label = Gender
step1.sex.options.Female.text = Female
step1.sex.options.Male.text = Male
step1.sex.v_required.err = Please specify gender
step1.patient_dob.hint = Patient's date of birth
step1.patient_dob.duration.label = Age
step1.patient_occupation_label.text = Occupation
step1.been_treated.label = Has been treated for malaria in the past 3 months?
step1.been_treated.options.Yes.text = Yes
step1.been_treated.options.No.text = No
step1.been_treated.options.not_answered.text = Not Answered
step1.been_treated.v_required.err = Has the patient been treated for malaria in the past 3 months?
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
step1.title = Data Pasien Baru
step1.previous_label = SIMPAN DAN KELUAR
step1.submit_label = SIMPAN
step1.patient_name_label.text = Nama
step1.sex.label = Jenis kelamin pasien
step1.sex.options.Female.text = Perempuan
step1.sex.options.Male.text = Laki-laki
step1.sex.v_required.err = Silakan sebutkan jenis kelamin
step1.patient_dob.hint = Tanggal lahir pasien
step1.patient_dob.duration.label = Usia
step1.patient_occupation_label.text = Pekerjaan pasien
step1.been_treated.label = Pernah dirawat karena Malaria dalam 3 bulan terakhir?
step1.been_treated.options.Yes.text = Ya
step1.been_treated.options.No.text = Tidak
step1.been_treated.options.not_answered.text = Tidak dijawab
step1.been_treated.v_required.err = Pernahkah pasien dirawat karena malaria dalam 3 bulan terakhir?
Loading

0 comments on commit 5011d67

Please sign in to comment.