-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BXC-4678 chompb command to list projects (#105)
* list_projects service and command * fix tests * imageFormats constant, add image formats, lowercase file extension, allowedActions return list, add test, remove jackson.version * allowedAction JsonArray, fix imageFormats, fix test * allowedActions ArrayNode, fix tests * add try/catch * fix project path * fix tests
- Loading branch information
Showing
5 changed files
with
494 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
src/main/java/edu/unc/lib/boxc/migration/cdm/ListProjectsCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package edu.unc.lib.boxc.migration.cdm; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import edu.unc.lib.boxc.migration.cdm.exceptions.MigrationException; | ||
import edu.unc.lib.boxc.migration.cdm.services.CdmFieldService; | ||
import edu.unc.lib.boxc.migration.cdm.services.CdmIndexService; | ||
import edu.unc.lib.boxc.migration.cdm.services.ListProjectsService; | ||
import edu.unc.lib.boxc.migration.cdm.services.ProjectPropertiesService; | ||
import edu.unc.lib.boxc.migration.cdm.services.SourceFileService; | ||
import org.slf4j.Logger; | ||
import picocli.CommandLine.Command; | ||
import picocli.CommandLine.ParentCommand; | ||
|
||
import java.io.IOException; | ||
import java.util.concurrent.Callable; | ||
|
||
import static edu.unc.lib.boxc.migration.cdm.util.CLIConstants.outputLogger; | ||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
/** | ||
* @author krwong | ||
*/ | ||
@Command(name = "list_projects", | ||
description = "List all chompb projects in a directory.") | ||
public class ListProjectsCommand implements Callable<Integer> { | ||
private static final Logger log = getLogger(ListProjectsCommand.class); | ||
|
||
@ParentCommand | ||
private CLIMain parentCommand; | ||
|
||
private CdmFieldService fieldService; | ||
private CdmIndexService indexService; | ||
private ProjectPropertiesService propertiesService; | ||
private SourceFileService sourceFileService; | ||
private ListProjectsService listProjectsService; | ||
|
||
@Override | ||
public Integer call() { | ||
try { | ||
initialize(); | ||
ObjectMapper mapper = new ObjectMapper(); | ||
JsonNode listProjects = listProjectsService.listProjects(parentCommand.getWorkingDirectory()); | ||
String prettyPrintList = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(listProjects); | ||
outputLogger.info(prettyPrintList); | ||
return 0; | ||
} catch(MigrationException | IllegalArgumentException e) { | ||
outputLogger.info("List projects failed: {}", e.getMessage()); | ||
return 1; | ||
} catch(Exception e) { | ||
log.error("Failed to list projects", e); | ||
outputLogger.info("List projects failed: {}", e.getMessage(), e); | ||
return 1; | ||
} | ||
} | ||
|
||
private void initialize() throws IOException { | ||
fieldService = new CdmFieldService(); | ||
indexService = new CdmIndexService(); | ||
indexService.setFieldService(fieldService); | ||
sourceFileService = new SourceFileService(); | ||
sourceFileService.setIndexService(indexService); | ||
propertiesService = new ProjectPropertiesService(); | ||
listProjectsService = new ListProjectsService(); | ||
listProjectsService.setFieldService(fieldService); | ||
listProjectsService.setIndexService(indexService); | ||
listProjectsService.setSourceFileService(sourceFileService); | ||
listProjectsService.setPropertiesService(propertiesService); | ||
} | ||
} |
156 changes: 156 additions & 0 deletions
156
src/main/java/edu/unc/lib/boxc/migration/cdm/services/ListProjectsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package edu.unc.lib.boxc.migration.cdm.services; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.SerializationFeature; | ||
import com.fasterxml.jackson.databind.node.ArrayNode; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; | ||
import edu.unc.lib.boxc.migration.cdm.exceptions.InvalidProjectStateException; | ||
import edu.unc.lib.boxc.migration.cdm.model.MigrationProject; | ||
import edu.unc.lib.boxc.migration.cdm.model.SourceFilesInfo; | ||
import org.apache.commons.io.FilenameUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.File; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* Service for listing all chompb projects in a given directory | ||
* @author krwong | ||
*/ | ||
public class ListProjectsService { | ||
private static final Logger log = LoggerFactory.getLogger(ListProjectsService.class); | ||
|
||
private CdmFieldService fieldService; | ||
private CdmIndexService indexService; | ||
private ProjectPropertiesService propertiesService; | ||
private SourceFileService sourceFileService; | ||
|
||
public static final String PROJECT_PATH = "projectPath"; | ||
public static final String STATUS = "status"; | ||
public static final String ALLOWED_ACTIONS = "allowedActions"; | ||
private static final Set<String> IMAGE_FORMATS = new HashSet<>(Arrays.asList("tif", "tiff", "jpeg", "jpg", "png", | ||
"gif", "pict", "bmp", "psd", "jp2", "nef", "crw", "cr2", "dng", "raf")); | ||
|
||
/** | ||
* List projects in given directory | ||
* @return jsonNode of projects | ||
*/ | ||
public JsonNode listProjects(Path directory) throws Exception { | ||
if (Files.notExists(directory)) { | ||
throw new InvalidProjectStateException("Path " + directory + " does not exist"); | ||
} | ||
|
||
// create JSON | ||
ObjectMapper mapper = new ObjectMapper(); | ||
mapper.registerModule(new JavaTimeModule()); | ||
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); | ||
ArrayNode arrayNode = mapper.createArrayNode(); | ||
|
||
for (File file : directory.toFile().listFiles()) { | ||
if (file.isDirectory()) { | ||
try { | ||
MigrationProject project = initializeProject(file.toPath()); | ||
|
||
Path projectPath = file.toPath().toAbsolutePath(); | ||
String projectStatus = status(project); | ||
ArrayNode allowedActions = mapper.valueToTree(allowedActions(project)); | ||
JsonNode projectProperties = mapper.readTree(project.getProjectPropertiesPath().toFile()); | ||
|
||
// add project info to JSON | ||
ObjectNode objectNode = mapper.createObjectNode(); | ||
objectNode.put(PROJECT_PATH, projectPath.toString()); | ||
objectNode.put(STATUS, projectStatus); | ||
objectNode.putArray(ALLOWED_ACTIONS).addAll(allowedActions); | ||
objectNode.set("projectProperties", projectProperties); | ||
arrayNode.add(objectNode); | ||
} catch (Exception e) { | ||
log.error(e.getMessage()); | ||
} | ||
} | ||
} | ||
log.debug(arrayNode.toString()); | ||
|
||
return arrayNode; | ||
} | ||
|
||
/** | ||
* Condensed representation of the phase a project is in | ||
* possible values: initialized, indexed, sources_mapped, sips_generated, ingested, archived | ||
* @return project status | ||
*/ | ||
private String status(MigrationProject project) { | ||
String status = null; | ||
|
||
// TODO: add archived state | ||
// if () { | ||
// status = "archived"; | ||
// } | ||
if (!project.getProjectProperties().getSipsSubmitted().isEmpty()) { | ||
status = "ingested"; | ||
} else if (project.getProjectProperties().getSipsGeneratedDate() != null) { | ||
status = "sips_generated"; | ||
} else if (project.getProjectProperties().getSourceFilesUpdatedDate() != null) { | ||
status = "sources_mapped"; | ||
} else if (project.getProjectProperties().getIndexedDate() != null) { | ||
status = "indexed"; | ||
} else if (Files.exists(project.getProjectPropertiesPath())) { | ||
status = "initialized"; | ||
} | ||
|
||
return status; | ||
} | ||
|
||
/** | ||
* Tell other applications (boxc) what processes are supported by the project | ||
* crop_color_bars: populated if source files are mapped and if project contains any images (based off source file extensions) | ||
* @return allowed_actions | ||
*/ | ||
private List<String> allowedActions(MigrationProject project) throws Exception { | ||
List<String> allowedActions = new ArrayList<>(); | ||
|
||
if (project.getProjectProperties().getSourceFilesUpdatedDate() != null) { | ||
SourceFilesInfo info = sourceFileService.loadMappings(); | ||
if (info.getMappings().stream().map(entry -> | ||
FilenameUtils.getExtension(entry.getFirstSourcePath().toString().toLowerCase())) | ||
.anyMatch(IMAGE_FORMATS::contains)) { | ||
allowedActions.add("crop_color_bars"); | ||
} | ||
} | ||
return allowedActions; | ||
} | ||
|
||
public MigrationProject initializeProject(Path path) throws Exception { | ||
MigrationProject project = MigrationProjectFactory.loadMigrationProject(path); | ||
propertiesService.setProject(project); | ||
sourceFileService.setProject(project); | ||
indexService.setProject(project); | ||
fieldService.setProject(project); | ||
|
||
return project; | ||
} | ||
|
||
public void setFieldService(CdmFieldService fieldService) { | ||
this.fieldService = fieldService; | ||
} | ||
|
||
public void setIndexService(CdmIndexService indexService) { | ||
this.indexService = indexService; | ||
} | ||
|
||
public void setPropertiesService(ProjectPropertiesService propertiesService) { | ||
this.propertiesService = propertiesService; | ||
} | ||
|
||
public void setSourceFileService(SourceFileService sourceFileService) { | ||
this.sourceFileService = sourceFileService; | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
src/test/java/edu/unc/lib/boxc/migration/cdm/ListProjectsCommandIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package edu.unc.lib.boxc.migration.cdm; | ||
|
||
import edu.unc.lib.boxc.migration.cdm.model.MigrationProject; | ||
import edu.unc.lib.boxc.migration.cdm.services.ListProjectsService; | ||
import edu.unc.lib.boxc.migration.cdm.services.MigrationProjectFactory; | ||
import edu.unc.lib.boxc.migration.cdm.test.BxcEnvironmentHelper; | ||
import edu.unc.lib.boxc.migration.cdm.test.CdmEnvironmentHelper; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.nio.file.Path; | ||
|
||
public class ListProjectsCommandIT extends AbstractCommandIT { | ||
private static final String PROJECT_ID_2 = "proj2"; | ||
|
||
@BeforeEach | ||
public void setup() throws Exception { | ||
initProjectAndHelper(); | ||
setupChompbConfig(); | ||
} | ||
|
||
@Test | ||
public void invalidDirectoryTest() throws Exception { | ||
String[] args = new String[] { | ||
"-w", String.valueOf(Path.of("test")), | ||
"list_projects" }; | ||
executeExpectFailure(args); | ||
|
||
assertOutputContains("does not exist"); | ||
} | ||
|
||
@Test | ||
public void listProjectsTest() throws Exception { | ||
String[] args = new String[] { | ||
"-w", String.valueOf(baseDir), | ||
"list_projects" }; | ||
executeExpectSuccess(args); | ||
|
||
assertOutputContains("\"" + ListProjectsService.PROJECT_PATH + "\" : \"" + Path.of(baseDir + "/" + PROJECT_ID) + "\""); | ||
assertOutputContains("\"" + ListProjectsService.STATUS + "\" : \"initialized\""); | ||
assertOutputContains("\"" + ListProjectsService.ALLOWED_ACTIONS + "\" : [ ]"); | ||
assertOutputContains("\"name\" : \"" + PROJECT_ID + "\""); | ||
} | ||
|
||
@Test | ||
public void listMultipleProjectsTest() throws Exception { | ||
project = MigrationProjectFactory.createMigrationProject( | ||
tmpFolder, PROJECT_ID_2, null, "user", CdmEnvironmentHelper.DEFAULT_ENV_ID, | ||
BxcEnvironmentHelper.DEFAULT_ENV_ID, MigrationProject.PROJECT_SOURCE_CDM); | ||
|
||
String[] args = new String[] { | ||
"-w", String.valueOf(baseDir), | ||
"list_projects" }; | ||
executeExpectSuccess(args); | ||
|
||
assertOutputContains("\"" + ListProjectsService.PROJECT_PATH + "\" : \"" + | ||
Path.of(baseDir + "/" + PROJECT_ID) + "\""); | ||
assertOutputContains("\"" + ListProjectsService.PROJECT_PATH + "\" : \"" + | ||
Path.of(baseDir + "/" + PROJECT_ID_2) + "\""); | ||
assertOutputContains("\""+ ListProjectsService.STATUS + "\" : \"initialized\""); | ||
assertOutputContains("\"" + ListProjectsService.ALLOWED_ACTIONS + "\" : [ ]"); | ||
assertOutputContains("\"name\" : \"" + PROJECT_ID + "\""); | ||
assertOutputContains("\"name\" : \"" + PROJECT_ID_2 + "\""); | ||
} | ||
} |
Oops, something went wrong.