From 150193ccb47d1b85802990f7acd7e8bac314ad53 Mon Sep 17 00:00:00 2001 From: bourgesl <bourges.laurent@gmail.com> Date: Tue, 27 Mar 2018 12:18:49 +0200 Subject: [PATCH] improved remove pipeline (more robust if some folders are missing + delete orphan projects) --- src/main/java/fr/osug/DOIApplication.java | 8 +- .../java/fr/osug/doi/PipelineCommonData.java | 13 +- src/main/java/fr/osug/doi/ProjectConfig.java | 172 ++++++++++-------- src/main/java/fr/osug/doi/RemovePipeline.java | 72 ++++++-- .../java/fr/osug/doi/service/DoiService.java | 38 +++- .../java/fr/osug/doi/DOITextToXmlTest.java | 2 +- 6 files changed, 203 insertions(+), 102 deletions(-) diff --git a/src/main/java/fr/osug/DOIApplication.java b/src/main/java/fr/osug/DOIApplication.java index 2c557d3..9042489 100644 --- a/src/main/java/fr/osug/DOIApplication.java +++ b/src/main/java/fr/osug/DOIApplication.java @@ -208,7 +208,7 @@ public class DOIApplication { if (Character.toLowerCase(ch) == 'y') { // Staging only - final AbstractPipeline<?> pipeline = doiConfig.getRemovePipeline(getProjectConfig(project), doiPattern); + final AbstractPipeline<?> pipeline = doiConfig.getRemovePipeline(getProjectConfig(project, false), doiPattern); pipeline.execute(); } else { logger.info("Action cancelled ({})", ch); @@ -238,7 +238,11 @@ public class DOIApplication { } private ProjectConfig getProjectConfig(final String project) throws IOException { - return new ProjectConfig(doiConfig.getPathConfig(), project); + return getProjectConfig(project, true); + } + + private ProjectConfig getProjectConfig(final String project, final boolean required) throws IOException { + return new ProjectConfig(doiConfig.getPathConfig(), project, required); } /** Show command arguments help. */ diff --git a/src/main/java/fr/osug/doi/PipelineCommonData.java b/src/main/java/fr/osug/doi/PipelineCommonData.java index 032ccbf..a74d437 100644 --- a/src/main/java/fr/osug/doi/PipelineCommonData.java +++ b/src/main/java/fr/osug/doi/PipelineCommonData.java @@ -38,7 +38,12 @@ public class PipelineCommonData { projectConfigs.put(projectConfig.getProjectName(), projectConfig); addProjectConfigAll(projectConfig); } - + + public void removeProjectConfig(final ProjectConfig projectConfig) { + projectConfigs.remove(projectConfig.getProjectName()); + removeProjectConfigAll(projectConfig); + } + public Collection<ProjectConfig> getProjectConfigs() { return projectConfigs.values(); } @@ -47,10 +52,14 @@ public class PipelineCommonData { projectConfigsAll.put(projectConfig.getProjectName(), projectConfig); } + public void removeProjectConfigAll(final ProjectConfig projectConfig) { + projectConfigsAll.remove(projectConfig.getProjectName()); + } + public Collection<ProjectConfig> getProjectConfigsAll() { return projectConfigsAll.values(); } - + public ProjectConfig getProjectConfigAll(final String projectName) throws IOException { ProjectConfig projectConfig = projectConfigsAll.get(projectName); if (projectConfig == null) { diff --git a/src/main/java/fr/osug/doi/ProjectConfig.java b/src/main/java/fr/osug/doi/ProjectConfig.java index b15d82f..31389f0 100644 --- a/src/main/java/fr/osug/doi/ProjectConfig.java +++ b/src/main/java/fr/osug/doi/ProjectConfig.java @@ -71,55 +71,66 @@ public final class ProjectConfig { private Map<String, NameEntry> overrideNameEntryMap = null; public ProjectConfig(final PathConfig pathConfig, final String projectName) throws IOException { + this(pathConfig, projectName, true); + } + + public ProjectConfig(final PathConfig pathConfig, final String projectName, final boolean required) throws IOException { this.projectName = projectName; // may fail: - this.projectConf = FileUtils.getRequiredDirectory(Paths.DIR_CONFIG + projectName).getCanonicalFile(); + this.projectConf = dir(absPath(Paths.DIR_CONFIG, projectName), required); logger.info("Project Config: {}", projectConf); - // preload properties to ensure the folder exists: - getProperties(); - - initMetadataDir( - new File(this.projectConf, Paths.DIR_PROJECT_METADATA).getAbsolutePath() - ); - initInputDir( - new File(this.projectConf, Paths.DIR_PROJECT_INPUTS).getAbsolutePath() - ); - initTmpDir( - new File(Paths.DIR_TMP, projectName).getAbsolutePath() - ); - initTmpDoiDir( - new File(tmpDir, Paths.DIR_TMP_DOI).getAbsolutePath() - ); - - initStagingDir( - new File(Paths.DIR_STAGING, projectName).getAbsolutePath() - ); - initPublicDir( - new File(Paths.DIR_PUBLIC, projectName).getAbsolutePath() - ); + if (required) { + // preload properties to ensure the folder contains the property file: + getProperties(); + } + + initInputDir(absPath(this.projectConf, Paths.DIR_PROJECT_INPUTS), required); + initMetadataDir(absPath(this.projectConf, Paths.DIR_PROJECT_METADATA), required); + + initTmpDir(absPath(Paths.DIR_TMP, projectName)); + initTmpDoiDir(absPath(tmpDir, Paths.DIR_TMP_DOI)); + + initStagingDir(absPath(Paths.DIR_STAGING, projectName)); + initPublicDir(absPath(Paths.DIR_PUBLIC, projectName)); // /www/staging directories: - initWebStagingProjectDir( - new File(pathConfig.getWebStagingDir(), projectName).getAbsolutePath() - ); - initWebStagingProjectEmbedDir( - new File(webStagingProjectDir, Paths.DIR_WEB_EMBED).getAbsolutePath() - ); - initWebStagingProjectXmlDir( - new File(webStagingProjectDir, Paths.DIR_WEB_XML).getAbsolutePath() - ); + initWebStagingProjectDir(absPath(pathConfig.getWebStagingDir(), projectName)); + initWebStagingProjectEmbedDir(absPath(webStagingProjectDir, Paths.DIR_WEB_EMBED)); + initWebStagingProjectXmlDir(absPath(webStagingProjectDir, Paths.DIR_WEB_XML)); + // /www/public directories: - initWebPublicProjectDir( - new File(pathConfig.getWebPublicDir(), projectName).getAbsolutePath() - ); - initWebPublicProjectEmbedDir( - new File(webPublicProjectDir, Paths.DIR_WEB_EMBED).getAbsolutePath() - ); - initWebPublicProjectXmlDir( - new File(webPublicProjectDir, Paths.DIR_WEB_XML).getAbsolutePath() - ); + initWebPublicProjectDir(absPath(pathConfig.getWebPublicDir(), projectName)); + initWebPublicProjectEmbedDir(absPath(webPublicProjectDir, Paths.DIR_WEB_EMBED)); + initWebPublicProjectXmlDir(absPath(webPublicProjectDir, Paths.DIR_WEB_XML)); + } + + public String dumpProjectDirs() { + final StringBuilder sb = new StringBuilder(1024); + + sb.append(getProjectConf()).append('\n'); + sb.append(getInputDir()).append('\n'); + sb.append(getMetadataDir()).append('\n'); + sb.append(getTemplatesDir()).append('\n'); + + sb.append(getTmpDir()).append('\n'); + sb.append(getTmpDoiDir()).append('\n'); + + sb.append(getStagingDir()).append('\n'); + sb.append(getPublicDir()).append('\n'); + + // /www/staging directories: + sb.append(getWebStagingProjectDir()).append('\n'); + sb.append(getWebPublicProjectEmbedDir()).append('\n'); + sb.append(getWebPublicProjectXmlDir()).append('\n'); + + // /www/public directories: + sb.append(getWebPublicProjectDir()).append('\n'); + sb.append(getWebPublicProjectEmbedDir()).append('\n'); + sb.append(getWebPublicProjectXmlDir()).append('\n'); + + return sb.toString(); } public void prepareProcess() throws IOException { @@ -130,62 +141,58 @@ public final class ProjectConfig { getOverrideNameMap(); } - public void initMetadataDir(final String dirPath) throws IOException { - this.metadataDir = FileUtils.getRequiredDirectory(dirPath).getCanonicalFile(); + public void initInputDir(final String dirPath, final boolean required) throws IOException { + this.inputDir = dir(dirPath, required); } - public void initInputDir(final String dirPath) throws IOException { - this.inputDir = FileUtils.getRequiredDirectory(dirPath).getCanonicalFile(); + public void initMetadataDir(final String dirPath, final boolean required) throws IOException { + this.metadataDir = dir(dirPath, required); } - public void initTmpDir(final String path) throws IOException { - this.tmpDir = FileUtils.createDirectories(path); + public void initTmpDir(final String dirPath) throws IOException { + this.tmpDir = FileUtils.createDirectories(dirPath); } - public void initTmpDoiDir(final String path) throws IOException { - this.tmpDoiDir = FileUtils.createDirectories(path); + public void initTmpDoiDir(final String dirPath) throws IOException { + this.tmpDoiDir = FileUtils.createDirectories(dirPath); } - public void initStagingDir(final String path) throws IOException { - this.stagingDir = FileUtils.createDirectories(path); + public void initStagingDir(final String dirPath) throws IOException { + this.stagingDir = FileUtils.createDirectories(dirPath); } - public void initPublicDir(final String path) throws IOException { - this.publicDir = FileUtils.createDirectories(path); + public void initPublicDir(final String dirPath) throws IOException { + this.publicDir = FileUtils.createDirectories(dirPath); } - public void initWebStagingProjectDir(final String path) throws IOException { - this.webStagingProjectDir = FileUtils.createDirectories(path); + public void initWebStagingProjectDir(final String dirPath) throws IOException { + this.webStagingProjectDir = FileUtils.createDirectories(dirPath); } - public void initWebStagingProjectEmbedDir(final String path) throws IOException { - this.webStagingProjectEmbedDir = FileUtils.createDirectories(path); + public void initWebStagingProjectEmbedDir(final String dirPath) throws IOException { + this.webStagingProjectEmbedDir = FileUtils.createDirectories(dirPath); } - public void initWebStagingProjectXmlDir(final String path) throws IOException { - this.webStagingProjectXmlDir = FileUtils.createDirectories(path); + public void initWebStagingProjectXmlDir(final String dirPath) throws IOException { + this.webStagingProjectXmlDir = FileUtils.createDirectories(dirPath); } - public void initWebPublicProjectDir(final String path) throws IOException { - this.webPublicProjectDir = FileUtils.createDirectories(path); + public void initWebPublicProjectDir(final String dirPath) throws IOException { + this.webPublicProjectDir = FileUtils.createDirectories(dirPath); } - public void initWebPublicProjectEmbedDir(final String path) throws IOException { - this.webPublicProjectEmbedDir = FileUtils.createDirectories(path); + public void initWebPublicProjectEmbedDir(final String dirPath) throws IOException { + this.webPublicProjectEmbedDir = FileUtils.createDirectories(dirPath); } - public void initWebPublicProjectXmlDir(final String path) throws IOException { - this.webPublicProjectXmlDir = FileUtils.createDirectories(path); + public void initWebPublicProjectXmlDir(final String dirPath) throws IOException { + this.webPublicProjectXmlDir = FileUtils.createDirectories(dirPath); } public String getProjectName() { return projectName; } - public File getProjectConf() { - return projectConf; - } - /* properties */ private Properties getProperties() { if (properties == null) { @@ -244,9 +251,7 @@ public final class ProjectConfig { /* templates */ public DoiTemplates getTemplates() throws IOException { if (templates == null) { - templates = new DoiTemplates( - new File(this.projectConf, Paths.DIR_PROJECT_TEMPLATES).getAbsolutePath() - ); + templates = new DoiTemplates(getTemplatesDir()); } return templates; } @@ -264,6 +269,14 @@ public final class ProjectConfig { } /* Directories */ + public File getProjectConf() { + return projectConf; + } + + private String getTemplatesDir() { + return absPath(this.projectConf, Paths.DIR_PROJECT_TEMPLATES); + } + public File getMetadataDir() { return metadataDir; } @@ -407,4 +420,19 @@ public final class ProjectConfig { logger.debug("nameEntryMap: {}", nameEntryMap); return nameEntryMap; } + + private File dir(final String dirPath, final boolean required) throws IOException { + if (required) { + return FileUtils.getRequiredDirectory(dirPath).getCanonicalFile(); + } + return FileUtils.createDirectories(dirPath); + } + + private static String absPath(final String dir, final String name) { + return new File(dir, name).getAbsolutePath(); + } + + private static String absPath(final File dir, final String name) { + return new File(dir, name).getAbsolutePath(); + } } diff --git a/src/main/java/fr/osug/doi/RemovePipeline.java b/src/main/java/fr/osug/doi/RemovePipeline.java index 4a70905..dd3e372 100644 --- a/src/main/java/fr/osug/doi/RemovePipeline.java +++ b/src/main/java/fr/osug/doi/RemovePipeline.java @@ -6,12 +6,15 @@ package fr.osug.doi; import static fr.osug.doi.GeneratePipeline.HTML_EXT; import fr.osug.doi.domain.Doi; import fr.osug.doi.domain.DoiStaging; +import fr.osug.doi.domain.Project; import fr.osug.doi.domain.Status; import fr.osug.doi.repository.DoiStagingRepository; +import fr.osug.doi.repository.ProjectRepository; import fr.osug.doi.service.DoiService; import fr.osug.util.FileUtils; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Date; import java.util.List; import org.slf4j.Logger; @@ -32,45 +35,76 @@ public final class RemovePipeline extends AbstractPipeline<PipelineCommonData> { @Override public void doExecute() throws IOException { - for (ProjectConfig projectConfig : pipeData.getProjectConfigs()) { - remove(projectConfig, pipeData.getDoiPattern()); + // Copy current project configs: + final List<ProjectConfig> projectConfigs = new ArrayList<ProjectConfig>(pipeData.getProjectConfigs()); + + for (ProjectConfig projectConfig : projectConfigs) { + if (remove(projectConfig, pipeData.getDoiPattern())) { + pipeData.removeProjectConfig(projectConfig); + + logger.warn("Please remove project paths:\n{}", projectConfig.dumpProjectDirs()); + } } } - private void remove(final ProjectConfig projectConfig, final String doiPattern) throws IOException { + private boolean remove(final ProjectConfig projectConfig, final String doiPattern) throws IOException { logger.info("remove ..."); + boolean skip = false; + final String pattern = DoiService.convertPattern(doiPattern); logger.debug("pattern: {}", pattern); final String projectName = projectConfig.getProjectName(); - final Date now = pipeData.now; + logger.info("project: {}", projectName); final DoiService doiService = doiConfig.getDoiService(); - final DoiStagingRepository dsr = doiService.getDoiStagingRepository(); + final ProjectRepository pr = doiService.getProjectRepository(); - final List<DoiStaging> dsList = dsr.findByProjectAndPattern(projectName, pattern); + final Project p = pr.findOneByName(projectName); - logger.debug("DoiCommon list for project[{}]: {}", projectName, dsList); + if (p == null) { + logger.warn("Unknown Project [{}]", projectName); + skip = true; + } else { + final Date now = pipeData.now; - boolean changed = false; + final DoiStagingRepository dsr = doiService.getDoiStagingRepository(); - for (DoiStaging ds : dsList) { - logger.debug("DoiStaging: {}", ds); + final List<DoiStaging> dsList = dsr.findByProjectAndPattern(projectName, pattern); - final Doi doi = ds.getDoi(); - final String doiSuffix = doi.getIdentifier(); + logger.debug("DoiCommon list for project[{}]: {}", projectName, dsList); + + if (dsList.isEmpty()) { + logger.info("Project {} has no DOI", projectName); + logger.info("removing {}", projectName); + doiService.removeOrphanProject(projectName); + skip = true; - if (doi.getStatus() == Status.PUBLIC) { - logger.warn("Ignoring {} - DOI is public", doiSuffix); } else { - changed |= remove(projectConfig, ds); + boolean changed = false; + + for (DoiStaging ds : dsList) { + logger.debug("DoiStaging: {}", ds); + + final Doi doi = ds.getDoi(); + final String doiSuffix = doi.getIdentifier(); + + if (doi.getStatus() == Status.PUBLIC) { + logger.warn("Ignoring {} - DOI is public", doiSuffix); + } else { + changed |= remove(projectConfig, ds); + } + } + if (changed) { + // Update Project: + doiService.updateProjectDate(projectName, now); + } } } - if (changed) { - // Update Project: - doiService.updateProjectDate(projectName, now); - } + + logger.info("remove: done."); + return skip; } private boolean remove(final ProjectConfig projectConfig, final DoiStaging ds) throws IOException { diff --git a/src/main/java/fr/osug/doi/service/DoiService.java b/src/main/java/fr/osug/doi/service/DoiService.java index c53ecc4..14c17f2 100644 --- a/src/main/java/fr/osug/doi/service/DoiService.java +++ b/src/main/java/fr/osug/doi/service/DoiService.java @@ -14,6 +14,7 @@ import fr.osug.doi.repository.DoiRepository; import fr.osug.doi.repository.DoiStagingRepository; import fr.osug.doi.repository.ProjectRepository; import java.util.Date; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -73,6 +74,26 @@ public class DoiService { projectRepository.save(project); } + @Transactional + public void removeOrphanProject(final String name) { + // Check no DOI references this project: + final List<Doi> dois = doiRepository.findByProject(name); + + if (!dois.isEmpty()) { + throw new IllegalArgumentException("Project [" + name + "] is not empty - can not remove !"); + } + + Project project = projectRepository.findOneByName(name); + + if (project == null) { + throw new IllegalArgumentException("Missing project with name: " + name); + } + + logger.debug("deleting: {}", project); + + projectRepository.delete(project); + } + @Transactional(readOnly = true) public Doi getDoi(final String identifier) { return doiRepository.findOneByIdentifier(identifier); @@ -273,7 +294,7 @@ public class DoiService { return changed; } - + @Transactional public void removeStagingDoiDatacite(final String identifier) { @@ -289,7 +310,7 @@ public class DoiService { logger.debug("deleting: {}", doiStaging); doiStagingRepository.delete(doiStaging); - + logger.debug("deleting: {}", doiStaging.getDoi()); doiRepository.delete(doiStaging.getDoi()); } @@ -406,12 +427,17 @@ public class DoiService { public static String convertPattern(final String doiPattern) { String pattern; - // escape '%' and '_' - pattern = doiPattern.replaceAll("_", "\\_"); - pattern = pattern.replaceAll("%", "\\%"); + + if ("*".equals(doiPattern)) { + pattern = ""; + } else { + // escape '%' and '_' + pattern = doiPattern.replaceAll("_", "\\_"); + pattern = pattern.replaceAll("%", "\\%"); + } // '<pattern>%' return pattern + "%"; } - + } diff --git a/src/test/java/fr/osug/doi/DOITextToXmlTest.java b/src/test/java/fr/osug/doi/DOITextToXmlTest.java index f2f36af..d7d898b 100644 --- a/src/test/java/fr/osug/doi/DOITextToXmlTest.java +++ b/src/test/java/fr/osug/doi/DOITextToXmlTest.java @@ -91,7 +91,7 @@ public class DOITextToXmlTest { final ProjectConfig projectConfig = new ProjectConfig(pathConfig, project); // redirect outputs: - projectConfig.initInputDir(DIR_TEST); + projectConfig.initInputDir(DIR_TEST, true); projectConfig.initTmpDir(DIR_OUTPUT); projectConfig.initStagingDir(DIR_STAGING); -- GitLab