Skip to content

Commit

Permalink
Refactor ♻️ + Fix Build 💚
Browse files Browse the repository at this point in the history
- Refactor rollback implementation
- Refactor + Clean up tests

Co-authored-by: Hilary Baraka Egesa <[email protected]>
  • Loading branch information
ndegwamartin and hilpitome committed Jul 29, 2024
1 parent f2d5404 commit 313e846
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.annotations.VisibleForTesting;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.smartregister.util.FCTConstants;
import org.smartregister.util.FctUtils;
import picocli.CommandLine;
Expand Down Expand Up @@ -69,7 +70,7 @@ public void run() {
}
if (extractionType != null && !Arrays.asList(extractionTypes).contains(extractionType)) {
throw new RuntimeException(
"extractionTypes should either be `all`, `configs`, `fhir_content`");
"extractionTypes should either be " + StringUtils.join(extractionTypes, ", "));
}

if (Objects.equals(mode, "extract")) {
Expand All @@ -80,16 +81,11 @@ public void run() {
FctUtils.printInfo(String.format("Input file \u001b[35m%s\u001b[0m", resourceFile));

try {
Path translationsDirectoryPath = inputFilePath.getParent().resolve("translations");

if (Objects.equals(extractionType, "configs")) {
tempsConfig = Files.createTempDirectory("configs");
} else tempsConfig = null;
if (!Files.exists(translationsDirectoryPath))
Files.createDirectories(translationsDirectoryPath);
if (translationFile == null) {
translationFile = translationsDirectoryPath + "/strings_default.properties";
}

// Check if the input path is a directory or a JSON file
if (Files.isDirectory(inputFilePath)) {
if (Objects.equals(extractionType, "configs") || inputFilePath.endsWith("configs")) {
Expand Down Expand Up @@ -443,7 +439,7 @@ private static void replaceTargetFieldsWithHashedValues(
JsonNode node,
Set<String> targetFields,
Map<String, String> textToHash,
Path filePath,
Path tempFilePath,
Path tempConfigsDir)
throws NoSuchAlgorithmException, IOException {

Expand All @@ -468,7 +464,7 @@ private static void replaceTargetFieldsWithHashedValues(
if (fieldValue.isObject() || fieldValue.isArray()) {
// Recursively update nested objects or arrays
replaceTargetFieldsWithHashedValues(
fieldValue, targetFields, textToHash, filePath, tempConfigsDir);
fieldValue, targetFields, textToHash, tempFilePath, tempConfigsDir);
}
}
} else if (node.isArray()) {
Expand All @@ -478,14 +474,11 @@ private static void replaceTargetFieldsWithHashedValues(
if (arrayElement.isObject() || arrayElement.isArray()) {
// Recursively update nested objects or arrays
replaceTargetFieldsWithHashedValues(
arrayElement, targetFields, textToHash, filePath, tempConfigsDir);
arrayElement, targetFields, textToHash, tempFilePath, tempConfigsDir);
}
}
}

String configFileSubDirectory = filePath.subpath(2, filePath.getNameCount()).toString();

Path tempFilePath = tempConfigsDir.resolve(configFileSubDirectory);
// Write the updated JSON to temp file
try (BufferedWriter writer = Files.newBufferedWriter(tempFilePath, StandardCharsets.UTF_8)) {
ObjectMapper objectMapper = new ObjectMapper();
Expand Down Expand Up @@ -551,62 +544,13 @@ private static void writePropertiesFile(Properties properties, String filePath)
}
}

public void copyDirectoryContent(Path sourceDir, Path destinationDir) {
try {
Files.walkFileTree(
sourceDir,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
Path targetDir = destinationDir.resolve(sourceDir.relativize(dir));
if (!Files.exists(targetDir)) {
Files.createDirectory(targetDir);
}
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {

Files.copy(
file,
destinationDir.resolve(sourceDir.relativize(file)),
StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
@VisibleForTesting
protected void copyDirectoryContent(Path sourceDir, Path destinationDir) {
FctUtils.copyDirectoryContent(sourceDir, destinationDir);
}

public void deleteDirectoryRecursively(Path dirPath) {

try {
// Delete the directory and its contents recursively
Files.walkFileTree(
dirPath,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});

System.out.println("Directory and its contents deleted successfully: " + dirPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
@VisibleForTesting
protected void deleteDirectoryRecursively(Path dirPath) {
FctUtils.deleteDirectoryRecursively(dirPath);
}
}
65 changes: 60 additions & 5 deletions efsity/src/main/java/org/smartregister/util/FctUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.HashMap;
Expand Down Expand Up @@ -176,6 +172,65 @@ public static <T extends IBaseResource> T getFhirResource(Class<T> t, String con
return iParser.parseResource(t, contentAsString);
}

public static void copyDirectoryContent(Path sourceDir, Path destinationDir) {
try {
Files.walkFileTree(
sourceDir,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
Path targetDir = destinationDir.resolve(sourceDir.relativize(dir));
if (!Files.exists(targetDir)) {
Files.createDirectory(targetDir);
}
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {

Files.copy(
file,
destinationDir.resolve(sourceDir.relativize(file)),
StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static void deleteDirectoryRecursively(Path dirPath) {

try {
// Delete the directory and its contents recursively
Files.walkFileTree(
dirPath,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});

System.out.println("Directory and its contents deleted successfully: " + dirPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static final class Constants {
public static final String HL7_FHIR_PACKAGE = "hl7.fhir.r4.core";
public static final String HL7_FHIR_PACKAGE_VERSION = "4.0.1";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,31 @@
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Properties;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.smartregister.util.FctUtils;

public class TranslateCommandTest {

private Path tempCleanConfigsFolder;
private TranslateCommand translateCommand;

@BeforeEach
public void setUp() {
public void setUp() throws IOException {

tempCleanConfigsFolder = Files.createTempDirectory("temp_clean_configs_folder");
Path cleanConfigsFolder = Paths.get("src/test/resources/clean_configs_folder");
FctUtils.copyDirectoryContent(cleanConfigsFolder, tempCleanConfigsFolder);

translateCommand = new TranslateCommand();
}

@AfterEach
public void tearDown() {
FctUtils.deleteDirectoryRecursively(tempCleanConfigsFolder);
}

@Test
public void testRunInvalidMode() {
translateCommand.mode = "invalid_mode";
Expand Down Expand Up @@ -70,33 +81,41 @@ public void testRunExtract() throws IOException {

@Test
public void testRunExtractConfigWithCleanConfigsFolderRunsSuccessfully() throws IOException {
Path cleanConfigsFolder = Paths.get("src/test/resources/clean_configs_folder");
TranslateCommand translateCommandForCopyingTemp = new TranslateCommand();

Path cleanConfigsFolder = tempCleanConfigsFolder;
Path backupFolder = Files.createTempDirectory("temp_back_up_dir");
translateCommandForCopyingTemp.copyDirectoryContent(cleanConfigsFolder, backupFolder);
FctUtils.copyDirectoryContent(cleanConfigsFolder, backupFolder);
TranslateCommand translateCommandSpy = Mockito.spy(translateCommand);
translateCommandSpy.mode = "extract";
translateCommandSpy.extractionType = "configs";
translateCommandSpy.resourceFile = cleanConfigsFolder.toString();

Path frPropertiesPathOriginal = Paths.get("src/test/resources/strings_fr.properties");
Path frPropertiesPathTest =
tempCleanConfigsFolder.resolve(frPropertiesPathOriginal.getFileName());
Files.copy(frPropertiesPathOriginal, frPropertiesPathTest, StandardCopyOption.REPLACE_EXISTING);
translateCommandSpy.translationFile = frPropertiesPathTest.toString();
translateCommandSpy.run();
Mockito.verify(translateCommandSpy, Mockito.atLeast(2))
.copyDirectoryContent(Mockito.any(), Mockito.any());
Mockito.verify(translateCommandSpy, Mockito.atLeast(1))
.deleteDirectoryRecursively(Mockito.any());
// restore clean_configs_folder
translateCommandForCopyingTemp.copyDirectoryContent(backupFolder, cleanConfigsFolder);
}

@Test
public void testRunExtractConfigWithDirtyConfigsFolderDeletesTempFileOnFailure()
throws RuntimeException {
Path cleanConfigsFolder = Paths.get("src/test/resources/dirty_configs_folder");
Path dirtyConfigsFolder = Paths.get("src/test/resources/dirty_configs_folder");
TranslateCommand translateCommandSpy = Mockito.spy(translateCommand);
translateCommandSpy.mode = "extract";
translateCommandSpy.extractionType = "configs";
translateCommandSpy.resourceFile = cleanConfigsFolder.toString();
translateCommandSpy.resourceFile = dirtyConfigsFolder.toString();

Path frPropertiesPath = Paths.get("src/test/resources/strings_fr.properties");
translateCommandSpy.translationFile = frPropertiesPath.toString();

assertThrows(RuntimeException.class, translateCommandSpy::run);

Mockito.verify(translateCommandSpy, Mockito.atLeast(1))
.copyDirectoryContent(Mockito.any(), Mockito.any());
Mockito.verify(translateCommandSpy, Mockito.atLeast(1))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"DO NOT REMOVE _ MALFORMED JSON CONTENT FOR TESTING",
"appId": "app_id_name",
"configType": "profile",
"id": "config_id",
Expand Down Expand Up @@ -48,7 +49,7 @@
],
"overFlowMenuItems": [
{
"title": "Edit Client Info",u
"title": "Edit Client Info",
"titleColor": "@{patientTextColor}",
"visible": "true",
"enabled": "@{patientActive}",
Expand Down

0 comments on commit 313e846

Please sign in to comment.