From 6adbcab4ff4fd7120469df625e901f820f4e81d1 Mon Sep 17 00:00:00 2001 From: William Welling Date: Sat, 23 Dec 2023 17:27:31 -0600 Subject: [PATCH 01/48] Fix email workflow rules resetting on restart --- .../vireo/model/repo/impl/UserRepoImpl.java | 2 +- .../tdl/vireo/service/SystemDataLoader.java | 119 +++++++----------- src/main/resources/application-test.yml | 2 +- .../integration/AbstractIntegrationTest.java | 15 ++- .../EmailWorkflowRulesIntegrationTest.java | 93 ++++++++++++++ 5 files changed, 155 insertions(+), 76 deletions(-) create mode 100644 src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java index 85ffa78b85..6b01fe4b12 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java @@ -70,7 +70,7 @@ public User create(User user) { } /** - * Clear the active filter group for the given user, creating a persisted filer group if necessary. + * Clear the active filter group for the given user, creating a persisted filter group if necessary. * * This removes existing filters and columns on the persisted filter group (aka not-"saved" filter group). * diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 41cd59457e..51556f5d94 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -167,12 +167,6 @@ public class SystemDataLoader { @Autowired private SubmissionListColumnRepo submissionListColumnRepo; - @Autowired - private DefaultSubmissionListColumnService defaultSubmissionListColumnService; - - @Autowired - private DefaultFiltersService defaultFiltersService; - @Autowired private AbstractPackagerRepo abstractPackagerRepo; @@ -185,6 +179,12 @@ public class SystemDataLoader { @Autowired private DefaultSettingsService defaultSettingsService; + @Autowired + private DefaultSubmissionListColumnService defaultSubmissionListColumnService; + + @Autowired + private DefaultFiltersService defaultFiltersService; + @Transactional public void loadSystemData() { @@ -411,30 +411,22 @@ private void loadOrganization() { organization = organizationRepo.create(systemOrganization.getName(), category); organization.setAcceptsSubmissions(systemOrganization.getAcceptsSubmissions()); } - // else set systemOrganization to existing organization - else { - systemOrganization = organization; - } - List systemOrganizationWorkflowSteps = new ArrayList<>(systemOrganization.getOriginalWorkflowSteps()); + processWorkflowSteps(organization, systemOrganization); - organization.setAggregateWorkflowSteps(processWorkflowSteps(organization, systemOrganizationWorkflowSteps)); + processEmailWorflowRules(organization, systemOrganization); organization = organizationRepo.save(organization); - processEmailWorflowRules(); - } catch (IOException e) { throw new IllegalStateException("Unable to generate system organization", e); } } - private List processWorkflowSteps(Organization organization, List systemOrganizationWorkflowSteps) { - - List workflowSteps = new ArrayList(); + private void processWorkflowSteps(Organization organization, Organization systemOrganization) { - for (WorkflowStep workflowStep : systemOrganizationWorkflowSteps) { + for (WorkflowStep workflowStep : systemOrganization.getOriginalWorkflowSteps()) { // check to see if the WorkflowStep exists WorkflowStep newWorkflowStep = workflowStepRepo.findByNameAndOriginatingOrganization(workflowStep.getName(), organization); @@ -524,82 +516,63 @@ private List processWorkflowSteps(Organization organization, List< newWorkflowStep.setInstructions(workflowStep.getInstructions()); newWorkflowStep = workflowStepRepo.save(newWorkflowStep); - - workflowSteps.add(newWorkflowStep); } - return workflowSteps; } - private void processEmailWorflowRules() { - - Organization organization = organizationRepo.findById(1L).get(); + private void processEmailWorflowRules(Organization organization, Organization systemOrganization) { + List emailWorkflowRules = organization.getEmailWorkflowRules(); - try { - Organization systemOrganization = objectMapper.readValue(getFileFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); + for (EmailWorkflowRule emailWorkflowRule : systemOrganization.getEmailWorkflowRules()) { - // temporary set of EmailWorkflowRule - List emailWorkflowRules = new ArrayList(); + // check to see if the SubmissionStatus exists + SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(emailWorkflowRule.getSubmissionStatus().getName()); - systemOrganization.getEmailWorkflowRules().forEach(emailWorkflowRule -> { - - // check to see if the SubmissionStatus exists - SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(emailWorkflowRule.getSubmissionStatus().getName()); - - // create new SubmissionStatus if not already exists - if (newSubmissionStatus == null) { - newSubmissionStatus = submissionStatusRepo.create(emailWorkflowRule.getSubmissionStatus().getName(), emailWorkflowRule.getSubmissionStatus().isArchived(), emailWorkflowRule.getSubmissionStatus().isPublishable(), emailWorkflowRule.getSubmissionStatus().isDeletable(), emailWorkflowRule.getSubmissionStatus().isEditableByReviewer(), emailWorkflowRule.getSubmissionStatus().isEditableByStudent(), emailWorkflowRule.getSubmissionStatus().isActive(), - emailWorkflowRule.getSubmissionStatus().getSubmissionState()); - newSubmissionStatus = submissionStatusRepo.save(recursivelyFindOrCreateSubmissionStatus(emailWorkflowRule.getSubmissionStatus())); - } + // create new SubmissionStatus if not already exists + if (newSubmissionStatus == null) { + newSubmissionStatus = submissionStatusRepo.create(emailWorkflowRule.getSubmissionStatus().getName(), emailWorkflowRule.getSubmissionStatus().isArchived(), emailWorkflowRule.getSubmissionStatus().isPublishable(), emailWorkflowRule.getSubmissionStatus().isDeletable(), emailWorkflowRule.getSubmissionStatus().isEditableByReviewer(), emailWorkflowRule.getSubmissionStatus().isEditableByStudent(), emailWorkflowRule.getSubmissionStatus().isActive(), + emailWorkflowRule.getSubmissionStatus().getSubmissionState()); + newSubmissionStatus = submissionStatusRepo.save(recursivelyFindOrCreateSubmissionStatus(emailWorkflowRule.getSubmissionStatus())); + } - // check to see if the EmailTemplate exists - EmailTemplate newEmailTemplate = emailTemplateRepo.findByNameAndSystemRequired(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSystemRequired()); + // check to see if the EmailTemplate exists + EmailTemplate newEmailTemplate = emailTemplateRepo.findByNameAndSystemRequired(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSystemRequired()); - // create new EmailTemplate if not already exists - if (newEmailTemplate == null) { - newEmailTemplate = emailTemplateRepo.create(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSubject(), emailWorkflowRule.getEmailTemplate().getMessage()); - } + // create new EmailTemplate if not already exists + if (newEmailTemplate == null) { + newEmailTemplate = emailTemplateRepo.create(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSubject(), emailWorkflowRule.getEmailTemplate().getMessage()); + } - if (emailWorkflowRule.getEmailRecipient() == null) { + if (emailWorkflowRule.getEmailRecipient() == null) { - if (newEmailTemplate.getName().equals("SYSTEM Advisor Review Request")) { - organization.getAggregateWorkflowSteps().forEach(awfs -> { - awfs.getAggregateFieldProfiles().forEach(afp -> { - if (afp.getFieldPredicate().getValue().equals("dc.contributor.advisor")) { - EmailRecipient recipient = abstractEmailRecipientRepo.createContactRecipient(afp.getGloss(), afp.getFieldPredicate()); - emailWorkflowRule.setEmailRecipient(recipient); - } - }); + if (newEmailTemplate.getName().equals("SYSTEM Advisor Review Request")) { + organization.getAggregateWorkflowSteps().forEach(awfs -> { + awfs.getAggregateFieldProfiles().forEach(afp -> { + if (afp.getFieldPredicate().getValue().equals("dc.contributor.advisor")) { + EmailRecipient recipient = abstractEmailRecipientRepo.createContactRecipient(afp.getGloss(), afp.getFieldPredicate()); + emailWorkflowRule.setEmailRecipient(recipient); + } }); - - } - - if (newEmailTemplate.getName().equals("SYSTEM Initial Submission")) { - EmailRecipient recipient = abstractEmailRecipientRepo.createOrganizationRecipient(organization); - emailWorkflowRule.setEmailRecipient(recipient); - } + }); } - // check to see if the EmailWorkflowRule exists - EmailWorkflowRule newEmailWorkflowRule = emailWorkflowRuleRepo.findBySubmissionStatusAndEmailRecipientAndEmailTemplate(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate); - - if (newEmailWorkflowRule == null) { - newEmailWorkflowRule = emailWorkflowRuleRepo.create(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate, emailWorkflowRule.isSystem()); + if (newEmailTemplate.getName().equals("SYSTEM Initial Submission")) { + EmailRecipient recipient = abstractEmailRecipientRepo.createOrganizationRecipient(organization); + emailWorkflowRule.setEmailRecipient(recipient); } - emailWorkflowRules.add(newEmailWorkflowRule); - - }); + } - organization.setEmailWorkflowRules(emailWorkflowRules); + // check to see if the EmailWorkflowRule exists + EmailWorkflowRule existingEmailWorkflowRule = emailWorkflowRuleRepo.findBySubmissionStatusAndEmailRecipientAndEmailTemplate(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate); - organizationRepo.save(organization); + if (existingEmailWorkflowRule == null) { + emailWorkflowRules.add(emailWorkflowRuleRepo.create(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate, emailWorkflowRule.isSystem())); + } - } catch (IOException e) { - throw new IllegalStateException("Unable to generate system organization", e); } + organization.setEmailWorkflowRules(emailWorkflowRules); } private void loadSubmissionStatuses() { diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 8bf1400c0e..70d002a31b 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -7,7 +7,7 @@ spring: datasource: url: jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - driverClassName: org.h2.Driver + driver-class-name: org.h2.Driver jpa: database-platform: org.hibernate.dialect.H2Dialect diff --git a/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java index 906ae47d85..e5e4404032 100644 --- a/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java @@ -1,6 +1,5 @@ package org.tdl.vireo.integration; -import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; @@ -10,8 +9,13 @@ import org.springframework.web.context.WebApplicationContext; import org.tdl.vireo.Application; import org.tdl.vireo.mock.MockData; +import org.tdl.vireo.service.DefaultFiltersService; +import org.tdl.vireo.service.DefaultSubmissionListColumnService; +import org.tdl.vireo.service.EntityControlledVocabularyService; import org.tdl.vireo.service.SystemDataLoader; +import com.fasterxml.jackson.databind.ObjectMapper; + @Transactional(propagation = Propagation.REQUIRES_NEW) @ActiveProfiles("test") @SpringBootTest(classes = { Application.class }) @@ -28,6 +32,15 @@ public abstract class AbstractIntegrationTest extends MockData { @Autowired protected SystemDataLoader systemDataLoader; + @Autowired + protected EntityControlledVocabularyService entityControlledVocabularyService; + + @Autowired + protected DefaultSubmissionListColumnService defaultSubmissionListColumnService; + + @Autowired + protected DefaultFiltersService defaultFiltersService; + protected MockMvc mockMvc; } diff --git a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java new file mode 100644 index 0000000000..215602be7a --- /dev/null +++ b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java @@ -0,0 +1,93 @@ +package org.tdl.vireo.integration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.tdl.vireo.model.EmailRecipient; +import org.tdl.vireo.model.EmailTemplate; +import org.tdl.vireo.model.EmailWorkflowRule; +import org.tdl.vireo.model.Organization; +import org.tdl.vireo.model.SubmissionStatus; +import org.tdl.vireo.model.repo.AbstractEmailRecipientRepo; +import org.tdl.vireo.model.repo.EmailTemplateRepo; +import org.tdl.vireo.model.repo.EmailWorkflowRuleRepo; +import org.tdl.vireo.model.repo.OrganizationRepo; +import org.tdl.vireo.model.repo.SubmissionStatusRepo; + +public class EmailWorkflowRulesIntegrationTest extends AbstractIntegrationTest { + + @Autowired + private EmailWorkflowRuleRepo emailWorkflowRuleRepo; + + @Autowired + private EmailTemplateRepo emailTemplateRepo; + + @Autowired + private AbstractEmailRecipientRepo abstractEmailRecipientRepo; + + @Autowired + private OrganizationRepo organizationRepo; + + @Autowired + private SubmissionStatusRepo submissionStatusRepo; + + @BeforeEach + public void setup() throws Exception { + // takes a long time, try not to add more tests in this class + systemDataLoader.loadSystemData(); + entityControlledVocabularyService.scanForEntityControlledVocabularies(); + } + + @Test + public void testEmailWorkflowRulePersistenceUponReload() throws Exception { + Organization org = organizationRepo.findAll().get(0); + + assertEquals(2, org.getEmailWorkflowRules().size()); + + SubmissionStatus submissionStatus = submissionStatusRepo.findAll().get(0); + + EmailTemplate emailTemplate = emailTemplateRepo.findAll().get(0); + + EmailRecipient emailRecipient = abstractEmailRecipientRepo.findAll().get(0); + + EmailWorkflowRule newEmailWorkflowRule = emailWorkflowRuleRepo.create(submissionStatus, emailRecipient, emailTemplate); + org.addEmailWorkflowRule(newEmailWorkflowRule); + organizationRepo.update(org); + + Long existingOrgWithNewWorkflowRuleId = org.getId(); + Long newlyCreatedEmailWorkflowRuleId = newEmailWorkflowRule.getId(); + + int numberOfWorkflowRulesForOrg = org.getEmailWorkflowRules().size(); + + assertEquals(3, numberOfWorkflowRulesForOrg); + + this.setup(); + + EmailWorkflowRule newWorkflowRule = emailWorkflowRuleRepo.getById(newlyCreatedEmailWorkflowRuleId); + assertNotNull(newWorkflowRule); + Organization newOrgRef = organizationRepo.getById(existingOrgWithNewWorkflowRuleId); + assertNotNull(newOrgRef); + + List emailWorkflowRulesForOrg = newOrgRef.getEmailWorkflowRules(); + + assertEquals(numberOfWorkflowRulesForOrg, emailWorkflowRulesForOrg.size()); + + EmailWorkflowRule newEmailWorkflowRuleRef = emailWorkflowRulesForOrg.get(emailWorkflowRulesForOrg.size() - 1); + + assertEquals(newlyCreatedEmailWorkflowRuleId, newEmailWorkflowRuleRef.getId()); + } + + @AfterEach + public void cleanup() { + defaultFiltersService.setDefaultFilter(new ArrayList<>()); + defaultSubmissionListColumnService.setDefaultSubmissionListColumns(new ArrayList<>()); + } + +} From 95ce645bcd026e69a43b259309e5a054e0751c70 Mon Sep 17 00:00:00 2001 From: William Welling Date: Sat, 23 Dec 2023 17:28:35 -0600 Subject: [PATCH 02/48] Switch application initialization to initializing bean --- .../java/org/tdl/vireo/ApplicationInitialization.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/tdl/vireo/ApplicationInitialization.java b/src/main/java/org/tdl/vireo/ApplicationInitialization.java index d9c1666578..2412ed0d4a 100644 --- a/src/main/java/org/tdl/vireo/ApplicationInitialization.java +++ b/src/main/java/org/tdl/vireo/ApplicationInitialization.java @@ -1,19 +1,19 @@ package org.tdl.vireo; +import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.Ordered; -import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Profile; +import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.tdl.vireo.service.EntityControlledVocabularyService; import org.tdl.vireo.service.SystemDataLoader; @Order(Ordered.HIGHEST_PRECEDENCE) -@Component +@Component("ApplicationInitialization") @Profile("!test") -public class ApplicationInitialization implements CommandLineRunner { +public class ApplicationInitialization implements InitializingBean { @Lazy @Autowired @@ -24,7 +24,7 @@ public class ApplicationInitialization implements CommandLineRunner { private EntityControlledVocabularyService entityControlledVocabularyService; @Override - public void run(String... args) throws Exception { + public void afterPropertiesSet() throws Exception { // load defaults first systemDataLoader.loadSystemData(); // assumes one language defined in defaults From 9425e6b534134b6cb1a37b985fd3cf5ca44469ca Mon Sep 17 00:00:00 2001 From: William Welling Date: Sat, 23 Dec 2023 17:29:11 -0600 Subject: [PATCH 03/48] Have abstract email recipient implement email recipient --- src/main/java/org/tdl/vireo/model/AbstractEmailRecipient.java | 2 +- .../vireo/model/repo/impl/AbstractEmailRecipientRepoImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/tdl/vireo/model/AbstractEmailRecipient.java b/src/main/java/org/tdl/vireo/model/AbstractEmailRecipient.java index 2b689281a2..e7fcc25849 100644 --- a/src/main/java/org/tdl/vireo/model/AbstractEmailRecipient.java +++ b/src/main/java/org/tdl/vireo/model/AbstractEmailRecipient.java @@ -8,7 +8,7 @@ @Entity @Inheritance -public abstract class AbstractEmailRecipient extends ValidatingBaseEntity { +public abstract class AbstractEmailRecipient extends ValidatingBaseEntity implements EmailRecipient { @Column(nullable = false) private String name; diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/AbstractEmailRecipientRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/AbstractEmailRecipientRepoImpl.java index c954ea2d9d..ca38d77698 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/AbstractEmailRecipientRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/AbstractEmailRecipientRepoImpl.java @@ -63,7 +63,7 @@ private EmailRecipient findOneByName(String name) { // query using jpql // TODO: this should not be needed, named queries should work - return (EmailRecipient) abstractEmailRecipientRepo.findAll().stream().filter(r -> r.getName().equals(name)).findFirst().orElse(null); + return abstractEmailRecipientRepo.findAll().stream().filter(r -> r.getName().equals(name)).findFirst().orElse(null); } @Override From bf2b3927a30c46d95903b8af8ea9055f58ecacd2 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 10:15:56 -0600 Subject: [PATCH 04/48] Make default collections class members final and remove unused methods --- .../org/tdl/vireo/service/DefaultFiltersService.java | 12 ++---------- .../tdl/vireo/service/DefaultSettingsService.java | 2 +- .../service/DefaultSubmissionListColumnService.java | 10 +++------- .../java/org/tdl/vireo/service/DepositorService.java | 6 +++++- .../org/tdl/vireo/service/ProquestCodesService.java | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java b/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java index 2db4289413..4e2de9f4e9 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java @@ -9,14 +9,10 @@ @Service public class DefaultFiltersService { - private List defaultFilters = new ArrayList(); + private final List defaultFilters; public DefaultFiltersService() { - - } - - public void setDefaultFilter(List defaultFilter) { - this.defaultFilters = defaultFilter; + this.defaultFilters = new ArrayList(); } public List getDefaultFilter() { @@ -27,8 +23,4 @@ public void addDefaultFilter(SubmissionListColumn defaultFilter) { this.defaultFilters.add(defaultFilter); } - public void removeDefaultFilter(SubmissionListColumn defaultFilter) { - this.defaultFilters.remove(defaultFilter); - } - } diff --git a/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java b/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java index 5616b6420a..2bc02843f9 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java @@ -11,7 +11,7 @@ @Service public class DefaultSettingsService { - private static List defaultSettings; + private final List defaultSettings; public DefaultSettingsService() { defaultSettings = new ArrayList(); diff --git a/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java b/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java index df6d37efb7..057445570b 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java @@ -9,10 +9,10 @@ @Service public class DefaultSubmissionListColumnService { - private List defaultSubmissionListColumns = new ArrayList(); + private final List defaultSubmissionListColumns; - public void setDefaultSubmissionListColumns(List defaultSubmissionListColumns) { - this.defaultSubmissionListColumns = defaultSubmissionListColumns; + public DefaultSubmissionListColumnService() { + this.defaultSubmissionListColumns = new ArrayList(); } public List getDefaultSubmissionListColumns() { @@ -23,8 +23,4 @@ public void addDefaultSubmissionListColumn(SubmissionListColumn defaultSubmissio this.defaultSubmissionListColumns.add(defaultSubmissionListColumn); } - public void removeDefaultSubmissionListColumn(SubmissionListColumn defaultSubmissionListColumn) { - this.defaultSubmissionListColumns.remove(defaultSubmissionListColumn); - } - } diff --git a/src/main/java/org/tdl/vireo/service/DepositorService.java b/src/main/java/org/tdl/vireo/service/DepositorService.java index 2423c7a4d4..8548780fed 100644 --- a/src/main/java/org/tdl/vireo/service/DepositorService.java +++ b/src/main/java/org/tdl/vireo/service/DepositorService.java @@ -9,7 +9,11 @@ @Service public class DepositorService { - private Map depositors = new HashMap(); + private final Map depositors; + + public DepositorService() { + this.depositors = new HashMap(); + } public Depositor getDepositor(String depositorName) { return depositors.get(depositorName); diff --git a/src/main/java/org/tdl/vireo/service/ProquestCodesService.java b/src/main/java/org/tdl/vireo/service/ProquestCodesService.java index 7c6f1f7071..d2c21b4d3e 100644 --- a/src/main/java/org/tdl/vireo/service/ProquestCodesService.java +++ b/src/main/java/org/tdl/vireo/service/ProquestCodesService.java @@ -8,7 +8,7 @@ @Service public class ProquestCodesService { - private Map> codes; + private final Map> codes; public ProquestCodesService() { codes = new HashMap>(); From 8974332e3fc104314f29d8cdd35e82e353144366 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 10:16:34 -0600 Subject: [PATCH 05/48] Minor cleanup of integration tests --- .../tdl/vireo/service/SystemDataLoader.java | 5 +++- .../integration/AbstractIntegrationTest.java | 2 +- .../integration/AuthIntegrationTest.java | 25 ++++++++++++++++--- .../ControlledVocabularyIntegrationTest.java | 6 +++-- .../EmailWorkflowRulesIntegrationTest.java | 5 ++-- .../integration/LanguageIntegrationTest.java | 14 +++++++---- .../integration/UserIntegrationTest.java | 17 ++++++------- 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 51556f5d94..95a6264af8 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -88,6 +88,9 @@ import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.TypeFactory; +/** + * This class is to load and persist system data from resources. + */ @Service public class SystemDataLoader { @@ -916,7 +919,7 @@ private void loadEmbargos() { } } - public void loadSystemDefaults() { + private void loadSystemDefaults() { try { JsonNode systemDefaults = objectMapper.readTree(getFileFromResource("classpath:/settings/SYSTEM_Defaults.json")); Iterator> it = systemDefaults.fields(); diff --git a/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java index e5e4404032..b23938cdc3 100644 --- a/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java @@ -16,9 +16,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; -@Transactional(propagation = Propagation.REQUIRES_NEW) @ActiveProfiles("test") @SpringBootTest(classes = { Application.class }) +@Transactional(propagation = Propagation.REQUIRES_NEW) public abstract class AbstractIntegrationTest extends MockData { protected static final String jwtString = "ToY1Y3O6o-iESvV_c3NR3XHvi1vqfYtLIB83HC-d80_qqS98EzfWfPxkP2faL-tEIu9b9wm-q0-T3aNzBWxphQ7ZVxnJSYvtBLzEAh7WVYbezyA3Dgj-nMbsUypCujnuEa0fDwnXXSDr2DRjw4JakMACdPZifN6hcz5-oYFqgWFOPvDE3Gr28ko4XpExXcRaZxYv0p4KW7ISquenB9clu6aKjoKrNwbXqHQvXyk_uFD7GmNuG7RB5Je3jrS0a4q5GSdRyegcoxbGGsNGTKx1f7-f6U4pAHD6fYUmoheZag975Py1Bk8PtUmI8rFWbh8YYPhnnOjGIdJ9qMBFC4-hmVi5hVGhqRdIX9VFeQjxP9gHGqQf5uihmJ8WUY9jh1IP"; diff --git a/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java index 62c0029db4..9f0bc0ebf2 100644 --- a/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java @@ -1,27 +1,38 @@ package org.tdl.vireo.integration; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.JsonNode; -import edu.tamu.weaver.auth.service.CryptoService; import java.util.HashMap; import java.util.Map; + +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import org.tdl.vireo.model.Role; import org.tdl.vireo.model.repo.EmailTemplateRepo; +import org.tdl.vireo.model.repo.NamedSearchFilterGroupRepo; import org.tdl.vireo.model.repo.UserRepo; +import com.fasterxml.jackson.databind.JsonNode; + +import edu.tamu.weaver.auth.service.CryptoService; + public class AuthIntegrationTest extends AbstractIntegrationTest { @Autowired private UserRepo userRepo; + @Autowired + private NamedSearchFilterGroupRepo namedSearchFilterRepo; + @Autowired private EmailTemplateRepo emailTemplateRepo; @@ -30,16 +41,22 @@ public class AuthIntegrationTest extends AbstractIntegrationTest { @BeforeEach public void setup() { - systemDataLoader.loadSystemDefaults(); - userRepo.deleteAll(); + assertEquals(0, userRepo.count()); + assertEquals(0, namedSearchFilterRepo.count()); + assertEquals(0, emailTemplateRepo.count()); userRepo.create(TEST_USER2_EMAIL, TEST_USER2.getFirstName(), TEST_USER2.getLastName(), Role.ROLE_ADMIN); userRepo.create(TEST_USER3_EMAIL, TEST_USER3.getFirstName(), TEST_USER3.getLastName(), Role.ROLE_MANAGER); userRepo.create(TEST_USER4_EMAIL, TEST_USER4.getFirstName(), TEST_USER4.getLastName(), Role.ROLE_STUDENT); + assertEquals(3, userRepo.count()); + assertEquals(2, namedSearchFilterRepo.count()); + emailTemplateRepo.create(TEST_REGISTRATION_EMAIL_TEMPLATE_NAME, TEST_EMAIL_TEMPLATE_SUBJECT, TEST_EMAIL_TEMPLATE_MESSAGE); + assertEquals(1, emailTemplateRepo.count()); + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } diff --git a/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java index 7334568581..b183a664dc 100644 --- a/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java @@ -1,5 +1,7 @@ package org.tdl.vireo.integration; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -12,13 +14,13 @@ public class ControlledVocabularyIntegrationTest extends AbstractIntegrationTest @BeforeEach public void setup() { - - systemDataLoader.loadSystemDefaults(); + assertEquals(0, controlledVocabularyRepo.count()); controlledVocabularyRepo.create(TEST_CONTROLLED_VOCABULARY_NAME1); controlledVocabularyRepo.create(TEST_CONTROLLED_VOCABULARY_NAME2); controlledVocabularyRepo.create(TEST_CONTROLLED_VOCABULARY_NAME3); + assertEquals(3, controlledVocabularyRepo.count()); } @Test diff --git a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java index 215602be7a..4612f3020c 100644 --- a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java @@ -3,7 +3,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -86,8 +85,8 @@ public void testEmailWorkflowRulePersistenceUponReload() throws Exception { @AfterEach public void cleanup() { - defaultFiltersService.setDefaultFilter(new ArrayList<>()); - defaultSubmissionListColumnService.setDefaultSubmissionListColumns(new ArrayList<>()); + defaultFiltersService.getDefaultFilter().clear(); + defaultSubmissionListColumnService.getDefaultSubmissionListColumns().clear(); } } diff --git a/src/test/java/org/tdl/vireo/integration/LanguageIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/LanguageIntegrationTest.java index 7abf10a4a6..a031ed0ce7 100644 --- a/src/test/java/org/tdl/vireo/integration/LanguageIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/LanguageIntegrationTest.java @@ -1,14 +1,18 @@ package org.tdl.vireo.integration; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.io.IOException; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.tdl.vireo.model.repo.LanguageRepo; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + public class LanguageIntegrationTest extends AbstractIntegrationTest { @Autowired @@ -16,15 +20,15 @@ public class LanguageIntegrationTest extends AbstractIntegrationTest { @BeforeEach public void setup() { - - systemDataLoader.loadSystemDefaults(); + assertEquals(0, languageRepo.count()); languageRepo.create(TEST_LANGUAGE_NAME1); languageRepo.create(TEST_LANGUAGE_NAME2); languageRepo.create(TEST_LANGUAGE_NAME3); - mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); + assertEquals(3, languageRepo.count()); + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test diff --git a/src/test/java/org/tdl/vireo/integration/UserIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/UserIntegrationTest.java index cf2875d0e6..518089404d 100644 --- a/src/test/java/org/tdl/vireo/integration/UserIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/UserIntegrationTest.java @@ -1,10 +1,10 @@ package org.tdl.vireo.integration; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.http.MediaType; -//import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.tdl.vireo.model.Role; import org.tdl.vireo.model.repo.NamedSearchFilterGroupRepo; @@ -20,19 +20,18 @@ public class UserIntegrationTest extends AbstractIntegrationTest { @BeforeEach public void setup() { + assertEquals(0, userRepo.count()); - systemDataLoader.loadSystemDefaults(); - - namedSearchFilterRepo.findAll().forEach(nsf -> { - namedSearchFilterRepo.delete(nsf); - }); - - userRepo.deleteAll(); + assertEquals(0, namedSearchFilterRepo.count()); userRepo.create(TEST_USER2_EMAIL, TEST_USER2.getFirstName(), TEST_USER2.getLastName(), Role.ROLE_ADMIN); userRepo.create(TEST_USER3_EMAIL, TEST_USER3.getFirstName(), TEST_USER3.getLastName(), Role.ROLE_MANAGER); userRepo.create(TEST_USER4_EMAIL, TEST_USER4.getFirstName(), TEST_USER4.getLastName(), Role.ROLE_STUDENT); + assertEquals(3, userRepo.count()); + + assertEquals(2, namedSearchFilterRepo.count()); + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } From 30fa312155b01b4749dd092703283834e2b7f704 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 10:17:44 -0600 Subject: [PATCH 06/48] Remove unused imports --- .../java/org/tdl/vireo/integration/AuthIntegrationTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java index 9f0bc0ebf2..1f0ddef1ba 100644 --- a/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/AuthIntegrationTest.java @@ -8,14 +8,11 @@ import java.util.HashMap; import java.util.Map; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; import org.tdl.vireo.model.Role; import org.tdl.vireo.model.repo.EmailTemplateRepo; import org.tdl.vireo.model.repo.NamedSearchFilterGroupRepo; From f1bf6f9586e630ab347799ea6627f6a8be298d3f Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 10:22:06 -0600 Subject: [PATCH 07/48] More cleanup --- .../vireo/service/ControlledVocabularyCachingService.java | 8 ++++++-- .../vireo/service/EntityControlledVocabularyService.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/ControlledVocabularyCachingService.java b/src/main/java/org/tdl/vireo/service/ControlledVocabularyCachingService.java index f512b84ae0..dfa5be9501 100644 --- a/src/main/java/org/tdl/vireo/service/ControlledVocabularyCachingService.java +++ b/src/main/java/org/tdl/vireo/service/ControlledVocabularyCachingService.java @@ -21,7 +21,11 @@ public class ControlledVocabularyCachingService { @Value("${app.cvcache.duration}") private Long duration; - private Map cvCacheMap = new HashMap(); + private final Map cvCacheMap; + + public ControlledVocabularyCachingService() { + cvCacheMap = new HashMap(); + } /** * @@ -63,7 +67,7 @@ public boolean doesControlledVocabularyExist(String controlledVocabularyName) { * Clear the cache. */ public void clearCache() { - cvCacheMap = new HashMap(); + cvCacheMap.clear(); } /** diff --git a/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java b/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java index 0aefe68fd8..d58d1a45fb 100644 --- a/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java +++ b/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java @@ -35,7 +35,7 @@ public class EntityControlledVocabularyService { @Autowired private ControlledVocabularyRepo controlledVocabularyRepo; - private Map> entityControlledVocabularyRepos; + private final Map> entityControlledVocabularyRepos; public EntityControlledVocabularyService() { entityControlledVocabularyRepos = new HashMap>(); From 5c6c0c4c81b239c327cf17ed795906bcf0f94084 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 10:55:02 -0600 Subject: [PATCH 08/48] Organize imports and return rule id in payload of create new email workflow rule --- .../controller/OrganizationController.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/OrganizationController.java b/src/main/java/org/tdl/vireo/controller/OrganizationController.java index daad654290..0fc46f64d5 100644 --- a/src/main/java/org/tdl/vireo/controller/OrganizationController.java +++ b/src/main/java/org/tdl/vireo/controller/OrganizationController.java @@ -9,15 +9,10 @@ import static org.springframework.beans.BeanUtils.copyProperties; import static org.springframework.web.bind.annotation.RequestMethod.POST; -import com.fasterxml.jackson.annotation.JsonView; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.tamu.weaver.response.ApiResponse; -import edu.tamu.weaver.response.ApiView; -import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel; -import edu.tamu.weaver.validation.aspect.annotation.WeaverValidation; +import java.util.HashMap; import java.util.Map; import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -47,6 +42,15 @@ import org.tdl.vireo.view.ShallowOrganizationView; import org.tdl.vireo.view.TreeOrganizationView; +import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import edu.tamu.weaver.response.ApiResponse; +import edu.tamu.weaver.response.ApiView; +import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel; +import edu.tamu.weaver.validation.aspect.annotation.WeaverValidation; + @RestController @RequestMapping("/organization") public class OrganizationController { @@ -253,6 +257,10 @@ public ApiResponse addEmailWorkflowRule(@PathVariable Long requestingOrgId, @Req EmailWorkflowRule newEmailWorkflowRule = emailWorkflowRuleRepo.create(submissionStatus, emailRecipient, emailTemplate); org.addEmailWorkflowRule(newEmailWorkflowRule); organizationRepo.update(org); + + HashMap payload = new HashMap(); + payload.put("id", newEmailWorkflowRule.getId()); + response.setPayload(payload); } return response; From e54aedb828d152a421fb9ec1ad4c441ab522bbe6 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 10:55:32 -0600 Subject: [PATCH 09/48] Use mock mvc to call controller in email workflow rule integration tests --- pom.xml | 6 +++ .../ControlledVocabularyIntegrationTest.java | 3 ++ .../EmailWorkflowRulesIntegrationTest.java | 51 ++++++++++++++----- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index ca0e102d30..aef8ab23fd 100644 --- a/pom.xml +++ b/pom.xml @@ -222,6 +222,12 @@ test + + org.springframework.security + spring-security-test + test + + org.mockito mockito-core diff --git a/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java index b183a664dc..5d19620896 100644 --- a/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/ControlledVocabularyIntegrationTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.tdl.vireo.model.repo.ControlledVocabularyRepo; public class ControlledVocabularyIntegrationTest extends AbstractIntegrationTest { @@ -21,6 +22,8 @@ public void setup() { controlledVocabularyRepo.create(TEST_CONTROLLED_VOCABULARY_NAME3); assertEquals(3, controlledVocabularyRepo.count()); + + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test diff --git a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java index 4612f3020c..090b2f5c53 100644 --- a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java @@ -2,24 +2,33 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.tdl.vireo.model.EmailRecipient; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.tdl.vireo.model.EmailTemplate; import org.tdl.vireo.model.EmailWorkflowRule; import org.tdl.vireo.model.Organization; import org.tdl.vireo.model.SubmissionStatus; -import org.tdl.vireo.model.repo.AbstractEmailRecipientRepo; import org.tdl.vireo.model.repo.EmailTemplateRepo; import org.tdl.vireo.model.repo.EmailWorkflowRuleRepo; import org.tdl.vireo.model.repo.OrganizationRepo; import org.tdl.vireo.model.repo.SubmissionStatusRepo; +import com.fasterxml.jackson.databind.JsonNode; + public class EmailWorkflowRulesIntegrationTest extends AbstractIntegrationTest { @Autowired @@ -28,9 +37,6 @@ public class EmailWorkflowRulesIntegrationTest extends AbstractIntegrationTest { @Autowired private EmailTemplateRepo emailTemplateRepo; - @Autowired - private AbstractEmailRecipientRepo abstractEmailRecipientRepo; - @Autowired private OrganizationRepo organizationRepo; @@ -42,9 +48,12 @@ public void setup() throws Exception { // takes a long time, try not to add more tests in this class systemDataLoader.loadSystemData(); entityControlledVocabularyService.scanForEntityControlledVocabularies(); + + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } @Test + @WithMockUser(roles = { "MANAGER" }) public void testEmailWorkflowRulePersistenceUponReload() throws Exception { Organization org = organizationRepo.findAll().get(0); @@ -54,18 +63,32 @@ public void testEmailWorkflowRulePersistenceUponReload() throws Exception { EmailTemplate emailTemplate = emailTemplateRepo.findAll().get(0); - EmailRecipient emailRecipient = abstractEmailRecipientRepo.findAll().get(0); + Long existingOrgWithNewWorkflowRuleId = org.getId(); + Long submissionStatusId = submissionStatus.getId(); + Long emailTemplateId = emailTemplate.getId(); - EmailWorkflowRule newEmailWorkflowRule = emailWorkflowRuleRepo.create(submissionStatus, emailRecipient, emailTemplate); - org.addEmailWorkflowRule(newEmailWorkflowRule); - organizationRepo.update(org); + JsonNode recipientNode = objectMapper.createObjectNode() + .put("type", "SUBMITTER"); - Long existingOrgWithNewWorkflowRuleId = org.getId(); - Long newlyCreatedEmailWorkflowRuleId = newEmailWorkflowRule.getId(); + Map data = new HashMap<>(); + data.put("recipient", recipientNode); + data.put("submissionStatusId", submissionStatusId); + data.put("templateId", emailTemplateId); + + MvcResult results = mockMvc.perform(post("/organization/{requestingOrgId}/add-email-workflow-rule", org.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.convertValue(data, JsonNode.class).toString().getBytes("utf-8")) + ) + .andExpect(status().isOk()).andExpect(jsonPath("$.meta.status").value("SUCCESS")) + .andExpect(jsonPath("$.payload.id").isNumber()) + .andReturn(); - int numberOfWorkflowRulesForOrg = org.getEmailWorkflowRules().size(); + Long newlyCreatedEmailWorkflowRuleId = objectMapper.readTree(results.getResponse().getContentAsString()) + .get("payload") + .get("id") + .asLong(); - assertEquals(3, numberOfWorkflowRulesForOrg); + assertEquals(3, org.getEmailWorkflowRules().size()); this.setup(); @@ -76,7 +99,7 @@ public void testEmailWorkflowRulePersistenceUponReload() throws Exception { List emailWorkflowRulesForOrg = newOrgRef.getEmailWorkflowRules(); - assertEquals(numberOfWorkflowRulesForOrg, emailWorkflowRulesForOrg.size()); + assertEquals(3, emailWorkflowRulesForOrg.size()); EmailWorkflowRule newEmailWorkflowRuleRef = emailWorkflowRulesForOrg.get(emailWorkflowRulesForOrg.size() - 1); From 0217b725858aeb881f9cd785b3d30a1c0684be68 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 11:16:33 -0600 Subject: [PATCH 10/48] Initial breaking system data loader test --- .../default_filter_columns.json | 2 +- .../vireo/service/SystemDataLoaderTest.java | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java diff --git a/src/main/resources/filter_columns/default_filter_columns.json b/src/main/resources/filter_columns/default_filter_columns.json index 583181c6d5..24ac54ffbc 100644 --- a/src/main/resources/filter_columns/default_filter_columns.json +++ b/src/main/resources/filter_columns/default_filter_columns.json @@ -2,7 +2,7 @@ { "inputType": { "name": "INPUT_TEXT" - }, + }, "title": "Search Box", "predicate": null }, diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java new file mode 100644 index 0000000000..6ca105e8ae --- /dev/null +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -0,0 +1,52 @@ +package org.tdl.vireo.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.tdl.vireo.Application; + +@SpringBootTest(classes = { Application.class }) +@Transactional(propagation = Propagation.REQUIRES_NEW) +public class SystemDataLoaderTest { + + @Autowired + private SystemDataLoader systemDataLoader; + + @Autowired + private ProquestCodesService proquesteCodesService; + + @Autowired + private DepositorService depositorService; + + @Autowired + private DefaultSettingsService defaultSettingsService; + + @Autowired + private DefaultSubmissionListColumnService defaultSubmissionListColumnService; + + @Autowired + private DefaultFiltersService defaultFiltersService; + + @Test + public void testLoadSystemData() throws Exception { + systemDataLoader.loadSystemData(); + this.assertPersistedSystemData(false); + + // reload to ensure nothing changes + // this breaks the in memory defaults + // technically the cache clears after restart + // however, this is still an undesired side effect of load system data + systemDataLoader.loadSystemData(); + this.assertPersistedSystemData(true); + } + + private void assertPersistedSystemData(boolean isReload) { + assertEquals(10, this.defaultSubmissionListColumnService.getDefaultSubmissionListColumns().size(), isReload ? "Incorrect number of default submission list columns" : "Incorrect number of default submission list columns after reload"); + assertEquals(5, this.defaultFiltersService.getDefaultFilter().size(), isReload ? "Incorrect number of default filters" : "Incorrect number of default filters after reload"); + } + +} From 78309e374310caecc44a5d4b8b41e29863acd16f Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 12:40:22 -0600 Subject: [PATCH 11/48] Decouple submission list column default services --- .../tdl/vireo/ApplicationInitialization.java | 17 ++++--- .../org/tdl/vireo/config/AppEmailConfig.java | 2 +- src/main/java/org/tdl/vireo/model/User.java | 3 ++ .../vireo/model/listener/UserListener.java | 38 ++++++++++++++ .../vireo/model/repo/impl/UserRepoImpl.java | 16 ++---- .../vireo/service/DefaultFiltersService.java | 49 +++++++++++++++++-- .../vireo/service/DefaultSettingsService.java | 1 + .../DefaultSubmissionListColumnService.java | 49 +++++++++++++++++-- .../tdl/vireo/service/DepositorService.java | 1 + .../vireo/service/ProquestCodesService.java | 1 + .../tdl/vireo/service/SystemDataLoader.java | 36 ++------------ .../default_filter_columns.json | 2 +- .../controller/AbstractControllerTest.java | 2 +- .../vireo/controller/AuthControllerTest.java | 2 +- .../ConfigurableSettingsControllerTest.java | 2 +- .../ControlledVocabularyControllerTest.java | 2 +- .../CustomActionControllerTest.java | 2 +- .../controller/DegreeControllerTest.java | 2 +- .../controller/DegreeLevelControllerTest.java | 2 +- .../DepositLocationControllerTest.java | 2 +- .../DocumentTypeControllerTest.java | 2 +- .../EmailTemplateControllerTest.java | 2 +- .../controller/EmbargoControllerTest.java | 2 +- .../FieldPredicateControllerTest.java | 2 +- .../FieldProfileControllerTest.java | 2 +- .../GraduationMonthControllerTest.java | 2 +- .../controller/InputTypeControllerTest.java | 2 +- .../controller/LanguageControllerTest.java | 2 +- .../controller/LookAndFeelControllerTest.java | 2 +- .../vireo/controller/NoteControllerTest.java | 2 +- .../OrganizationCategoryControllerTest.java | 2 +- .../OrganizationControllerTest.java | 2 +- .../controller/PackagerControllerTest.java | 2 +- .../controller/SubmissionControllerTest.java | 2 +- .../SubmissionListControllerTest.java | 2 +- .../SubmissionStatusControllerTest.java | 2 +- .../vireo/controller/UserControllerTest.java | 2 +- .../WorkflowStepControllerTest.java | 2 +- .../integration/AbstractIntegrationTest.java | 2 +- .../EmailWorkflowRulesIntegrationTest.java | 2 +- .../org/tdl/vireo/model/AbstractEnumTest.java | 2 +- .../model/AbstractModelCustomMethodTest.java | 2 +- .../tdl/vireo/model/AbstractModelTest.java | 2 +- .../vireo/model/repo/AbstractRepoTest.java | 2 +- .../tdl/vireo/model/response/ViewsTest.java | 2 +- ...ontrolledVocabularyCachingServiceTest.java | 2 +- .../vireo/service/EntityCVServiceTest.java | 2 +- .../service/OrderedEntityServiceTest.java | 2 +- .../service/SubmissionEmailServiceTest.java | 2 +- .../vireo/service/SystemDataLoaderTest.java | 8 +-- 50 files changed, 196 insertions(+), 101 deletions(-) create mode 100644 src/main/java/org/tdl/vireo/model/listener/UserListener.java diff --git a/src/main/java/org/tdl/vireo/ApplicationInitialization.java b/src/main/java/org/tdl/vireo/ApplicationInitialization.java index 2412ed0d4a..9f5069e534 100644 --- a/src/main/java/org/tdl/vireo/ApplicationInitialization.java +++ b/src/main/java/org/tdl/vireo/ApplicationInitialization.java @@ -3,18 +3,21 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; -import org.springframework.context.annotation.Profile; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; +import org.springframework.core.env.Environment; +import org.springframework.core.env.Profiles; import org.springframework.stereotype.Component; import org.tdl.vireo.service.EntityControlledVocabularyService; import org.tdl.vireo.service.SystemDataLoader; @Order(Ordered.HIGHEST_PRECEDENCE) @Component("ApplicationInitialization") -@Profile("!test") public class ApplicationInitialization implements InitializingBean { + @Autowired + private Environment env; + @Lazy @Autowired private SystemDataLoader systemDataLoader; @@ -25,10 +28,12 @@ public class ApplicationInitialization implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { - // load defaults first - systemDataLoader.loadSystemData(); - // assumes one language defined in defaults - entityControlledVocabularyService.scanForEntityControlledVocabularies(); + if (env.acceptsProfiles(Profiles.of("!isolated-test"))) { + // load defaults first + systemDataLoader.loadSystemData(); + // assumes one language defined in defaults + entityControlledVocabularyService.scanForEntityControlledVocabularies(); + } } } diff --git a/src/main/java/org/tdl/vireo/config/AppEmailConfig.java b/src/main/java/org/tdl/vireo/config/AppEmailConfig.java index 7b55c37c5e..c4fba8c32e 100644 --- a/src/main/java/org/tdl/vireo/config/AppEmailConfig.java +++ b/src/main/java/org/tdl/vireo/config/AppEmailConfig.java @@ -9,7 +9,7 @@ import edu.tamu.weaver.email.service.EmailSender; @Configuration -@Profile(value = { "!test" }) +@Profile(value = { "!test", "!isolated-test" }) public class AppEmailConfig extends WeaverEmailConfig { @Bean diff --git a/src/main/java/org/tdl/vireo/model/User.java b/src/main/java/org/tdl/vireo/model/User.java index ff1ded4b8f..87a9d9fc4a 100644 --- a/src/main/java/org/tdl/vireo/model/User.java +++ b/src/main/java/org/tdl/vireo/model/User.java @@ -19,6 +19,7 @@ import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.EntityListeners; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.ManyToMany; @@ -33,6 +34,7 @@ import org.hibernate.annotations.Formula; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.tdl.vireo.model.listener.UserListener; import org.tdl.vireo.model.response.Views; import org.tdl.vireo.model.validation.UserValidator; @@ -46,6 +48,7 @@ import edu.tamu.weaver.user.model.IRole; @Entity +@EntityListeners(UserListener.class) @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" }) public class User extends AbstractWeaverUserDetails { diff --git a/src/main/java/org/tdl/vireo/model/listener/UserListener.java b/src/main/java/org/tdl/vireo/model/listener/UserListener.java new file mode 100644 index 0000000000..69ad28bd40 --- /dev/null +++ b/src/main/java/org/tdl/vireo/model/listener/UserListener.java @@ -0,0 +1,38 @@ +package org.tdl.vireo.model.listener; + +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.core.env.Environment; +import org.springframework.core.env.Profiles; +import org.springframework.stereotype.Component; +import org.tdl.vireo.model.User; +import org.tdl.vireo.service.DefaultFiltersService; +import org.tdl.vireo.service.DefaultSubmissionListColumnService; + +@Component +public class UserListener { + + @Autowired + private Environment env; + + @Lazy + @Autowired + private DefaultFiltersService defaultFiltersService; + + @Lazy + @Autowired + private DefaultSubmissionListColumnService defaultSubmissionViewColumnService; + + @PrePersist + @PreUpdate + private void beforeAnyUpdate(User user) { + if (env.acceptsProfiles(Profiles.of("!isolated-test"))) { + user.setFilterColumns(defaultFiltersService.getDefaultFilter()); + user.setSubmissionViewColumns(defaultSubmissionViewColumnService.getDefaultSubmissionListColumns()); + } + } + +} diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java index 6b01fe4b12..fa543b4641 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/UserRepoImpl.java @@ -2,10 +2,9 @@ import static edu.tamu.weaver.response.ApiStatus.SUCCESS; -import edu.tamu.weaver.data.model.repo.impl.AbstractWeaverRepoImpl; -import edu.tamu.weaver.response.ApiResponse; import java.util.ArrayList; import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.tdl.vireo.model.NamedSearchFilter; @@ -17,8 +16,9 @@ import org.tdl.vireo.model.repo.NamedSearchFilterRepo; import org.tdl.vireo.model.repo.UserRepo; import org.tdl.vireo.model.repo.custom.UserRepoCustom; -import org.tdl.vireo.service.DefaultFiltersService; -import org.tdl.vireo.service.DefaultSubmissionListColumnService; + +import edu.tamu.weaver.data.model.repo.impl.AbstractWeaverRepoImpl; +import edu.tamu.weaver.response.ApiResponse; public class UserRepoImpl extends AbstractWeaverRepoImpl implements UserRepoCustom { @@ -28,12 +28,6 @@ public class UserRepoImpl extends AbstractWeaverRepoImpl impleme @Autowired private NamedSearchFilterGroupRepo namedSearchFilterGroupRepo; - @Autowired - private DefaultFiltersService defaultFiltersService; - - @Autowired - private DefaultSubmissionListColumnService defaultSubmissionViewColumnService; - @Autowired private NamedSearchFilterRepo namedSearchFilterRepo; @@ -56,8 +50,6 @@ private User saveAndAddSettings(User user) { user.putSetting("id", user.getId().toString()); user.putSetting("displayName", user.getFirstName() + " " + user.getLastName()); user.putSetting("preferedEmail", user.getEmail()); - user.setFilterColumns(defaultFiltersService.getDefaultFilter()); - user.setSubmissionViewColumns(defaultSubmissionViewColumnService.getDefaultSubmissionListColumns()); return userRepo.update(user); } diff --git a/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java b/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java index 4e2de9f4e9..3c2b0bf154 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java @@ -1,26 +1,67 @@ package org.tdl.vireo.service; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.DependsOn; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.stereotype.Service; import org.tdl.vireo.model.SubmissionListColumn; +import org.tdl.vireo.model.repo.SubmissionListColumnRepo; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; @Service +@DependsOn("ApplicationInitialization") public class DefaultFiltersService { + private final Logger logger = LoggerFactory.getLogger(DefaultFiltersService.class); + private final List defaultFilters; + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private ResourcePatternResolver resourcePatternResolver; + + @Autowired + private SubmissionListColumnRepo submissionListColumnRepo; + public DefaultFiltersService() { this.defaultFilters = new ArrayList(); } - public List getDefaultFilter() { - return defaultFilters; + @PostConstruct + public void init() throws StreamReadException, DatabindException, IOException { + logger.info("Loading default filter columns"); + + Resource resource = resourcePatternResolver.getResource("classpath:/filter_columns/default_filter_columns.json"); + List defaultFilterColumns = objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + + for (SubmissionListColumn defaultFilterColumn : defaultFilterColumns) { + SubmissionListColumn dbDefaultFilterColumn = submissionListColumnRepo.findByTitle(defaultFilterColumn.getTitle()); + if (dbDefaultFilterColumn != null) { + this.defaultFilters.add(dbDefaultFilterColumn); + } else { + logger.warn("Unable to find default filter for column " + defaultFilterColumn.getTitle() + "!"); + } + } } - public void addDefaultFilter(SubmissionListColumn defaultFilter) { - this.defaultFilters.add(defaultFilter); + public List getDefaultFilter() { + return Collections.unmodifiableList(defaultFilters); } } diff --git a/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java b/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java index 2bc02843f9..a92a09e4c6 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java @@ -11,6 +11,7 @@ @Service public class DefaultSettingsService { + // TODO: make list immutable after setting default values private final List defaultSettings; public DefaultSettingsService() { diff --git a/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java b/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java index 057445570b..3674b88e3a 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java @@ -1,26 +1,67 @@ package org.tdl.vireo.service; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.DependsOn; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.stereotype.Service; import org.tdl.vireo.model.SubmissionListColumn; +import org.tdl.vireo.model.repo.SubmissionListColumnRepo; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; @Service +@DependsOn("ApplicationInitialization") public class DefaultSubmissionListColumnService { + private final Logger logger = LoggerFactory.getLogger(DefaultSubmissionListColumnService.class); + private final List defaultSubmissionListColumns; + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private ResourcePatternResolver resourcePatternResolver; + + @Autowired + private SubmissionListColumnRepo submissionListColumnRepo; + public DefaultSubmissionListColumnService() { this.defaultSubmissionListColumns = new ArrayList(); } - public List getDefaultSubmissionListColumns() { - return defaultSubmissionListColumns; + @PostConstruct + public void init() throws StreamReadException, DatabindException, IOException { + logger.info("Loading default Submission List Columns"); + + Resource resource = resourcePatternResolver.getResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"); + String[] defaultSubmissionListColumnTitles = objectMapper.readValue(resource.getInputStream(), new TypeReference() { }); + + for (String defaultTitle : defaultSubmissionListColumnTitles) { + SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); + if (dbSubmissionListColumn != null) { + this.defaultSubmissionListColumns.add(dbSubmissionListColumn); + } else { + logger.warn("Unable to find submission list column with title " + defaultTitle); + } + } } - public void addDefaultSubmissionListColumn(SubmissionListColumn defaultSubmissionListColumn) { - this.defaultSubmissionListColumns.add(defaultSubmissionListColumn); + public List getDefaultSubmissionListColumns() { + return Collections.unmodifiableList(defaultSubmissionListColumns); } } diff --git a/src/main/java/org/tdl/vireo/service/DepositorService.java b/src/main/java/org/tdl/vireo/service/DepositorService.java index 8548780fed..b87f3eb593 100644 --- a/src/main/java/org/tdl/vireo/service/DepositorService.java +++ b/src/main/java/org/tdl/vireo/service/DepositorService.java @@ -9,6 +9,7 @@ @Service public class DepositorService { + // TODO: make map immutable after setting values private final Map depositors; public DepositorService() { diff --git a/src/main/java/org/tdl/vireo/service/ProquestCodesService.java b/src/main/java/org/tdl/vireo/service/ProquestCodesService.java index d2c21b4d3e..06a2fa36b5 100644 --- a/src/main/java/org/tdl/vireo/service/ProquestCodesService.java +++ b/src/main/java/org/tdl/vireo/service/ProquestCodesService.java @@ -8,6 +8,7 @@ @Service public class ProquestCodesService { + // TODO: make map immutable after setting values private final Map> codes; public ProquestCodesService() { diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 95a6264af8..9bac834a45 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -104,6 +104,7 @@ public class SystemDataLoader { @Autowired private ResourcePatternResolver resourcePatternResolver; + // TODO: replace use with the ResourcePatternResolver for loading system data @Autowired private AssetService fileIOUtility; @@ -182,12 +183,6 @@ public class SystemDataLoader { @Autowired private DefaultSettingsService defaultSettingsService; - @Autowired - private DefaultSubmissionListColumnService defaultSubmissionListColumnService; - - @Autowired - private DefaultFiltersService defaultFiltersService; - @Transactional public void loadSystemData() { @@ -242,9 +237,6 @@ public void loadSystemData() { logger.info("Loading default Submission List Columns"); loadSubmissionListColumns(); - logger.info("Loading default Submission List Columns Filters"); - loadSubmissionListColumnsFilters(); - logger.info("Loading default Packagers"); loadPackagers(); @@ -832,18 +824,15 @@ private void loadSubmissionListColumns() { } try { - - String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { - }); + String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); int count = 0; for (String defaultTitle : defaultSubmissionListColumnTitles) { SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); if (dbSubmissionListColumn != null) { if (dbSubmissionListColumn.getSort() != Sort.NONE) { + logger.warn("Updating sort order for default submission list column with title " + defaultTitle); dbSubmissionListColumn.setSortOrder(++count); - defaultSubmissionListColumnService.addDefaultSubmissionListColumn(submissionListColumnRepo.save(dbSubmissionListColumn)); - } else { - defaultSubmissionListColumnService.addDefaultSubmissionListColumn(dbSubmissionListColumn); + submissionListColumnRepo.update(dbSubmissionListColumn); } } else { logger.warn("Unable to find submission list column with title " + defaultTitle); @@ -857,23 +846,6 @@ private void loadSubmissionListColumns() { } - private void loadSubmissionListColumnsFilters() { - try { - List defaultFilterColumns = objectMapper.readValue(getFileFromResource("classpath:/filter_columns/default_filter_columns.json"), new TypeReference>() {}); - - for (SubmissionListColumn defaultFilterColumn : defaultFilterColumns) { - SubmissionListColumn dbDefaultFilterColumn = submissionListColumnRepo.findByTitle(defaultFilterColumn.getTitle()); - if (dbDefaultFilterColumn != null) { - defaultFiltersService.addDefaultFilter(dbDefaultFilterColumn); - } else { - logger.warn("Unable to find default filter for column " + defaultFilterColumn.getTitle() + "!"); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - private List getAllSystemEmailTemplateNames() { try { diff --git a/src/main/resources/filter_columns/default_filter_columns.json b/src/main/resources/filter_columns/default_filter_columns.json index 24ac54ffbc..17b9c8b6ed 100644 --- a/src/main/resources/filter_columns/default_filter_columns.json +++ b/src/main/resources/filter_columns/default_filter_columns.json @@ -17,7 +17,7 @@ "inputType": { "name": "INPUT_TEXT" }, - "title": "Assigned to", + "title": "Assigned To", "predicate": null }, { diff --git a/src/test/java/org/tdl/vireo/controller/AbstractControllerTest.java b/src/test/java/org/tdl/vireo/controller/AbstractControllerTest.java index da691f93fe..08e07ada1c 100644 --- a/src/test/java/org/tdl/vireo/controller/AbstractControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/AbstractControllerTest.java @@ -22,7 +22,7 @@ import org.tdl.vireo.mock.MockData; import org.tdl.vireo.utility.TemplateUtility; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @ExtendWith(MockitoExtension.class) @ExtendWith(SpringExtension.class) public abstract class AbstractControllerTest extends MockData { diff --git a/src/test/java/org/tdl/vireo/controller/AuthControllerTest.java b/src/test/java/org/tdl/vireo/controller/AuthControllerTest.java index c3632b0a00..2623b501b8 100644 --- a/src/test/java/org/tdl/vireo/controller/AuthControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/AuthControllerTest.java @@ -37,7 +37,7 @@ import org.tdl.vireo.model.repo.UserRepo; import org.tdl.vireo.service.VireoEmailSender; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class AuthControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/ConfigurableSettingsControllerTest.java b/src/test/java/org/tdl/vireo/controller/ConfigurableSettingsControllerTest.java index 582093f706..5776ea1c2b 100644 --- a/src/test/java/org/tdl/vireo/controller/ConfigurableSettingsControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/ConfigurableSettingsControllerTest.java @@ -25,7 +25,7 @@ import org.tdl.vireo.model.repo.ConfigurationRepo; import org.tdl.vireo.service.VireoThemeManagerService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class ConfigurableSettingsControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/ControlledVocabularyControllerTest.java b/src/test/java/org/tdl/vireo/controller/ControlledVocabularyControllerTest.java index 144f660cb7..4e759eccf2 100644 --- a/src/test/java/org/tdl/vireo/controller/ControlledVocabularyControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/ControlledVocabularyControllerTest.java @@ -36,7 +36,7 @@ import org.tdl.vireo.service.ControlledVocabularyCachingService; @SpringBootTest(classes = { Application.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class ControlledVocabularyControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/CustomActionControllerTest.java b/src/test/java/org/tdl/vireo/controller/CustomActionControllerTest.java index 24caa203fe..3ceda82701 100644 --- a/src/test/java/org/tdl/vireo/controller/CustomActionControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/CustomActionControllerTest.java @@ -20,7 +20,7 @@ import org.tdl.vireo.model.CustomActionDefinition; import org.tdl.vireo.model.repo.CustomActionDefinitionRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class CustomActionControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/DegreeControllerTest.java b/src/test/java/org/tdl/vireo/controller/DegreeControllerTest.java index 4c14c2f8a8..59d1a5bd48 100644 --- a/src/test/java/org/tdl/vireo/controller/DegreeControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/DegreeControllerTest.java @@ -24,7 +24,7 @@ import org.tdl.vireo.model.repo.DegreeRepo; import org.tdl.vireo.service.ProquestCodesService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class DegreeControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/DegreeLevelControllerTest.java b/src/test/java/org/tdl/vireo/controller/DegreeLevelControllerTest.java index cdd9701944..74a86685d0 100644 --- a/src/test/java/org/tdl/vireo/controller/DegreeLevelControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/DegreeLevelControllerTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.model.DegreeLevel; import org.tdl.vireo.model.repo.DegreeLevelRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class DegreeLevelControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/DepositLocationControllerTest.java b/src/test/java/org/tdl/vireo/controller/DepositLocationControllerTest.java index ce50fc0bc7..4c48ba698f 100644 --- a/src/test/java/org/tdl/vireo/controller/DepositLocationControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/DepositLocationControllerTest.java @@ -25,7 +25,7 @@ import org.tdl.vireo.model.repo.DepositLocationRepo; import org.tdl.vireo.service.DepositorService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class DepositLocationControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/DocumentTypeControllerTest.java b/src/test/java/org/tdl/vireo/controller/DocumentTypeControllerTest.java index f63a31a4b4..5d810672c7 100644 --- a/src/test/java/org/tdl/vireo/controller/DocumentTypeControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/DocumentTypeControllerTest.java @@ -22,7 +22,7 @@ import org.tdl.vireo.model.FieldPredicate; import org.tdl.vireo.model.repo.DocumentTypeRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class DocumentTypeControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/EmailTemplateControllerTest.java b/src/test/java/org/tdl/vireo/controller/EmailTemplateControllerTest.java index dd29446290..9cd953bcb3 100644 --- a/src/test/java/org/tdl/vireo/controller/EmailTemplateControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/EmailTemplateControllerTest.java @@ -20,7 +20,7 @@ import org.tdl.vireo.model.EmailTemplate; import org.tdl.vireo.model.repo.EmailTemplateRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class EmailTemplateControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/EmbargoControllerTest.java b/src/test/java/org/tdl/vireo/controller/EmbargoControllerTest.java index 464c5253b0..5be0a051bf 100644 --- a/src/test/java/org/tdl/vireo/controller/EmbargoControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/EmbargoControllerTest.java @@ -22,7 +22,7 @@ import org.tdl.vireo.model.EmbargoGuarantor; import org.tdl.vireo.model.repo.EmbargoRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class EmbargoControllerTest extends AbstractControllerTest { protected static final String EMBARGO_NAME = "Embargo Name"; diff --git a/src/test/java/org/tdl/vireo/controller/FieldPredicateControllerTest.java b/src/test/java/org/tdl/vireo/controller/FieldPredicateControllerTest.java index 5ef731da7d..a63d6a2a7b 100644 --- a/src/test/java/org/tdl/vireo/controller/FieldPredicateControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/FieldPredicateControllerTest.java @@ -20,7 +20,7 @@ import org.tdl.vireo.model.FieldPredicate; import org.tdl.vireo.model.repo.FieldPredicateRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class FieldPredicateControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/FieldProfileControllerTest.java b/src/test/java/org/tdl/vireo/controller/FieldProfileControllerTest.java index ccccba637c..3e72fec328 100644 --- a/src/test/java/org/tdl/vireo/controller/FieldProfileControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/FieldProfileControllerTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.model.FieldProfile; import org.tdl.vireo.model.repo.FieldProfileRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class FieldProfileControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/GraduationMonthControllerTest.java b/src/test/java/org/tdl/vireo/controller/GraduationMonthControllerTest.java index 45b849dd2b..ef519d5731 100644 --- a/src/test/java/org/tdl/vireo/controller/GraduationMonthControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/GraduationMonthControllerTest.java @@ -21,7 +21,7 @@ import org.tdl.vireo.model.GraduationMonth; import org.tdl.vireo.model.repo.GraduationMonthRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class GraduationMonthControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/InputTypeControllerTest.java b/src/test/java/org/tdl/vireo/controller/InputTypeControllerTest.java index 6083efb904..29d7d4b52d 100644 --- a/src/test/java/org/tdl/vireo/controller/InputTypeControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/InputTypeControllerTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.model.InputType; import org.tdl.vireo.model.repo.InputTypeRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class InputTypeControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/LanguageControllerTest.java b/src/test/java/org/tdl/vireo/controller/LanguageControllerTest.java index 6374825a0c..d7d70169a8 100644 --- a/src/test/java/org/tdl/vireo/controller/LanguageControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/LanguageControllerTest.java @@ -23,7 +23,7 @@ import org.tdl.vireo.model.repo.LanguageRepo; import org.tdl.vireo.service.ProquestCodesService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class LanguageControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/LookAndFeelControllerTest.java b/src/test/java/org/tdl/vireo/controller/LookAndFeelControllerTest.java index e720150835..c242991d81 100644 --- a/src/test/java/org/tdl/vireo/controller/LookAndFeelControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/LookAndFeelControllerTest.java @@ -21,7 +21,7 @@ import org.tdl.vireo.model.repo.ConfigurationRepo; import org.tdl.vireo.service.AssetService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class LookAndFeelControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/NoteControllerTest.java b/src/test/java/org/tdl/vireo/controller/NoteControllerTest.java index 4f27f78794..39467856ef 100644 --- a/src/test/java/org/tdl/vireo/controller/NoteControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/NoteControllerTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.model.Note; import org.tdl.vireo.model.repo.NoteRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class NoteControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/OrganizationCategoryControllerTest.java b/src/test/java/org/tdl/vireo/controller/OrganizationCategoryControllerTest.java index 1d24a41cca..e3f73fb83b 100644 --- a/src/test/java/org/tdl/vireo/controller/OrganizationCategoryControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/OrganizationCategoryControllerTest.java @@ -20,7 +20,7 @@ import org.tdl.vireo.model.OrganizationCategory; import org.tdl.vireo.model.repo.OrganizationCategoryRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class OrganizationCategoryControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/OrganizationControllerTest.java b/src/test/java/org/tdl/vireo/controller/OrganizationControllerTest.java index 23334147a0..6790712cfc 100644 --- a/src/test/java/org/tdl/vireo/controller/OrganizationControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/OrganizationControllerTest.java @@ -53,7 +53,7 @@ import org.tdl.vireo.model.repo.SubmissionStatusRepo; import org.tdl.vireo.model.repo.WorkflowStepRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class OrganizationControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/PackagerControllerTest.java b/src/test/java/org/tdl/vireo/controller/PackagerControllerTest.java index d587fef32b..b581eba546 100644 --- a/src/test/java/org/tdl/vireo/controller/PackagerControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/PackagerControllerTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.model.packager.AbstractPackager; import org.tdl.vireo.model.repo.AbstractPackagerRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class PackagerControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/SubmissionControllerTest.java b/src/test/java/org/tdl/vireo/controller/SubmissionControllerTest.java index 4f0e551106..093ac657b8 100644 --- a/src/test/java/org/tdl/vireo/controller/SubmissionControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/SubmissionControllerTest.java @@ -27,7 +27,7 @@ import org.tdl.vireo.model.User; import org.tdl.vireo.model.repo.ActionLogRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class SubmissionControllerTest extends AbstractControllerTest { private static final String TEST_USER_1_EMAIL = "User 1 email"; diff --git a/src/test/java/org/tdl/vireo/controller/SubmissionListControllerTest.java b/src/test/java/org/tdl/vireo/controller/SubmissionListControllerTest.java index e1bea5d673..0ecdcc6fe4 100644 --- a/src/test/java/org/tdl/vireo/controller/SubmissionListControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/SubmissionListControllerTest.java @@ -37,7 +37,7 @@ import org.tdl.vireo.model.repo.UserRepo; import org.tdl.vireo.service.DefaultSubmissionListColumnService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class SubmissionListControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/SubmissionStatusControllerTest.java b/src/test/java/org/tdl/vireo/controller/SubmissionStatusControllerTest.java index dc103ce2da..2a979fcbe3 100644 --- a/src/test/java/org/tdl/vireo/controller/SubmissionStatusControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/SubmissionStatusControllerTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.model.SubmissionStatus; import org.tdl.vireo.model.repo.SubmissionStatusRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class SubmissionStatusControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/UserControllerTest.java b/src/test/java/org/tdl/vireo/controller/UserControllerTest.java index 7461fd962c..7935bca65d 100644 --- a/src/test/java/org/tdl/vireo/controller/UserControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/UserControllerTest.java @@ -34,7 +34,7 @@ import org.tdl.vireo.model.repo.UserRepo; import org.tdl.vireo.model.request.FilteredPageRequest; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class UserControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java b/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java index 6ef4288224..f4ab1d899d 100644 --- a/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java @@ -36,7 +36,7 @@ import org.tdl.vireo.model.repo.OrganizationRepo; import org.tdl.vireo.model.repo.WorkflowStepRepo; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class WorkflowStepControllerTest extends AbstractControllerTest { @Mock diff --git a/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java index b23938cdc3..a73884430a 100644 --- a/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/AbstractIntegrationTest.java @@ -16,7 +16,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @SpringBootTest(classes = { Application.class }) @Transactional(propagation = Propagation.REQUIRES_NEW) public abstract class AbstractIntegrationTest extends MockData { diff --git a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java index 090b2f5c53..e904ec2070 100644 --- a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java @@ -45,7 +45,7 @@ public class EmailWorkflowRulesIntegrationTest extends AbstractIntegrationTest { @BeforeEach public void setup() throws Exception { - // takes a long time, try not to add more tests in this class + // takes a long time, try not to add more tests in this class or switch to static @BeforeAll systemDataLoader.loadSystemData(); entityControlledVocabularyService.scanForEntityControlledVocabularies(); diff --git a/src/test/java/org/tdl/vireo/model/AbstractEnumTest.java b/src/test/java/org/tdl/vireo/model/AbstractEnumTest.java index 289879edc5..264640cef9 100644 --- a/src/test/java/org/tdl/vireo/model/AbstractEnumTest.java +++ b/src/test/java/org/tdl/vireo/model/AbstractEnumTest.java @@ -8,7 +8,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ActiveProfiles; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @ExtendWith(MockitoExtension.class) public abstract class AbstractEnumTest> { diff --git a/src/test/java/org/tdl/vireo/model/AbstractModelCustomMethodTest.java b/src/test/java/org/tdl/vireo/model/AbstractModelCustomMethodTest.java index 3050d7f8f2..7f0f2196e1 100644 --- a/src/test/java/org/tdl/vireo/model/AbstractModelCustomMethodTest.java +++ b/src/test/java/org/tdl/vireo/model/AbstractModelCustomMethodTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.util.ReflectionTestUtils; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public abstract class AbstractModelCustomMethodTest extends AbstractModelTest { /** diff --git a/src/test/java/org/tdl/vireo/model/AbstractModelTest.java b/src/test/java/org/tdl/vireo/model/AbstractModelTest.java index ab623a5109..d259b6e46f 100644 --- a/src/test/java/org/tdl/vireo/model/AbstractModelTest.java +++ b/src/test/java/org/tdl/vireo/model/AbstractModelTest.java @@ -9,7 +9,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.util.ReflectionTestUtils; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @ExtendWith(MockitoExtension.class) public abstract class AbstractModelTest { diff --git a/src/test/java/org/tdl/vireo/model/repo/AbstractRepoTest.java b/src/test/java/org/tdl/vireo/model/repo/AbstractRepoTest.java index 9bded16789..80c272910c 100644 --- a/src/test/java/org/tdl/vireo/model/repo/AbstractRepoTest.java +++ b/src/test/java/org/tdl/vireo/model/repo/AbstractRepoTest.java @@ -38,7 +38,7 @@ import org.tdl.vireo.model.packager.Packager; import org.tdl.vireo.service.EntityControlledVocabularyService; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @SpringBootTest(classes = { Application.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public abstract class AbstractRepoTest { diff --git a/src/test/java/org/tdl/vireo/model/response/ViewsTest.java b/src/test/java/org/tdl/vireo/model/response/ViewsTest.java index b1065d7841..b7f4d1d4ac 100644 --- a/src/test/java/org/tdl/vireo/model/response/ViewsTest.java +++ b/src/test/java/org/tdl/vireo/model/response/ViewsTest.java @@ -11,7 +11,7 @@ import org.tdl.vireo.model.response.Views.SubmissionIndividualActionLogs; import org.tdl.vireo.model.response.Views.SubmissionList; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) public class ViewsTest { @Test diff --git a/src/test/java/org/tdl/vireo/service/ControlledVocabularyCachingServiceTest.java b/src/test/java/org/tdl/vireo/service/ControlledVocabularyCachingServiceTest.java index 3d28b249c9..72838bfaf6 100644 --- a/src/test/java/org/tdl/vireo/service/ControlledVocabularyCachingServiceTest.java +++ b/src/test/java/org/tdl/vireo/service/ControlledVocabularyCachingServiceTest.java @@ -16,7 +16,7 @@ import org.tdl.vireo.Application; import org.tdl.vireo.model.ControlledVocabularyCache; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @SpringBootTest(classes = { Application.class }) @ContextConfiguration public class ControlledVocabularyCachingServiceTest { diff --git a/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java b/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java index 07949ecb65..8e1915dc4b 100644 --- a/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java +++ b/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.ActiveProfiles; import org.tdl.vireo.Application; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @SpringBootTest(classes = { Application.class }) public class EntityCVServiceTest { diff --git a/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java b/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java index c560f6eb15..5c716b64fe 100644 --- a/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java +++ b/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.ActiveProfiles; import org.tdl.vireo.Application; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @SpringBootTest(classes = { Application.class }) public class OrderedEntityServiceTest { diff --git a/src/test/java/org/tdl/vireo/service/SubmissionEmailServiceTest.java b/src/test/java/org/tdl/vireo/service/SubmissionEmailServiceTest.java index 77819c9f59..a3bf251422 100644 --- a/src/test/java/org/tdl/vireo/service/SubmissionEmailServiceTest.java +++ b/src/test/java/org/tdl/vireo/service/SubmissionEmailServiceTest.java @@ -60,7 +60,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; -@ActiveProfiles("test") +@ActiveProfiles(value = { "test", "isolated-test" }) @ExtendWith(MockitoExtension.class) @SpringBootTest(classes = { Application.class }) public class SubmissionEmailServiceTest extends MockData { diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java index 6ca105e8ae..613283fc71 100644 --- a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -5,10 +5,12 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.tdl.vireo.Application; +@ActiveProfiles(value = { "test" }) @SpringBootTest(classes = { Application.class }) @Transactional(propagation = Propagation.REQUIRES_NEW) public class SystemDataLoaderTest { @@ -33,11 +35,9 @@ public class SystemDataLoaderTest { @Test public void testLoadSystemData() throws Exception { - systemDataLoader.loadSystemData(); this.assertPersistedSystemData(false); // reload to ensure nothing changes - // this breaks the in memory defaults // technically the cache clears after restart // however, this is still an undesired side effect of load system data systemDataLoader.loadSystemData(); @@ -45,8 +45,8 @@ public void testLoadSystemData() throws Exception { } private void assertPersistedSystemData(boolean isReload) { - assertEquals(10, this.defaultSubmissionListColumnService.getDefaultSubmissionListColumns().size(), isReload ? "Incorrect number of default submission list columns" : "Incorrect number of default submission list columns after reload"); - assertEquals(5, this.defaultFiltersService.getDefaultFilter().size(), isReload ? "Incorrect number of default filters" : "Incorrect number of default filters after reload"); + assertEquals(10, this.defaultSubmissionListColumnService.getDefaultSubmissionListColumns().size(), isReload ? "Incorrect number of default submission list columns after reload" : "Incorrect number of default submission list columns"); + assertEquals(5, this.defaultFiltersService.getDefaultFilter().size(), isReload ? "Incorrect number of default filters after reload" : "Incorrect number of default filters"); } } From 2caff3e984088ba905993d54b1acccb92a1118c0 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 12:43:06 -0600 Subject: [PATCH 12/48] Fix broken test due to immutable in memory defaults --- .../EmailWorkflowRulesIntegrationTest.java | 7 ------- .../org/tdl/vireo/service/SystemDataLoaderTest.java | 11 +++++++++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java index e904ec2070..5f18cdee00 100644 --- a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java @@ -10,7 +10,6 @@ import java.util.List; import java.util.Map; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -106,10 +105,4 @@ public void testEmailWorkflowRulePersistenceUponReload() throws Exception { assertEquals(newlyCreatedEmailWorkflowRuleId, newEmailWorkflowRuleRef.getId()); } - @AfterEach - public void cleanup() { - defaultFiltersService.getDefaultFilter().clear(); - defaultSubmissionListColumnService.getDefaultSubmissionListColumns().clear(); - } - } diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java index 613283fc71..18d3d03b2d 100644 --- a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -45,8 +45,15 @@ public void testLoadSystemData() throws Exception { } private void assertPersistedSystemData(boolean isReload) { - assertEquals(10, this.defaultSubmissionListColumnService.getDefaultSubmissionListColumns().size(), isReload ? "Incorrect number of default submission list columns after reload" : "Incorrect number of default submission list columns"); - assertEquals(5, this.defaultFiltersService.getDefaultFilter().size(), isReload ? "Incorrect number of default filters after reload" : "Incorrect number of default filters"); + assertEquals(10, this.defaultSubmissionListColumnService.getDefaultSubmissionListColumns().size(), + isReload + ? "Incorrect number of default submission list columns after reload" + : "Incorrect number of default submission list columns"); + + assertEquals(5, this.defaultFiltersService.getDefaultFilter().size(), + isReload + ? "Incorrect number of default filters after reload" + : "Incorrect number of default filters"); } } From 55439e4fffd3b23720a34d50ab29cc4dc5a5710e Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 13:29:14 -0600 Subject: [PATCH 13/48] Decouple system default settings from system data loader --- .../vireo/service/DefaultFiltersService.java | 4 +- .../vireo/service/DefaultSettingsService.java | 82 ++++++++-- .../DefaultSubmissionListColumnService.java | 4 +- .../tdl/vireo/service/SystemDataLoader.java | 75 +++------ .../resources/settings/SYSTEM_Defaults.json | 148 +++++++++--------- .../vireo/service/SystemDataLoaderTest.java | 36 ++++- 6 files changed, 193 insertions(+), 156 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java b/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java index 3c2b0bf154..a1eae6309c 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultFiltersService.java @@ -39,12 +39,12 @@ public class DefaultFiltersService { @Autowired private SubmissionListColumnRepo submissionListColumnRepo; - public DefaultFiltersService() { + DefaultFiltersService() { this.defaultFilters = new ArrayList(); } @PostConstruct - public void init() throws StreamReadException, DatabindException, IOException { + void init() throws StreamReadException, DatabindException, IOException { logger.info("Loading default filter columns"); Resource resource = resourcePatternResolver.getResource("classpath:/filter_columns/default_filter_columns.json"); diff --git a/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java b/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java index a92a09e4c6..e841db3ba2 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultSettingsService.java @@ -1,23 +1,75 @@ package org.tdl.vireo.service; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; import java.util.List; -import java.util.Optional; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.stereotype.Service; import org.tdl.vireo.model.DefaultConfiguration; import org.tdl.vireo.model.DefaultPreferences; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + @Service public class DefaultSettingsService { - // TODO: make list immutable after setting default values + private final Logger logger = LoggerFactory.getLogger(DefaultSettingsService.class); + private final List defaultSettings; - public DefaultSettingsService() { + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private ResourcePatternResolver resourcePatternResolver; + + DefaultSettingsService() { defaultSettings = new ArrayList(); } + @PostConstruct + void init() throws IOException { + logger.info("Loading default settings"); + + Resource resource = resourcePatternResolver.getResource("classpath:/settings/SYSTEM_Defaults.json"); + JsonNode systemDefaults = objectMapper.readTree(resource.getInputStream()); + + Iterator> it = systemDefaults.fields(); + + while (it.hasNext()) { + Map.Entry entry = (Map.Entry) it.next(); + List defaultConfigurations = new ArrayList(); + if (entry.getValue().isArray()) { + for (JsonNode objNode : entry.getValue()) { + objNode.fieldNames().forEachRemaining(n -> { + defaultConfigurations.add(new DefaultConfiguration(n, objNode.get(n).asText(), entry.getKey())); + }); + } + } + defaultSettings.add(new DefaultPreferences(entry.getKey(), defaultConfigurations)); + } + + getTypes().forEach(t -> { + logger.debug("Stored preferences for type: " + t); + getSettingsByType(t).forEach(c -> { + logger.debug(c.getName() + ": " + c.getValue()); + }); + }); + } + public DefaultConfiguration getSettingByName(String field) { for (DefaultPreferences defaultPreferences : defaultSettings) { for (DefaultConfiguration defaultConfiguration : defaultPreferences.getPreferences()) { @@ -30,24 +82,24 @@ public DefaultConfiguration getSettingByName(String field) { } public DefaultConfiguration getSettingByNameAndType(String field, String type) { - return getSettingsByType(type).stream().filter(preference -> preference.getName().equals(field)).findFirst().orElse(null); + return getSettingsByType(type).stream() + .filter(preference -> preference.getName().equals(field)) + .findFirst() + .orElse(null); } public List getTypes() { - List types = new ArrayList(); - defaultSettings.forEach(p -> { - types.add(p.getType()); - }); - return types; + return defaultSettings.stream() + .map(p -> p.getType()) + .collect(Collectors.toUnmodifiableList()); } public List getSettingsByType(String type) { - Optional defaultConfiguration = defaultSettings.stream().filter(preferences -> preferences.getType().equals(type)).findFirst(); - return defaultConfiguration.isPresent() ? defaultConfiguration.get().getPreferences() : new ArrayList(); - } - - public void addSettings(String type, List preferences) { - defaultSettings.add(new DefaultPreferences(type, preferences)); + return Collections.unmodifiableList(defaultSettings.stream() + .filter(preferences -> preferences.getType().equals(type)) + .map(preferences -> preferences.getPreferences()) + .findFirst() + .orElse(new ArrayList())); } } diff --git a/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java b/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java index 3674b88e3a..d6c8a5da56 100644 --- a/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java +++ b/src/main/java/org/tdl/vireo/service/DefaultSubmissionListColumnService.java @@ -39,12 +39,12 @@ public class DefaultSubmissionListColumnService { @Autowired private SubmissionListColumnRepo submissionListColumnRepo; - public DefaultSubmissionListColumnService() { + DefaultSubmissionListColumnService() { this.defaultSubmissionListColumns = new ArrayList(); } @PostConstruct - public void init() throws StreamReadException, DatabindException, IOException { + void init() throws StreamReadException, DatabindException, IOException { logger.info("Loading default Submission List Columns"); Resource resource = resourcePatternResolver.getResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"); diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 9bac834a45..0080289ef7 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -9,7 +9,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,7 +27,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.tdl.vireo.model.ControlledVocabulary; -import org.tdl.vireo.model.DefaultConfiguration; import org.tdl.vireo.model.Degree; import org.tdl.vireo.model.DegreeLevel; import org.tdl.vireo.model.DocumentType; @@ -83,7 +81,6 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.TypeFactory; @@ -180,70 +177,64 @@ public class SystemDataLoader { @Autowired private DepositorService depositorService; - @Autowired - private DefaultSettingsService defaultSettingsService; - @Transactional public void loadSystemData() { - logger.info("Loading default languages"); + logger.info("Loading system languages"); loadLanguages(); - logger.info("Loading default input types"); + logger.info("Loading system input types"); loadInputTypes(); - logger.info("Loading default email templates"); + logger.info("Loading system email templates"); loadEmailTemplates(); - logger.info("Loading default degree levels"); + logger.info("Loading system degree levels"); loadDegreeLevels(); - logger.info("Loading default degrees"); + logger.info("Loading system degrees"); loadDegrees(); - logger.info("Loading default graduation months"); + logger.info("Loading system graduation months"); loadGraduationMonths(); - logger.info("Loading default embargos"); + logger.info("Loading system embargos"); loadEmbargos(); - logger.info("Loading default submission statuses"); + logger.info("Loading system submission statuses"); loadSubmissionStatuses(); - logger.info("Loading default organization catagories"); + logger.info("Loading system organization catagories"); loadOrganizationCategories(); - logger.info("Loading default document types"); + logger.info("Loading system document types"); loadDocumentTypes(); - logger.info("Loading default organization"); + logger.info("Loading system organization"); loadOrganization(); - logger.info("Loading default controlled vocabularies"); + logger.info("Loading system controlled vocabularies"); loadControlledVocabularies(); - logger.info("Loading default settings"); - loadSystemDefaults(); - - logger.info("Loading default Proquest language codes"); + logger.info("Loading system Proquest language codes"); loadProquestLanguageCodes(); - logger.info("Loading default Proquest degree codes"); + logger.info("Loading system Proquest degree codes"); loadProquestDegreeCodes(); - logger.info("Loading default Proquest subject codes"); + logger.info("Loading system Proquest subject codes"); loadProquestSubjectCodes(); - logger.info("Loading default Submission List Columns"); + logger.info("Loading system Submission List Columns"); loadSubmissionListColumns(); - logger.info("Loading default Packagers"); + logger.info("Loading system Packagers"); loadPackagers(); - logger.info("Loading default Depositors"); + logger.info("Loading system Depositors"); loadDepositors(); - logger.info("Finished loading system defaults"); + logger.info("Finished loading system data"); } private void loadControlledVocabularies() { @@ -891,34 +882,6 @@ private void loadEmbargos() { } } - private void loadSystemDefaults() { - try { - JsonNode systemDefaults = objectMapper.readTree(getFileFromResource("classpath:/settings/SYSTEM_Defaults.json")); - Iterator> it = systemDefaults.fields(); - - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - List defaultConfigurations = new ArrayList(); - if (entry.getValue().isArray()) { - for (JsonNode objNode : entry.getValue()) { - objNode.fieldNames().forEachRemaining(n -> { - defaultConfigurations.add(new DefaultConfiguration(n, objNode.get(n).asText(), entry.getKey())); - }); - } - } - defaultSettingsService.addSettings(entry.getKey(), defaultConfigurations); - } - defaultSettingsService.getTypes().forEach(t -> { - logger.debug("Stored preferences for type: " + t); - defaultSettingsService.getSettingsByType(t).forEach(c -> { - logger.debug(c.getName() + ": " + c.getValue()); - }); - }); - } catch (Exception e) { - e.printStackTrace(); - } - } - private void loadDocumentTypes() { try { diff --git a/src/main/resources/settings/SYSTEM_Defaults.json b/src/main/resources/settings/SYSTEM_Defaults.json index bea6e82458..e424239358 100644 --- a/src/main/resources/settings/SYSTEM_Defaults.json +++ b/src/main/resources/settings/SYSTEM_Defaults.json @@ -1,79 +1,79 @@ { - "application":[ + "application": [ { - "submissions_open":false + "submissions_open": false }, { - "allow_multiple_submissions":false + "allow_multiple_submissions": false }, { - "current_semester":"May 2020" + "current_semester": "May 2020" }, { - "grantor":"Texas A&M University" + "grantor": "Texas A&M University" }, { - "email_from":"noreply@tdl.org" + "email_from": "noreply@tdl.org" }, { - "email_reply_to":"dev@tdl.org" + "email_reply_to": "dev@tdl.org" }, { - "hierarchical":"false" + "hierarchical": "false" }, { - "new_submission_header_text":"Choose Your Organization" + "new_submission_header_text": "Choose Your Organization" } ], - "footer":[ + "footer": [ { - "link_webmaster":"dev@tdl.org" + "link_webmaster": "dev@tdl.org" }, { - "link_legal":"dev@tdl.org" + "link_legal": "dev@tdl.org" }, { - "link_comments":"dev@tdl.org" + "link_comments": "dev@tdl.org" }, { - "link_accessibility":"dev@tdl.org" + "link_accessibility": "dev@tdl.org" } ], - "orcid":[ + "orcid": [ { - "orcid_validation":true + "orcid_validation": true }, { - "orcid_authentication":false + "orcid_authentication": false } ], - "proquest_umi_degree_code":[ + "proquest_umi_degree_code": [ { "proquest_license": "

This Agreement is between the author (Author) and ProQuest LLC, through its ProQuest dissertation business (ProQuest). Under this Agreement, the Author grants ProQuest certain rights to preserve, archive and disseminate the dissertation or thesis, abstract, and index terms (the Work) provided by Author to ProQuest.<\/span><\/p>

 <\/p>

Section I. License for Inclusion of the Work in ProQuest® Publishing Program.<\/span><\/p>

Grant of Rights.<\/strong> Author hereby grants to ProQuest the non-exclusive<\/strong>, worldwide right to reproduce, distribute, display and transmit the Work (in whole or in part) in such tangible and electronic formats as may be in existence now or developed in the future.  Author further grants to ProQuest the right to include the abstract, bibliography and other metadata in the ProQuest Dissertations and Theses Global<\/em> database (PQDT) and in ProQuest's Dissertation Abstracts International<\/em> and any successor or related index and\/or finding products or services.<\/span><\/p>

ProQuest Publishing Program – Election and Elements.<\/strong> The rights granted shall be subject to the following additional requirements:<\/span><\/p>

Redistribution of the Work.<\/span> Except as restricted by the Author, the rights granted by the Author automatically include (1) the right to allow sale and distribution of the Work, in whole or in part, by agents and distributors, and (2) the right to make the Abstract, bibliographic data and any metadata associated with the Work available to search engines and harvesters.<\/span><\/p>

Restrictions.<\/span> ProQuest will use commercially reasonable efforts to restrict the distribution of the Work as provided under the publishing option selected by Author or as later elected by Author through direct contact with ProQuest. Such election is subject to Author's Degree Granting Institution Directives (see below). With respect to restrictions requested after submission of the Work, Author acknowledges that ProQuest cannot recall or amend previously distributed versions of the Work.<\/span><\/p>

Removal of Work from the Program.<\/span> ProQuest may elect not to distribute the Work if it believes that all necessary rights of third parties have not been secured. If Author's degree is rescinded, and the degree granting institution so directs, ProQuest will expunge the Work from its publishing program in accordance with its then current publishing policies.<\/span><\/p>

Degree Granting Institution Directives.<\/span> Author is solely responsible for any conflict between policies and directions of Author's degree-granting institution, Author's choice of publishing model, and\/or any restriction Author places on the use of the Work. For the avoidance of doubt, ProQuest is not responsible for access to the Work that is provided by Author's degree-granting institution through its library or institutional repository. Author must work directly with Author's degree granting institution to ensure application of any restrictions to access relating to the Work by Author's degree granting institution.<\/span><\/p>

Rights Verification.<\/strong> Author represents and warrants that Author is the copyright holder of the Work and has obtained all necessary rights to permit ProQuest to reproduce and distribute third party materials contained in any part of the Work, including all necessary licenses for any nonpublic, third party software necessary to access, display, and run or print the Work.  Author is solely responsible and will indemnify ProQuest for any third party claims related to the Work as submitted for publication.<\/span><\/p>

 <\/span><\/p>

Section II. Rights pursuant to Traditional Publishing.<\/span><\/p>

Author's election of Traditional as the type of Publishing confirms Author's choice to have ProQuest publish the Work according to the Traditional Publishing option described below.<\/span><\/p>

Traditional Publishing.<\/span> ProQuest may exercise the rights granted under Section I above including through the sale of individual copies of the Work in tangible or electronic media and\/or as part of electronic database and reference products or services.<\/span><\/p>

Publishing Fees and Royalties.<\/span> Under this agreement no publishing fee is charged by ProQuest to the author or author’s institution.<\/span><\/p>

ProQuest will pay royalties of 10% of its net revenue from sales of the Work to the Author, conditioned on Author maintaining a current address on record with ProQuest by contacting disspub@proquest.com.  Royalties will be paid when accrued earned royalties reach $25.00 USD. If, after 25 years, earned royalties do not accrue to at least $25.00 USD, ProQuest's royalty payment obligation will cease.<\/span><\/p>

Acknowledgement:<\/strong> I have read, understand and agree to this ProQuest Agreement, including all rights and restrictions included within the publishing option that I have chosen.<\/span><\/p>" }, { - "proquest_institution_code":"INSTITUTIONID" + "proquest_institution_code": "INSTITUTIONID" }, { - "proquest_indexing":false + "proquest_indexing": false }, { - "external_id_prefix":"vireo:" + "external_id_prefix": "vireo:" }, { - "apply_for_copyright":false + "apply_for_copyright": false }, { - "sale_restriction_code":0 + "sale_restriction_code": 0 }, { - "sale_restriction_remove":" " + "sale_restriction_remove": " " }, { - "format_restriction_code":0 + "format_restriction_code": 0 }, { - "format_restriction_remove":" " + "format_restriction_remove": " " } ], "export": [ @@ -81,78 +81,78 @@ "release_student_contact_information": true } ], - "lookAndFeel":[ + "lookAndFeel": [ { - "theme_path":"configuration/theme/" + "theme_path": "configuration/theme/" }, { - "text_main_color":"#757575" + "text_main_color": "#757575" }, { - "background_main_color":"#1b333f" + "background_main_color": "#1b333f" }, { - "background_highlight_color":"#43606e" + "background_highlight_color": "#43606e" }, { - "background_header_text_color":"#ffffff" + "background_header_text_color": "#ffffff" }, { - "background_footer_text_color":"#ffffff" + "background_footer_text_color": "#ffffff" }, { - "button_main_color_on":"#1b333f" + "button_main_color_on": "#1b333f" }, { - "button_highlight_color_on":"#43606e" + "button_highlight_color_on": "#43606e" }, { - "button_text_color_on":"#ffffff" + "button_text_color_on": "#ffffff" }, { - "button_main_color_off":"#424D46" + "button_main_color_off": "#424D46" }, { - "button_highlight_color_off":"#697A70" + "button_highlight_color_off": "#697A70" }, { - "button_text_color_off":"#ffffff" + "button_text_color_off": "#ffffff" }, { - "admin_tab_main_color":"#adbdaa" + "admin_tab_main_color": "#adbdaa" }, { - "admin_tab_selected_color":"#ffffff" + "admin_tab_selected_color": "#ffffff" }, { - "admin_tab_main_text_color":"#1D3541" + "admin_tab_main_text_color": "#1D3541" }, { - "admin_tab_selected_text_color":"#1D3541" + "admin_tab_selected_text_color": "#1D3541" }, { - "left_logo":"resources/images/default-left-logo.png" + "left_logo": "resources/images/default-left-logo.png" }, { - "right_logo":"resources/images/default-right-logo.gif" + "right_logo": "resources/images/default-right-logo.gif" }, { - "custom_css":"/* Insert Custom CSS here! */" + "custom_css": "/* Insert Custom CSS here! */" }, { - "front_page_instructions_before":"

Welcome to the Thesis
& Dissertation Submission System

Once you have passed the final defense and satisfied the requirements of the committee, you are ready to submit your manuscript to the Thesis Office for review. This submission process is fully electronic, and is made through an online application developed and maintained by the Texas Digital Library, in conjunction with Texas A&M, Texas Tech, and Baylor Universities.

To get started with your submission, click the link below. You will be asked to authenticate using your NetID:

" + "front_page_instructions_before": "

Welcome to the Thesis
& Dissertation Submission System

Once you have passed the final defense and satisfied the requirements of the committee, you are ready to submit your manuscript to the Thesis Office for review. This submission process is fully electronic, and is made through an online application developed and maintained by the Texas Digital Library, in conjunction with Texas A&M, Texas Tech, and Baylor Universities.

To get started with your submission, click the link below. You will be asked to authenticate using your NetID:

" }, { - "front_page_instructions_after":"

Your help can make things better

You feedback is very important to us; it allows us to continue to improve the system. Please feel free to notify us directly at dev@tdl.org if you have any suggestions to increase the usability or effectiveness of this application. You can talk to the your Thesis Office regarding any issues that may arise during the submission process.

" + "front_page_instructions_after": "

Your help can make things better

You feedback is very important to us; it allows us to continue to improve the system. Please feel free to notify us directly at dev@tdl.org if you have any suggestions to increase the usability or effectiveness of this application. You can talk to the your Thesis Office regarding any issues that may arise during the submission process.

" }, { - "post_submission_instructions":"

The Thesis Office has received your electronic submittal. You will also receive an email confirmation. We will check your records as soon as possible to determine whether or not we have the signed Approval Form on file. Please be aware that your file is not complete and cannot be reviewed until we have both the electronic manuscript and the signed Approval Form.

As soon as both items have been received, your manuscript will be placed in the queue and will be processed along with all other submissions for the semester in the order in which your completed file (manuscript and Approval Form) was received.

The following are approximate turn-around times after the manuscript and the signed approval form have been submitted to the Thesis Office. Manuscripts are reviewed in the order received.

 

Early in semester – 5 working days

Week before Deadline Day – 10 working days

Deadline Day – 15 working days

 

If you have any questions about your submittal, feel free to contact our office.

 

Thank you, Thesis Office

" + "post_submission_instructions": "

The Thesis Office has received your electronic submittal. You will also receive an email confirmation. We will check your records as soon as possible to determine whether or not we have the signed Approval Form on file. Please be aware that your file is not complete and cannot be reviewed until we have both the electronic manuscript and the signed Approval Form.

As soon as both items have been received, your manuscript will be placed in the queue and will be processed along with all other submissions for the semester in the order in which your completed file (manuscript and Approval Form) was received.

The following are approximate turn-around times after the manuscript and the signed approval form have been submitted to the Thesis Office. Manuscripts are reviewed in the order received.

 

Early in semester – 5 working days

Week before Deadline Day – 10 working days

Deadline Day – 15 working days

 

If you have any questions about your submittal, feel free to contact our office.

 

Thank you, Thesis Office

" }, { - "post_correction_instructions":"

The Thesis Office has received your corrections. Manuscripts are reviewed in the order received.

 

Early in semester – 5 working days

Week before Deadline Day – 10 working days

Deadline Day – 15 working days

 

If you have any questions about your submittal, feel free to contact our office.

 

Thank you, Thesis Office

" + "post_correction_instructions": "

The Thesis Office has received your corrections. Manuscripts are reviewed in the order received.

 

Early in semester – 5 working days

Week before Deadline Day – 10 working days

Deadline Day – 15 working days

 

If you have any questions about your submittal, feel free to contact our office.

 

Thank you, Thesis Office

" } ], - "submission":[ + "submission": [ { "submit_license":"

I grant the Texas Digital Library (hereafter called \"TDL\"), my home institution (hereafter called \"Institution\"), and my academic department (hereafter called \"Department\") the non-exclusive rights to copy, display, perform, distribute and publish the content I submit to this repository (hereafter called \"Work\") and to make the Work available in any format in perpetuity as part of a TDL, Institution or Department repository communication or distribution effort.

@@ -181,72 +181,72 @@

" } ], - "shibboleth":[ + "shibboleth": [ { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_NETID":"netid" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_NETID": "netid" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_EMAIL":"email" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_EMAIL": "email" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_FIRST_NAME":"firstName" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_FIRST_NAME": "firstName" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_LAST_NAME":"lastName" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_LAST_NAME": "lastName" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTION_IDENTIFIER":"institutionid" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTION_IDENTIFIER": "institutionid" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER":"uin" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER": "uin" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_MIDDLE_NAME":"middleName" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_MIDDLE_NAME": "middleName" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR":"birthYear" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_BIRTH_YEAR": "birthYear" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_AFFILIATIONS":"affiliations" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_AFFILIATIONS": "affiliations" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_PHONE_NUMBER":"currentPhoneNumber" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_PHONE_NUMBER": "currentPhoneNumber" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_POSTAL_ADDRESS":"currentPostalAddress" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_POSTAL_ADDRESS": "currentPostalAddress" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_EMAIL_ADDRESS":"currentEmailAddress" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_EMAIL_ADDRESS": "currentEmailAddress" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_PERMANENT_PHONE_NUMBER":"permanentPhoneNumber" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_PERMANENT_PHONE_NUMBER": "permanentPhoneNumber" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_PERMANENT_POSTAL_ADDRESS":"permanentPostalAddress" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_PERMANENT_POSTAL_ADDRESS": "permanentPostalAddress" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_PERMANENT_EMAIL_ADDRESS":"permanentEmailAddress" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_PERMANENT_EMAIL_ADDRESS": "permanentEmailAddress" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_DEGREE":"currentDegree" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_DEGREE": "currentDegree" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_DEPARTMENT":"currentDepartment" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_DEPARTMENT": "currentDepartment" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_COLLEGE":"currentCollege" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_COLLEGE": "currentCollege" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_MAJOR":"currentMajor" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_MAJOR": "currentMajor" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_GRADUATION_YEAR":"currentGraduationYear" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_GRADUATION_YEAR": "currentGraduationYear" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_GRADUATION_MONTH":"currentGraduationMonth" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_CURRENT_GRADUATION_MONTH": "currentGraduationMonth" }, { - "APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID":"orcid" + "APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID": "orcid" } ] } diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java index 18d3d03b2d..b5866a85c9 100644 --- a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -19,32 +19,47 @@ public class SystemDataLoaderTest { private SystemDataLoader systemDataLoader; @Autowired - private ProquestCodesService proquesteCodesService; + private DefaultSettingsService defaultSettingsService; @Autowired - private DepositorService depositorService; + private DefaultSubmissionListColumnService defaultSubmissionListColumnService; @Autowired - private DefaultSettingsService defaultSettingsService; + private DefaultFiltersService defaultFiltersService; @Autowired - private DefaultSubmissionListColumnService defaultSubmissionListColumnService; + private DepositorService depositorService; @Autowired - private DefaultFiltersService defaultFiltersService; + private ProquestCodesService proquesteCodesService; @Test public void testLoadSystemData() throws Exception { - this.assertPersistedSystemData(false); + assertPersistedSystemData(false); // reload to ensure nothing changes // technically the cache clears after restart // however, this is still an undesired side effect of load system data systemDataLoader.loadSystemData(); - this.assertPersistedSystemData(true); + assertPersistedSystemData(true); } private void assertPersistedSystemData(boolean isReload) { + + assertEquals(8, this.defaultSettingsService.getTypes().size(), + isReload + ? "Incorrect number of default setting types after reload" + : "Incorrect number of default setting types"); + + assertSettingsType(8, "application", isReload); + assertSettingsType(4, "footer", isReload); + assertSettingsType(2, "orcid", isReload); + assertSettingsType(9, "proquest_umi_degree_code", isReload); + assertSettingsType(1, "export", isReload); + assertSettingsType(23, "lookAndFeel", isReload); + assertSettingsType(1, "submission", isReload); + assertSettingsType(22, "shibboleth", isReload); + assertEquals(10, this.defaultSubmissionListColumnService.getDefaultSubmissionListColumns().size(), isReload ? "Incorrect number of default submission list columns after reload" @@ -56,4 +71,11 @@ private void assertPersistedSystemData(boolean isReload) { : "Incorrect number of default filters"); } + private void assertSettingsType(int expected, String type, boolean isReload) { + assertEquals(expected, this.defaultSettingsService.getSettingsByType(type).size(), + isReload + ? String.format("Incorrect number of default %s settings after reload", type) + : String.format("Incorrect number of default %s settings", type)); + } + } From 01c8da4d1c4183eec9d3db7347987fc971441357 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 13:53:34 -0600 Subject: [PATCH 14/48] Decouple loading in memory proquest codes from persisting controlled vocabulary --- .../vireo/service/ProquestCodesService.java | 92 ++++++++- .../tdl/vireo/service/SystemDataLoader.java | 174 +++++------------- .../vireo/service/SystemDataLoaderTest.java | 21 ++- 3 files changed, 151 insertions(+), 136 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/ProquestCodesService.java b/src/main/java/org/tdl/vireo/service/ProquestCodesService.java index 06a2fa36b5..7fb53c4c1f 100644 --- a/src/main/java/org/tdl/vireo/service/ProquestCodesService.java +++ b/src/main/java/org/tdl/vireo/service/ProquestCodesService.java @@ -1,28 +1,70 @@ package org.tdl.vireo.service; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import javax.annotation.PostConstruct; + +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.stereotype.Service; @Service public class ProquestCodesService { - // TODO: make map immutable after setting values + private final Logger logger = LoggerFactory.getLogger(ProquestCodesService.class); + private final Map> codes; - public ProquestCodesService() { + @Autowired + private ResourcePatternResolver resourcePatternResolver; + + ProquestCodesService() { codes = new HashMap>(); } - public void setCodes(String key, Map codes) { - checkCreateCodes(key); - this.codes.put(key, codes); + @PostConstruct + void init() throws IOException { + loadProquestLanguageCodes(); + loadProquestDegreeCodes(); + loadProquestSubjectCodes(); } public Map getCodes(String key) { checkCreateCodes(key); - return codes.get(key); + return Collections.unmodifiableMap(codes.get(key)); + } + + private void loadProquestLanguageCodes() throws IOException { + logger.info("Loading proquest language codes"); + setCodes("languages", getProquestCodes("language_codes.xls")); + } + + private void loadProquestDegreeCodes() throws IOException { + logger.info("Loading proquest degree codes"); + setCodes("degrees", getProquestCodes("degree_codes.xls")); + } + + private void loadProquestSubjectCodes() throws IOException { + logger.info("Loading proquest subjects codes"); + setCodes("subjects", getProquestCodes("umi_subjects.xls")); + } + + private void setCodes(String key, Map codes) { + checkCreateCodes(key); + this.codes.put(key, codes); } private void checkCreateCodes(String key) { @@ -31,4 +73,42 @@ private void checkCreateCodes(String key) { } } + private Map getProquestCodes(String xslFileName) throws IOException { + Map proquestCodes = new HashMap(); + + Resource resource = resourcePatternResolver.getResource("classpath:/proquest/" + xslFileName); + + try ( + InputStream file = resource.getInputStream(); + HSSFWorkbook workbook = new HSSFWorkbook(file); + ) { + HSSFSheet sheet = workbook.getSheetAt(0); + + Iterator rowIterator = sheet.iterator(); + while (rowIterator.hasNext()) { + Row row = rowIterator.next(); + + String code = null, description = ""; + + Iterator cellIterator = row.cellIterator(); + while (cellIterator.hasNext()) { + + Cell cell = cellIterator.next(); + if (cell.getCellType() == CellType.STRING) { + String cellValue = cell.getStringCellValue(); + if (code == null) { + code = cellValue; + } else { + description = cellValue; + } + } + } + + proquestCodes.put(code, description); + } + } + + return proquestCodes; + } + } diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 0080289ef7..405ad1d798 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -2,11 +2,9 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -14,11 +12,6 @@ import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -216,14 +209,8 @@ public void loadSystemData() { logger.info("Loading system controlled vocabularies"); loadControlledVocabularies(); - logger.info("Loading system Proquest language codes"); - loadProquestLanguageCodes(); - - logger.info("Loading system Proquest degree codes"); - loadProquestDegreeCodes(); - - logger.info("Loading system Proquest subject codes"); - loadProquestSubjectCodes(); + logger.info("Loading system Proquest subjects codes controlled vocabulary"); + loadProquestSubjectCodesControlledVocabulary(); logger.info("Loading system Submission List Columns"); loadSubmissionListColumns(); @@ -237,51 +224,7 @@ public void loadSystemData() { logger.info("Finished loading system data"); } - private void loadControlledVocabularies() { - - List controlledVocabularyFiles = new ArrayList(); - try { - controlledVocabularyFiles = fileIOUtility.getResourceDirectoryListing("classpath:/controlled_vocabularies/"); - } catch (IOException e) { - e.printStackTrace(); - } - - for (File vocabularyJson : controlledVocabularyFiles) { - try { - ControlledVocabulary cv = objectMapper.readValue(vocabularyJson, ControlledVocabulary.class); - - // check to see if Controlled Vocabulary exists, and if so, merge up with it - ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - - if (persistedCV == null) { - persistedCV = controlledVocabularyRepo.create(cv.getName()); - } - - for (VocabularyWord vw : cv.getDictionary()) { - - VocabularyWord persistedVW = vocabularyRepo.findByNameAndControlledVocabulary(vw.getName(), persistedCV); - - if (persistedVW == null) { - persistedVW = vocabularyRepo.create(persistedCV, vw.getName(), vw.getDefinition(), vw.getIdentifier(), vw.getContacts()); - persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - } else { - persistedVW.setDefinition(vw.getDefinition()); - persistedVW.setIdentifier(vw.getIdentifier()); - persistedVW.setContacts(vw.getContacts()); - persistedVW = vocabularyRepo.save(persistedVW); - } - } - - } catch (JsonParseException e) { - e.printStackTrace(); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - } - } + private void loadOrganizationCategories() { try { @@ -917,23 +860,54 @@ private void loadDocumentTypes() { } } - private void loadProquestLanguageCodes() { - proquesteCodesService.setCodes("languages", getProquestCodes("language_codes.xls")); - } + private void loadControlledVocabularies() { - private void loadProquestDegreeCodes() { - proquesteCodesService.setCodes("degrees", getProquestCodes("degree_codes.xls")); - } + List controlledVocabularyFiles = new ArrayList(); + try { + controlledVocabularyFiles = fileIOUtility.getResourceDirectoryListing("classpath:/controlled_vocabularies/"); + } catch (IOException e) { + e.printStackTrace(); + } + + for (File vocabularyJson : controlledVocabularyFiles) { + try { + ControlledVocabulary cv = objectMapper.readValue(vocabularyJson, ControlledVocabulary.class); - private void loadProquestSubjectCodes() { - Map subjectCodes = getProquestCodes("umi_subjects.xls"); + // check to see if Controlled Vocabulary exists, and if so, merge up with it + ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName(cv.getName()); + + if (persistedCV == null) { + persistedCV = controlledVocabularyRepo.create(cv.getName()); + } + + for (VocabularyWord vw : cv.getDictionary()) { + + VocabularyWord persistedVW = vocabularyRepo.findByNameAndControlledVocabulary(vw.getName(), persistedCV); + + if (persistedVW == null) { + persistedVW = vocabularyRepo.create(persistedCV, vw.getName(), vw.getDefinition(), vw.getIdentifier(), vw.getContacts()); + persistedCV = controlledVocabularyRepo.findByName(cv.getName()); + } else { + persistedVW.setDefinition(vw.getDefinition()); + persistedVW.setIdentifier(vw.getIdentifier()); + persistedVW.setContacts(vw.getContacts()); + persistedVW = vocabularyRepo.save(persistedVW); + } + } - proquesteCodesService.setCodes("subjects", subjectCodes); + } catch (JsonParseException e) { + e.printStackTrace(); + } catch (JsonMappingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } - createSubjectControlledVocabulary(subjectCodes); + } } - private void createSubjectControlledVocabulary(Map subjectCodes) { + private void loadProquestSubjectCodesControlledVocabulary() { + Map subjectCodes = proquesteCodesService.getCodes("subjects"); // check to see if Controlled Vocabulary exists, and if so, merge up with it ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName("Subjects"); @@ -957,64 +931,6 @@ private void createSubjectControlledVocabulary(Map subjectCodes) persistedVW = vocabularyRepo.save(persistedVW); } } - - } - - private Map getProquestCodes(String xslFileName) { - Map proquestCodes = new HashMap(); - Resource resource = resourcePatternResolver.getResource("classpath:/proquest/" + xslFileName); - - InputStream file = null; - try { - file = resource.getInputStream(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (file != null) { - - HSSFWorkbook workbook = null; - try { - workbook = new HSSFWorkbook(file); - } catch (IOException e) { - e.printStackTrace(); - } - if (workbook != null) { - - HSSFSheet sheet = workbook.getSheetAt(0); - - Iterator rowIterator = sheet.iterator(); - while (rowIterator.hasNext()) { - Row row = rowIterator.next(); - - String code = null, description = ""; - - Iterator cellIterator = row.cellIterator(); - while (cellIterator.hasNext()) { - - Cell cell = cellIterator.next(); - if (cell.getCellType() == CellType.STRING) { - String cellValue = cell.getStringCellValue(); - if (code == null) { - code = cellValue; - } else { - description = cellValue; - } - } - } - - proquestCodes.put(code, description); - } - } - - try { - file.close(); - } catch (IOException e) { - e.printStackTrace(); - } - - } - return proquestCodes; } private void loadPackagers() { diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java index b5866a85c9..ca9dabfc85 100644 --- a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -1,6 +1,10 @@ package org.tdl.vireo.service; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -45,7 +49,6 @@ public void testLoadSystemData() throws Exception { } private void assertPersistedSystemData(boolean isReload) { - assertEquals(8, this.defaultSettingsService.getTypes().size(), isReload ? "Incorrect number of default setting types after reload" @@ -69,6 +72,10 @@ private void assertPersistedSystemData(boolean isReload) { isReload ? "Incorrect number of default filters after reload" : "Incorrect number of default filters"); + + assertProquestCodes(82, "languages", isReload); + assertProquestCodes(1219, "degrees", isReload); + assertProquestCodes(288, "subjects", isReload); } private void assertSettingsType(int expected, String type, boolean isReload) { @@ -78,4 +85,16 @@ private void assertSettingsType(int expected, String type, boolean isReload) { : String.format("Incorrect number of default %s settings", type)); } + private void assertProquestCodes(int expected, String key, boolean isReload) { + Map codes = this.proquesteCodesService.getCodes(key); + assertNotNull(codes, + isReload + ? String.format("Missing proquest %s codes after reload", key) + : String.format("Missing proquest %s codes", key)); + assertEquals(expected, codes.size(), + isReload + ? String.format("Incorrect number of proquest %s codes after reload", key) + : String.format("Incorrect number of proquest %s codes", key)); + } + } From 319fd14c36c8ed76bb920f55b71546e4a8244639 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 14:17:02 -0600 Subject: [PATCH 15/48] Decouple initializing depositor services from system data loader --- .../tdl/vireo/service/DepositorService.java | 18 +++++++++++++++--- .../tdl/vireo/service/SystemDataLoader.java | 15 +-------------- .../vireo/service/SystemDataLoaderTest.java | 8 +++++--- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/DepositorService.java b/src/main/java/org/tdl/vireo/service/DepositorService.java index b87f3eb593..4d4dfb781e 100644 --- a/src/main/java/org/tdl/vireo/service/DepositorService.java +++ b/src/main/java/org/tdl/vireo/service/DepositorService.java @@ -3,16 +3,28 @@ import java.util.HashMap; import java.util.Map; +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.tdl.vireo.model.depositor.Depositor; +import org.tdl.vireo.model.depositor.SWORDv1Depositor; @Service public class DepositorService { - // TODO: make map immutable after setting values + private final Logger logger = LoggerFactory.getLogger(DepositorService.class); + private final Map depositors; - public DepositorService() { + @PostConstruct + void init() { + logger.info("Loading SWORDv1 depositor"); + addDepositor(new SWORDv1Depositor()); + } + + DepositorService() { this.depositors = new HashMap(); } @@ -20,7 +32,7 @@ public Depositor getDepositor(String depositorName) { return depositors.get(depositorName); } - protected void addDepositor(Depositor depositor) { + private void addDepositor(Depositor depositor) { depositors.put(depositor.getName(), depositor); } diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 405ad1d798..e37c70cb94 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -41,7 +41,6 @@ import org.tdl.vireo.model.SubmissionStatus; import org.tdl.vireo.model.VocabularyWord; import org.tdl.vireo.model.WorkflowStep; -import org.tdl.vireo.model.depositor.SWORDv1Depositor; import org.tdl.vireo.model.formatter.DSpaceMetsFormatter; import org.tdl.vireo.model.formatter.DSpaceSimpleFormatter; import org.tdl.vireo.model.formatter.ExcelFormatter; @@ -167,9 +166,6 @@ public class SystemDataLoader { @Autowired private ProquestCodesService proquesteCodesService; - @Autowired - private DepositorService depositorService; - @Transactional public void loadSystemData() { @@ -209,7 +205,7 @@ public void loadSystemData() { logger.info("Loading system controlled vocabularies"); loadControlledVocabularies(); - logger.info("Loading system Proquest subjects codes controlled vocabulary"); + logger.info("Loading system Proquest subject codes controlled vocabulary"); loadProquestSubjectCodesControlledVocabulary(); logger.info("Loading system Submission List Columns"); @@ -218,14 +214,9 @@ public void loadSystemData() { logger.info("Loading system Packagers"); loadPackagers(); - logger.info("Loading system Depositors"); - loadDepositors(); - logger.info("Finished loading system data"); } - - private void loadOrganizationCategories() { try { @@ -954,10 +945,6 @@ private void loadPackagers() { } } - private void loadDepositors() { - depositorService.addDepositor(new SWORDv1Depositor()); - } - private static String encodeTemplateName(String name) { return name.replaceAll(" ", "_") + ".email"; } diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java index ca9dabfc85..2eea2026d0 100644 --- a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Map; @@ -42,8 +41,6 @@ public void testLoadSystemData() throws Exception { assertPersistedSystemData(false); // reload to ensure nothing changes - // technically the cache clears after restart - // however, this is still an undesired side effect of load system data systemDataLoader.loadSystemData(); assertPersistedSystemData(true); } @@ -73,6 +70,11 @@ private void assertPersistedSystemData(boolean isReload) { ? "Incorrect number of default filters after reload" : "Incorrect number of default filters"); + assertNotNull(this.depositorService.getDepositor("SWORDv1Depositor"), + isReload + ? "SWORDv1 depositor not found after reload" + : "SWORDv1 depositor not found"); + assertProquestCodes(82, "languages", isReload); assertProquestCodes(1219, "degrees", isReload); assertProquestCodes(288, "subjects", isReload); From 42767171afd5556424903fe23aa036ae3d03f8d3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 14:28:37 -0600 Subject: [PATCH 16/48] Reorder system data loader methods according to use in class --- .../tdl/vireo/service/SystemDataLoader.java | 800 +++++++++--------- 1 file changed, 397 insertions(+), 403 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index e37c70cb94..e38493be16 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -217,282 +217,267 @@ public void loadSystemData() { logger.info("Finished loading system data"); } - private void loadOrganizationCategories() { + private void loadLanguages() { try { + List languages = objectMapper.readValue(getFileFromResource("classpath:/languages/SYSTEM_Languages.json"), new TypeReference>() {}); - List organizationCategories = objectMapper.readValue(getFileFromResource("classpath:/organization_categories/SYSTEM_Organizaiton_Categories.json"), new TypeReference>() {}); - - for (OrganizationCategory organizationCategory : organizationCategories) { - OrganizationCategory dbOrganizationCategory = organizationCategoryRepo.findByName(organizationCategory.getName()); + for (Language language : languages) { + Language persistedLanguage = languageRepo.findByName(language.getName()); - if (dbOrganizationCategory == null) { - dbOrganizationCategory = organizationCategoryRepo.create(organizationCategory.getName()); + if (persistedLanguage == null) { + persistedLanguage = languageRepo.create(language.getName()); + } else { + persistedLanguage.setName(language.getName()); + persistedLanguage = languageRepo.save(persistedLanguage); } - } } catch (RuntimeException | IOException e) { e.printStackTrace(); - logger.debug("Unable to initialize default embargos. ", e); + logger.debug("Unable to initialize default languages. ", e); } } - private void loadDegreeLevels() { + private void loadInputTypes() { try { + List inputTypes = objectMapper.readValue(getFileFromResource("classpath:/input_types/SYSTEM_Input_Types.json"), new TypeReference>() {}); - List degreeLevels = objectMapper.readValue(getFileFromResource("classpath:/degree_levels/SYSTEM_Degree_Levels.json"), new TypeReference>() {}); - - for (DegreeLevel degreeLevel : degreeLevels) { - DegreeLevel dbDegreeLevel = degreeLevelRepo.findByName(degreeLevel.getName()); + for (InputType inputType : inputTypes) { + InputType persistedInputType = inputTypeRepo.findByName(inputType.getName()); - if (dbDegreeLevel == null) { - dbDegreeLevel = degreeLevelRepo.create(degreeLevel.getName()); + if (persistedInputType == null) { + persistedInputType = inputTypeRepo.create(inputType); + } else { + persistedInputType.setName(inputType.getName()); + persistedInputType = inputTypeRepo.save(persistedInputType); } - } } catch (RuntimeException | IOException e) { e.printStackTrace(); - logger.debug("Unable to initialize default degree levels.", e); + logger.debug("Unable to initialize default input types. ", e); } } - private void loadDegrees() { - try { + private void loadEmailTemplates() { + for (String name : getAllSystemEmailTemplateNames()) { - List degrees = objectMapper.readValue(getFileFromResource("classpath:/degrees/SYSTEM_Degrees.json"), new TypeReference>() {}); + // try to see if it already exists in the DB + EmailTemplate dbTemplate = emailTemplateRepo.findByNameAndSystemRequired(name, true); - for (Degree degree : degrees) { + // create template or upgrade the old one + if (dbTemplate == null) { + dbTemplate = loadSystemEmailTemplate(name); + logger.info("New System Email template being installed [" + dbTemplate.getName() + "]"); + } else { + EmailTemplate loadedTemplate = loadSystemEmailTemplate(name); - DegreeLevel degreeLevel = degreeLevelRepo.findByName(degree.getLevel().getName()); + // if the template in the DB doesn't match in content with the + // one loaded from .email file + if (!(dbTemplate.getMessage().equals(loadedTemplate.getMessage())) || !(dbTemplate.getSubject().equals(loadedTemplate.getSubject()))) { - if (degreeLevel == null) { - degreeLevel = degreeLevelRepo.create(degree.getLevel().getName()); - } else { - degreeLevel.setName(degree.getLevel().getName()); - degreeLevel = degreeLevelRepo.save(degreeLevel); - } + EmailTemplate possibleCustomTemplate = emailTemplateRepo.findByNameAndSystemRequired(name, false); - Degree dbDegree = degreeRepo.findByNameAndLevel(degree.getName(), degreeLevel); + // if this System template already has a custom template + // (meaning one named the same but that is + // !systemRequired) + if (possibleCustomTemplate != null) { - if (dbDegree == null) { - dbDegree = degreeRepo.create(degree.getName(), degreeLevel); - } else { - dbDegree.setName(degree.getName()); - dbDegree.setLevel(degreeLevel); - dbDegree = degreeRepo.save(dbDegree); - } + // a custom version of this System email template + // already exists, it's safe to override dbTemplate's + // data and save + dbTemplate.setMessage(loadedTemplate.getMessage()); + dbTemplate.setSubject(loadedTemplate.getSubject()); + dbTemplate.setSystemRequired(true); + logger.info("Upgrading Old System Email Template for [" + dbTemplate.getName() + "]"); + + emailTemplateRepo.save(dbTemplate); + } + // there is no custom one yet, we need to make the + // dbTemplate !systemRequired and the save loadedTemplate + else { + logger.info("Upgrading Old System Email Template and creating custom version for [" + dbTemplate.getName() + "]"); + dbTemplate.setSystemRequired(false); + emailTemplateRepo.save(dbTemplate); + emailTemplateRepo.save(loadedTemplate); + } + } } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default degrees.", e); } } - private void loadGraduationMonths() { + private List getAllSystemEmailTemplateNames() { try { - List graduationMonths = objectMapper.readValue(getFileFromResource("classpath:/graduation_months/SYSTEM_Graduation_Months.json"), new TypeReference>() {}); - - for (GraduationMonth graduationMonth : graduationMonths) { - GraduationMonth persistedGraduationMonth = graduationMonthRepo.findByMonth(graduationMonth.getMonth()); + List names = new ArrayList(); + for (Resource resource : resourcePatternResolver.getResources("classpath:/emails/*.email")) { + String fileName = resource.getFilename(); + String templateName = decodeTemplateName(fileName); + names.add(templateName); + } - if (persistedGraduationMonth == null) { - persistedGraduationMonth = graduationMonthRepo.create(graduationMonth.getMonth()); - } + return names; - } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default graduation months.", e); + } catch (IOException e) { + throw new IllegalStateException("Unable to get emails directory from classpath."); } } - private void loadOrganization() { + private String decodeTemplateName(String path) { + if (path.endsWith(".email")) { + path = path.substring(0, path.length() - ".email".length()); + } + return path.replaceAll("_", " "); + } - Organization organization = null; + private EmailTemplate loadSystemEmailTemplate(String name) { try { - // read and map json to Organization - Organization systemOrganization = objectMapper.readValue(getFileFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); + Resource resource = resourcePatternResolver.getResource("classpath:/emails/" + encodeTemplateName(name)); + String data = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8); - // check to see if organization category exists - OrganizationCategory category = organizationCategoryRepo.findByName(systemOrganization.getCategory().getName()); + // Remove any comment lines + data = data.replaceAll("\\s*#.*[\\n\\r]{1}", ""); - // create organization category if does not already exists - if (category == null) { - category = organizationCategoryRepo.create(systemOrganization.getCategory().getName()); + // Extract the subject + Matcher subjectMatcher = SUBJECT_PATTERN.matcher(data); + if (!subjectMatcher.find()) { + throw new IllegalStateException("Unable to identify the template's subject."); } + String subject = subjectMatcher.group(1).trim(); - // check to see if organization with organization category exists - organization = organizationRepo.findByNameAndCategory(systemOrganization.getName(), category); + // Trim the subject leaving just the body. + int index = data.indexOf("\n"); + if (index < 0) { + index = data.indexOf("\r"); + } - // create new organization if not already exists - if (organization == null) { - organization = organizationRepo.create(systemOrganization.getName(), category); - organization.setAcceptsSubmissions(systemOrganization.getAcceptsSubmissions()); + String message = data.substring(index); + + if (subject == null || subject.length() == 0) { + throw new IllegalStateException("Unable to identify the template's subject."); } - processWorkflowSteps(organization, systemOrganization); + if (message == null || message.length() == 0) { + throw new IllegalStateException("Unable to identify the template's message."); + } - processEmailWorflowRules(organization, systemOrganization); + EmailTemplate template = emailTemplateRepo.findByNameAndSystemRequired(name, true); - organization = organizationRepo.save(organization); + if (template == null) { + template = emailTemplateRepo.create(name, subject, message); + template.setSystemRequired(true); + } else { + template.setSubject(subject); + template.setMessage(message); + } + + return emailTemplateRepo.save(template); } catch (IOException e) { - throw new IllegalStateException("Unable to generate system organization", e); + throw new IllegalStateException("Unable to generate system email template: " + name, e); } - } - private void processWorkflowSteps(Organization organization, Organization systemOrganization) { - - for (WorkflowStep workflowStep : systemOrganization.getOriginalWorkflowSteps()) { - - // check to see if the WorkflowStep exists - WorkflowStep newWorkflowStep = workflowStepRepo.findByNameAndOriginatingOrganization(workflowStep.getName(), organization); - - // create new workflow step if not already exists - if (newWorkflowStep == null) { - organization = organizationRepo.findById(organization.getId()).get(); - newWorkflowStep = workflowStepRepo.create(workflowStep.getName(), organization); - } - - List originalFieldProfiles = new ArrayList<>(workflowStep.getOriginalFieldProfiles()); + private static String encodeTemplateName(String name) { + return name.replaceAll(" ", "_") + ".email"; + } - for (FieldProfile fieldProfile : originalFieldProfiles) { - // check to see if the FieldPredicate exists - FieldPredicate fieldPredicate = fieldPredicateRepo.findByValue(fieldProfile.getFieldPredicate().getValue()); + private void loadDegreeLevels() { + try { - // create new FieldPredicate if not already exists - if (fieldPredicate == null) { - fieldPredicate = fieldPredicateRepo.create(fieldProfile.getFieldPredicate().getValue(), fieldProfile.getFieldPredicate().getDocumentTypePredicate()); - } + List degreeLevels = objectMapper.readValue(getFileFromResource("classpath:/degree_levels/SYSTEM_Degree_Levels.json"), new TypeReference>() {}); - // check to see if the InputType exists - InputType inputType = inputTypeRepo.findByName(fieldProfile.getInputType().getName()); + for (DegreeLevel degreeLevel : degreeLevels) { + DegreeLevel dbDegreeLevel = degreeLevelRepo.findByName(degreeLevel.getName()); - if (inputType == null) { - inputType = inputTypeRepo.create(fieldProfile.getInputType().getName()); + if (dbDegreeLevel == null) { + dbDegreeLevel = degreeLevelRepo.create(degreeLevel.getName()); } - // check to see if the ControlledVocabulary exists - ControlledVocabulary controlledVocabulary = fieldProfile.getControlledVocabulary(); + } + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize default degree levels.", e); + } + } - // create new ControlledVocabulary if not already exists - if (controlledVocabulary != null) { - ControlledVocabulary persistedControlledVocabulary = controlledVocabularyRepo.findByName(controlledVocabulary.getName()); - if (persistedControlledVocabulary == null) { - persistedControlledVocabulary = controlledVocabularyRepo.create(controlledVocabulary.getName(), controlledVocabulary.getIsEntityProperty()); - } - fieldProfile.setControlledVocabulary(persistedControlledVocabulary); - } + private void loadDegrees() { + try { - // check to see if the ManagedConfiguration exists - ManagedConfiguration managedConfiguration = fieldProfile.getMappedShibAttribute(); + List degrees = objectMapper.readValue(getFileFromResource("classpath:/degrees/SYSTEM_Degrees.json"), new TypeReference>() {}); - // create new ManagedConfiguration if not already exists - if (managedConfiguration != null) { - ManagedConfiguration persistedManagedConfiguration = configurationRepo.findByNameAndType(managedConfiguration.getName(), managedConfiguration.getType()); - if (persistedManagedConfiguration == null) { - persistedManagedConfiguration = configurationRepo.create(managedConfiguration); - } - fieldProfile.setMappedShibAttribute(persistedManagedConfiguration); - } + for (Degree degree : degrees) { - // check to see if the FieldProfile exists - FieldProfile newFieldProfile = fieldProfileRepo.findByFieldPredicateAndOriginatingWorkflowStep(fieldPredicate, newWorkflowStep); + DegreeLevel degreeLevel = degreeLevelRepo.findByName(degree.getLevel().getName()); - // create new FieldProfile if not already exists - if (newFieldProfile == null) { - newWorkflowStep = workflowStepRepo.findById(newWorkflowStep.getId()).get(); - newFieldProfile = fieldProfileRepo.create(newWorkflowStep, fieldPredicate, inputType, fieldProfile.getUsage(), fieldProfile.getHelp(), fieldProfile.getGloss(), fieldProfile.getRepeatable(), fieldProfile.getOverrideable(), fieldProfile.getEnabled(), fieldProfile.getOptional(), fieldProfile.getHidden(), fieldProfile.getFlagged(), fieldProfile.getLogged(), fieldProfile.getControlledVocabulary(), fieldProfile.getMappedShibAttribute(), fieldProfile.getDefaultValue()); + if (degreeLevel == null) { + degreeLevel = degreeLevelRepo.create(degree.getLevel().getName()); + } else { + degreeLevel.setName(degree.getLevel().getName()); + degreeLevel = degreeLevelRepo.save(degreeLevel); } - newWorkflowStep.addOriginalFieldProfile(newFieldProfile); - - newWorkflowStep = workflowStepRepo.save(newWorkflowStep); - } - - // temporary list of Note - List notes = new ArrayList(); - - for (Note note : workflowStep.getOriginalNotes()) { - - // check to see if the Note exists - Note newNote = noteRepo.findByNameAndOriginatingWorkflowStep(note.getName(), newWorkflowStep); + Degree dbDegree = degreeRepo.findByNameAndLevel(degree.getName(), degreeLevel); - // create new Note if not already exists - if (newNote == null) { - newNote = noteRepo.create(newWorkflowStep, note.getName(), note.getText()); - newWorkflowStep = workflowStepRepo.findById(newWorkflowStep.getId()).get(); + if (dbDegree == null) { + dbDegree = degreeRepo.create(degree.getName(), degreeLevel); + } else { + dbDegree.setName(degree.getName()); + dbDegree.setLevel(degreeLevel); + dbDegree = degreeRepo.save(dbDegree); } - notes.add(newNote); - } - - newWorkflowStep.setOriginalNotes(notes); - - newWorkflowStep.setInstructions(workflowStep.getInstructions()); - - newWorkflowStep = workflowStepRepo.save(newWorkflowStep); + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize default degrees.", e); } } - private void processEmailWorflowRules(Organization organization, Organization systemOrganization) { - List emailWorkflowRules = organization.getEmailWorkflowRules(); - - for (EmailWorkflowRule emailWorkflowRule : systemOrganization.getEmailWorkflowRules()) { + private void loadGraduationMonths() { + try { - // check to see if the SubmissionStatus exists - SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(emailWorkflowRule.getSubmissionStatus().getName()); + List graduationMonths = objectMapper.readValue(getFileFromResource("classpath:/graduation_months/SYSTEM_Graduation_Months.json"), new TypeReference>() {}); - // create new SubmissionStatus if not already exists - if (newSubmissionStatus == null) { - newSubmissionStatus = submissionStatusRepo.create(emailWorkflowRule.getSubmissionStatus().getName(), emailWorkflowRule.getSubmissionStatus().isArchived(), emailWorkflowRule.getSubmissionStatus().isPublishable(), emailWorkflowRule.getSubmissionStatus().isDeletable(), emailWorkflowRule.getSubmissionStatus().isEditableByReviewer(), emailWorkflowRule.getSubmissionStatus().isEditableByStudent(), emailWorkflowRule.getSubmissionStatus().isActive(), - emailWorkflowRule.getSubmissionStatus().getSubmissionState()); - newSubmissionStatus = submissionStatusRepo.save(recursivelyFindOrCreateSubmissionStatus(emailWorkflowRule.getSubmissionStatus())); - } + for (GraduationMonth graduationMonth : graduationMonths) { + GraduationMonth persistedGraduationMonth = graduationMonthRepo.findByMonth(graduationMonth.getMonth()); - // check to see if the EmailTemplate exists - EmailTemplate newEmailTemplate = emailTemplateRepo.findByNameAndSystemRequired(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSystemRequired()); + if (persistedGraduationMonth == null) { + persistedGraduationMonth = graduationMonthRepo.create(graduationMonth.getMonth()); + } - // create new EmailTemplate if not already exists - if (newEmailTemplate == null) { - newEmailTemplate = emailTemplateRepo.create(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSubject(), emailWorkflowRule.getEmailTemplate().getMessage()); } + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize default graduation months.", e); + } + } - if (emailWorkflowRule.getEmailRecipient() == null) { + private void loadEmbargos() { + try { - if (newEmailTemplate.getName().equals("SYSTEM Advisor Review Request")) { - organization.getAggregateWorkflowSteps().forEach(awfs -> { - awfs.getAggregateFieldProfiles().forEach(afp -> { - if (afp.getFieldPredicate().getValue().equals("dc.contributor.advisor")) { - EmailRecipient recipient = abstractEmailRecipientRepo.createContactRecipient(afp.getGloss(), afp.getFieldPredicate()); - emailWorkflowRule.setEmailRecipient(recipient); - } - }); - }); + List embargoDefinitions = objectMapper.readValue(getFileFromResource("classpath:/embargos/SYSTEM_Embargo_Definitions.json"), new TypeReference>() {}); - } + for (Embargo embargoDefinition : embargoDefinitions) { + Embargo dbEmbargo = embargoRepo.findByNameAndGuarantorAndSystemRequired(embargoDefinition.getName(), embargoDefinition.getGuarantor(), true); - if (newEmailTemplate.getName().equals("SYSTEM Initial Submission")) { - EmailRecipient recipient = abstractEmailRecipientRepo.createOrganizationRecipient(organization); - emailWorkflowRule.setEmailRecipient(recipient); + if (dbEmbargo == null) { + dbEmbargo = embargoRepo.create(embargoDefinition.getName(), embargoDefinition.getDescription(), embargoDefinition.getDuration(), embargoDefinition.getGuarantor(), embargoDefinition.isActive()); + dbEmbargo.setSystemRequired(true); + embargoRepo.save(dbEmbargo); + } else { + dbEmbargo.setDescription(embargoDefinition.getDescription()); + dbEmbargo.setDuration(embargoDefinition.getDuration()); + dbEmbargo.setGuarantor(embargoDefinition.getGuarantor()); + dbEmbargo.isActive(embargoDefinition.isActive()); + dbEmbargo.setSystemRequired(embargoDefinition.getSystemRequired()); + embargoRepo.save(dbEmbargo); } - } - - // check to see if the EmailWorkflowRule exists - EmailWorkflowRule existingEmailWorkflowRule = emailWorkflowRuleRepo.findBySubmissionStatusAndEmailRecipientAndEmailTemplate(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate); - - if (existingEmailWorkflowRule == null) { - emailWorkflowRules.add(emailWorkflowRuleRepo.create(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate, emailWorkflowRule.isSystem())); - } - + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize default embargos. ", e); } - - organization.setEmailWorkflowRules(emailWorkflowRules); } private void loadSubmissionStatuses() { @@ -539,7 +524,6 @@ private void loadSubmissionStatuses() { } private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(SubmissionStatus submissionStatus) { - // check to see if the SubmissionStatus exists SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(submissionStatus.getName()); @@ -571,284 +555,245 @@ private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(SubmissionStatu return submissionStatusRepo.save(newSubmissionStatus); } - private EmailTemplate loadSystemEmailTemplate(String name) { - + private void loadOrganizationCategories() { try { - Resource resource = resourcePatternResolver.getResource("classpath:/emails/" + encodeTemplateName(name)); - String data = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8); - - // Remove any comment lines - data = data.replaceAll("\\s*#.*[\\n\\r]{1}", ""); - - // Extract the subject - Matcher subjectMatcher = SUBJECT_PATTERN.matcher(data); - if (!subjectMatcher.find()) { - throw new IllegalStateException("Unable to identify the template's subject."); - } - String subject = subjectMatcher.group(1).trim(); - - // Trim the subject leaving just the body. - int index = data.indexOf("\n"); - if (index < 0) { - index = data.indexOf("\r"); - } - - String message = data.substring(index); - if (subject == null || subject.length() == 0) { - throw new IllegalStateException("Unable to identify the template's subject."); - } + List organizationCategories = objectMapper.readValue(getFileFromResource("classpath:/organization_categories/SYSTEM_Organizaiton_Categories.json"), new TypeReference>() {}); - if (message == null || message.length() == 0) { - throw new IllegalStateException("Unable to identify the template's message."); - } + for (OrganizationCategory organizationCategory : organizationCategories) { + OrganizationCategory dbOrganizationCategory = organizationCategoryRepo.findByName(organizationCategory.getName()); - EmailTemplate template = emailTemplateRepo.findByNameAndSystemRequired(name, true); + if (dbOrganizationCategory == null) { + dbOrganizationCategory = organizationCategoryRepo.create(organizationCategory.getName()); + } - if (template == null) { - template = emailTemplateRepo.create(name, subject, message); - template.setSystemRequired(true); - } else { - template.setSubject(subject); - template.setMessage(message); } - - return emailTemplateRepo.save(template); - - } catch (IOException e) { - throw new IllegalStateException("Unable to generate system email template: " + name, e); + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize default embargos. ", e); } } - private void loadLanguages() { + private void loadDocumentTypes() { try { - List languages = objectMapper.readValue(getFileFromResource("classpath:/languages/SYSTEM_Languages.json"), new TypeReference>() {}); - for (Language language : languages) { - Language persistedLanguage = languageRepo.findByName(language.getName()); + List documentTypes = objectMapper.readValue(getFileFromResource("classpath:/document_types/SYSTEM_Document_Types.json"), new TypeReference>() {}); - if (persistedLanguage == null) { - persistedLanguage = languageRepo.create(language.getName()); + for (DocumentType documentType : documentTypes) { + + FieldPredicate fieldPredicate = documentType.getFieldPredicate(); + + FieldPredicate dbFieldPredicate = fieldPredicateRepo.findByValue(fieldPredicate.getValue()); + if (dbFieldPredicate == null) { + dbFieldPredicate = fieldPredicateRepo.create(fieldPredicate.getValue(), Boolean.valueOf(true)); } else { - persistedLanguage.setName(language.getName()); - persistedLanguage = languageRepo.save(persistedLanguage); + dbFieldPredicate.setValue(fieldPredicate.getValue()); + dbFieldPredicate.setDocumentTypePredicate(fieldPredicate.getDocumentTypePredicate()); + dbFieldPredicate = fieldPredicateRepo.save(dbFieldPredicate); } - } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default languages. ", e); - } - } - - private void loadInputTypes() { - try { - List inputTypes = objectMapper.readValue(getFileFromResource("classpath:/input_types/SYSTEM_Input_Types.json"), new TypeReference>() {}); - for (InputType inputType : inputTypes) { - InputType persistedInputType = inputTypeRepo.findByName(inputType.getName()); + DocumentType dbDocumentType = documentTypeRepo.findByNameAndFieldPredicate(documentType.getName(), dbFieldPredicate); - if (persistedInputType == null) { - persistedInputType = inputTypeRepo.create(inputType); + if (dbDocumentType == null) { + dbDocumentType = documentTypeRepo.create(documentType.getName(), dbFieldPredicate); } else { - persistedInputType.setName(inputType.getName()); - persistedInputType = inputTypeRepo.save(persistedInputType); + dbDocumentType.setName(documentType.getName()); + dbDocumentType.setFieldPredicate(dbFieldPredicate); + documentTypeRepo.save(dbDocumentType); } } } catch (RuntimeException | IOException e) { e.printStackTrace(); - logger.debug("Unable to initialize default input types. ", e); + logger.debug("Unable to initialize default document types. ", e); } } - private void loadEmailTemplates() { + private void loadOrganization() { - for (String name : getAllSystemEmailTemplateNames()) { + Organization organization = null; - // try to see if it already exists in the DB - EmailTemplate dbTemplate = emailTemplateRepo.findByNameAndSystemRequired(name, true); + try { + // read and map json to Organization + Organization systemOrganization = objectMapper.readValue(getFileFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); - // create template or upgrade the old one - if (dbTemplate == null) { - dbTemplate = loadSystemEmailTemplate(name); - logger.info("New System Email template being installed [" + dbTemplate.getName() + "]"); - } else { - EmailTemplate loadedTemplate = loadSystemEmailTemplate(name); + // check to see if organization category exists + OrganizationCategory category = organizationCategoryRepo.findByName(systemOrganization.getCategory().getName()); - // if the template in the DB doesn't match in content with the - // one loaded from .email file - if (!(dbTemplate.getMessage().equals(loadedTemplate.getMessage())) || !(dbTemplate.getSubject().equals(loadedTemplate.getSubject()))) { + // create organization category if does not already exists + if (category == null) { + category = organizationCategoryRepo.create(systemOrganization.getCategory().getName()); + } - EmailTemplate possibleCustomTemplate = emailTemplateRepo.findByNameAndSystemRequired(name, false); + // check to see if organization with organization category exists + organization = organizationRepo.findByNameAndCategory(systemOrganization.getName(), category); - // if this System template already has a custom template - // (meaning one named the same but that is - // !systemRequired) - if (possibleCustomTemplate != null) { + // create new organization if not already exists + if (organization == null) { + organization = organizationRepo.create(systemOrganization.getName(), category); + organization.setAcceptsSubmissions(systemOrganization.getAcceptsSubmissions()); + } - // a custom version of this System email template - // already exists, it's safe to override dbTemplate's - // data and save - dbTemplate.setMessage(loadedTemplate.getMessage()); - dbTemplate.setSubject(loadedTemplate.getSubject()); - dbTemplate.setSystemRequired(true); + processWorkflowSteps(organization, systemOrganization); - logger.info("Upgrading Old System Email Template for [" + dbTemplate.getName() + "]"); + processEmailWorflowRules(organization, systemOrganization); - emailTemplateRepo.save(dbTemplate); - } - // there is no custom one yet, we need to make the - // dbTemplate !systemRequired and the save loadedTemplate - else { - logger.info("Upgrading Old System Email Template and creating custom version for [" + dbTemplate.getName() + "]"); - dbTemplate.setSystemRequired(false); - emailTemplateRepo.save(dbTemplate); - emailTemplateRepo.save(loadedTemplate); - } - } - } + organization = organizationRepo.save(organization); + + } catch (IOException e) { + throw new IllegalStateException("Unable to generate system organization", e); } + } - private void loadSubmissionListColumns() { + private void processWorkflowSteps(Organization organization, Organization systemOrganization) { - try { + for (WorkflowStep workflowStep : systemOrganization.getOriginalWorkflowSteps()) { - List submissionListColumns = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json"), new TypeReference>() {}); + // check to see if the WorkflowStep exists + WorkflowStep newWorkflowStep = workflowStepRepo.findByNameAndOriginatingOrganization(workflowStep.getName(), organization); - for (SubmissionListColumn submissionListColumn : submissionListColumns) { - SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(submissionListColumn.getTitle()); + // create new workflow step if not already exists + if (newWorkflowStep == null) { + organization = organizationRepo.findById(organization.getId()).get(); + newWorkflowStep = workflowStepRepo.create(workflowStep.getName(), organization); + } + + List originalFieldProfiles = new ArrayList<>(workflowStep.getOriginalFieldProfiles()); + + for (FieldProfile fieldProfile : originalFieldProfiles) { + // check to see if the FieldPredicate exists + FieldPredicate fieldPredicate = fieldPredicateRepo.findByValue(fieldProfile.getFieldPredicate().getValue()); + + // create new FieldPredicate if not already exists + if (fieldPredicate == null) { + fieldPredicate = fieldPredicateRepo.create(fieldProfile.getFieldPredicate().getValue(), fieldProfile.getFieldPredicate().getDocumentTypePredicate()); + } // check to see if the InputType exists - InputType inputType = inputTypeRepo.findByName(submissionListColumn.getInputType().getName()); + InputType inputType = inputTypeRepo.findByName(fieldProfile.getInputType().getName()); if (inputType == null) { - inputType = inputTypeRepo.create(submissionListColumn.getInputType().getName()); - } else { - inputType.setName(submissionListColumn.getInputType().getName()); - inputType = inputTypeRepo.save(inputType); + inputType = inputTypeRepo.create(fieldProfile.getInputType().getName()); } - if (dbSubmissionListColumn == null) { - if (submissionListColumn.getPredicate() != null) { - submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getPredicate(), inputType); - } else { - submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getValuePath(), inputType); - } - } else { - dbSubmissionListColumn.setSort(submissionListColumn.getSort()); - if (submissionListColumn.getPredicate() != null) { - dbSubmissionListColumn.setPredicate(submissionListColumn.getPredicate()); + // check to see if the ControlledVocabulary exists + ControlledVocabulary controlledVocabulary = fieldProfile.getControlledVocabulary(); + + // create new ControlledVocabulary if not already exists + if (controlledVocabulary != null) { + ControlledVocabulary persistedControlledVocabulary = controlledVocabularyRepo.findByName(controlledVocabulary.getName()); + if (persistedControlledVocabulary == null) { + persistedControlledVocabulary = controlledVocabularyRepo.create(controlledVocabulary.getName(), controlledVocabulary.getIsEntityProperty()); } - dbSubmissionListColumn.setValuePath(submissionListColumn.getValuePath()); - submissionListColumnRepo.save(dbSubmissionListColumn); + fieldProfile.setControlledVocabulary(persistedControlledVocabulary); } - } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize submission list columns. ", e); - } - try { - String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); - int count = 0; - for (String defaultTitle : defaultSubmissionListColumnTitles) { - SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); - if (dbSubmissionListColumn != null) { - if (dbSubmissionListColumn.getSort() != Sort.NONE) { - logger.warn("Updating sort order for default submission list column with title " + defaultTitle); - dbSubmissionListColumn.setSortOrder(++count); - submissionListColumnRepo.update(dbSubmissionListColumn); + // check to see if the ManagedConfiguration exists + ManagedConfiguration managedConfiguration = fieldProfile.getMappedShibAttribute(); + + // create new ManagedConfiguration if not already exists + if (managedConfiguration != null) { + ManagedConfiguration persistedManagedConfiguration = configurationRepo.findByNameAndType(managedConfiguration.getName(), managedConfiguration.getType()); + if (persistedManagedConfiguration == null) { + persistedManagedConfiguration = configurationRepo.create(managedConfiguration); } - } else { - logger.warn("Unable to find submission list column with title " + defaultTitle); + fieldProfile.setMappedShibAttribute(persistedManagedConfiguration); + } + + // check to see if the FieldProfile exists + FieldProfile newFieldProfile = fieldProfileRepo.findByFieldPredicateAndOriginatingWorkflowStep(fieldPredicate, newWorkflowStep); + + // create new FieldProfile if not already exists + if (newFieldProfile == null) { + newWorkflowStep = workflowStepRepo.findById(newWorkflowStep.getId()).get(); + newFieldProfile = fieldProfileRepo.create(newWorkflowStep, fieldPredicate, inputType, fieldProfile.getUsage(), fieldProfile.getHelp(), fieldProfile.getGloss(), fieldProfile.getRepeatable(), fieldProfile.getOverrideable(), fieldProfile.getEnabled(), fieldProfile.getOptional(), fieldProfile.getHidden(), fieldProfile.getFlagged(), fieldProfile.getLogged(), fieldProfile.getControlledVocabulary(), fieldProfile.getMappedShibAttribute(), fieldProfile.getDefaultValue()); } + + newWorkflowStep.addOriginalFieldProfile(newFieldProfile); + + newWorkflowStep = workflowStepRepo.save(newWorkflowStep); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default submission list column titles. ", e); - } + // temporary list of Note + List notes = new ArrayList(); - } + for (Note note : workflowStep.getOriginalNotes()) { - private List getAllSystemEmailTemplateNames() { - try { + // check to see if the Note exists + Note newNote = noteRepo.findByNameAndOriginatingWorkflowStep(note.getName(), newWorkflowStep); + + // create new Note if not already exists + if (newNote == null) { + newNote = noteRepo.create(newWorkflowStep, note.getName(), note.getText()); + newWorkflowStep = workflowStepRepo.findById(newWorkflowStep.getId()).get(); + } + + notes.add(newNote); - List names = new ArrayList(); - for (Resource resource : resourcePatternResolver.getResources("classpath:/emails/*.email")) { - String fileName = resource.getFilename(); - String templateName = decodeTemplateName(fileName); - names.add(templateName); } - return names; + newWorkflowStep.setOriginalNotes(notes); - } catch (IOException e) { - throw new IllegalStateException("Unable to get emails directory from classpath."); + newWorkflowStep.setInstructions(workflowStep.getInstructions()); + + newWorkflowStep = workflowStepRepo.save(newWorkflowStep); } } - private void loadEmbargos() { - - try { + private void processEmailWorflowRules(Organization organization, Organization systemOrganization) { + List emailWorkflowRules = organization.getEmailWorkflowRules(); - List embargoDefinitions = objectMapper.readValue(getFileFromResource("classpath:/embargos/SYSTEM_Embargo_Definitions.json"), new TypeReference>() {}); + for (EmailWorkflowRule emailWorkflowRule : systemOrganization.getEmailWorkflowRules()) { - for (Embargo embargoDefinition : embargoDefinitions) { - Embargo dbEmbargo = embargoRepo.findByNameAndGuarantorAndSystemRequired(embargoDefinition.getName(), embargoDefinition.getGuarantor(), true); + // check to see if the SubmissionStatus exists + SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(emailWorkflowRule.getSubmissionStatus().getName()); - if (dbEmbargo == null) { - dbEmbargo = embargoRepo.create(embargoDefinition.getName(), embargoDefinition.getDescription(), embargoDefinition.getDuration(), embargoDefinition.getGuarantor(), embargoDefinition.isActive()); - dbEmbargo.setSystemRequired(true); - embargoRepo.save(dbEmbargo); - } else { - dbEmbargo.setDescription(embargoDefinition.getDescription()); - dbEmbargo.setDuration(embargoDefinition.getDuration()); - dbEmbargo.setGuarantor(embargoDefinition.getGuarantor()); - dbEmbargo.isActive(embargoDefinition.isActive()); - dbEmbargo.setSystemRequired(embargoDefinition.getSystemRequired()); - embargoRepo.save(dbEmbargo); - } + // create new SubmissionStatus if not already exists + if (newSubmissionStatus == null) { + newSubmissionStatus = submissionStatusRepo.create(emailWorkflowRule.getSubmissionStatus().getName(), emailWorkflowRule.getSubmissionStatus().isArchived(), emailWorkflowRule.getSubmissionStatus().isPublishable(), emailWorkflowRule.getSubmissionStatus().isDeletable(), emailWorkflowRule.getSubmissionStatus().isEditableByReviewer(), emailWorkflowRule.getSubmissionStatus().isEditableByStudent(), emailWorkflowRule.getSubmissionStatus().isActive(), + emailWorkflowRule.getSubmissionStatus().getSubmissionState()); + newSubmissionStatus = submissionStatusRepo.save(recursivelyFindOrCreateSubmissionStatus(emailWorkflowRule.getSubmissionStatus())); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default embargos. ", e); - } - } - private void loadDocumentTypes() { + // check to see if the EmailTemplate exists + EmailTemplate newEmailTemplate = emailTemplateRepo.findByNameAndSystemRequired(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSystemRequired()); - try { + // create new EmailTemplate if not already exists + if (newEmailTemplate == null) { + newEmailTemplate = emailTemplateRepo.create(emailWorkflowRule.getEmailTemplate().getName(), emailWorkflowRule.getEmailTemplate().getSubject(), emailWorkflowRule.getEmailTemplate().getMessage()); + } - List documentTypes = objectMapper.readValue(getFileFromResource("classpath:/document_types/SYSTEM_Document_Types.json"), new TypeReference>() {}); + if (emailWorkflowRule.getEmailRecipient() == null) { - for (DocumentType documentType : documentTypes) { + if (newEmailTemplate.getName().equals("SYSTEM Advisor Review Request")) { + organization.getAggregateWorkflowSteps().forEach(awfs -> { + awfs.getAggregateFieldProfiles().forEach(afp -> { + if (afp.getFieldPredicate().getValue().equals("dc.contributor.advisor")) { + EmailRecipient recipient = abstractEmailRecipientRepo.createContactRecipient(afp.getGloss(), afp.getFieldPredicate()); + emailWorkflowRule.setEmailRecipient(recipient); + } + }); + }); - FieldPredicate fieldPredicate = documentType.getFieldPredicate(); + } - FieldPredicate dbFieldPredicate = fieldPredicateRepo.findByValue(fieldPredicate.getValue()); - if (dbFieldPredicate == null) { - dbFieldPredicate = fieldPredicateRepo.create(fieldPredicate.getValue(), Boolean.valueOf(true)); - } else { - dbFieldPredicate.setValue(fieldPredicate.getValue()); - dbFieldPredicate.setDocumentTypePredicate(fieldPredicate.getDocumentTypePredicate()); - dbFieldPredicate = fieldPredicateRepo.save(dbFieldPredicate); + if (newEmailTemplate.getName().equals("SYSTEM Initial Submission")) { + EmailRecipient recipient = abstractEmailRecipientRepo.createOrganizationRecipient(organization); + emailWorkflowRule.setEmailRecipient(recipient); } - DocumentType dbDocumentType = documentTypeRepo.findByNameAndFieldPredicate(documentType.getName(), dbFieldPredicate); + } - if (dbDocumentType == null) { - dbDocumentType = documentTypeRepo.create(documentType.getName(), dbFieldPredicate); - } else { - dbDocumentType.setName(documentType.getName()); - dbDocumentType.setFieldPredicate(dbFieldPredicate); - documentTypeRepo.save(dbDocumentType); - } + // check to see if the EmailWorkflowRule exists + EmailWorkflowRule existingEmailWorkflowRule = emailWorkflowRuleRepo.findBySubmissionStatusAndEmailRecipientAndEmailTemplate(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate); + + if (existingEmailWorkflowRule == null) { + emailWorkflowRules.add(emailWorkflowRuleRepo.create(newSubmissionStatus, emailWorkflowRule.getEmailRecipient(), newEmailTemplate, emailWorkflowRule.isSystem())); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default document types. ", e); + } + + organization.setEmailWorkflowRules(emailWorkflowRules); } private void loadControlledVocabularies() { @@ -924,6 +869,66 @@ private void loadProquestSubjectCodesControlledVocabulary() { } } + private void loadSubmissionListColumns() { + try { + + List submissionListColumns = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json"), new TypeReference>() {}); + + for (SubmissionListColumn submissionListColumn : submissionListColumns) { + SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(submissionListColumn.getTitle()); + + // check to see if the InputType exists + InputType inputType = inputTypeRepo.findByName(submissionListColumn.getInputType().getName()); + + if (inputType == null) { + inputType = inputTypeRepo.create(submissionListColumn.getInputType().getName()); + } else { + inputType.setName(submissionListColumn.getInputType().getName()); + inputType = inputTypeRepo.save(inputType); + } + + if (dbSubmissionListColumn == null) { + if (submissionListColumn.getPredicate() != null) { + submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getPredicate(), inputType); + } else { + submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getValuePath(), inputType); + } + } else { + dbSubmissionListColumn.setSort(submissionListColumn.getSort()); + if (submissionListColumn.getPredicate() != null) { + dbSubmissionListColumn.setPredicate(submissionListColumn.getPredicate()); + } + dbSubmissionListColumn.setValuePath(submissionListColumn.getValuePath()); + submissionListColumnRepo.save(dbSubmissionListColumn); + } + } + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize submission list columns. ", e); + } + + try { + String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); + int count = 0; + for (String defaultTitle : defaultSubmissionListColumnTitles) { + SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); + if (dbSubmissionListColumn != null) { + if (dbSubmissionListColumn.getSort() != Sort.NONE) { + logger.warn("Updating sort order for default submission list column with title " + defaultTitle); + dbSubmissionListColumn.setSortOrder(++count); + submissionListColumnRepo.update(dbSubmissionListColumn); + } + } else { + logger.warn("Unable to find submission list column with title " + defaultTitle); + } + } + + } catch (RuntimeException | IOException e) { + e.printStackTrace(); + logger.debug("Unable to initialize default submission list column titles. ", e); + } + } + private void loadPackagers() { if (abstractPackagerRepo.findByName("DSpaceMETS") == null) { abstractPackagerRepo.createDSpaceMetsPackager("DSpaceMETS", new DSpaceMetsFormatter()); @@ -945,17 +950,6 @@ private void loadPackagers() { } } - private static String encodeTemplateName(String name) { - return name.replaceAll(" ", "_") + ".email"; - } - - private String decodeTemplateName(String path) { - if (path.endsWith(".email")) { - path = path.substring(0, path.length() - ".email".length()); - } - return path.replaceAll("_", " "); - } - private File getFileFromResource(String resourcePath) throws IOException { return fileIOUtility.getFileFromResource(resourcePath); } From 47035dad1f53fbdf4c0b84c85801bb5075d9f50b Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 14:42:57 -0600 Subject: [PATCH 17/48] Directly use resource pattern resolver during system data loading --- .../org/tdl/vireo/service/AssetService.java | 6 +- .../tdl/vireo/service/SystemDataLoader.java | 102 ++++++++---------- 2 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/AssetService.java b/src/main/java/org/tdl/vireo/service/AssetService.java index c92b9036d1..cfaefc0dfc 100644 --- a/src/main/java/org/tdl/vireo/service/AssetService.java +++ b/src/main/java/org/tdl/vireo/service/AssetService.java @@ -48,6 +48,8 @@ public class AssetService { private static final Logger LOG = LoggerFactory.getLogger(AssetService.class); + private final FileHelperUtility fileHelperUtility = new FileHelperUtility(); + @Autowired private ObjectMapper objectMapper; @@ -57,8 +59,6 @@ public class AssetService { @Autowired private ResourcePatternResolver resourcePatternResolver; - private final FileHelperUtility fileHelperUtility = new FileHelperUtility(); - public void write(byte[] data, String relativePath) throws IOException { Files.write(processAssetsRelativePath(relativePath), data); } @@ -214,7 +214,7 @@ public List getResourceDirectoryListing(String resourceDirectory) throws I return Arrays.asList(resource.getFile().listFiles()); } - public Resource getResource(String resourcePath) { + private Resource getResource(String resourcePath) { return resourcePatternResolver.getResource(resourcePath); } diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index e38493be16..401b0c5285 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -1,7 +1,7 @@ package org.tdl.vireo.service; -import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; @@ -93,10 +93,6 @@ public class SystemDataLoader { @Autowired private ResourcePatternResolver resourcePatternResolver; - // TODO: replace use with the ResourcePatternResolver for loading system data - @Autowired - private AssetService fileIOUtility; - @Autowired private InputTypeRepo inputTypeRepo; @@ -219,7 +215,7 @@ public void loadSystemData() { private void loadLanguages() { try { - List languages = objectMapper.readValue(getFileFromResource("classpath:/languages/SYSTEM_Languages.json"), new TypeReference>() {}); + List languages = objectMapper.readValue(getInputStreamFromResource("classpath:/languages/SYSTEM_Languages.json"), new TypeReference>() {}); for (Language language : languages) { Language persistedLanguage = languageRepo.findByName(language.getName()); @@ -239,7 +235,7 @@ private void loadLanguages() { private void loadInputTypes() { try { - List inputTypes = objectMapper.readValue(getFileFromResource("classpath:/input_types/SYSTEM_Input_Types.json"), new TypeReference>() {}); + List inputTypes = objectMapper.readValue(getInputStreamFromResource("classpath:/input_types/SYSTEM_Input_Types.json"), new TypeReference>() {}); for (InputType inputType : inputTypes) { InputType persistedInputType = inputTypeRepo.findByName(inputType.getName()); @@ -330,8 +326,8 @@ private String decodeTemplateName(String path) { } private EmailTemplate loadSystemEmailTemplate(String name) { - try { + Resource resource = resourcePatternResolver.getResource("classpath:/emails/" + encodeTemplateName(name)); String data = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8); @@ -385,7 +381,7 @@ private static String encodeTemplateName(String name) { private void loadDegreeLevels() { try { - List degreeLevels = objectMapper.readValue(getFileFromResource("classpath:/degree_levels/SYSTEM_Degree_Levels.json"), new TypeReference>() {}); + List degreeLevels = objectMapper.readValue(getInputStreamFromResource("classpath:/degree_levels/SYSTEM_Degree_Levels.json"), new TypeReference>() {}); for (DegreeLevel degreeLevel : degreeLevels) { DegreeLevel dbDegreeLevel = degreeLevelRepo.findByName(degreeLevel.getName()); @@ -404,7 +400,7 @@ private void loadDegreeLevels() { private void loadDegrees() { try { - List degrees = objectMapper.readValue(getFileFromResource("classpath:/degrees/SYSTEM_Degrees.json"), new TypeReference>() {}); + List degrees = objectMapper.readValue(getInputStreamFromResource("classpath:/degrees/SYSTEM_Degrees.json"), new TypeReference>() {}); for (Degree degree : degrees) { @@ -437,7 +433,7 @@ private void loadDegrees() { private void loadGraduationMonths() { try { - List graduationMonths = objectMapper.readValue(getFileFromResource("classpath:/graduation_months/SYSTEM_Graduation_Months.json"), new TypeReference>() {}); + List graduationMonths = objectMapper.readValue(getInputStreamFromResource("classpath:/graduation_months/SYSTEM_Graduation_Months.json"), new TypeReference>() {}); for (GraduationMonth graduationMonth : graduationMonths) { GraduationMonth persistedGraduationMonth = graduationMonthRepo.findByMonth(graduationMonth.getMonth()); @@ -456,7 +452,7 @@ private void loadGraduationMonths() { private void loadEmbargos() { try { - List embargoDefinitions = objectMapper.readValue(getFileFromResource("classpath:/embargos/SYSTEM_Embargo_Definitions.json"), new TypeReference>() {}); + List embargoDefinitions = objectMapper.readValue(getInputStreamFromResource("classpath:/embargos/SYSTEM_Embargo_Definitions.json"), new TypeReference>() {}); for (Embargo embargoDefinition : embargoDefinitions) { Embargo dbEmbargo = embargoRepo.findByNameAndGuarantorAndSystemRequired(embargoDefinition.getName(), embargoDefinition.getGuarantor(), true); @@ -482,13 +478,13 @@ private void loadEmbargos() { private void loadSubmissionStatuses() { try { - File statusesFile = getFileFromResource("classpath:/submission_statuses/SYSTEM_Submission_Statuses.json"); - File transitionsFile = getFileFromResource("classpath:/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json"); + InputStream statusesInputStream = getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Statuses.json"); + InputStream transitionsInputStream = getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json"); // read and map json to SubmissionStatus TypeFactory tf = TypeFactory.defaultInstance(); CollectionType type = tf.constructCollectionType(ArrayList.class, SubmissionStatus.class); - List systemSubmissionStatuses = objectMapper.readValue(statusesFile, type); + List systemSubmissionStatuses = objectMapper.readValue(statusesInputStream, type); systemSubmissionStatuses.forEach(ss -> { SubmissionStatus found = submissionStatusRepo.findByName(ss.getName()); @@ -500,7 +496,7 @@ private void loadSubmissionStatuses() { }); type = tf.constructCollectionType(ArrayList.class, HashMap.class); - List> transitions = objectMapper.readValue(transitionsFile, type); + List> transitions = objectMapper.readValue(transitionsInputStream, type); for (Map transition : transitions) { List list = new ArrayList<>(); @@ -558,7 +554,7 @@ private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(SubmissionStatu private void loadOrganizationCategories() { try { - List organizationCategories = objectMapper.readValue(getFileFromResource("classpath:/organization_categories/SYSTEM_Organizaiton_Categories.json"), new TypeReference>() {}); + List organizationCategories = objectMapper.readValue(getInputStreamFromResource("classpath:/organization_categories/SYSTEM_Organizaiton_Categories.json"), new TypeReference>() {}); for (OrganizationCategory organizationCategory : organizationCategories) { OrganizationCategory dbOrganizationCategory = organizationCategoryRepo.findByName(organizationCategory.getName()); @@ -577,7 +573,7 @@ private void loadOrganizationCategories() { private void loadDocumentTypes() { try { - List documentTypes = objectMapper.readValue(getFileFromResource("classpath:/document_types/SYSTEM_Document_Types.json"), new TypeReference>() {}); + List documentTypes = objectMapper.readValue(getInputStreamFromResource("classpath:/document_types/SYSTEM_Document_Types.json"), new TypeReference>() {}); for (DocumentType documentType : documentTypes) { @@ -614,7 +610,7 @@ private void loadOrganization() { try { // read and map json to Organization - Organization systemOrganization = objectMapper.readValue(getFileFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); + Organization systemOrganization = objectMapper.readValue(getInputStreamFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); // check to see if organization category exists OrganizationCategory category = organizationCategoryRepo.findByName(systemOrganization.getCategory().getName()); @@ -797,48 +793,44 @@ private void processEmailWorflowRules(Organization organization, Organization sy } private void loadControlledVocabularies() { - - List controlledVocabularyFiles = new ArrayList(); try { - controlledVocabularyFiles = fileIOUtility.getResourceDirectoryListing("classpath:/controlled_vocabularies/"); - } catch (IOException e) { - e.printStackTrace(); - } + for (Resource vocabularyResourceJson : resourcePatternResolver.getResources("classpath:/controlled_vocabularies/*.json")) { + try { + ControlledVocabulary cv = objectMapper.readValue(vocabularyResourceJson.getInputStream(), ControlledVocabulary.class); - for (File vocabularyJson : controlledVocabularyFiles) { - try { - ControlledVocabulary cv = objectMapper.readValue(vocabularyJson, ControlledVocabulary.class); + // check to see if Controlled Vocabulary exists, and if so, merge up with it + ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - // check to see if Controlled Vocabulary exists, and if so, merge up with it - ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - - if (persistedCV == null) { - persistedCV = controlledVocabularyRepo.create(cv.getName()); - } + if (persistedCV == null) { + persistedCV = controlledVocabularyRepo.create(cv.getName()); + } - for (VocabularyWord vw : cv.getDictionary()) { + for (VocabularyWord vw : cv.getDictionary()) { - VocabularyWord persistedVW = vocabularyRepo.findByNameAndControlledVocabulary(vw.getName(), persistedCV); + VocabularyWord persistedVW = vocabularyRepo.findByNameAndControlledVocabulary(vw.getName(), persistedCV); - if (persistedVW == null) { - persistedVW = vocabularyRepo.create(persistedCV, vw.getName(), vw.getDefinition(), vw.getIdentifier(), vw.getContacts()); - persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - } else { - persistedVW.setDefinition(vw.getDefinition()); - persistedVW.setIdentifier(vw.getIdentifier()); - persistedVW.setContacts(vw.getContacts()); - persistedVW = vocabularyRepo.save(persistedVW); + if (persistedVW == null) { + persistedVW = vocabularyRepo.create(persistedCV, vw.getName(), vw.getDefinition(), vw.getIdentifier(), vw.getContacts()); + persistedCV = controlledVocabularyRepo.findByName(cv.getName()); + } else { + persistedVW.setDefinition(vw.getDefinition()); + persistedVW.setIdentifier(vw.getIdentifier()); + persistedVW.setContacts(vw.getContacts()); + persistedVW = vocabularyRepo.save(persistedVW); + } } + + } catch (JsonParseException e) { + e.printStackTrace(); + } catch (JsonMappingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); } - } catch (JsonParseException e) { - e.printStackTrace(); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); } - + } catch (IOException e) { + e.printStackTrace(); } } @@ -872,7 +864,7 @@ private void loadProquestSubjectCodesControlledVocabulary() { private void loadSubmissionListColumns() { try { - List submissionListColumns = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json"), new TypeReference>() {}); + List submissionListColumns = objectMapper.readValue(getInputStreamFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json"), new TypeReference>() {}); for (SubmissionListColumn submissionListColumn : submissionListColumns) { SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(submissionListColumn.getTitle()); @@ -908,7 +900,7 @@ private void loadSubmissionListColumns() { } try { - String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getFileFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); + String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getInputStreamFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); int count = 0; for (String defaultTitle : defaultSubmissionListColumnTitles) { SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); @@ -950,8 +942,8 @@ private void loadPackagers() { } } - private File getFileFromResource(String resourcePath) throws IOException { - return fileIOUtility.getFileFromResource(resourcePath); + private InputStream getInputStreamFromResource(String resourcePath) throws IOException { + return resourcePatternResolver.getResource(resourcePath).getInputStream(); } } From c9f320ae882da2e1999f1c2ffa9c1d8af174d190 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 14:54:55 -0600 Subject: [PATCH 18/48] Fix submission controller indentation --- .../controller/SubmissionController.java | 263 +++++++++--------- 1 file changed, 132 insertions(+), 131 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionController.java b/src/main/java/org/tdl/vireo/controller/SubmissionController.java index b842b72794..5ee324da76 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionController.java @@ -106,104 +106,106 @@ @RequestMapping("/submission") public class SubmissionController { - private static final Logger LOG = LoggerFactory.getLogger(SubmissionController.class); + private static final Logger LOG = LoggerFactory.getLogger(SubmissionController.class); - private static final String STARTING_SUBMISSION_STATUS_NAME = "In Progress"; + private static final String STARTING_SUBMISSION_STATUS_NAME = "In Progress"; - private static final String NEEDS_CORRECTION_SUBMISSION_STATUS_NAME = "Needs Correction"; + private static final String NEEDS_CORRECTION_SUBMISSION_STATUS_NAME = "Needs Correction"; - private static final String CORRECTIONS_RECEIVED_SUBMISSION_STATUS_NAME = "Corrections Received"; + private static final String CORRECTIONS_RECEIVED_SUBMISSION_STATUS_NAME = "Corrections Received"; - @Autowired - private UserRepo userRepo; + @Autowired + private UserRepo userRepo; - @Autowired - private SubmissionRepo submissionRepo; + @Autowired + private SubmissionRepo submissionRepo; - @Autowired - private FieldValueRepo fieldValueRepo; + @Autowired + private FieldValueRepo fieldValueRepo; - @Autowired - private SubmissionFieldProfileRepo submissionFieldProfileRepo; + @Autowired + private SubmissionFieldProfileRepo submissionFieldProfileRepo; - @Autowired - private NamedSearchFilterGroupRepo namedSearchFilterGroupRepo; + @Autowired + private NamedSearchFilterGroupRepo namedSearchFilterGroupRepo; - @Autowired - private OrganizationRepo organizationRepo; + @Autowired + private OrganizationRepo organizationRepo; - @Autowired - private SubmissionStatusRepo submissionStatusRepo; + @Autowired + private SubmissionStatusRepo submissionStatusRepo; - @Autowired - private CustomActionDefinitionRepo customActionDefinitionRepo; + @Autowired + private CustomActionDefinitionRepo customActionDefinitionRepo; - @Autowired - private SubmissionEmailService submissionEmailService; + @Autowired + private SubmissionEmailService submissionEmailService; - @Autowired - private TemplateUtility templateUtility; + @Autowired + private TemplateUtility templateUtility; - @Autowired - private AssetService assetService; + @Autowired + private AssetService assetService; - @Autowired - private ConfigurationRepo configurationRepo; + @Autowired + private ConfigurationRepo configurationRepo; - @Autowired - private ActionLogRepo actionLogRepo; + @Autowired + private ActionLogRepo actionLogRepo; - @Autowired - private DepositLocationRepo depositLocationRepo; + @Autowired + private DepositLocationRepo depositLocationRepo; - @Autowired - private DepositorService depositorService; + @Autowired + private DepositorService depositorService; - @Autowired - private PackagerUtility packagerUtility; + @Autowired + private PackagerUtility packagerUtility; - @Autowired - private SimpMessagingTemplate simpMessagingTemplate; + @Autowired + private SimpMessagingTemplate simpMessagingTemplate; - @Autowired - private ObjectMapper objectMapper; + @Autowired + private ObjectMapper objectMapper; - @Autowired - private CustomActionValueRepo customActionValueRepo; + @Autowired + private CustomActionValueRepo customActionValueRepo; - @Value("${app.document.folder:private}") - private String documentFolder; + @Value("${app.document.folder:private}") + private String documentFolder; - @Value("${app.documentType.rename:}") - private String documentTypesToRename; + @Value("${app.documentType.rename:}") + private String documentTypesToRename; - @RequestMapping("/all") - @PreAuthorize("hasRole('ADMIN')") - public ApiResponse getAll() { - return new ApiResponse(SUCCESS, submissionRepo.findAll()); - } - - @RequestMapping("/all-by-user") - @PreAuthorize("hasRole('STUDENT')") - public ApiResponse getAllByUser(@WeaverUser User user) { - return new ApiResponse(SUCCESS, submissionRepo.findAllViewBySubmitterId(user.getId(), FieldValueSubmissionView.class)); - } + @RequestMapping("/all") + @PreAuthorize("hasRole('ADMIN')") + public ApiResponse getAll() { + return new ApiResponse(SUCCESS, submissionRepo.findAll()); + } - @JsonView(Views.SubmissionIndividualActionLogs.class) - @RequestMapping("/get-one/{submissionId}") - @PreAuthorize("hasRole('STUDENT')") - public ApiResponse getOne(@WeaverUser User user, @PathVariable Long submissionId) { - Submission submission = null; - if (user.getRole().ordinal() <= Role.ROLE_REVIEWER.ordinal()) { - submission = submissionRepo.read(submissionId); - } else { - submission = submissionRepo.findOneBySubmitterAndId(user, submissionId); + @RequestMapping("/all-by-user") + @PreAuthorize("hasRole('STUDENT')") + public ApiResponse getAllByUser(@WeaverUser User user) { + return new ApiResponse(SUCCESS, submissionRepo.findAllViewBySubmitterId(user.getId(), FieldValueSubmissionView.class)); } - if (submission == null) { - return new ApiResponse(ERROR, "Submission not found"); + + @JsonView(Views.SubmissionIndividualActionLogs.class) + @RequestMapping("/get-one/{submissionId}") + @PreAuthorize("hasRole('STUDENT')") + public ApiResponse getOne(@WeaverUser User user, @PathVariable Long submissionId) { + Submission submission = null; + if (user.getRole().ordinal() <= Role.ROLE_REVIEWER.ordinal()) { + submission = submissionRepo.read(submissionId); + } else { + submission = submissionRepo.findOneBySubmitterAndId(user, submissionId); + } + + if (submission == null) { + return new ApiResponse(ERROR, "Submission not found"); + } + + return new ApiResponse(SUCCESS, submission); } - return new ApiResponse(SUCCESS, submission); - } @GetMapping("/get-one/{submissionId}/action-logs") @PreAuthorize("hasRole('STUDENT')") @@ -226,68 +228,67 @@ public ApiResponse getActionLogsForAdvisement(@PathVariable String advisorAccess return new ApiResponse(SUCCESS, actionLogRepo.getAllActionLogs(advisorAccessHash, false, pageable)); } - @RequestMapping(value = "/create", method = RequestMethod.POST) - @PreAuthorize("hasRole('STUDENT')") - public ApiResponse createSubmission(@WeaverUser User user, @WeaverCredentials Credentials credentials, - @RequestBody Map data) throws OrganizationDoesNotAcceptSubmissionsException { - - Submission submission = submissionRepo.create( - user, - organizationRepo.read(Long.valueOf(data.get("organizationId"))), - submissionStatusRepo.findByName(STARTING_SUBMISSION_STATUS_NAME), - credentials, - customActionDefinitionRepo.findAll() - ); - actionLogRepo.createPublicLog(submission, user, "Submission created."); - - return new ApiResponse(SUCCESS, submission.getId()); - } - - @Transactional - @RequestMapping("/delete/{submissionId}") - @PreAuthorize("hasRole('STUDENT')") - public ApiResponse deleteSubmission(@WeaverUser User user, @PathVariable Long submissionId) { - Submission submissionToDelete = submissionRepo.read(submissionId); - - ApiResponse response = new ApiResponse(SUCCESS); - if (submissionToDelete.getSubmitter().getEmail().equals(user.getEmail()) - || user.getRole().ordinal() <= Role.ROLE_MANAGER.ordinal()) { - submissionRepo.delete(submissionToDelete); - } else { - response = new ApiResponse(ERROR, "Insufficient permisions to delete this submission."); + @RequestMapping(value = "/create", method = RequestMethod.POST) + @PreAuthorize("hasRole('STUDENT')") + public ApiResponse createSubmission(@WeaverUser User user, @WeaverCredentials Credentials credentials, + @RequestBody Map data) throws OrganizationDoesNotAcceptSubmissionsException { + + Submission submission = submissionRepo.create( + user, + organizationRepo.read(Long.valueOf(data.get("organizationId"))), + submissionStatusRepo.findByName(STARTING_SUBMISSION_STATUS_NAME), + credentials, + customActionDefinitionRepo.findAll() + ); + actionLogRepo.createPublicLog(submission, user, "Submission created."); + + return new ApiResponse(SUCCESS, submission.getId()); } - return response; - } + @Transactional + @RequestMapping("/delete/{submissionId}") + @PreAuthorize("hasRole('STUDENT')") + public ApiResponse deleteSubmission(@WeaverUser User user, @PathVariable Long submissionId) { + Submission submissionToDelete = submissionRepo.read(submissionId); + + ApiResponse response = new ApiResponse(SUCCESS); + if (submissionToDelete.getSubmitter().getEmail().equals(user.getEmail()) || user.getRole().ordinal() <= Role.ROLE_MANAGER.ordinal()) { + submissionRepo.delete(submissionToDelete); + } else { + response = new ApiResponse(ERROR, "Insufficient permisions to delete this submission."); + } - @RequestMapping(value = "/{submissionId}/add-comment", method = RequestMethod.POST) - @PreAuthorize("hasRole('STUDENT')") - public ApiResponse addComment(@WeaverUser User user, @PathVariable Long submissionId, - @RequestBody Map data) throws JsonProcessingException, IOException { + return response; + } + + @RequestMapping(value = "/{submissionId}/add-comment", method = RequestMethod.POST) + @PreAuthorize("hasRole('STUDENT')") + public ApiResponse addComment(@WeaverUser User user, @PathVariable Long submissionId, + @RequestBody Map data) throws JsonProcessingException, IOException { - Submission submission = submissionRepo.read(submissionId); + Submission submission = submissionRepo.read(submissionId); - String commentVisibility = data.get("commentVisibility") != null ? (String) data.get("commentVisibility") : "public"; - Boolean sendEmailToRecipient = data.get("sendEmailToRecipient") != null ? (Boolean) data.get("sendEmailToRecipient") : true; + String commentVisibility = data.get("commentVisibility") != null ? (String) data.get("commentVisibility") : "public"; + Boolean sendEmailToRecipient = data.get("sendEmailToRecipient") != null ? (Boolean) data.get("sendEmailToRecipient") : true; - data.forEach((key, value) -> System.out.println(key + ":" + value)); + data.forEach((key, value) -> System.out.println(key + ":" + value)); - if (commentVisibility.equals("public")) { - if (sendEmailToRecipient.equals(true)) { - submissionEmailService.sendAutomatedEmails(user, submission.getId(), data); - } else{ + if (commentVisibility.equals("public")) { + if (sendEmailToRecipient.equals(true)) { + submissionEmailService.sendAutomatedEmails(user, submission.getId(), data); + } else{ + String subject = (String) data.get("subject"); + String templatedMessage = templateUtility.compileString((String) data.get("message"), submission); + actionLogRepo.createPublicLog(submission, user, subject + ": " + templatedMessage); + } + } else { String subject = (String) data.get("subject"); String templatedMessage = templateUtility.compileString((String) data.get("message"), submission); - actionLogRepo.createPublicLog(submission, user, subject + ": " + templatedMessage); - } - } else { - String subject = (String) data.get("subject"); - String templatedMessage = templateUtility.compileString((String) data.get("message"), submission); - actionLogRepo.createPrivateLog(submission, user, subject + ": " + templatedMessage); - } + actionLogRepo.createPrivateLog(submission, user, subject + ": " + templatedMessage); + } - return new ApiResponse(SUCCESS); - } + return new ApiResponse(SUCCESS); + } @RequestMapping(value = "/{submissionId}/send-email", method = RequestMethod.POST) @PreAuthorize("hasRole('REVIEWER')") @@ -321,9 +322,9 @@ public ApiResponse batchComment(@WeaverUser User user, @RequestBody Map0){ licFileName = licFileName.substring(0,sfxIndx).toUpperCase()+licFileName.substring(sfxIndx); } - b.putNextEntry(new ZipEntry(personName+"_permission/"+licFileName)); - b.write(fileBytes); + b.putNextEntry(new ZipEntry(personName+"_permission/"+licFileName)); + b.write(fileBytes); b.closeEntry(); } // PRIMARY_DOC @@ -702,7 +703,7 @@ private void processBatchExport(HttpServletResponse response, User user, String ExportPackage exportPackage = packagerUtility.packageExport(packager, submission); - //METADATA + //METADATA if (exportPackage.isMap()) { for (Map.Entry fileEntry : ((Map) exportPackage.getPayload()).entrySet()) { zos.putNextEntry(new ZipEntry(submissionName + fileEntry.getKey())); From 0494d5f45e299024e36d2c9aeaf1cf01c0c026d9 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 14:55:19 -0600 Subject: [PATCH 19/48] Add private constructor for ORCID utility --- src/main/java/org/tdl/vireo/utility/OrcidUtility.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/tdl/vireo/utility/OrcidUtility.java b/src/main/java/org/tdl/vireo/utility/OrcidUtility.java index 49006746a3..597d0f64cc 100644 --- a/src/main/java/org/tdl/vireo/utility/OrcidUtility.java +++ b/src/main/java/org/tdl/vireo/utility/OrcidUtility.java @@ -17,6 +17,11 @@ public class OrcidUtility { private static final String ORCID_API = "https://pub.orcid.org/v2.0/#/"; + + private OrcidUtility() { + + } + public static Map verifyOrcid(User user, FieldValue fieldValue) { Map errors = new HashMap(); if (fieldValue.getValue() == "") { @@ -78,4 +83,5 @@ private static DocumentBuilder getBuilder() { } return builder; } + } From 5d9395176fa872df3657412f0110c0a20b705220 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 15:25:10 -0600 Subject: [PATCH 20/48] Correct registration error response message --- src/main/java/org/tdl/vireo/auth/controller/AuthController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/auth/controller/AuthController.java b/src/main/java/org/tdl/vireo/auth/controller/AuthController.java index bb63b151cd..6270a15284 100644 --- a/src/main/java/org/tdl/vireo/auth/controller/AuthController.java +++ b/src/main/java/org/tdl/vireo/auth/controller/AuthController.java @@ -133,7 +133,7 @@ public ApiResponse registration(@RequestBody(required = false) Map Date: Thu, 28 Dec 2023 15:32:51 -0600 Subject: [PATCH 21/48] Only set default columns on user before create/persist --- .../org/tdl/vireo/model/listener/UserListener.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/tdl/vireo/model/listener/UserListener.java b/src/main/java/org/tdl/vireo/model/listener/UserListener.java index 69ad28bd40..8dff2c7501 100644 --- a/src/main/java/org/tdl/vireo/model/listener/UserListener.java +++ b/src/main/java/org/tdl/vireo/model/listener/UserListener.java @@ -1,7 +1,8 @@ package org.tdl.vireo.model.listener; +import java.util.ArrayList; + import javax.persistence.PrePersist; -import javax.persistence.PreUpdate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -27,11 +28,10 @@ public class UserListener { private DefaultSubmissionListColumnService defaultSubmissionViewColumnService; @PrePersist - @PreUpdate - private void beforeAnyUpdate(User user) { + private void beforeCreate(User user) { if (env.acceptsProfiles(Profiles.of("!isolated-test"))) { - user.setFilterColumns(defaultFiltersService.getDefaultFilter()); - user.setSubmissionViewColumns(defaultSubmissionViewColumnService.getDefaultSubmissionListColumns()); + user.setFilterColumns(new ArrayList<>(defaultFiltersService.getDefaultFilter())); + user.setSubmissionViewColumns(new ArrayList<>(defaultSubmissionViewColumnService.getDefaultSubmissionListColumns())); } } From 522b885d4e21b19b9684260cc034b486cc714815 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 15:59:10 -0600 Subject: [PATCH 22/48] Fix ORCiD authentication - issue 1877 For authentication the following must match: - ORCiD given-names must match first name input exactly - ORCiD family-name must match last name input exactly - ORCiD email be public and match email input exactly --- .../org/tdl/vireo/utility/OrcidUtility.java | 28 +++++++++++-------- .../SYSTEM_Organization_Definition.json | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/tdl/vireo/utility/OrcidUtility.java b/src/main/java/org/tdl/vireo/utility/OrcidUtility.java index 597d0f64cc..902ada3ff9 100644 --- a/src/main/java/org/tdl/vireo/utility/OrcidUtility.java +++ b/src/main/java/org/tdl/vireo/utility/OrcidUtility.java @@ -8,6 +8,8 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.tdl.vireo.model.FieldValue; import org.tdl.vireo.model.User; import org.w3c.dom.Document; @@ -16,7 +18,9 @@ public class OrcidUtility { - private static final String ORCID_API = "https://pub.orcid.org/v2.0/#/"; + private static final Logger logger = LoggerFactory.getLogger(OrcidUtility.class); + + private static final String ORCID_API = "https://pub.orcid.org/v3.0/#/"; private OrcidUtility() { @@ -34,13 +38,13 @@ public static Map verifyOrcid(User user, FieldValue fieldValue) if (doc.getElementsByTagName("record") == null) { errors.put("orcid-no-document", "No public profile was found for this ORCID"); } - if (!tagMatchesCredentials(user.getFirstName(), doc.getElementsByTagName("given-names"))) { + if (!tagMatchesCredentials(user.getFirstName(), doc.getElementsByTagName("personal-details:given-names"))) { errors.put("orcid-invalid-first-name", "The first name you registered with does not match this ORCID profile"); } - if (!tagMatchesCredentials(user.getLastName(), doc.getElementsByTagName("family-name"))) { + if (!tagMatchesCredentials(user.getLastName(), doc.getElementsByTagName("personal-details:family-name"))) { errors.put("orcid-invalid-last-name", "The last name you registered with does not match this ORCID profile"); } - if (!tagMatchesCredentials(user.getEmail(), doc.getElementsByTagName("email"))) { + if (!tagMatchesCredentials(user.getEmail(), doc.getElementsByTagName("email:email"))) { errors.put("orcid-no-invalid-email", "The email you registered with does not match this ORCID profile"); } } @@ -63,12 +67,10 @@ private static Document getDocument(String orcid) { Document doc = null; try { doc = builder.parse(ORCID_API.replace("#", orcid)); - } catch (IOException ioex) { - System.out.println("IO error occurred while verifying ORCID: " + ioex.getMessage()); - } catch (SAXException saxex) { - System.out.println("IO error occurred while verifying ORCID: " + saxex.getMessage()); - } catch (IllegalArgumentException argex) { - System.out.println("IO error occurred while verifying ORCID: " + argex.getMessage()); + } catch (IOException | SAXException | IllegalArgumentException e) { + String message = "IO error occurred while verifying ORCID"; + logger.error(message + ": " + e.getMessage()); + logger.debug(message, e); } return doc; } @@ -78,8 +80,10 @@ private static DocumentBuilder getBuilder() { DocumentBuilder builder = null; try { builder = dbf.newDocumentBuilder(); - } catch (ParserConfigurationException pcex) { - System.out.println("IO error occurred while verifying ORCID: " + pcex.getMessage()); + } catch (ParserConfigurationException e) { + String message = "IO error occurred while verifying ORCID"; + logger.error(message + ": " + e.getMessage()); + logger.debug(message, e); } return builder; } diff --git a/src/main/resources/organization/SYSTEM_Organization_Definition.json b/src/main/resources/organization/SYSTEM_Organization_Definition.json index 1e90a9ed21..3219c09b49 100644 --- a/src/main/resources/organization/SYSTEM_Organization_Definition.json +++ b/src/main/resources/organization/SYSTEM_Organization_Definition.json @@ -143,7 +143,7 @@ "enabled":true, "optional":true, "usage":"", - "help":"Enter your ORCID author identifier (ID). If you do not have an ORCID ID, you may register here orcid.org.", + "help":"Enter your ORCID author identifier (ID) associated with email. If you do not have an ORCID ID, you may register here orcid.org.", "htmlTooltip":true, "gloss": "ORCID" }, From bcace83b60c4087dc1ff60f955fa723b0949bb26 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 16:56:01 -0600 Subject: [PATCH 23/48] Avoid null pointer exception --- .../java/org/tdl/vireo/controller/SubmissionListController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java index 100e1dc4ed..daded5bbab 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionListController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionListController.java @@ -341,7 +341,7 @@ public ApiResponse saveFilterCriteria(@WeaverUser User user, @WeaverValidatedMod simpMessagingTemplate.convertAndSend("/channel/active-filters/user/" + user.getId(), new ApiResponse(SUCCESS, FilterAction.REFRESH, user.getActiveFilter())); simpMessagingTemplate.convertAndSend("/channel/saved-filters/user/" + user.getId(), new ApiResponse(SUCCESS, FilterAction.REFRESH, user.getSavedFilters())); - if (existingFilter.getPublicFlag() == true || wasPublic) { + if (existingFilter != null && existingFilter.getPublicFlag() == true || wasPublic) { simpMessagingTemplate.convertAndSend("/channel/saved-filters/public", new ApiResponse(SUCCESS, FilterAction.SAVE, existingFilter)); } From c2e821294a02007e89361faf1f8ba22506a31f48 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 16:57:58 -0600 Subject: [PATCH 24/48] Remove redundant superinterface --- src/main/java/org/tdl/vireo/model/EmailRecipientAssignee.java | 2 +- src/main/java/org/tdl/vireo/model/EmailRecipientContact.java | 2 +- .../java/org/tdl/vireo/model/EmailRecipientOrganization.java | 2 +- .../java/org/tdl/vireo/model/EmailRecipientPlainAddress.java | 2 +- src/main/java/org/tdl/vireo/model/EmailRecipientSubmitter.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/tdl/vireo/model/EmailRecipientAssignee.java b/src/main/java/org/tdl/vireo/model/EmailRecipientAssignee.java index 9ca247c1d9..a884a6df83 100644 --- a/src/main/java/org/tdl/vireo/model/EmailRecipientAssignee.java +++ b/src/main/java/org/tdl/vireo/model/EmailRecipientAssignee.java @@ -6,7 +6,7 @@ import javax.persistence.Entity; @Entity -public class EmailRecipientAssignee extends AbstractEmailRecipient implements EmailRecipient { +public class EmailRecipientAssignee extends AbstractEmailRecipient { public EmailRecipientAssignee() { setName("Assignee"); diff --git a/src/main/java/org/tdl/vireo/model/EmailRecipientContact.java b/src/main/java/org/tdl/vireo/model/EmailRecipientContact.java index bdbddfe9b8..d20b2f48a1 100644 --- a/src/main/java/org/tdl/vireo/model/EmailRecipientContact.java +++ b/src/main/java/org/tdl/vireo/model/EmailRecipientContact.java @@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory; @Entity -public class EmailRecipientContact extends AbstractEmailRecipient implements EmailRecipient { +public class EmailRecipientContact extends AbstractEmailRecipient { @Transient private Logger LOG = LoggerFactory.getLogger(this.getClass()); diff --git a/src/main/java/org/tdl/vireo/model/EmailRecipientOrganization.java b/src/main/java/org/tdl/vireo/model/EmailRecipientOrganization.java index 7a1fd98766..184a501188 100644 --- a/src/main/java/org/tdl/vireo/model/EmailRecipientOrganization.java +++ b/src/main/java/org/tdl/vireo/model/EmailRecipientOrganization.java @@ -10,7 +10,7 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerators; @Entity -public class EmailRecipientOrganization extends AbstractEmailRecipient implements EmailRecipient { +public class EmailRecipientOrganization extends AbstractEmailRecipient { @ManyToOne @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, scope = Organization.class, property = "id") diff --git a/src/main/java/org/tdl/vireo/model/EmailRecipientPlainAddress.java b/src/main/java/org/tdl/vireo/model/EmailRecipientPlainAddress.java index 3b06c9b943..e35105d98a 100644 --- a/src/main/java/org/tdl/vireo/model/EmailRecipientPlainAddress.java +++ b/src/main/java/org/tdl/vireo/model/EmailRecipientPlainAddress.java @@ -6,7 +6,7 @@ import javax.persistence.Entity; @Entity -public class EmailRecipientPlainAddress extends AbstractEmailRecipient implements EmailRecipient { +public class EmailRecipientPlainAddress extends AbstractEmailRecipient { public EmailRecipientPlainAddress() {} diff --git a/src/main/java/org/tdl/vireo/model/EmailRecipientSubmitter.java b/src/main/java/org/tdl/vireo/model/EmailRecipientSubmitter.java index ebdf692cd8..61dedab26a 100644 --- a/src/main/java/org/tdl/vireo/model/EmailRecipientSubmitter.java +++ b/src/main/java/org/tdl/vireo/model/EmailRecipientSubmitter.java @@ -6,7 +6,7 @@ import javax.persistence.Entity; @Entity -public class EmailRecipientSubmitter extends AbstractEmailRecipient implements EmailRecipient { +public class EmailRecipientSubmitter extends AbstractEmailRecipient { public EmailRecipientSubmitter() { setName("Submitter"); From 042395c62783c62e1e523542887b6459effd998c Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 19:39:22 -0600 Subject: [PATCH 25/48] Consistently format system default JSON --- .../controlled_vocabularies/Colleges.json | 80 +- .../CommitteeMembers.json | 38 +- .../controlled_vocabularies/Departments.json | 722 +++---- .../controlled_vocabularies/Majors.json | 770 ++++---- .../ManuscriptAllowedMimeTypes.json | 12 +- .../SubmissionTypes.json | 56 +- .../degree_levels/SYSTEM_Degree_Levels.json | 2 +- .../resources/degrees/SYSTEM_Degrees.json | 290 +-- .../document_types/SYSTEM_Document_Types.json | 68 +- .../embargos/SYSTEM_Embargo_Definitions.json | 3 +- .../default_filter_columns.json | 2 +- .../SYSTEM_Graduation_Months.json | 2 +- .../input_types/SYSTEM_Input_Types.json | 35 +- .../resources/languages/SYSTEM_Languages.json | 8 +- .../SYSTEM_Organization_Definition.json | 1700 ++++++++--------- .../resources/settings/SYSTEM_Defaults.json | 4 +- ...Default_Submission_List_Column_Titles.json | 13 +- ...YSTEM_Default_Submission_List_Columns.json | 72 +- 18 files changed, 1965 insertions(+), 1912 deletions(-) diff --git a/src/main/resources/controlled_vocabularies/Colleges.json b/src/main/resources/controlled_vocabularies/Colleges.json index 2c6d13b820..39b9cc67bc 100644 --- a/src/main/resources/controlled_vocabularies/Colleges.json +++ b/src/main/resources/controlled_vocabularies/Colleges.json @@ -1,66 +1,66 @@ { - "name":"Colleges", - "isEntityProperty":false, - "dictionary":[ + "name": "Colleges", + "isEntityProperty": false, + "dictionary": [ { - "name":"College of Science", - "definition":"College", - "identifier":"c6962923-3430-11e6-934e-5ce0c5308215" + "name": "College of Science", + "definition": "College", + "identifier": "c6962923-3430-11e6-934e-5ce0c5308215" }, { - "name":"Irma Lerma Rangel College of Pharmacy", - "definition":"College", - "identifier":"fa66ad06-91b1-11e6-99e2-00059a3c7a00" + "name": "Irma Lerma Rangel College of Pharmacy", + "definition": "College", + "identifier": "fa66ad06-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"College of Dentistry", - "definition":"College", - "identifier":"fa66acbf-91b1-11e6-99e2-00059a3c7a00" + "name": "College of Dentistry", + "definition": "College", + "identifier": "fa66acbf-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"College of Engineering", - "definition":"College", - "identifier":"fa66ac64-91b1-11e6-99e2-00059a3c7a00" + "name": "College of Engineering", + "definition": "College", + "identifier": "fa66ac64-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"College of Nursing", - "definition":"College", - "identifier":"c6962c50-3430-11e6-934e-5ce0c5308215" + "name": "College of Nursing", + "definition": "College", + "identifier": "c6962c50-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Geosciences", - "definition":"College", - "identifier":"c696283a-3430-11e6-934e-5ce0c5308215" + "name": "College of Geosciences", + "definition": "College", + "identifier": "c696283a-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Architecture", - "definition":"College", - "identifier":"c6950771-3430-11e6-934e-5ce0c5308215" + "name": "College of Architecture", + "definition": "College", + "identifier": "c6950771-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Liberal Arts", - "definition":"College", - "identifier":"c69628e7-3430-11e6-934e-5ce0c5308215" + "name": "College of Liberal Arts", + "definition": "College", + "identifier": "c69628e7-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Veterinary Medicine and Biomedical Sciences", - "definition":"College", - "identifier":"c696295a-3430-11e6-934e-5ce0c5308215" + "name": "College of Veterinary Medicine and Biomedical Sciences", + "definition": "College", + "identifier": "c696295a-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Medicine", - "definition":"College", - "identifier":"c69628b0-3430-11e6-934e-5ce0c5308215" + "name": "College of Medicine", + "definition": "College", + "identifier": "c69628b0-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Education and Human Development", - "definition":"College", - "identifier":"c69627c7-3430-11e6-934e-5ce0c5308215" + "name": "College of Education and Human Development", + "definition": "College", + "identifier": "c69627c7-3430-11e6-934e-5ce0c5308215" }, { - "name":"College of Agriculture and Life Sciences", - "definition":"College", - "identifier":"c6962751-3430-11e6-934e-5ce0c5308215" + "name": "College of Agriculture and Life Sciences", + "definition": "College", + "identifier": "c6962751-3430-11e6-934e-5ce0c5308215" } ] -} \ No newline at end of file +} diff --git a/src/main/resources/controlled_vocabularies/CommitteeMembers.json b/src/main/resources/controlled_vocabularies/CommitteeMembers.json index c183dba976..4e41e1a7b1 100644 --- a/src/main/resources/controlled_vocabularies/CommitteeMembers.json +++ b/src/main/resources/controlled_vocabularies/CommitteeMembers.json @@ -1,36 +1,36 @@ { - "name":"Committee Members", - "isEntityProperty":false, - "dictionary":[ + "name": "Committee Members", + "isEntityProperty": false, + "dictionary": [ { - "name":"Dr. Bob Boring", - "definition":"Chair of Computer Science", - "identifier":"", - "contacts":[ + "name": "Dr. Bob Boring", + "definition": "Chair of Computer Science", + "identifier": "", + "contacts": [ "bobboring@mailinator.com" ] }, { - "name":"Eddie Ed Exciting", - "definition":"Chair of Anthropology", - "identifier":"", - "contacts":[ + "name": "Eddie Ed Exciting", + "definition": "Chair of Anthropology", + "identifier": "", + "contacts": [ "eddieexciting@mailinator.com" ] }, { - "name":"Aggie Jack", - "definition":"", - "identifier":"", - "contacts":[ + "name": "Aggie Jack", + "definition": "", + "identifier": "", + "contacts": [ "aggiejack@mailinator.com" ] }, { - "name":"Ted To Marrow", - "definition":"", - "identifier":"", - "contacts":[ + "name": "Ted To Marrow", + "definition": "", + "identifier": "", + "contacts": [ "tmarrow@mailinator.com" ] } diff --git a/src/main/resources/controlled_vocabularies/Departments.json b/src/main/resources/controlled_vocabularies/Departments.json index 900d3bc055..a031c71a10 100644 --- a/src/main/resources/controlled_vocabularies/Departments.json +++ b/src/main/resources/controlled_vocabularies/Departments.json @@ -1,601 +1,601 @@ { - "name":"Departments", - "isEntityProperty":false, - "dictionary":[ + "name": "Departments", + "isEntityProperty": false, + "dictionary": [ { - "name":"Obstetrics and Gynecology", - "definition":"Academic Department", - "identifier":"fa66af82-91b1-11e6-99e2-00059a3c7a00" + "name": "Obstetrics and Gynecology", + "definition": "Academic Department", + "identifier": "fa66af82-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Surgery", - "definition":"Academic Department", - "identifier":"fa66b306-91b1-11e6-99e2-00059a3c7a00" + "name": "Surgery", + "definition": "Academic Department", + "identifier": "fa66b306-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Pediatrics", - "definition":"Academic Department", - "identifier":"fa66b037-91b1-11e6-99e2-00059a3c7a00" + "name": "Pediatrics", + "definition": "Academic Department", + "identifier": "fa66b037-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"International Studies", - "definition":"Academic Department", - "identifier":"fa66b351-91b1-11e6-99e2-00059a3c7a00" + "name": "International Studies", + "definition": "Academic Department", + "identifier": "fa66b351-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Teaching, Learning and Culture", - "definition":"Academic Department", - "identifier":"fa66b877-91b1-11e6-99e2-00059a3c7a00" + "name": "Teaching, Learning and Culture", + "definition": "Academic Department", + "identifier": "fa66b877-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"IP and Technology Law", - "definition":"Academic Department", - "identifier":"fa6b626f-91b1-11e6-99e2-00059a3c7a00" + "name": "IP and Technology Law", + "definition": "Academic Department", + "identifier": "fa6b626f-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Civil Engineering", - "definition":"Academic Department", - "identifier":"c695101f-3430-11e6-934e-5ce0c5308215" + "name": "Civil Engineering", + "definition": "Academic Department", + "identifier": "c695101f-3430-11e6-934e-5ce0c5308215" }, { - "name":"Landscape Architecture and Urban Planning", - "definition":"Academic Department", - "identifier":"c6950807-3430-11e6-934e-5ce0c5308215" + "name": "Landscape Architecture and Urban Planning", + "definition": "Academic Department", + "identifier": "c6950807-3430-11e6-934e-5ce0c5308215" }, { - "name":"Entomology", - "definition":"Academic Department", - "identifier":"c6950496-3430-11e6-934e-5ce0c5308215" + "name": "Entomology", + "definition": "Academic Department", + "identifier": "c6950496-3430-11e6-934e-5ce0c5308215" }, { - "name":"Veterinary Integrative Biosciences", - "definition":"Academic Department", - "identifier":"c6961eb2-3430-11e6-934e-5ce0c5308215" + "name": "Veterinary Integrative Biosciences", + "definition": "Academic Department", + "identifier": "c6961eb2-3430-11e6-934e-5ce0c5308215" }, { - "name":"Veterinary Pathobiology", - "definition":"Academic Department", - "identifier":"c695fe19-3430-11e6-934e-5ce0c5308215" + "name": "Veterinary Pathobiology", + "definition": "Academic Department", + "identifier": "c695fe19-3430-11e6-934e-5ce0c5308215" }, { - "name":"Sociology", - "definition":"Academic Department", - "identifier":"c695217c-3430-11e6-934e-5ce0c5308215" + "name": "Sociology", + "definition": "Academic Department", + "identifier": "c695217c-3430-11e6-934e-5ce0c5308215" }, { - "name":"Soil and Crop Sciences", - "definition":"Academic Department", - "identifier":"c6950674-3430-11e6-934e-5ce0c5308215" + "name": "Soil and Crop Sciences", + "definition": "Academic Department", + "identifier": "c6950674-3430-11e6-934e-5ce0c5308215" }, { - "name":"Neuroscience and Experimental Therapeutics", - "definition":"Academic Department", - "identifier":"c6962a0c-3430-11e6-934e-5ce0c5308215" + "name": "Neuroscience and Experimental Therapeutics", + "definition": "Academic Department", + "identifier": "c6962a0c-3430-11e6-934e-5ce0c5308215" }, { - "name":"Environmental and Occupational Health", - "definition":"Academic Department", - "identifier":"c16f12be-40c2-11e6-aff6-00059a3c7a00" + "name": "Environmental and Occupational Health", + "definition": "Academic Department", + "identifier": "c16f12be-40c2-11e6-aff6-00059a3c7a00" }, { - "name":"Nuclear Engineering", - "definition":"Academic Department", - "identifier":"c6951666-3430-11e6-934e-5ce0c5308215" + "name": "Nuclear Engineering", + "definition": "Academic Department", + "identifier": "c6951666-3430-11e6-934e-5ce0c5308215" }, { - "name":"Management", - "definition":"Academic Department", - "identifier":"c6950b63-3430-11e6-934e-5ce0c5308215" + "name": "Management", + "definition": "Academic Department", + "identifier": "c6950b63-3430-11e6-934e-5ce0c5308215" }, { - "name":"Large Animal Clinical Sciences", - "definition":"Academic Department", - "identifier":"c6961f58-3430-11e6-934e-5ce0c5308215" + "name": "Large Animal Clinical Sciences", + "definition": "Academic Department", + "identifier": "c6961f58-3430-11e6-934e-5ce0c5308215" }, { - "name":"Ocean Engineering", - "definition":"Academic Department", - "identifier":"fa66b935-91b1-11e6-99e2-00059a3c7a00" + "name": "Ocean Engineering", + "definition": "Academic Department", + "identifier": "fa66b935-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Environmental Law", - "definition":"Academic Department", - "identifier":"fa6b1d08-91b1-11e6-99e2-00059a3c7a00" + "name": "Environmental Law", + "definition": "Academic Department", + "identifier": "fa6b1d08-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Statistics", - "definition":"Academic Department", - "identifier":"c695fbe9-3430-11e6-934e-5ce0c5308215" + "name": "Statistics", + "definition": "Academic Department", + "identifier": "c695fbe9-3430-11e6-934e-5ce0c5308215" }, { - "name":"Performance Studies", - "definition":"Academic Department", - "identifier":"fa66ba02-91b1-11e6-99e2-00059a3c7a00" + "name": "Performance Studies", + "definition": "Academic Department", + "identifier": "fa66ba02-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Information and Operations Management", - "definition":"Academic Department", - "identifier":"c69623b9-3430-11e6-934e-5ce0c5308215" + "name": "Information and Operations Management", + "definition": "Academic Department", + "identifier": "c69623b9-3430-11e6-934e-5ce0c5308215" }, { - "name":"Environmental Programs in Geosciences", - "definition":"Academic Department", - "identifier":"fa66b97c-91b1-11e6-99e2-00059a3c7a00" + "name": "Environmental Programs in Geosciences", + "definition": "Academic Department", + "identifier": "fa66b97c-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Nutrition and Food Science", - "definition":"Academic Department", - "identifier":"c6950538-3430-11e6-934e-5ce0c5308215" + "name": "Nutrition and Food Science", + "definition": "Academic Department", + "identifier": "c6950538-3430-11e6-934e-5ce0c5308215" }, { - "name":"Oceanography", - "definition":"Academic Department", - "identifier":"c69518fd-3430-11e6-934e-5ce0c5308215" + "name": "Oceanography", + "definition": "Academic Department", + "identifier": "c69518fd-3430-11e6-934e-5ce0c5308215" }, { - "name":"Civil Litigation", - "definition":"Academic Department", - "identifier":"fa6b1858-91b1-11e6-99e2-00059a3c7a00" + "name": "Civil Litigation", + "definition": "Academic Department", + "identifier": "fa6b1858-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Oil and Gas Law", - "definition":"Academic Department", - "identifier":"fa6b62e2-91b1-11e6-99e2-00059a3c7a00" + "name": "Oil and Gas Law", + "definition": "Academic Department", + "identifier": "fa6b62e2-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Marketing", - "definition":"Academic Department", - "identifier":"c6950b97-3430-11e6-934e-5ce0c5308215" + "name": "Marketing", + "definition": "Academic Department", + "identifier": "c6950b97-3430-11e6-934e-5ce0c5308215" }, { - "name":"Health Policy and Management", - "definition":"Academic Department", - "identifier":"c16f13af-40c2-11e6-aff6-00059a3c7a00" + "name": "Health Policy and Management", + "definition": "Academic Department", + "identifier": "c16f13af-40c2-11e6-aff6-00059a3c7a00" }, { - "name":"Material Sciences and Engineering", - "definition":"Academic Department", - "identifier":"fa66b8f9-91b1-11e6-99e2-00059a3c7a00" + "name": "Material Sciences and Engineering", + "definition": "Academic Department", + "identifier": "fa66b8f9-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Commercial Law", - "definition":"Academic Department", - "identifier":"fa6b18ea-91b1-11e6-99e2-00059a3c7a00" + "name": "Commercial Law", + "definition": "Academic Department", + "identifier": "fa6b18ea-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Mathematics", - "definition":"Academic Department", - "identifier":"c695faad-3430-11e6-934e-5ce0c5308215" + "name": "Mathematics", + "definition": "Academic Department", + "identifier": "c695faad-3430-11e6-934e-5ce0c5308215" }, { - "name":"Anthropology", - "definition":"Academic Department", - "identifier":"c69519be-3430-11e6-934e-5ce0c5308215" + "name": "Anthropology", + "definition": "Academic Department", + "identifier": "c69519be-3430-11e6-934e-5ce0c5308215" }, { - "name":"Wildlife and Fisheries Sciences", - "definition":"Academic Department", - "identifier":"c69506db-3430-11e6-934e-5ce0c5308215" + "name": "Wildlife and Fisheries Sciences", + "definition": "Academic Department", + "identifier": "c69506db-3430-11e6-934e-5ce0c5308215" }, { - "name":"Mechanical Engineering", - "definition":"Academic Department", - "identifier":"c6951211-3430-11e6-934e-5ce0c5308215" + "name": "Mechanical Engineering", + "definition": "Academic Department", + "identifier": "c6951211-3430-11e6-934e-5ce0c5308215" }, { - "name":"Workplace Law", - "definition":"Academic Department", - "identifier":"fa6b63c3-91b1-11e6-99e2-00059a3c7a00" + "name": "Workplace Law", + "definition": "Academic Department", + "identifier": "fa6b63c3-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Internal Medicine", - "definition":"Academic Department", - "identifier":"c6962cbe-3430-11e6-934e-5ce0c5308215" + "name": "Internal Medicine", + "definition": "Academic Department", + "identifier": "c6962cbe-3430-11e6-934e-5ce0c5308215" }, { - "name":"Periodontics", - "definition":"Academic Department", - "identifier":"fa66b7ae-91b1-11e6-99e2-00059a3c7a00" + "name": "Periodontics", + "definition": "Academic Department", + "identifier": "fa66b7ae-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Medical Physiology", - "definition":"Academic Department", - "identifier":"c6962a7e-3430-11e6-934e-5ce0c5308215" + "name": "Medical Physiology", + "definition": "Academic Department", + "identifier": "c6962a7e-3430-11e6-934e-5ce0c5308215" }, { - "name":"Communication", - "definition":"Academic Department", - "identifier":"c6962433-3430-11e6-934e-5ce0c5308215" + "name": "Communication", + "definition": "Academic Department", + "identifier": "c6962433-3430-11e6-934e-5ce0c5308215" }, { - "name":"Health Promotion and Community Health Science", - "definition":"Academic Department", - "identifier":"fa6be3c7-91b1-11e6-99e2-00059a3c7a00" + "name": "Health Promotion and Community Health Science", + "definition": "Academic Department", + "identifier": "fa6be3c7-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Business Law", - "definition":"Academic Department", - "identifier":"fa6b1730-91b1-11e6-99e2-00059a3c7a00" + "name": "Business Law", + "definition": "Academic Department", + "identifier": "fa6b1730-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Hispanic Studies", - "definition":"Academic Department", - "identifier":"c6951d2f-3430-11e6-934e-5ce0c5308215" + "name": "Hispanic Studies", + "definition": "Academic Department", + "identifier": "c6951d2f-3430-11e6-934e-5ce0c5308215" }, { - "name":"Chemical Engineering", - "definition":"Academic Department", - "identifier":"c6950ee7-3430-11e6-934e-5ce0c5308215" + "name": "Chemical Engineering", + "definition": "Academic Department", + "identifier": "c6950ee7-3430-11e6-934e-5ce0c5308215" }, { - "name":"Epidemiology and Biostatics", - "definition":"Academic Department", - "identifier":"c16f1439-40c2-11e6-aff6-00059a3c7a00" + "name": "Epidemiology and Biostatics", + "definition": "Academic Department", + "identifier": "c16f1439-40c2-11e6-aff6-00059a3c7a00" }, { - "name":"Microbial Pathogenesis and Immunology", - "definition":"Academic Department", - "identifier":"c6962ab9-3430-11e6-934e-5ce0c5308215" + "name": "Microbial Pathogenesis and Immunology", + "definition": "Academic Department", + "identifier": "c6962ab9-3430-11e6-934e-5ce0c5308215" }, { - "name":"Petroleum Engineering", - "definition":"Academic Department", - "identifier":"c69516e0-3430-11e6-934e-5ce0c5308215" + "name": "Petroleum Engineering", + "definition": "Academic Department", + "identifier": "c69516e0-3430-11e6-934e-5ce0c5308215" }, { - "name":"Office of Scholarly Communications", - "definition":"Department ", - "identifier":"fa6b6431-91b1-11e6-99e2-00059a3c7a00" + "name": "Office of Scholarly Communications", + "definition": "Department ", + "identifier": "fa6b6431-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"International Affairs", - "definition":"Academic Department", - "identifier":"c69626da-3430-11e6-934e-5ce0c5308215" + "name": "International Affairs", + "definition": "Academic Department", + "identifier": "c69626da-3430-11e6-934e-5ce0c5308215" }, { - "name":"Oral and Maxillofacial Surgery", - "definition":"Academic Department", - "identifier":"fa66b6ad-91b1-11e6-99e2-00059a3c7a00" + "name": "Oral and Maxillofacial Surgery", + "definition": "Academic Department", + "identifier": "fa66b6ad-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Estate Planning", - "definition":"Academic Department", - "identifier":"fa6b2035-91b1-11e6-99e2-00059a3c7a00" + "name": "Estate Planning", + "definition": "Academic Department", + "identifier": "fa6b2035-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Chemistry", - "definition":"Academic Department", - "identifier":"c695f5c2-3430-11e6-934e-5ce0c5308215" + "name": "Chemistry", + "definition": "Academic Department", + "identifier": "c695f5c2-3430-11e6-934e-5ce0c5308215" }, { - "name":"History", - "definition":"Academic Department", - "identifier":"c6951d91-3430-11e6-934e-5ce0c5308215" + "name": "History", + "definition": "Academic Department", + "identifier": "c6951d91-3430-11e6-934e-5ce0c5308215" }, { - "name":"Architecture", - "definition":"Academic Department", - "identifier":"c695070a-3430-11e6-934e-5ce0c5308215" + "name": "Architecture", + "definition": "Academic Department", + "identifier": "c695070a-3430-11e6-934e-5ce0c5308215" }, { - "name":"Horticultural Science", - "definition":"Academic Department", - "identifier":"c6962126-3430-11e6-934e-5ce0c5308215" + "name": "Horticultural Science", + "definition": "Academic Department", + "identifier": "c6962126-3430-11e6-934e-5ce0c5308215" }, { - "name":"Orthodontics", - "definition":"Academic Department", - "identifier":"fa66b6fc-91b1-11e6-99e2-00059a3c7a00" + "name": "Orthodontics", + "definition": "Academic Department", + "identifier": "fa66b6fc-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Humanities in Medicine", - "definition":"Academic Department", - "identifier":"c69629cc-3430-11e6-934e-5ce0c5308215" + "name": "Humanities in Medicine", + "definition": "Academic Department", + "identifier": "c69629cc-3430-11e6-934e-5ce0c5308215" }, { - "name":"Agricultural Leadership, Education, and Communications", - "definition":"Academic Department", - "identifier":"fa66b390-91b1-11e6-99e2-00059a3c7a00" + "name": "Agricultural Leadership, Education, and Communications", + "definition": "Academic Department", + "identifier": "fa66b390-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Family and Community Medicine", - "definition":"Academic Department", - "identifier":"fa66af13-91b1-11e6-99e2-00059a3c7a00" + "name": "Family and Community Medicine", + "definition": "Academic Department", + "identifier": "fa66af13-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Alternative Dispute Resolution", - "definition":"Academic Department", - "identifier":"fa66bbb4-91b1-11e6-99e2-00059a3c7a00" + "name": "Alternative Dispute Resolution", + "definition": "Academic Department", + "identifier": "fa66bbb4-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Immigration Law", - "definition":"Academic Department", - "identifier":"fa6b6163-91b1-11e6-99e2-00059a3c7a00" + "name": "Immigration Law", + "definition": "Academic Department", + "identifier": "fa6b6163-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Family Law", - "definition":"Academic Department", - "identifier":"fa6b258b-91b1-11e6-99e2-00059a3c7a00" + "name": "Family Law", + "definition": "Academic Department", + "identifier": "fa6b258b-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Diagnostic Science", - "definition":"Academic Department", - "identifier":"fa66b5b8-91b1-11e6-99e2-00059a3c7a00" + "name": "Diagnostic Science", + "definition": "Academic Department", + "identifier": "fa66b5b8-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Molecular and Cellular Medicine", - "definition":"Academic Department", - "identifier":"c6962a47-3430-11e6-934e-5ce0c5308215" + "name": "Molecular and Cellular Medicine", + "definition": "Academic Department", + "identifier": "c6962a47-3430-11e6-934e-5ce0c5308215" }, { - "name":"Endodontics", - "definition":"Academic Department", - "identifier":"fa66b63b-91b1-11e6-99e2-00059a3c7a00" + "name": "Endodontics", + "definition": "Academic Department", + "identifier": "fa66b63b-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Pathology", - "definition":"Academic Department", - "identifier":"fa66aff4-91b1-11e6-99e2-00059a3c7a00" + "name": "Pathology", + "definition": "Academic Department", + "identifier": "fa66aff4-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Industrial and Systems Engineering", - "definition":"Academic Department", - "identifier":"fa66b8ca-91b1-11e6-99e2-00059a3c7a00" + "name": "Industrial and Systems Engineering", + "definition": "Academic Department", + "identifier": "fa66b8ca-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Energy Law", - "definition":"Academic Department", - "identifier":"fa6b1c8d-91b1-11e6-99e2-00059a3c7a00" + "name": "Energy Law", + "definition": "Academic Department", + "identifier": "fa6b1c8d-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Atmospheric Sciences", - "definition":"Academic Department", - "identifier":"c696246b-3430-11e6-934e-5ce0c5308215" + "name": "Atmospheric Sciences", + "definition": "Academic Department", + "identifier": "c696246b-3430-11e6-934e-5ce0c5308215" }, { - "name":"Pediatric Dentistry", - "definition":"Academic Department", - "identifier":"fa66b75b-91b1-11e6-99e2-00059a3c7a00" + "name": "Pediatric Dentistry", + "definition": "Academic Department", + "identifier": "fa66b75b-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Anesthesiology", - "definition":"Academic Department", - "identifier":"fa66ae3a-91b1-11e6-99e2-00059a3c7a00" + "name": "Anesthesiology", + "definition": "Academic Department", + "identifier": "fa66ae3a-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Geography", - "definition":"Academic Department", - "identifier":"c695183c-3430-11e6-934e-5ce0c5308215" + "name": "Geography", + "definition": "Academic Department", + "identifier": "c695183c-3430-11e6-934e-5ce0c5308215" }, { - "name":"Biological and Agricultural Engineering", - "definition":"Academic Department", - "identifier":"c69620eb-3430-11e6-934e-5ce0c5308215" + "name": "Biological and Agricultural Engineering", + "definition": "Academic Department", + "identifier": "c69620eb-3430-11e6-934e-5ce0c5308215" }, { - "name":"Economics", - "definition":"Academic Department", - "identifier":"c6951b1a-3430-11e6-934e-5ce0c5308215" + "name": "Economics", + "definition": "Academic Department", + "identifier": "c6951b1a-3430-11e6-934e-5ce0c5308215" }, { - "name":"Biochemistry and Biophysics", - "definition":"Academic Department", - "identifier":"c69503f5-3430-11e6-934e-5ce0c5308215" + "name": "Biochemistry and Biophysics", + "definition": "Academic Department", + "identifier": "c69503f5-3430-11e6-934e-5ce0c5308215" }, { - "name":"Public Health Sciences", - "definition":"Academic Department", - "identifier":"fa66b7fd-91b1-11e6-99e2-00059a3c7a00" + "name": "Public Health Sciences", + "definition": "Academic Department", + "identifier": "fa66b7fd-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Veterinary Physiology and Pharmacology", - "definition":"Academic Department", - "identifier":"c695fe8c-3430-11e6-934e-5ce0c5308215" + "name": "Veterinary Physiology and Pharmacology", + "definition": "Academic Department", + "identifier": "c695fe8c-3430-11e6-934e-5ce0c5308215" }, { - "name":"Geology and Geophysics", - "definition":"Academic Department", - "identifier":"c69623f8-3430-11e6-934e-5ce0c5308215" + "name": "Geology and Geophysics", + "definition": "Academic Department", + "identifier": "c69623f8-3430-11e6-934e-5ce0c5308215" }, { - "name":"Accounting", - "definition":"Academic Department", - "identifier":"c6950871-3430-11e6-934e-5ce0c5308215" + "name": "Accounting", + "definition": "Academic Department", + "identifier": "c6950871-3430-11e6-934e-5ce0c5308215" }, { - "name":"Public Health Studies", - "definition":"Academic Department", - "identifier":"fa66adc4-91b1-11e6-99e2-00059a3c7a00" + "name": "Public Health Studies", + "definition": "Academic Department", + "identifier": "fa66adc4-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Engineering Technology and Industrial Distribution", - "definition":"Academic Department", - "identifier":"c69510f8-3430-11e6-934e-5ce0c5308215" + "name": "Engineering Technology and Industrial Distribution", + "definition": "Academic Department", + "identifier": "c69510f8-3430-11e6-934e-5ce0c5308215" }, { - "name":"Animal Science", - "definition":"Academic Department", - "identifier":"c69503bd-3430-11e6-934e-5ce0c5308215" + "name": "Animal Science", + "definition": "Academic Department", + "identifier": "c69503bd-3430-11e6-934e-5ce0c5308215" }, { - "name":"Ecosystem Science and Management", - "definition":"Academic Department", - "identifier":"c69504ca-3430-11e6-934e-5ce0c5308215" + "name": "Ecosystem Science and Management", + "definition": "Academic Department", + "identifier": "c69504ca-3430-11e6-934e-5ce0c5308215" }, { - "name":"Health and Kinesiology", - "definition":"Academic Department", - "identifier":"c6950d02-3430-11e6-934e-5ce0c5308215" + "name": "Health and Kinesiology", + "definition": "Academic Department", + "identifier": "c6950d02-3430-11e6-934e-5ce0c5308215" }, { - "name":"Aerospace Engineering", - "definition":"Academic Department", - "identifier":"c6950d64-3430-11e6-934e-5ce0c5308215" + "name": "Aerospace Engineering", + "definition": "Academic Department", + "identifier": "c6950d64-3430-11e6-934e-5ce0c5308215" }, { - "name":"Health Law", - "definition":"Academic Department", - "identifier":"fa6b608e-91b1-11e6-99e2-00059a3c7a00" + "name": "Health Law", + "definition": "Academic Department", + "identifier": "fa6b608e-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Biology ", - "definition":"Academic Department", - "identifier":"c695f48a-3430-11e6-934e-5ce0c5308215" + "name": "Biology ", + "definition": "Academic Department", + "identifier": "c695f48a-3430-11e6-934e-5ce0c5308215" }, { - "name":"Public Service and Administration", - "definition":"Academic Department", - "identifier":"c69626a3-3430-11e6-934e-5ce0c5308215" + "name": "Public Service and Administration", + "definition": "Academic Department", + "identifier": "c69626a3-3430-11e6-934e-5ce0c5308215" }, { - "name":"Computer Science and Engineering", - "definition":"Academic Department", - "identifier":"c69625b6-3430-11e6-934e-5ce0c5308215" + "name": "Computer Science and Engineering", + "definition": "Academic Department", + "identifier": "c69625b6-3430-11e6-934e-5ce0c5308215" }, { - "name":"Finance", - "definition":"Academic Department", - "identifier":"c6950ad5-3430-11e6-934e-5ce0c5308215" + "name": "Finance", + "definition": "Academic Department", + "identifier": "c6950ad5-3430-11e6-934e-5ce0c5308215" }, { - "name":"English", - "definition":"Academic Department", - "identifier":"c6951c07-3430-11e6-934e-5ce0c5308215" + "name": "English", + "definition": "Academic Department", + "identifier": "c6951c07-3430-11e6-934e-5ce0c5308215" }, { - "name":"Construction Science", - "definition":"Academic Department", - "identifier":"c69507d3-3430-11e6-934e-5ce0c5308215" + "name": "Construction Science", + "definition": "Academic Department", + "identifier": "c69507d3-3430-11e6-934e-5ce0c5308215" }, { - "name":"Visualization", - "definition":"Academic Department", - "identifier":"c695083e-3430-11e6-934e-5ce0c5308215" + "name": "Visualization", + "definition": "Academic Department", + "identifier": "c695083e-3430-11e6-934e-5ce0c5308215" }, { - "name":"Biomedical Engineering", - "definition":"Academic Department", - "identifier":"c6950e71-3430-11e6-934e-5ce0c5308215" + "name": "Biomedical Engineering", + "definition": "Academic Department", + "identifier": "c6950e71-3430-11e6-934e-5ce0c5308215" }, { - "name":"Radiology", - "definition":"Academic Department", - "identifier":"fa66b2c3-91b1-11e6-99e2-00059a3c7a00" + "name": "Radiology", + "definition": "Academic Department", + "identifier": "fa66b2c3-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"General Dentistry", - "definition":"Academic Department", - "identifier":"fa66b67a-91b1-11e6-99e2-00059a3c7a00" + "name": "General Dentistry", + "definition": "Academic Department", + "identifier": "fa66b67a-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Criminal Law and Procedure", - "definition":"Academic Department", - "identifier":"fa6b1958-91b1-11e6-99e2-00059a3c7a00" + "name": "Criminal Law and Procedure", + "definition": "Academic Department", + "identifier": "fa6b1958-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Real Estate Law", - "definition":"Academic Department", - "identifier":"fa6b6325-91b1-11e6-99e2-00059a3c7a00" + "name": "Real Estate Law", + "definition": "Academic Department", + "identifier": "fa6b6325-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Agricultural Economics", - "definition":"Academic Department", - "identifier":"c6950382-3430-11e6-934e-5ce0c5308215" + "name": "Agricultural Economics", + "definition": "Academic Department", + "identifier": "c6950382-3430-11e6-934e-5ce0c5308215" }, { - "name":"Recreation, Park and Tourism Science", - "definition":"Academic Department", - "identifier":"fa66b3fe-91b1-11e6-99e2-00059a3c7a00" + "name": "Recreation, Park and Tourism Science", + "definition": "Academic Department", + "identifier": "fa66b3fe-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Educational Administration and Human Resource Development", - "definition":"Academic Department", - "identifier":"c6950c97-3430-11e6-934e-5ce0c5308215" + "name": "Educational Administration and Human Resource Development", + "definition": "Academic Department", + "identifier": "c6950c97-3430-11e6-934e-5ce0c5308215" }, { - "name":"Dental Hygiene", - "definition":"Academic Department", - "identifier":"fa66b546-91b1-11e6-99e2-00059a3c7a00" + "name": "Dental Hygiene", + "definition": "Academic Department", + "identifier": "fa66b546-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Educational Psychology", - "definition":"Academic Department", - "identifier":"c6950cce-3430-11e6-934e-5ce0c5308215" + "name": "Educational Psychology", + "definition": "Academic Department", + "identifier": "c6950cce-3430-11e6-934e-5ce0c5308215" }, { - "name":"Water Law", - "definition":"Academic Department", - "identifier":"fa6b636c-91b1-11e6-99e2-00059a3c7a00" + "name": "Water Law", + "definition": "Academic Department", + "identifier": "fa6b636c-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"General Practice", - "definition":"Academic Department", - "identifier":"fa6b28e3-91b1-11e6-99e2-00059a3c7a00" + "name": "General Practice", + "definition": "Academic Department", + "identifier": "fa6b28e3-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Biomedical Science", - "definition":"Academic Department", - "identifier":"fa66b4d0-91b1-11e6-99e2-00059a3c7a00" + "name": "Biomedical Science", + "definition": "Academic Department", + "identifier": "fa66b4d0-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Electrical and Computer Engineering", - "definition":"Academic Department", - "identifier":"c696257f-3430-11e6-934e-5ce0c5308215" + "name": "Electrical and Computer Engineering", + "definition": "Academic Department", + "identifier": "c696257f-3430-11e6-934e-5ce0c5308215" }, { - "name":"Restorative Sciences", - "definition":"Academic Department", - "identifier":"fa66b838-91b1-11e6-99e2-00059a3c7a00" + "name": "Restorative Sciences", + "definition": "Academic Department", + "identifier": "fa66b838-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Political Science", - "definition":"Academic Department", - "identifier":"c6951f18-3430-11e6-934e-5ce0c5308215" + "name": "Political Science", + "definition": "Academic Department", + "identifier": "c6951f18-3430-11e6-934e-5ce0c5308215" }, { - "name":"Water Program", - "definition":"Academic Department", - "identifier":"fa66b9ab-91b1-11e6-99e2-00059a3c7a00" + "name": "Water Program", + "definition": "Academic Department", + "identifier": "fa66b9ab-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Philosophy", - "definition":"Academic Department", - "identifier":"fa66ba84-91b1-11e6-99e2-00059a3c7a00" + "name": "Philosophy", + "definition": "Academic Department", + "identifier": "fa66ba84-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Emergency Medicine", - "definition":"Academic Department", - "identifier":"fa66aea9-91b1-11e6-99e2-00059a3c7a00" + "name": "Emergency Medicine", + "definition": "Academic Department", + "identifier": "fa66aea9-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Small Animal Clinical Sciences", - "definition":"Academic Department", - "identifier":"c6961f97-3430-11e6-934e-5ce0c5308215" + "name": "Small Animal Clinical Sciences", + "definition": "Academic Department", + "identifier": "c6961f97-3430-11e6-934e-5ce0c5308215" }, { - "name":"Poultry Science", - "definition":"Academic Department", - "identifier":"c69505d2-3430-11e6-934e-5ce0c5308215" + "name": "Poultry Science", + "definition": "Academic Department", + "identifier": "c69505d2-3430-11e6-934e-5ce0c5308215" }, { - "name":"Physics and Astronomy", - "definition":"Academic Department", - "identifier":"c695fb82-3430-11e6-934e-5ce0c5308215" + "name": "Physics and Astronomy", + "definition": "Academic Department", + "identifier": "c695fb82-3430-11e6-934e-5ce0c5308215" }, { - "name":"Psychiatry and Behavioral Science", - "definition":"Academic Department", - "identifier":"fa66b06b-91b1-11e6-99e2-00059a3c7a00" + "name": "Psychiatry and Behavioral Science", + "definition": "Academic Department", + "identifier": "fa66b06b-91b1-11e6-99e2-00059a3c7a00" }, { - "name":"Plant Pathology and Microbiology", - "definition":"Academic Department", - "identifier":"c695059f-3430-11e6-934e-5ce0c5308215" + "name": "Plant Pathology and Microbiology", + "definition": "Academic Department", + "identifier": "c695059f-3430-11e6-934e-5ce0c5308215" }, { - "name":"Psychology", - "definition":"Academic Department", - "identifier":"c695200d-3430-11e6-934e-5ce0c5308215" + "name": "Psychology", + "definition": "Academic Department", + "identifier": "c695200d-3430-11e6-934e-5ce0c5308215" } ] -} \ No newline at end of file +} diff --git a/src/main/resources/controlled_vocabularies/Majors.json b/src/main/resources/controlled_vocabularies/Majors.json index 80747f99fe..c4474b7dbe 100644 --- a/src/main/resources/controlled_vocabularies/Majors.json +++ b/src/main/resources/controlled_vocabularies/Majors.json @@ -1,641 +1,641 @@ { - "name":"Majors", - "isEntityProperty":false, - "dictionary":[ + "name": "Majors", + "isEntityProperty": false, + "dictionary": [ { - "name":"Ocean and Coastal Resources", - "definition":"", - "identifier":"" + "name": "Ocean and Coastal Resources", + "definition": "", + "identifier": "" }, { - "name":"Ocean Engineering", - "definition":"", - "identifier":"" + "name": "Ocean Engineering", + "definition": "", + "identifier": "" }, { - "name":"Oceanography", - "definition":"", - "identifier":"" + "name": "Oceanography", + "definition": "", + "identifier": "" }, { - "name":"Offshore and Coastal Systems Engineering", - "definition":"", - "identifier":"" + "name": "Offshore and Coastal Systems Engineering", + "definition": "", + "identifier": "" }, { - "name":"Marine Engineering Technology", - "definition":"", - "identifier":"" + "name": "Marine Engineering Technology", + "definition": "", + "identifier": "" }, { - "name":"Maritime Administration", - "definition":"", - "identifier":"" + "name": "Maritime Administration", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Journalism", - "definition":"", - "identifier":"" + "name": "University Studies - Journalism", + "definition": "", + "identifier": "" }, { - "name":"Molecular & Cell Biology", - "definition":"", - "identifier":"" + "name": "Molecular & Cell Biology", + "definition": "", + "identifier": "" }, { - "name":"Plant & Environmental Soil Science", - "definition":"", - "identifier":"" + "name": "Plant & Environmental Soil Science", + "definition": "", + "identifier": "" }, { - "name":"Marine Fisheries", - "definition":"", - "identifier":"" + "name": "Marine Fisheries", + "definition": "", + "identifier": "" }, { - "name":"Agricultural Systems Management", - "definition":"", - "identifier":"" + "name": "Agricultural Systems Management", + "definition": "", + "identifier": "" }, { - "name":"Marine Sciences", - "definition":"", - "identifier":"" + "name": "Marine Sciences", + "definition": "", + "identifier": "" }, { - "name":"Maritime Studies", - "definition":"", - "identifier":"" + "name": "Maritime Studies", + "definition": "", + "identifier": "" }, { - "name":"Chemistry", - "definition":"", - "identifier":"" + "name": "Chemistry", + "definition": "", + "identifier": "" }, { - "name":"Marketing", - "definition":"", - "identifier":"" + "name": "Marketing", + "definition": "", + "identifier": "" }, { - "name":"Food Science & Technology", - "definition":"", - "identifier":"" + "name": "Food Science & Technology", + "definition": "", + "identifier": "" }, { - "name":"Civil Engineering", - "definition":"", - "identifier":"" + "name": "Civil Engineering", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Leadership", - "definition":"", - "identifier":"" + "name": "University Studies - Leadership", + "definition": "", + "identifier": "" }, { - "name":"Classics", - "definition":"", - "identifier":"" + "name": "Classics", + "definition": "", + "identifier": "" }, { - "name":"Allied Health", - "definition":"", - "identifier":"" + "name": "Allied Health", + "definition": "", + "identifier": "" }, { - "name":"Communication", - "definition":"", - "identifier":"" + "name": "Communication", + "definition": "", + "identifier": "" }, { - "name":"Marine Transportation", - "definition":"", - "identifier":"" + "name": "Marine Transportation", + "definition": "", + "identifier": "" }, { - "name":"Biology", - "definition":"", - "identifier":"" + "name": "Biology", + "definition": "", + "identifier": "" }, { - "name":"Management", - "definition":"", - "identifier":"" + "name": "Management", + "definition": "", + "identifier": "" }, { - "name":"Political Science", - "definition":"", - "identifier":"" + "name": "Political Science", + "definition": "", + "identifier": "" }, { - "name":"Management Information Systems", - "definition":"", - "identifier":"" + "name": "Management Information Systems", + "definition": "", + "identifier": "" }, { - "name":"Biomedical Engineering", - "definition":"", - "identifier":"" + "name": "Biomedical Engineering", + "definition": "", + "identifier": "" }, { - "name":"Manufacturing & Mechanical Engineering Technology", - "definition":"", - "identifier":"" + "name": "Manufacturing & Mechanical Engineering Technology", + "definition": "", + "identifier": "" }, { - "name":"Biomedical Sciences", - "definition":"", - "identifier":"" + "name": "Biomedical Sciences", + "definition": "", + "identifier": "" }, { - "name":"Multidisciplinary Engineering Technology", - "definition":"", - "identifier":"" + "name": "Multidisciplinary Engineering Technology", + "definition": "", + "identifier": "" }, { - "name":"Chemical Engineering", - "definition":"", - "identifier":"" + "name": "Chemical Engineering", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Marine Environmental Law & Policy", - "definition":"", - "identifier":"" + "name": "University Studies - Marine Environmental Law & Policy", + "definition": "", + "identifier": "" }, { - "name":"Dance Science", - "definition":"", - "identifier":"" + "name": "Dance Science", + "definition": "", + "identifier": "" }, { - "name":"Ecological Restoration", - "definition":"", - "identifier":"" + "name": "Ecological Restoration", + "definition": "", + "identifier": "" }, { - "name":"Economics", - "definition":"", - "identifier":"" + "name": "Economics", + "definition": "", + "identifier": "" }, { - "name":"Electrical Engineering", - "definition":"", - "identifier":"" + "name": "Electrical Engineering", + "definition": "", + "identifier": "" }, { - "name":"Community Health", - "definition":"", - "identifier":"" + "name": "Community Health", + "definition": "", + "identifier": "" }, { - "name":"Computer Engineering", - "definition":"", - "identifier":"" + "name": "Computer Engineering", + "definition": "", + "identifier": "" }, { - "name":"Computer Science", - "definition":"", - "identifier":"" + "name": "Computer Science", + "definition": "", + "identifier": "" }, { - "name":"Forensic & Investigative Sciences", - "definition":"", - "identifier":"" + "name": "Forensic & Investigative Sciences", + "definition": "", + "identifier": "" }, { - "name":"Forestry", - "definition":"", - "identifier":"" + "name": "Forestry", + "definition": "", + "identifier": "" }, { - "name":"Genetics", - "definition":"", - "identifier":"" + "name": "Genetics", + "definition": "", + "identifier": "" }, { - "name":"Geographic Information Science & Technology", - "definition":"", - "identifier":"" + "name": "Geographic Information Science & Technology", + "definition": "", + "identifier": "" }, { - "name":"Mathematics", - "definition":"", - "identifier":"" + "name": "Mathematics", + "definition": "", + "identifier": "" }, { - "name":"Mechanical Engineering", - "definition":"", - "identifier":"" + "name": "Mechanical Engineering", + "definition": "", + "identifier": "" }, { - "name":"Geography", - "definition":"", - "identifier":"" + "name": "Geography", + "definition": "", + "identifier": "" }, { - "name":"Meteorology", - "definition":"", - "identifier":"" + "name": "Meteorology", + "definition": "", + "identifier": "" }, { - "name":"Microbiology", - "definition":"", - "identifier":"" + "name": "Microbiology", + "definition": "", + "identifier": "" }, { - "name":"Modern Languages", - "definition":"", - "identifier":"" + "name": "Modern Languages", + "definition": "", + "identifier": "" }, { - "name":"Interdisciplinary Studies-Middle Grades Math/Science", - "definition":"", - "identifier":"" + "name": "Interdisciplinary Studies-Middle Grades Math/Science", + "definition": "", + "identifier": "" }, { - "name":"Interdisciplinary Studies-Special Education", - "definition":"", - "identifier":"" + "name": "Interdisciplinary Studies-Special Education", + "definition": "", + "identifier": "" }, { - "name":"International Studies", - "definition":"", - "identifier":"" + "name": "International Studies", + "definition": "", + "identifier": "" }, { - "name":"Kinesiology-Applied Exercise Physiology", - "definition":"", - "identifier":"" + "name": "Kinesiology-Applied Exercise Physiology", + "definition": "", + "identifier": "" }, { - "name":"Kinesiology-Basic Exercise Physiology", - "definition":"", - "identifier":"" + "name": "Kinesiology-Basic Exercise Physiology", + "definition": "", + "identifier": "" }, { - "name":"Kinesiology-Motor Behavior", - "definition":"", - "identifier":"" + "name": "Kinesiology-Motor Behavior", + "definition": "", + "identifier": "" }, { - "name":"Kinesiology-Physical Education Certification", - "definition":"", - "identifier":"" + "name": "Kinesiology-Physical Education Certification", + "definition": "", + "identifier": "" }, { - "name":"Landscape Architecture", - "definition":"", - "identifier":"" + "name": "Landscape Architecture", + "definition": "", + "identifier": "" }, { - "name":"Construction Science", - "definition":"", - "identifier":"" + "name": "Construction Science", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Oceans and One Health", - "definition":"", - "identifier":"" + "name": "University Studies - Oceans and One Health", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Dance", - "definition":"", - "identifier":"" + "name": "University Studies - Dance", + "definition": "", + "identifier": "" }, { - "name":"Animal Science", - "definition":"", - "identifier":"" + "name": "Animal Science", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Environmental Business", - "definition":"", - "identifier":"" + "name": "University Studies - Environmental Business", + "definition": "", + "identifier": "" }, { - "name":"Anthropology", - "definition":"", - "identifier":"" + "name": "Anthropology", + "definition": "", + "identifier": "" }, { - "name":"Poultry Science", - "definition":"", - "identifier":"" + "name": "Poultry Science", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Geography", - "definition":"", - "identifier":"" + "name": "University Studies - Geography", + "definition": "", + "identifier": "" }, { - "name":"Marine Biology", - "definition":"", - "identifier":"" + "name": "Marine Biology", + "definition": "", + "identifier": "" }, { - "name":"Agricultural Communications & Journalism", - "definition":"", - "identifier":"" + "name": "Agricultural Communications & Journalism", + "definition": "", + "identifier": "" }, { - "name":"Nuclear Engineering", - "definition":"", - "identifier":"" + "name": "Nuclear Engineering", + "definition": "", + "identifier": "" }, { - "name":"Performance Studies", - "definition":"", - "identifier":"" + "name": "Performance Studies", + "definition": "", + "identifier": "" }, { - "name":"Nutritional Sciences", - "definition":"", - "identifier":"" + "name": "Nutritional Sciences", + "definition": "", + "identifier": "" }, { - "name":"Environmental Geosciences", - "definition":"", - "identifier":"" + "name": "Environmental Geosciences", + "definition": "", + "identifier": "" }, { - "name":"Geology", - "definition":"", - "identifier":"" + "name": "Geology", + "definition": "", + "identifier": "" }, { - "name":"Environmental Studies (Geosciences)", - "definition":"", - "identifier":"" + "name": "Environmental Studies (Geosciences)", + "definition": "", + "identifier": "" }, { - "name":"Geophysics", - "definition":"", - "identifier":"" + "name": "Geophysics", + "definition": "", + "identifier": "" }, { - "name":"Industrial Engineering", - "definition":"", - "identifier":"" + "name": "Industrial Engineering", + "definition": "", + "identifier": "" }, { - "name":"Environmental Studies (Plant Pathology & Microbiology)", - "definition":"", - "identifier":"" + "name": "Environmental Studies (Plant Pathology & Microbiology)", + "definition": "", + "identifier": "" }, { - "name":"Interdisciplinary Studies-Bilingual Education", - "definition":"", - "identifier":"" + "name": "Interdisciplinary Studies-Bilingual Education", + "definition": "", + "identifier": "" }, { - "name":"Finance", - "definition":"", - "identifier":"" + "name": "Finance", + "definition": "", + "identifier": "" }, { - "name":"Interdisciplinary Studies-Early Childhood", - "definition":"", - "identifier":"" + "name": "Interdisciplinary Studies-Early Childhood", + "definition": "", + "identifier": "" }, { - "name":"Sport Management", - "definition":"", - "identifier":"" + "name": "Sport Management", + "definition": "", + "identifier": "" }, { - "name":"Interdisciplinary Studies-Middle Grades English/Language Arts/Social Studies", - "definition":"", - "identifier":"" + "name": "Interdisciplinary Studies-Middle Grades English/Language Arts/Social Studies", + "definition": "", + "identifier": "" }, { - "name":"Agricultural Economics", - "definition":"", - "identifier":"" + "name": "Agricultural Economics", + "definition": "", + "identifier": "" }, { - "name":"Agricultural Leadership & Development", - "definition":"", - "identifier":"" + "name": "Agricultural Leadership & Development", + "definition": "", + "identifier": "" }, { - "name":"Agricultural Science", - "definition":"", - "identifier":"" + "name": "Agricultural Science", + "definition": "", + "identifier": "" }, { - "name":"Accounting", - "definition":"", - "identifier":"" + "name": "Accounting", + "definition": "", + "identifier": "" }, { - "name":"Psychology", - "definition":"", - "identifier":"" + "name": "Psychology", + "definition": "", + "identifier": "" }, { - "name":"University Studies - GIS & Technology", - "definition":"", - "identifier":"" + "name": "University Studies - GIS & Technology", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Race, Gender & Ethnicity", - "definition":"", - "identifier":"" + "name": "University Studies - Race, Gender & Ethnicity", + "definition": "", + "identifier": "" }, { - "name":"Applied Mathematical Sciences", - "definition":"", - "identifier":"" + "name": "Applied Mathematical Sciences", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Religious Thought, Practices & Cultures", - "definition":"", - "identifier":"" + "name": "University Studies - Religious Thought, Practices & Cultures", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Society, Ethics & Law", - "definition":"", - "identifier":"" + "name": "University Studies - Society, Ethics & Law", + "definition": "", + "identifier": "" }, { - "name":"Visualization", - "definition":"", - "identifier":"" + "name": "Visualization", + "definition": "", + "identifier": "" }, { - "name":"Urban & Regional Planning", - "definition":"", - "identifier":"" + "name": "Urban & Regional Planning", + "definition": "", + "identifier": "" }, { - "name":"Wildlife & Fisheries Sciences", - "definition":"", - "identifier":"" + "name": "Wildlife & Fisheries Sciences", + "definition": "", + "identifier": "" }, { - "name":"Aerospace Engineering", - "definition":"", - "identifier":"" + "name": "Aerospace Engineering", + "definition": "", + "identifier": "" }, { - "name":"Women's and Gender Studies", - "definition":"", - "identifier":"" + "name": "Women's and Gender Studies", + "definition": "", + "identifier": "" }, { - "name":"Agribusiness", - "definition":"", - "identifier":"" + "name": "Agribusiness", + "definition": "", + "identifier": "" }, { - "name":"Public Health", - "definition":"", - "identifier":"" + "name": "Public Health", + "definition": "", + "identifier": "" }, { - "name":"Rangeland Ecology & Management", - "definition":"", - "identifier":"" + "name": "Rangeland Ecology & Management", + "definition": "", + "identifier": "" }, { - "name":"Recreation, Park & Tourism Sciences", - "definition":"", - "identifier":"" + "name": "Recreation, Park & Tourism Sciences", + "definition": "", + "identifier": "" }, { - "name":"Renewable Natural Resources", - "definition":"", - "identifier":"" + "name": "Renewable Natural Resources", + "definition": "", + "identifier": "" }, { - "name":"Telecommunication Media Studies", - "definition":"", - "identifier":"" + "name": "Telecommunication Media Studies", + "definition": "", + "identifier": "" }, { - "name":"Turfgrass Science", - "definition":"", - "identifier":"" + "name": "Turfgrass Science", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Architecture", - "definition":"", - "identifier":"" + "name": "University Studies - Architecture", + "definition": "", + "identifier": "" }, { - "name":"Petroleum Engineering", - "definition":"", - "identifier":"" + "name": "Petroleum Engineering", + "definition": "", + "identifier": "" }, { - "name":"University Studies - Child Professional Services", - "definition":"", - "identifier":"" + "name": "University Studies - Child Professional Services", + "definition": "", + "identifier": "" }, { - "name":"Electronic Systems Engineering Technology", - "definition":"", - "identifier":"" + "name": "Electronic Systems Engineering Technology", + "definition": "", + "identifier": "" }, { - "name":"Zoology", - "definition":"", - "identifier":"" + "name": "Zoology", + "definition": "", + "identifier": "" }, { - "name":"School Health", - "definition":"", - "identifier":"" + "name": "School Health", + "definition": "", + "identifier": "" }, { - "name":"Biochemistry", - "definition":"", - "identifier":"" + "name": "Biochemistry", + "definition": "", + "identifier": "" }, { - "name":"Bioenvironmental Sciences", - "definition":"", - "identifier":"" + "name": "Bioenvironmental Sciences", + "definition": "", + "identifier": "" }, { - "name":"Philosophy", - "definition":"", - "identifier":"" + "name": "Philosophy", + "definition": "", + "identifier": "" }, { - "name":"History", - "definition":"", - "identifier":"" + "name": "History", + "definition": "", + "identifier": "" }, { - "name":"Statistics", - "definition":"", - "identifier":"" + "name": "Statistics", + "definition": "", + "identifier": "" }, { - "name":"Horticulture", - "definition":"", - "identifier":"" + "name": "Horticulture", + "definition": "", + "identifier": "" }, { - "name":"Supply Chain Management", - "definition":"", - "identifier":"" + "name": "Supply Chain Management", + "definition": "", + "identifier": "" }, { - "name":"Human Resource Development", - "definition":"", - "identifier":"" + "name": "Human Resource Development", + "definition": "", + "identifier": "" }, { - "name":"Physics", - "definition":"", - "identifier":"" + "name": "Physics", + "definition": "", + "identifier": "" }, { - "name":"Industrial Distribution", - "definition":"", - "identifier":"" + "name": "Industrial Distribution", + "definition": "", + "identifier": "" }, { - "name":"English", - "definition":"", - "identifier":"" + "name": "English", + "definition": "", + "identifier": "" }, { - "name":"Biological & Agricultural Engineering", - "definition":"", - "identifier":"" + "name": "Biological & Agricultural Engineering", + "definition": "", + "identifier": "" }, { - "name":"Entomology", - "definition":"", - "identifier":"" + "name": "Entomology", + "definition": "", + "identifier": "" }, { - "name":"Sociology", - "definition":"", - "identifier":"" + "name": "Sociology", + "definition": "", + "identifier": "" }, { - "name":"Technology Management", - "definition":"", - "identifier":"" + "name": "Technology Management", + "definition": "", + "identifier": "" }, { - "name":"Environmental Design", - "definition":"", - "identifier":"" + "name": "Environmental Design", + "definition": "", + "identifier": "" }, { - "name":"Spanish", - "definition":"", - "identifier":"" + "name": "Spanish", + "definition": "", + "identifier": "" }, { - "name":"Spatial Sciences", - "definition":"", - "identifier":"" + "name": "Spatial Sciences", + "definition": "", + "identifier": "" } ] -} \ No newline at end of file +} diff --git a/src/main/resources/controlled_vocabularies/ManuscriptAllowedMimeTypes.json b/src/main/resources/controlled_vocabularies/ManuscriptAllowedMimeTypes.json index 29e3d12be6..6b55800bd7 100644 --- a/src/main/resources/controlled_vocabularies/ManuscriptAllowedMimeTypes.json +++ b/src/main/resources/controlled_vocabularies/ManuscriptAllowedMimeTypes.json @@ -1,9 +1,11 @@ { "name": "Manuscript Allowed File Extensions", "isEntityProperty": false, - "dictionary": [{ - "name": "pdf", - "definition": "PDF file", - "identifier": "" - }] + "dictionary": [ + { + "name": "pdf", + "definition": "PDF file", + "identifier": "" + } + ] } diff --git a/src/main/resources/controlled_vocabularies/SubmissionTypes.json b/src/main/resources/controlled_vocabularies/SubmissionTypes.json index b88b29ec3e..1cdbfc0532 100644 --- a/src/main/resources/controlled_vocabularies/SubmissionTypes.json +++ b/src/main/resources/controlled_vocabularies/SubmissionTypes.json @@ -1,46 +1,46 @@ { - "name":"Submission Types", - "isEntityProperty":false, - "dictionary":[ + "name": "Submission Types", + "isEntityProperty": false, + "dictionary": [ { - "name":"Performance Piece", - "definition":"a live artistic performance", - "identifier":"" + "name": "Performance Piece", + "definition": "a live artistic performance", + "identifier": "" }, { - "name":"Thesis", - "definition":"", - "identifier":"" + "name": "Thesis", + "definition": "", + "identifier": "" }, { - "name":"Dissertation", - "definition":"", - "identifier":"" + "name": "Dissertation", + "definition": "", + "identifier": "" }, { - "name":"Honors Thesis", - "definition":"", - "identifier":"" + "name": "Honors Thesis", + "definition": "", + "identifier": "" }, { - "name":"Project Report", - "definition":"", - "identifier":"" + "name": "Project Report", + "definition": "", + "identifier": "" }, { - "name":"Capstone Project", - "definition":"", - "identifier":"" + "name": "Capstone Project", + "definition": "", + "identifier": "" }, { - "name":"Project Capstone", - "definition":"", - "identifier":"" + "name": "Project Capstone", + "definition": "", + "identifier": "" }, { - "name":"Treatise", - "definition":"", - "identifier":"" + "name": "Treatise", + "definition": "", + "identifier": "" } ] -} \ No newline at end of file +} diff --git a/src/main/resources/degree_levels/SYSTEM_Degree_Levels.json b/src/main/resources/degree_levels/SYSTEM_Degree_Levels.json index 35c16e60b4..9ac3222946 100644 --- a/src/main/resources/degree_levels/SYSTEM_Degree_Levels.json +++ b/src/main/resources/degree_levels/SYSTEM_Degree_Levels.json @@ -11,4 +11,4 @@ { "name": "DOCTORAL" } -] \ No newline at end of file +] diff --git a/src/main/resources/degrees/SYSTEM_Degrees.json b/src/main/resources/degrees/SYSTEM_Degrees.json index 166e82b3b9..c147ce53e7 100644 --- a/src/main/resources/degrees/SYSTEM_Degrees.json +++ b/src/main/resources/degrees/SYSTEM_Degrees.json @@ -1,290 +1,290 @@ [ { - "name":"Master of Engineering Technical Management", - "level":{ - "name":"MASTERS" + "name": "Master of Engineering Technical Management", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Real Estate", - "level":{ - "name":"MASTERS" + "name": "Master of Real Estate", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Science in Public Health", - "level":{ - "name":"MASTERS" + "name": "Master of Science in Public Health", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Geoscience", - "level":{ - "name":"MASTERS" + "name": "Master of Geoscience", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Laws", - "level":{ - "name":"MASTERS" + "name": "Master of Laws", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Industrial Distirubtion", - "level":{ - "name":"MASTERS" + "name": "Master of Industrial Distirubtion", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Engineering", - "level":{ - "name":"MASTERS" + "name": "Master of Engineering", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Jurisprudence", - "level":{ - "name":"MASTERS" + "name": "Master of Jurisprudence", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Land and Property Development", - "level":{ - "name":"MASTERS" + "name": "Master of Land and Property Development", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Natural Resource Development", - "level":{ - "name":"MASTERS" + "name": "Master of Natural Resource Development", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Public Health", - "level":{ - "name":"MASTERS" + "name": "Master of Public Health", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Recreation and Resources Development", - "level":{ - "name":"MASTERS" + "name": "Master of Recreation and Resources Development", + "level": { + "name": "MASTERS" } }, { - "name":"Doctor of Engineering", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Engineering", + "level": { + "name": "DOCTORAL" } }, { - "name":"Master of Architecture", - "level":{ - "name":"MASTERS" + "name": "Master of Architecture", + "level": { + "name": "MASTERS" } }, { - "name":"Bachelor of Arts", - "level":{ - "name":"UNDERGRADUATE" + "name": "Bachelor of Arts", + "level": { + "name": "UNDERGRADUATE" } }, { - "name":"Master of Business Administration", - "level":{ - "name":"MASTERS" + "name": "Master of Business Administration", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Health Administration", - "level":{ - "name":"MASTERS" + "name": "Master of Health Administration", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Fine Arts", - "level":{ - "name":"MASTERS" + "name": "Master of Fine Arts", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Ocean Science and Technology", - "level":{ - "name":"MASTERS" + "name": "Master of Ocean Science and Technology", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Water Management", - "level":{ - "name":"MASTERS" + "name": "Master of Water Management", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Equine Industry Management", - "level":{ - "name":"MASTERS" + "name": "Master of Equine Industry Management", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Marine Resource Management", - "level":{ - "name":"MASTERS" + "name": "Master of Marine Resource Management", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Financial Management", - "level":{ - "name":"MASTERS" + "name": "Master of Financial Management", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Biotechnology", - "level":{ - "name":"MASTERS" + "name": "Master of Biotechnology", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Wildlife Science", - "level":{ - "name":"MASTERS" + "name": "Master of Wildlife Science", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Maritime Administration and Logistics", - "level":{ - "name":"MASTERS" + "name": "Master of Maritime Administration and Logistics", + "level": { + "name": "MASTERS" } }, { - "name":"Bachelor of Business Administration", - "level":{ - "name":"UNDERGRADUATE" + "name": "Bachelor of Business Administration", + "level": { + "name": "UNDERGRADUATE" } }, { - "name":"Doctor of Dentistry", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Dentistry", + "level": { + "name": "DOCTORAL" } }, { - "name":"Master of Urban Planning", - "level":{ - "name":"MASTERS" + "name": "Master of Urban Planning", + "level": { + "name": "MASTERS" } }, { - "name":"Doctor of Education", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Education", + "level": { + "name": "DOCTORAL" } }, { - "name":"Master of Science", - "level":{ - "name":"MASTERS" + "name": "Master of Science", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Education", - "level":{ - "name":"MASTERS" + "name": "Master of Education", + "level": { + "name": "MASTERS" } }, { - "name":"Doctor of Medicine", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Medicine", + "level": { + "name": "DOCTORAL" } }, { - "name":"Doctor of Public Health", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Public Health", + "level": { + "name": "DOCTORAL" } }, { - "name":"Bachelor of Science in Nursing", - "level":{ - "name":"UNDERGRADUATE" + "name": "Bachelor of Science in Nursing", + "level": { + "name": "UNDERGRADUATE" } }, { - "name":"Doctor of Veterinary Medicine", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Veterinary Medicine", + "level": { + "name": "DOCTORAL" } }, { - "name":"Doctor of Jurisprudence", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Jurisprudence", + "level": { + "name": "DOCTORAL" } }, { - "name":"Bachelor of Environmental Design", - "level":{ - "name":"UNDERGRADUATE" + "name": "Bachelor of Environmental Design", + "level": { + "name": "UNDERGRADUATE" } }, { - "name":"Bachelor of Science", - "level":{ - "name":"UNDERGRADUATE" + "name": "Bachelor of Science", + "level": { + "name": "UNDERGRADUATE" } }, { - "name":"Master of International Affairs", - "level":{ - "name":"MASTERS" + "name": "Master of International Affairs", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Science in Nursing", - "level":{ - "name":"MASTERS" + "name": "Master of Science in Nursing", + "level": { + "name": "MASTERS" } }, { - "name":"Doctor of Philosophy", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Philosophy", + "level": { + "name": "DOCTORAL" } }, { - "name":"Master of Agribusiness", - "level":{ - "name":"MASTERS" + "name": "Master of Agribusiness", + "level": { + "name": "MASTERS" } }, { - "name":"Doctor of Pharmacy", - "level":{ - "name":"DOCTORAL" + "name": "Doctor of Pharmacy", + "level": { + "name": "DOCTORAL" } }, { - "name":"Master of Landscape Architecture", - "level":{ - "name":"MASTERS" + "name": "Master of Landscape Architecture", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Agricultural Economics", - "level":{ - "name":"MASTERS" + "name": "Master of Agricultural Economics", + "level": { + "name": "MASTERS" } }, { - "name":"Master of Public Service and Administration", - "level":{ - "name":"MASTERS" + "name": "Master of Public Service and Administration", + "level": { + "name": "MASTERS" } }, { - "name":"Bachelor of Landscape Architecture", - "level":{ - "name":"UNDERGRADUATE" + "name": "Bachelor of Landscape Architecture", + "level": { + "name": "UNDERGRADUATE" } } -] \ No newline at end of file +] diff --git a/src/main/resources/document_types/SYSTEM_Document_Types.json b/src/main/resources/document_types/SYSTEM_Document_Types.json index 13722eff5b..657ea52db7 100644 --- a/src/main/resources/document_types/SYSTEM_Document_Types.json +++ b/src/main/resources/document_types/SYSTEM_Document_Types.json @@ -1,58 +1,58 @@ -[ +[ { - "name":"Administrative Files", - "fieldPredicate":{ - "value":"_doctype_administrative", - "documentTypePredicate":true + "name": "Administrative Files", + "fieldPredicate": { + "value": "_doctype_administrative", + "documentTypePredicate": true } }, { - "name":"Source Files", - "fieldPredicate":{ - "value":"_doctype_source", - "documentTypePredicate":true + "name": "Source Files", + "fieldPredicate": { + "value": "_doctype_source", + "documentTypePredicate": true } }, { - "name":"Supplemental Files", - "fieldPredicate":{ - "value":"_doctype_supplemental", - "documentTypePredicate":true + "name": "Supplemental Files", + "fieldPredicate": { + "value": "_doctype_supplemental", + "documentTypePredicate": true } }, { - "name":"Manuscript in PDF", - "fieldPredicate":{ - "value":"_doctype_primary", - "documentTypePredicate":true + "name": "Manuscript in PDF", + "fieldPredicate": { + "value": "_doctype_primary", + "documentTypePredicate": true } }, { - "name":"License Files", - "fieldPredicate":{ - "value":"_doctype_license", - "documentTypePredicate":true + "name": "License Files", + "fieldPredicate": { + "value": "_doctype_license", + "documentTypePredicate": true } }, { - "name":"Feedback", - "fieldPredicate":{ - "value":"_doctype_feedback", - "documentTypePredicate":true + "name": "Feedback", + "fieldPredicate": { + "value": "_doctype_feedback", + "documentTypePredicate": true } }, { - "name":"Archived Files", - "fieldPredicate":{ - "value":"_doctype_archived", - "documentTypePredicate":true + "name": "Archived Files", + "fieldPredicate": { + "value": "_doctype_archived", + "documentTypePredicate": true } }, { - "name":"Unknown Files", - "fieldPredicate":{ - "value":"_doctype_unknown", - "documentTypePredicate":true + "name": "Unknown Files", + "fieldPredicate": { + "value": "_doctype_unknown", + "documentTypePredicate": true } } -] \ No newline at end of file +] diff --git a/src/main/resources/embargos/SYSTEM_Embargo_Definitions.json b/src/main/resources/embargos/SYSTEM_Embargo_Definitions.json index 100c057ad5..3e73fc817d 100644 --- a/src/main/resources/embargos/SYSTEM_Embargo_Definitions.json +++ b/src/main/resources/embargos/SYSTEM_Embargo_Definitions.json @@ -1,4 +1,5 @@ -[{ +[ + { "name": "None", "description": "The work will be published after approval.", "duration": 0, diff --git a/src/main/resources/filter_columns/default_filter_columns.json b/src/main/resources/filter_columns/default_filter_columns.json index 17b9c8b6ed..96458fb88b 100644 --- a/src/main/resources/filter_columns/default_filter_columns.json +++ b/src/main/resources/filter_columns/default_filter_columns.json @@ -34,4 +34,4 @@ "title": "Degree", "predicate": "thesis.degree.name" } -] \ No newline at end of file +] diff --git a/src/main/resources/graduation_months/SYSTEM_Graduation_Months.json b/src/main/resources/graduation_months/SYSTEM_Graduation_Months.json index 1e3b4c9c9a..aa439cc07e 100644 --- a/src/main/resources/graduation_months/SYSTEM_Graduation_Months.json +++ b/src/main/resources/graduation_months/SYSTEM_Graduation_Months.json @@ -8,4 +8,4 @@ { "month": 11 } -] \ No newline at end of file +] diff --git a/src/main/resources/input_types/SYSTEM_Input_Types.json b/src/main/resources/input_types/SYSTEM_Input_Types.json index 1cceacffc3..34cefb5e90 100644 --- a/src/main/resources/input_types/SYSTEM_Input_Types.json +++ b/src/main/resources/input_types/SYSTEM_Input_Types.json @@ -1,4 +1,5 @@ -[{ +[ + { "name": "INPUT_TEXT", "validationPattern": null, "validationMessage": null @@ -13,14 +14,14 @@ "validationPattern": null, "validationMessage": null, "validation": { - "name": { - "pattern": null, - "message": null - }, - "email": { - "pattern": "^([_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})|)$", - "message": "Field must be a valid email address" - } + "name": { + "pattern": null, + "message": null + }, + "email": { + "pattern": "^([_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})|)$", + "message": "Field must be a valid email address" + } } }, { @@ -28,14 +29,14 @@ "validationPattern": null, "validationMessage": null, "validation": { - "name": { - "pattern": null, - "message": null - }, - "email": { - "pattern": null, - "message": null - } + "name": { + "pattern": null, + "message": null + }, + "email": { + "pattern": null, + "message": null + } } }, { diff --git a/src/main/resources/languages/SYSTEM_Languages.json b/src/main/resources/languages/SYSTEM_Languages.json index 0d02546bc3..f0be08ae81 100644 --- a/src/main/resources/languages/SYSTEM_Languages.json +++ b/src/main/resources/languages/SYSTEM_Languages.json @@ -1,3 +1,5 @@ -[{ - "name":"English" -}] \ No newline at end of file +[ + { + "name": "English" + } +] diff --git a/src/main/resources/organization/SYSTEM_Organization_Definition.json b/src/main/resources/organization/SYSTEM_Organization_Definition.json index 3219c09b49..184717b65a 100644 --- a/src/main/resources/organization/SYSTEM_Organization_Definition.json +++ b/src/main/resources/organization/SYSTEM_Organization_Definition.json @@ -1,1058 +1,1056 @@ { - "name":"Institution", + "name": "Institution", "acceptsSubmissions": false, - "category":{ - "name":"System" + "category": { + "name": "System" }, - "originalWorkflowSteps":[ + "originalWorkflowSteps": [ { - "name":"Personal Information", + "name": "Personal Information", "instructions": "

Instructions:

Please verify all of your personal information. Some of the information has been provided by your school; if this information is in error, you will need to correct it through the appropriate office at your school.

Required fields are indicated with an asterisk.

", - "overrideable":true, - "originatingOrganization":{ - "name":"Institution", - "category":{ - "name":"System" + "overrideable": true, + "originatingOrganization": { + "name": "Institution", + "category": { + "name": "System" } }, - "originalNotes":[ + "originalNotes": [ { - "name":"name", - "text":"Your name should appear as it does on your title page. You can use Unicode characters, if your computer supports them.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "name", + "text": "Your name should appear as it does on your title page. You can use Unicode characters, if your computer supports them.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } }, { - "name":"degreeAndMajor", - "text":"Select the degree and major that are listed on your title page.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "degreeAndMajor", + "text": "Select the degree and major that are listed on your title page.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } }, { - "name":"permanentAddress", - "text":"You must enter a permanent, long-term address. If your present address is different, use the Current Address field.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "permanentAddress", + "text": "You must enter a permanent, long-term address. If your present address is different, use the Current Address field.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } } ], - "originalFieldProfiles":[ + "originalFieldProfiles": [ { - "fieldPredicate":{ - "value":"first_name", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter your first name.", - "gloss":"First Name" + "fieldPredicate": { + "value": "first_name", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter your first name.", + "gloss": "First Name" }, { - "fieldPredicate":{ - "value":"middle_name", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter your middle name or initial.", + "fieldPredicate": { + "value": "middle_name", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter your middle name or initial.", "gloss": "Middle Name" }, { - "fieldPredicate":{ - "value":"last_name", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter your last name.", + "fieldPredicate": { + "value": "last_name", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter your last name.", "gloss": "Last Name" }, { - "fieldPredicate":{ - "value":"email", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_EMAIL" - }, - "mappedShibAttribute":{ - "isSystemRequired":true, - "name":"APPLICATION_AUTH_SHIB_ATTRIBUTE_EMAIL", - "type":"shibboleth", - "value":"email" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter your email.", + "fieldPredicate": { + "value": "email", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_EMAIL" + }, + "mappedShibAttribute": { + "isSystemRequired": true, + "name": "APPLICATION_AUTH_SHIB_ATTRIBUTE_EMAIL", + "type": "shibboleth", + "value": "email" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter your email.", "gloss": "Email" }, { - "fieldPredicate":{ - "value":"local.etdauthor.orcid", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_ORCID" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter your ORCID author identifier (ID) associated with email. If you do not have an ORCID ID, you may register here orcid.org.", - "htmlTooltip":true, + "fieldPredicate": { + "value": "local.etdauthor.orcid", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_ORCID" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter your ORCID author identifier (ID) associated with email. If you do not have an ORCID ID, you may register here orcid.org.", + "htmlTooltip": true, "gloss": "ORCID" }, { - "fieldPredicate":{ - "value":"institutional_id", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "mappedShibAttribute":{ - "isSystemRequired":true, - "name":"APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER", - "type":"shibboleth", - "value":"uin" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "hidden":true, - "usage":"", - "help":"", + "fieldPredicate": { + "value": "institutional_id", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "mappedShibAttribute": { + "isSystemRequired": true, + "name": "APPLICATION_AUTH_SHIB_ATTRIBUTE_INSTITUTIONAL_IDENTIFIER", + "type": "shibboleth", + "value": "uin" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "hidden": true, + "usage": "", + "help": "", "gloss": "Institutional ID" }, { - "fieldPredicate":{ - "value":"birth_year", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter the year in which you were born. (e.g. 2000)", + "fieldPredicate": { + "value": "birth_year", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter the year in which you were born. (e.g. 2000)", "gloss": "Year of Birth" }, { - "fieldPredicate":{ - "value":"thesis.degree.school", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter the name of your degree granting institution.", + "fieldPredicate": { + "value": "thesis.degree.school", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter the name of your degree granting institution.", "gloss": "School" }, { - "fieldPredicate":{ - "value":"thesis.degree.college", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter the name of your college.", + "fieldPredicate": { + "value": "thesis.degree.college", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter the name of your college.", "gloss": "College", "controlledVocabulary": { - "name":"Colleges", - "isEntityProperty":false + "name": "Colleges", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"thesis.degree.program", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter the name of your program.", + "fieldPredicate": { + "value": "thesis.degree.program", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter the name of your program.", "gloss": "Program", - "controlledVocabulary":{ - "name":"Programs", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Programs", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"thesis.degree.department", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter the name of your department.", + "fieldPredicate": { + "value": "thesis.degree.department", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter the name of your department.", "gloss": "Department", - "controlledVocabulary":{ - "name":"Departments", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Departments", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"thesis.degree.name", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_SELECT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Select your degree type.", + "fieldPredicate": { + "value": "thesis.degree.name", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_SELECT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Select your degree type.", "gloss": "Degree", - "controlledVocabulary":{ - "name":"Degrees", - "entityName":"Degree", - "isEntityProperty":true + "controlledVocabulary": { + "name": "Degrees", + "entityName": "Degree", + "isEntityProperty": true } }, { - "fieldPredicate":{ - "value":"thesis.degree.major", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter the name of your major discipline.", + "fieldPredicate": { + "value": "thesis.degree.major", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter the name of your major discipline.", "gloss": "Major", - "controlledVocabulary":{ - "name":"Majors", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Majors", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"permanent_phone", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEL" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter a phone number where you can be reached after graduating.", + "fieldPredicate": { + "value": "permanent_phone", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEL" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter a phone number where you can be reached after graduating.", "gloss": "Permanent Phone" }, { - "fieldPredicate":{ - "value":"permanent_address", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXTAREA" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter an address where you can be reached after graduating.", + "fieldPredicate": { + "value": "permanent_address", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXTAREA" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter an address where you can be reached after graduating.", "gloss": "Permanent Address" }, { - "fieldPredicate":{ - "value":"permanent_email", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_EMAIL" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter an email address where you can be reached after graduating.", + "fieldPredicate": { + "value": "permanent_email", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_EMAIL" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter an email address where you can be reached after graduating.", "gloss": "Permanent Email" }, { - "fieldPredicate":{ - "value":"current_phone", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEL" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter your current phone number if different from your permanent phone number.", + "fieldPredicate": { + "value": "current_phone", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEL" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter your current phone number if different from your permanent phone number.", "gloss": "Current Phone" }, { - "fieldPredicate":{ - "value":"current_address", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Verify Personal Information" - }, - "inputType":{ - "name":"INPUT_TEXTAREA" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Enter your current address if different from your permanent address.", + "fieldPredicate": { + "value": "current_address", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Verify Personal Information" + }, + "inputType": { + "name": "INPUT_TEXTAREA" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Enter your current address if different from your permanent address.", "gloss": "Current Address" } ] }, { - "name":"License Agreement", + "name": "License Agreement", "instructions": "", - "overrideable":true, - "originatingOrganization":{ - "name":"Institution", - "category":{ - "name":"System" + "overrideable": true, + "originatingOrganization": { + "name": "Institution", + "category": { + "name": "System" } }, - "originalNotes":[ - - ], - "originalFieldProfiles":[ + "originalNotes": [], + "originalFieldProfiles": [ { - "fieldPredicate":{ - "value":"license_agreement", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"License Agreement" - }, - "inputType":{ - "name":"INPUT_LICENSE" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":true, - "usage":"", + "fieldPredicate": { + "value": "license_agreement", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "License Agreement" + }, + "inputType": { + "name": "INPUT_LICENSE" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": true, + "usage": "", "gloss": "License Agreement" }, { - "fieldPredicate":{ - "value":"umi_publication", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"License Agreement" - }, - "inputType":{ - "name":"INPUT_PROQUEST" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":true, - "usage":"", - "help":"I am requesting that ProQuest provide additional free non-exclusive distribution via the ProQuest Dissertation & Theses Database (PQDT), which reaches 3,000 universities with over 200 million searches annually, and supports discovery through major subject and discipline indexes (SciFinder, MLA, MathSciNet, PsycINFO, etc). I also will be eligible for a royalty based upon sales of my full-text work. More information is available here.", + "fieldPredicate": { + "value": "umi_publication", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "License Agreement" + }, + "inputType": { + "name": "INPUT_PROQUEST" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": true, + "usage": "", + "help": "I am requesting that ProQuest provide additional free non-exclusive distribution via the ProQuest Dissertation & Theses Database (PQDT), which reaches 3,000 universities with over 200 million searches annually, and supports discovery through major subject and discipline indexes (SciFinder, MLA, MathSciNet, PsycINFO, etc). I also will be eligible for a royalty based upon sales of my full-text work. More information is available here.", "gloss": "Proquest Publication" } ] }, { - "name":"Document Information", + "name": "Document Information", "instructions": "

Instructions:

Describe your thesis or dissertation. Please make sure that the information entered below matches the information contained in your document.

", - "overrideable":true, - "originatingOrganization":{ - "name":"Institution", - "category":{ - "name":"System" + "overrideable": true, + "originatingOrganization": { + "name": "Institution", + "category": { + "name": "System" } }, - "originalNotes":[ + "originalNotes": [ { - "name":"degreeDate", - "text":"For the graduation semester, enter the semester in which your degree will be conferred.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "degreeDate", + "text": "For the graduation semester, enter the semester in which your degree will be conferred.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } }, { - "name":"multipleKeywords", - "text":"Enter one keyword or key phrase per entry field.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "multipleKeywords", + "text": "Enter one keyword or key phrase per entry field.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } }, { - "name":"committeeMembers", - "text":"Please supply the names of your committee members, and a single email address to reach the chair or either co-chair.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "committeeMembers", + "text": "Please supply the names of your committee members, and a single email address to reach the chair or either co-chair.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } }, { - "name":"embargoCheckAdvisor", - "text":"If you don't know if you need an embargo, then you should check with your advisor. This option is typically only used for situations like patent holds or a request by a publisher if content from the document is pending publication.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "embargoCheckAdvisor", + "text": "If you don't know if you need an embargo, then you should check with your advisor. This option is typically only used for situations like patent holds or a request by a publisher if content from the document is pending publication.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } } ], - "originalFieldProfiles":[ + "originalFieldProfiles": [ { - "fieldPredicate":{ - "value":"dc.title", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter the title of your document.", + "fieldPredicate": { + "value": "dc.title", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter the title of your document.", "gloss": "Title" }, { - "fieldPredicate":{ - "value":"dc.date.issued", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_DEGREEDATE" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Select your graduation month. Format: May 2022", + "fieldPredicate": { + "value": "dc.date.issued", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_DEGREEDATE" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Select your graduation month. Format: May 2022", "gloss": "Graduation Semester", - "controlledVocabulary":{ - "name":"Graduation Months", - "isEntityProperty":true + "controlledVocabulary": { + "name": "Graduation Months", + "isEntityProperty": true } }, { - "fieldPredicate":{ - "value":"defense_date", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_DATE" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Select your defense date. Format: mm/dd/yyyy", + "fieldPredicate": { + "value": "defense_date", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_DATE" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Select your defense date. Format: mm/dd/yyyy", "gloss": "Defense Date" }, { - "fieldPredicate":{ - "value":"submission_type", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_SELECT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Select your submission type.", + "fieldPredicate": { + "value": "submission_type", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_SELECT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Select your submission type.", "gloss": "Submission Type", - "controlledVocabulary":{ - "name":"Submission Types", - "isEntityProperty":false - } + "controlledVocabulary": { + "name": "Submission Types", + "isEntityProperty": false + } }, { - "fieldPredicate":{ - "value":"dc.description.abstract", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_TEXTAREA" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter the abstract for your document.", + "fieldPredicate": { + "value": "dc.description.abstract", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_TEXTAREA" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter the abstract for your document.", "gloss": "Abstract" }, { - "fieldPredicate":{ - "value":"keywords", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter keywords for your document. You may enter multiple keywords by selecting the + sign.", + "fieldPredicate": { + "value": "keywords", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter keywords for your document. You may enter multiple keywords by selecting the + sign.", "gloss": "Keywords" }, { - "fieldPredicate":{ - "value":"dc.subject", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_TEXT" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter subjects for your document. You may enter multiple subjects by selecting the + sign.", + "fieldPredicate": { + "value": "dc.subject", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_TEXT" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter subjects for your document. You may enter multiple subjects by selecting the + sign.", "gloss": "Subjects", - "controlledVocabulary":{ - "name":"Subjects", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Subjects", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"dc.language.iso", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_SELECT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Select the primary language of your document.", + "fieldPredicate": { + "value": "dc.language.iso", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_SELECT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Select the primary language of your document.", "gloss": "Language", - "controlledVocabulary":{ - "name":"Languages", - "isEntityProperty":true + "controlledVocabulary": { + "name": "Languages", + "isEntityProperty": true } }, { - "fieldPredicate":{ - "value":"dc.contributor.advisor", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_CONTACT_SELECT" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Select the name and email address for your committee chair.", + "fieldPredicate": { + "value": "dc.contributor.advisor", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_CONTACT_SELECT" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Select the name and email address for your committee chair.", "gloss": "Committee Chair", - "controlledVocabulary":{ - "name":"Committee Members", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Committee Members", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"dc.contributor.committeeMember", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_CONTACT" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Enter the names and email addresses of your non-chairing committee members. You may enter multiple committee members by selecting the + sign.", + "fieldPredicate": { + "value": "dc.contributor.committeeMember", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_CONTACT" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Enter the names and email addresses of your non-chairing committee members. You may enter multiple committee members by selecting the + sign.", "gloss": "Non-Chairing Committee Members", - "controlledVocabulary":{ - "name":"Committee Members", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Committee Members", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"previously_published_material", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_CONDITIONAL_TEXTAREA" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Has any part of the material being submitted been previously published (i.e. book chapters or journal articles)? If so you will be asked identify the section where these materials are used in whole or in part.", + "fieldPredicate": { + "value": "previously_published_material", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_CONDITIONAL_TEXTAREA" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Has any part of the material being submitted been previously published (i.e. book chapters or journal articles)? If so you will be asked identify the section where these materials are used in whole or in part.", "gloss": "Previously Published Material" }, { - "fieldPredicate":{ - "value":"default_embargos", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_RADIO" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "flagged":false, - "logged":false, - "usage":"", - "help":"Select the default emborgo for the publication of your work. If you are unsure, you should discuss the options with your advisor.", + "fieldPredicate": { + "value": "default_embargos", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_RADIO" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "flagged": false, + "logged": false, + "usage": "", + "help": "Select the default emborgo for the publication of your work. If you are unsure, you should discuss the options with your advisor.", "gloss": "Default Embargos", - "controlledVocabulary":{ - "name":"Default Embargos", - "isEntityProperty":true + "controlledVocabulary": { + "name": "Default Embargos", + "isEntityProperty": true } }, { - "fieldPredicate":{ - "value":"proquest_embargos", - "documentTypePredicate":false - }, - "originatingWorkflowStep":{ - "name":"Document Information" - }, - "inputType":{ - "name":"INPUT_RADIO" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Select the ProQuest emborgo for the publication of your work. If you are unsure, you should discuss the options with your advisor.", + "fieldPredicate": { + "value": "proquest_embargos", + "documentTypePredicate": false + }, + "originatingWorkflowStep": { + "name": "Document Information" + }, + "inputType": { + "name": "INPUT_RADIO" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Select the ProQuest emborgo for the publication of your work. If you are unsure, you should discuss the options with your advisor.", "gloss": "ProQuest Embargos", - "controlledVocabulary":{ - "name":"Proquest Embargos", - "isEntityProperty":true + "controlledVocabulary": { + "name": "Proquest Embargos", + "isEntityProperty": true } } ] }, { - "name":"File Upload", + "name": "File Upload", "instructions": "

Instructions:

In this step you will upload your thesis or dissertation to the server. Optionally, you may upload additional supplementary files that will be available along with your document after publication.

", - "overrideable":true, - "originatingOrganization":{ - "name":"Institution", - "category":{ - "name":"System" + "overrideable": true, + "originatingOrganization": { + "name": "Institution", + "category": { + "name": "System" } }, - "originalNotes":[ + "originalNotes": [ { - "name":"onePdfFile", - "text":"Your thesis or dissertation can only be one file, and the only allowable file format is PDF. Please contact your school for help or information related to creating a PDF file.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "onePdfFile", + "text": "Your thesis or dissertation can only be one file, and the only allowable file format is PDF. Please contact your school for help or information related to creating a PDF file.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } }, { - "name":"noLimit", - "text":"There is no limit on the number or formats of supplementary files you may upload.", - "originatingWorkflowStep":{ - "name":"Verify Personal Information" + "name": "noLimit", + "text": "There is no limit on the number or formats of supplementary files you may upload.", + "originatingWorkflowStep": { + "name": "Verify Personal Information" } } ], - "originalFieldProfiles":[ + "originalFieldProfiles": [ { - "fieldPredicate":{ - "value":"_doctype_primary", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":false, - "flagged":false, - "logged":false, - "usage":"", - "help":"Upload the primary manuscript. You may only upload one file. Additional files may be uploaded below.", + "fieldPredicate": { + "value": "_doctype_primary", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": false, + "flagged": false, + "logged": false, + "usage": "", + "help": "Upload the primary manuscript. You may only upload one file. Additional files may be uploaded below.", "gloss": "Manuscript in PDF", - "controlledVocabulary":{ - "name":"Manuscript Allowed File Extensions", - "isEntityProperty":false + "controlledVocabulary": { + "name": "Manuscript Allowed File Extensions", + "isEntityProperty": false } }, { - "fieldPredicate":{ - "value":"_doctype_supplemental", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Upload only supplemental files such as audio, video or data sets. These files must be listed in the appendix of your thesis or dissertation.", + "fieldPredicate": { + "value": "_doctype_supplemental", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Upload only supplemental files such as audio, video or data sets. These files must be listed in the appendix of your thesis or dissertation.", "gloss": "Supplemental Files" }, { - "fieldPredicate":{ - "value":"_doctype_source", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Upload the source files used to create your manuscript such as a Word Document, LaTeX Source file, etc. These files will be used to improve the digital preservation potential of your document.", + "fieldPredicate": { + "value": "_doctype_source", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Upload the source files used to create your manuscript such as a Word Document, LaTeX Source file, etc. These files will be used to improve the digital preservation potential of your document.", "gloss": "Source Files" }, { - "fieldPredicate":{ - "value":"_doctype_administrative", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":true, - "usage":"", - "help":"Upload additional administrative files such as a signed graduation release form or other local administrative files.", + "fieldPredicate": { + "value": "_doctype_administrative", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": true, + "usage": "", + "help": "Upload additional administrative files such as a signed graduation release form or other local administrative files.", "gloss": "Administrative Files" }, { - "fieldPredicate":{ - "value":"_doctype_license", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":false, - "overrideable":true, - "enabled":true, - "optional":true, - "hidden":true, - "usage":"", - "help":"", + "fieldPredicate": { + "value": "_doctype_license", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": false, + "overrideable": true, + "enabled": true, + "optional": true, + "hidden": true, + "usage": "", + "help": "", "gloss": "License Files" }, { - "fieldPredicate":{ - "value":"_doctype_archived", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":true, - "hidden":true, - "usage":"", - "help":"", + "fieldPredicate": { + "value": "_doctype_archived", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": true, + "hidden": true, + "usage": "", + "help": "", "gloss": "Archived Files" }, { - "fieldPredicate":{ - "value":"_doctype_feedback", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":true, - "hidden":true, - "usage":"", - "help":"", + "fieldPredicate": { + "value": "_doctype_feedback", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": true, + "hidden": true, + "usage": "", + "help": "", "gloss": "Feedback Files" }, { - "fieldPredicate":{ - "value":"_doctype_unknown", - "documentTypePredicate":true - }, - "originatingWorkflowStep":{ - "name":"File Upload" - }, - "inputType":{ - "name":"INPUT_FILE" - }, - "repeatable":true, - "overrideable":true, - "enabled":true, - "optional":true, - "hidden":true, - "usage":"", - "help":"", + "fieldPredicate": { + "value": "_doctype_unknown", + "documentTypePredicate": true + }, + "originatingWorkflowStep": { + "name": "File Upload" + }, + "inputType": { + "name": "INPUT_FILE" + }, + "repeatable": true, + "overrideable": true, + "enabled": true, + "optional": true, + "hidden": true, + "usage": "", + "help": "", "gloss": "Unknown Files" } ] } ], - "parentOrganization":null, - "childrenOrganizations":null, - "emails":null, - "emailWorkflowRules":[ + "parentOrganization": null, + "childrenOrganizations": null, + "emails": null, + "emailWorkflowRules": [ { - "isSystem":true, - "isDisabled":false, + "isSystem": true, + "isDisabled": false, "submissionStatus": { "name": "Submitted" }, - "recipientType":2, - "emailTemplate":{ - "name":"SYSTEM Advisor Review Request", - "systemRequired":true + "recipientType": 2, + "emailTemplate": { + "name": "SYSTEM Advisor Review Request", + "systemRequired": true } }, { - "isSystem":true, - "isDisabled":false, + "isSystem": true, + "isDisabled": false, "submissionStatus": { "name": "Submitted" }, - "recipientType":1, - "emailTemplate":{ - "name":"SYSTEM Initial Submission", - "systemRequired":true + "recipientType": 1, + "emailTemplate": { + "name": "SYSTEM Initial Submission", + "systemRequired": true } } ] diff --git a/src/main/resources/settings/SYSTEM_Defaults.json b/src/main/resources/settings/SYSTEM_Defaults.json index e424239358..5c6f7b878f 100644 --- a/src/main/resources/settings/SYSTEM_Defaults.json +++ b/src/main/resources/settings/SYSTEM_Defaults.json @@ -154,7 +154,7 @@ ], "submission": [ { - "submit_license":"

I grant the Texas Digital Library (hereafter called \"TDL\"), my home institution (hereafter called \"Institution\"), and my academic department (hereafter called \"Department\") the non-exclusive rights to copy, display, perform, distribute and publish the content I submit to this repository (hereafter called \"Work\") and to make the Work available in any format in perpetuity as part of a TDL, Institution or Department repository communication or distribution effort.

+ "submit_license": "

I grant the Texas Digital Library (hereafter called \"TDL\"), my home institution (hereafter called \"Institution\"), and my academic department (hereafter called \"Department\") the non-exclusive rights to copy, display, perform, distribute and publish the content I submit to this repository (hereafter called \"Work\") and to make the Work available in any format in perpetuity as part of a TDL, Institution or Department repository communication or distribution effort.

I understand that once the Work is submitted, a bibliographic citation to the Work can remain visible in perpetuity, even if the Work is updated or removed.

@@ -249,4 +249,4 @@ "APPLICATION_AUTH_SHIB_ATTRIBUTE_ORCID": "orcid" } ] -} +} \ No newline at end of file diff --git a/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json b/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json index e4f63c6997..72741e5ad6 100644 --- a/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json +++ b/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json @@ -1 +1,12 @@ -["ID", "Last Name", "First Name", "Status", "Assigned To", "Title", "Submission Date", "Approval Date", "Default Embargos", "ProQuest Embargos"] +[ + "ID", + "Last Name", + "First Name", + "Status", + "Assigned To", + "Title", + "Submission Date", + "Approval Date", + "Default Embargos", + "ProQuest Embargos" +] diff --git a/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json b/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json index 9cc1797449..981b8ef6cd 100644 --- a/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json +++ b/src/main/resources/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json @@ -1,7 +1,10 @@ -[{ +[ + { "title": "ID", "sort": "ASC", - "valuePath": ["id"], + "valuePath": [ + "id" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -10,7 +13,10 @@ { "title": "Status", "sort": "NONE", - "valuePath": ["submissionStatus", "name"], + "valuePath": [ + "submissionStatus", + "name" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -19,7 +25,10 @@ { "title": "Organization", "sort": "NONE", - "valuePath": ["organization", "name"], + "valuePath": [ + "organization", + "name" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -28,7 +37,11 @@ { "title": "Organization Category", "sort": "NONE", - "valuePath": ["organization", "category", "name"], + "valuePath": [ + "organization", + "category", + "name" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -37,7 +50,10 @@ { "title": "Assigned To", "sort": "NONE", - "valuePath": ["assignee", "email"], + "valuePath": [ + "assignee", + "email" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -46,7 +62,9 @@ { "title": "Submission Date", "sort": "NONE", - "valuePath": ["submissionDate"], + "valuePath": [ + "submissionDate" + ], "status": null, "inputType": { "name": "INPUT_DATE" @@ -55,7 +73,9 @@ { "title": "Approval Date", "sort": "NONE", - "valuePath": ["approveApplicationDate"], + "valuePath": [ + "approveApplicationDate" + ], "status": null, "inputType": { "name": "INPUT_DATE" @@ -64,7 +84,9 @@ { "title": "License Agreement Date", "sort": "NONE", - "valuePath": ["submissionDate"], + "valuePath": [ + "submissionDate" + ], "status": null, "inputType": { "name": "INPUT_DATE" @@ -73,7 +95,9 @@ { "title": "Committee Approval Date", "sort": "NONE", - "valuePath": ["approveAdvisorDate"], + "valuePath": [ + "approveAdvisorDate" + ], "status": null, "inputType": { "name": "INPUT_DATE" @@ -82,7 +106,9 @@ { "title": "Committee Embargo Approval Date", "sort": "NONE", - "valuePath": ["approveEmbargoDate"], + "valuePath": [ + "approveEmbargoDate" + ], "status": null, "inputType": { "name": "INPUT_DATE" @@ -91,7 +117,9 @@ { "title": "Committee Contact Email", "sort": "NONE", - "valuePath": ["committeeContactEmail"], + "valuePath": [ + "committeeContactEmail" + ], "status": null, "inputType": { "name": "INPUT_CONTACT" @@ -100,7 +128,9 @@ { "title": "Custom Actions", "sort": "NONE", - "valuePath": ["customActionValues"], + "valuePath": [ + "customActionValues" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -109,7 +139,9 @@ { "title": "Deposit ID", "sort": "NONE", - "valuePath": ["depositURL"], + "valuePath": [ + "depositURL" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -118,7 +150,9 @@ { "title": "Notes", "sort": "NONE", - "valuePath": ["reviewerNotes"], + "valuePath": [ + "reviewerNotes" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -127,7 +161,9 @@ { "title": "Last Event", "sort": "NONE", - "valuePath": ["lastEvent"], + "valuePath": [ + "lastEvent" + ], "status": null, "inputType": { "name": "INPUT_TEXT" @@ -154,7 +190,9 @@ { "title": "Exclude", "sort": "NONE", - "valuePath": ["exclude"], + "valuePath": [ + "exclude" + ], "status": null, "inputType": { "name": "INPUT_TEXT" From 4ec8d06643ce27ba7a288bc365678d8bc46e2214 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 19:40:34 -0600 Subject: [PATCH 26/48] Simplify system submission status loading --- .../org/tdl/vireo/model/SubmissionState.java | 59 ++++--- .../org/tdl/vireo/model/SubmissionStatus.java | 5 +- .../tdl/vireo/service/SystemDataLoader.java | 83 ++++----- .../SYSTEM_Submission_Status.json | 159 ++++++++++++++++++ .../SYSTEM_Submission_Statuses.json | 146 ---------------- ...YSTEM_Submission_Statuses_Transitions.json | 79 --------- 6 files changed, 236 insertions(+), 295 deletions(-) create mode 100644 src/main/resources/submission_statuses/SYSTEM_Submission_Status.json delete mode 100644 src/main/resources/submission_statuses/SYSTEM_Submission_Statuses.json delete mode 100644 src/main/resources/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json diff --git a/src/main/java/org/tdl/vireo/model/SubmissionState.java b/src/main/java/org/tdl/vireo/model/SubmissionState.java index d3e0aefaea..a51cc409da 100644 --- a/src/main/java/org/tdl/vireo/model/SubmissionState.java +++ b/src/main/java/org/tdl/vireo/model/SubmissionState.java @@ -1,23 +1,27 @@ package org.tdl.vireo.model; public enum SubmissionState { - NONE(0), - IN_PROGRESS(1), - SUBMITTED(2), - UNDER_REVIEW(3), - NEEDS_CORRECTIONS(4), - CORRECTIONS_RECIEVED(5), - WAITING_ON_REQUIREMENTS(6), - APPROVED(7), - PENDING_PUBLICATION(8), - PUBLISHED(9), - ON_HOLD(10), - WITHDRAWN(11), - CANCELED(12); - - private int value; + NONE(0), + IN_PROGRESS(1), + SUBMITTED(2), + UNDER_REVIEW(3), + NEEDS_CORRECTIONS(4), + CORRECTIONS_RECIEVED(5), + WAITING_ON_REQUIREMENTS(6), + APPROVED(7), + PENDING_PUBLICATION(8), + PUBLISHED(9), + ON_HOLD(10), + WITHDRAWN(11), + CANCELED(12); - public int getValue() { + private int value; + + SubmissionState(int value) { + this.value = value; + } + + public int getValue() { return value; } @@ -25,8 +29,25 @@ public int getValue() { public String toString() { return this.name(); } - - SubmissionState(int value) { - this.value = value; + + public static SubmissionState from(int value) { + switch (value) { + case 0: return SubmissionState.NONE; + case 1: return SubmissionState.IN_PROGRESS; + case 2: return SubmissionState.SUBMITTED; + case 3: return SubmissionState.UNDER_REVIEW; + case 4: return SubmissionState.NEEDS_CORRECTIONS; + case 5: return SubmissionState.CORRECTIONS_RECIEVED; + case 6: return SubmissionState.WAITING_ON_REQUIREMENTS; + case 7: return SubmissionState.APPROVED; + case 8: return SubmissionState.PENDING_PUBLICATION; + case 9: return SubmissionState.PUBLISHED; + case 10: return SubmissionState.ON_HOLD; + case 11: return SubmissionState.WITHDRAWN; + case 12: return SubmissionState.CANCELED; + default: + return SubmissionState.NONE; + } } + } diff --git a/src/main/java/org/tdl/vireo/model/SubmissionStatus.java b/src/main/java/org/tdl/vireo/model/SubmissionStatus.java index c174b28d04..ef54f27447 100644 --- a/src/main/java/org/tdl/vireo/model/SubmissionStatus.java +++ b/src/main/java/org/tdl/vireo/model/SubmissionStatus.java @@ -22,10 +22,11 @@ import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import edu.tamu.weaver.data.resolver.BaseEntityIdResolver; import edu.tamu.weaver.validation.model.ValidatingBaseEntity; @Entity -@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" }) +@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" }) public class SubmissionStatus extends ValidatingBaseEntity { @JsonView(Views.SubmissionList.class) @@ -67,7 +68,7 @@ public class SubmissionStatus extends ValidatingBaseEntity { private SubmissionState submissionState; @ManyToMany(cascade = { DETACH, REFRESH, MERGE }, fetch = EAGER) - @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, scope = SubmissionStatus.class, property = "id") + @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, scope = SubmissionStatus.class, resolver = BaseEntityIdResolver.class, property = "id") @JsonIdentityReference(alwaysAsId = true) private List transitionSubmissionStatuses; diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 401b0c5285..5851fa4ff6 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -4,10 +4,8 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -38,6 +36,7 @@ import org.tdl.vireo.model.OrganizationCategory; import org.tdl.vireo.model.Sort; import org.tdl.vireo.model.SubmissionListColumn; +import org.tdl.vireo.model.SubmissionState; import org.tdl.vireo.model.SubmissionStatus; import org.tdl.vireo.model.VocabularyWord; import org.tdl.vireo.model.WorkflowStep; @@ -73,9 +72,9 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.CollectionType; -import com.fasterxml.jackson.databind.type.TypeFactory; +import com.fasterxml.jackson.databind.node.ArrayNode; /** * This class is to load and persist system data from resources. @@ -477,69 +476,44 @@ private void loadEmbargos() { } private void loadSubmissionStatuses() { - try { - InputStream statusesInputStream = getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Statuses.json"); - InputStream transitionsInputStream = getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json"); - - // read and map json to SubmissionStatus - TypeFactory tf = TypeFactory.defaultInstance(); - CollectionType type = tf.constructCollectionType(ArrayList.class, SubmissionStatus.class); - List systemSubmissionStatuses = objectMapper.readValue(statusesInputStream, type); - - systemSubmissionStatuses.forEach(ss -> { - SubmissionStatus found = submissionStatusRepo.findByName(ss.getName()); - - if (found == null) { - ss.setTransitionSubmissionStatuses(new ArrayList<>()); - found = submissionStatusRepo.create(ss.getName(), ss.isArchived(), ss.isPublishable(), ss.isDeletable(), ss.isEditableByReviewer(), ss.isEditableByStudent(), ss.isActive(), ss.getSubmissionState()); - } - }); - - type = tf.constructCollectionType(ArrayList.class, HashMap.class); - List> transitions = objectMapper.readValue(transitionsInputStream, type); - for (Map transition : transitions) { - List list = new ArrayList<>(); - Long transitionId = ((Integer) transition.get("id")).longValue(); - SubmissionStatus ss = submissionStatusRepo.findById(transitionId).get(); + try { + // read System Submission Status as JsonNode + JsonNode systemSubmissionStatus = objectMapper.readTree(getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Status.json")); - for (Object idObject : (ArrayList) transition.get("transitionSubmissionStatuses")) { - Long id = ((Integer) idObject).longValue(); - Optional submissionStatus = submissionStatusRepo.findById(id); - if (submissionStatus.isPresent()) { - list.add(submissionStatus.get()); - } - } + // check to see if the SubmissionStatus exists + SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(systemSubmissionStatus.get("name").asText()); - ss.setTransitionSubmissionStatuses(list); - submissionStatusRepo.save(ss); + // recursively find or create new SubmissionStatus if not already exists + if (newSubmissionStatus == null) { + recursivelyFindOrCreateSubmissionStatus(systemSubmissionStatus); } + } catch (IOException e) { - throw new IllegalStateException("Unable to generate system organization", e); + throw new IllegalStateException("Unable to generate system submission status", e); } } - private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(SubmissionStatus submissionStatus) { + private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(JsonNode submissionStatus) { // check to see if the SubmissionStatus exists - SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(submissionStatus.getName()); + SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(submissionStatus.get("name").asText()); // create new SubmissionStatus if not already exists if (newSubmissionStatus == null) { - newSubmissionStatus = submissionStatusRepo.create(submissionStatus.getName(), submissionStatus.isArchived(), submissionStatus.isPublishable(), submissionStatus.isDeletable(), submissionStatus.isEditableByReviewer(), submissionStatus.isEditableByStudent(), submissionStatus.isActive(), submissionStatus.getSubmissionState()); + newSubmissionStatus = createSubmissionStatus(submissionStatus); } - // temporary list of SubmissionState + // temporary list of transition SubmissionState List transitionStatuses = new ArrayList(); - submissionStatus.getTransitionSubmissionStatuses().forEach(transitionStatus -> { + ((ArrayNode) submissionStatus.get("transitionSubmissionStatuses")).forEach(transitionStatus -> { // check to see if the Transistion SubmissionStatus exists - SubmissionStatus newTransitionStatus = submissionStatusRepo.findByName(transitionStatus.getName()); + SubmissionStatus newTransitionStatus = submissionStatusRepo.findByName(transitionStatus.get("name").asText()); // create new Transistion SubmissionStatus if not already exists if (newTransitionStatus == null) { - newTransitionStatus = submissionStatusRepo.create(transitionStatus.getName(), transitionStatus.isArchived(), transitionStatus.isPublishable(), transitionStatus.isDeletable(), transitionStatus.isEditableByReviewer(), transitionStatus.isEditableByStudent(), transitionStatus.isActive(), transitionStatus.getSubmissionState()); - newTransitionStatus = submissionStatusRepo.save(recursivelyFindOrCreateSubmissionStatus(transitionStatus)); + newTransitionStatus = recursivelyFindOrCreateSubmissionStatus(transitionStatus); } transitionStatuses.add(newTransitionStatus); @@ -551,6 +525,19 @@ private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(SubmissionStatu return submissionStatusRepo.save(newSubmissionStatus); } + private SubmissionStatus createSubmissionStatus(JsonNode submissionStatus) { + return submissionStatusRepo.create( + submissionStatus.get("name").asText(), + submissionStatus.get("isArchived").asBoolean(), + submissionStatus.get("isPublishable").asBoolean(), + submissionStatus.get("isDeletable").asBoolean(), + submissionStatus.get("isEditableByReviewer").asBoolean(), + submissionStatus.get("isEditableByStudent").asBoolean(), + submissionStatus.get("isActive").asBoolean(), + SubmissionState.from(submissionStatus.get("submissionState").asInt()) + ); + } + private void loadOrganizationCategories() { try { @@ -746,9 +733,7 @@ private void processEmailWorflowRules(Organization organization, Organization sy // create new SubmissionStatus if not already exists if (newSubmissionStatus == null) { - newSubmissionStatus = submissionStatusRepo.create(emailWorkflowRule.getSubmissionStatus().getName(), emailWorkflowRule.getSubmissionStatus().isArchived(), emailWorkflowRule.getSubmissionStatus().isPublishable(), emailWorkflowRule.getSubmissionStatus().isDeletable(), emailWorkflowRule.getSubmissionStatus().isEditableByReviewer(), emailWorkflowRule.getSubmissionStatus().isEditableByStudent(), emailWorkflowRule.getSubmissionStatus().isActive(), - emailWorkflowRule.getSubmissionStatus().getSubmissionState()); - newSubmissionStatus = submissionStatusRepo.save(recursivelyFindOrCreateSubmissionStatus(emailWorkflowRule.getSubmissionStatus())); + throw new RuntimeException("No submission status found with name " + emailWorkflowRule.getSubmissionStatus().getName()); } // check to see if the EmailTemplate exists diff --git a/src/main/resources/submission_statuses/SYSTEM_Submission_Status.json b/src/main/resources/submission_statuses/SYSTEM_Submission_Status.json new file mode 100644 index 0000000000..4cf6646c6c --- /dev/null +++ b/src/main/resources/submission_statuses/SYSTEM_Submission_Status.json @@ -0,0 +1,159 @@ +{ + "name": "In Progress", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": false, + "isEditableByStudent": false, + "isActive": null, + "submissionState": 1, + "transitionSubmissionStatuses": [ + { + "name": "Submitted", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": true, + "submissionState": 2, + "transitionSubmissionStatuses": [ + { + "name": "Under Review", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": true, + "submissionState": 3, + "transitionSubmissionStatuses": [ + { + "name": "Needs Correction", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": true, + "isActive": true, + "submissionState": 4, + "transitionSubmissionStatuses": [ + { + "name": "Corrections Received", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": true, + "submissionState": 5, + "transitionSubmissionStatuses": [ + { + "name": "Under Review" + }, + { + "name": "Waiting On Requirements", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": true, + "submissionState": 6, + "transitionSubmissionStatuses": [ + { + "name": "Under Review" + }, + { + "name": "Approved", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": true, + "submissionState": 7, + "transitionSubmissionStatuses": [ + { + "name": "Pending Publication", + "isArchived": true, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": false, + "submissionState": 8, + "transitionSubmissionStatuses": [ + { + "name": "Published", + "isArchived": true, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": false, + "submissionState": 9, + "transitionSubmissionStatuses": [ + { + "name": "Pending Publication" + } + ] + } + ] + } + ] + } + ] + }, + { + "name": "Approved" + } + ] + } + ] + }, + { + "name": "Waiting On Requirements" + }, + { + "name": "Approved" + } + ] + } + ] + }, + { + "name": "On Hold", + "isArchived": false, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": true, + "submissionState": 10, + "transitionSubmissionStatuses": [] + }, + { + "name": "Withdrawn", + "isArchived": true, + "isPublishable": false, + "isDeletable": false, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": false, + "submissionState": 11, + "transitionSubmissionStatuses": [] + }, + { + "name": "Cancelled", + "isArchived": true, + "isPublishable": false, + "isDeletable": true, + "isEditableByReviewer": true, + "isEditableByStudent": false, + "isActive": false, + "submissionState": 12, + "transitionSubmissionStatuses": [] + } + ] +} diff --git a/src/main/resources/submission_statuses/SYSTEM_Submission_Statuses.json b/src/main/resources/submission_statuses/SYSTEM_Submission_Statuses.json deleted file mode 100644 index 7268644a6f..0000000000 --- a/src/main/resources/submission_statuses/SYSTEM_Submission_Statuses.json +++ /dev/null @@ -1,146 +0,0 @@ -[ - { - "id": 1, - "name": "In Progress", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": false, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 1, - "transitionSubmissionStatuses": [] - }, - { - "id": 2, - "name": "Submitted", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 2, - "transitionSubmissionStatuses": [] - }, - { - "id": 3, - "name": "Under Review", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 3, - "transitionSubmissionStatuses": [] - }, - { - "id": 4, - "name": "Needs Correction", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": true, - "isActive": true, - "submissionState": 4, - "transitionSubmissionStatuses": [] - }, - { - "id": 5, - "name": "Corrections Received", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 5, - "transitionSubmissionStatuses": [] - }, - { - "id": 6, - "name": "Waiting On Requirements", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 6, - "transitionSubmissionStatuses": [] - }, - { - "id": 7, - "name": "Approved", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 7, - "transitionSubmissionStatuses": [] - }, - { - "id": 8, - "name": "Pending Publication", - "isArchived": true, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": false, - "submissionState": 8, - "transitionSubmissionStatuses": [] - }, - { - "id": 9, - "name": "Published", - "isArchived": true, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": false, - "submissionState": 9, - "transitionSubmissionStatuses": [] - }, - { - "id": 10, - "name": "On Hold", - "isArchived": false, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": true, - "submissionState": 10, - "transitionSubmissionStatuses": [] - }, - { - "id": 11, - "name": "Withdrawn", - "isArchived": true, - "isPublishable": false, - "isDeletable": false, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": false, - "submissionState": 11, - "transitionSubmissionStatuses": [] - }, - { - "id": 12, - "name": "Cancelled", - "isArchived": true, - "isPublishable": false, - "isDeletable": true, - "isEditableByReviewer": true, - "isEditableByStudent": false, - "isActive": false, - "submissionState": 12, - "transitionSubmissionStatuses": [] - } -] diff --git a/src/main/resources/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json b/src/main/resources/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json deleted file mode 100644 index 6f1d75f465..0000000000 --- a/src/main/resources/submission_statuses/SYSTEM_Submission_Statuses_Transitions.json +++ /dev/null @@ -1,79 +0,0 @@ -[ - { - "id": 1, - "transitionSubmissionStatuses": [ - 2, - 10, - 11, - 12 - ] - }, - { - "id": 2, - "transitionSubmissionStatuses": [ - 3 - ] - }, - { - "id": 3, - "transitionSubmissionStatuses": [ - 4, - 6, - 7 - ] - }, - { - "id": 4, - "transitionSubmissionStatuses": [ - 5 - ] - }, - { - "id": 5, - "transitionSubmissionStatuses": [ - 3, - 6, - 7 - ] - }, - { - "id": 6, - "transitionSubmissionStatuses": [ - 3, - 7 - ] - }, - { - "id": 7, - "transitionSubmissionStatuses": [ - 8 - ] - }, - { - "id": 8, - "transitionSubmissionStatuses": [ - 9 - ] - }, - { - "id": 9, - "transitionSubmissionStatuses": [ - 8 - ] - }, - { - "id": 10, - "transitionSubmissionStatuses": [ - ] - }, - { - "id": 11, - "transitionSubmissionStatuses": [ - ] - }, - { - "id": 12, - "transitionSubmissionStatuses": [ - ] - } -] From 3abc1d0e3f208cd9ec6f70a609e32766c8504df8 Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 19:48:16 -0600 Subject: [PATCH 27/48] Use field profile heritable repo delete and remove orphaned submission list column - issue 1876 --- .../controller/WorkflowStepController.java | 36 +++-- .../model/repo/impl/FieldProfileRepoImpl.java | 10 ++ .../WorkflowStepControllerTest.java | 8 +- .../EmailWorkflowRulesIntegrationTest.java | 3 +- .../WorkflowStepIntegrationTest.java | 145 ++++++++++++++++++ 5 files changed, 184 insertions(+), 18 deletions(-) create mode 100644 src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java diff --git a/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java b/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java index dc07bfbfe2..1322b318bf 100644 --- a/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java +++ b/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java @@ -74,9 +74,9 @@ public ApiResponse createFieldProfile(@PathVariable Long requestingOrgId, @PathV if (!requestingOrganization.getId().equals(workflowStep.getOriginatingOrganization().getId())) { workflowStep = workflowStepRepo.update(workflowStep, requestingOrganization); } - fieldProfileRepo.create(workflowStep, fieldProfile.getFieldPredicate(), fieldProfile.getInputType(), fieldProfile.getUsage(), fieldProfile.getHelp(), fieldProfile.getGloss(), fieldProfile.getRepeatable(), fieldProfile.getOverrideable(), fieldProfile.getEnabled(), fieldProfile.getOptional(), fieldProfile.getFlagged(), fieldProfile.getLogged(), fieldProfile.getControlledVocabulary(), fieldProfile.getDefaultValue()); + FieldProfile fp = fieldProfileRepo.create(workflowStep, fieldProfile.getFieldPredicate(), fieldProfile.getInputType(), fieldProfile.getUsage(), fieldProfile.getHelp(), fieldProfile.getGloss(), fieldProfile.getRepeatable(), fieldProfile.getOverrideable(), fieldProfile.getEnabled(), fieldProfile.getOptional(), fieldProfile.getFlagged(), fieldProfile.getLogged(), fieldProfile.getControlledVocabulary(), fieldProfile.getDefaultValue()); organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); - return new ApiResponse(SUCCESS); + return new ApiResponse(SUCCESS, fp); } @RequestMapping(value = "/{requestingOrgId}/{workflowStepId}/update-field-profile", method = RequestMethod.POST) @@ -96,20 +96,35 @@ public ApiResponse updateFieldProfile(@PathVariable Long requestingOrgId, @PathV return new ApiResponse(SUCCESS); } + @Deprecated @RequestMapping(value = "/{requestingOrgId}/{workflowStepId}/remove-field-profile", method = RequestMethod.POST) @PreAuthorize("hasRole('MANAGER')") @WeaverValidation(business = { @WeaverValidation.Business(value = DELETE) }) public ApiResponse removeFieldProfile(@PathVariable Long requestingOrgId, @PathVariable Long workflowStepId, @WeaverValidatedModel FieldProfile fieldProfile) throws WorkflowStepNonOverrideableException, HeritableModelNonOverrideableException, ComponentNotPresentOnOrgException { - WorkflowStep workflowStep = workflowStepRepo.findById(workflowStepId).get(); + Optional organization = organizationRepo.findById(requestingOrgId); + + if (organization.isEmpty()) { + return new ApiResponse(ERROR, "Cannot delete Field Profile, the given Organization is unknown."); + } + + Optional workflowStep = workflowStepRepo.findById(workflowStepId); + + if (workflowStep.isEmpty()) { + return new ApiResponse(ERROR, "Cannot delete Field Profile, the given Workflow Step is unknown."); + } + FieldProfile persistedFieldProfile = fieldProfileRepo.findById(fieldProfile.getId()).get(); - fieldProfileRepo.removeFromWorkflowStep(organizationRepo.findById(requestingOrgId).get(), workflowStep, persistedFieldProfile); + + fieldProfileRepo.removeFromWorkflowStep(organization.get(), workflowStep.get(), persistedFieldProfile); + // If the field profile is being removed from its originating workflow step by the organization that originates that step, then it should be deleted. - if (persistedFieldProfile.getOriginatingWorkflowStep().getId().equals(workflowStep.getId()) && workflowStep.getOriginatingOrganization().getId().equals(requestingOrgId)) { + if (persistedFieldProfile.getOriginatingWorkflowStep().getId().equals(workflowStep.get().getId()) && workflowStep.get().getOriginatingOrganization().getId().equals(requestingOrgId)) { fieldProfileRepo.delete(persistedFieldProfile); + } else { + // only broadcast when not deleting field profile as it broadcasts ordered organizations + organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); } - organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); - return new ApiResponse(SUCCESS); } @@ -138,11 +153,12 @@ public ApiResponse removeFieldProfileById(@PathVariable Long requestingOrgId, @P // If the field profile is being removed from its originating workflow step by the organization that originates that step, then it should be deleted. if (fieldProfile.get().getOriginatingWorkflowStep().getId().equals(workflowStepId) && workflowStep.get().getOriginatingOrganization().getId().equals(requestingOrgId)) { - fieldProfileRepo.deleteById(fieldProfileId); + fieldProfileRepo.delete(fieldProfile.get()); + } else { + // only broadcast when not deleting field profile as it broadcasts ordered organizations + organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); } - organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); - return new ApiResponse(SUCCESS); } diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java index febeb2311e..e25aef0519 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java @@ -69,6 +69,16 @@ public FieldProfile create(WorkflowStep originatingWorkflowStep, FieldPredicate return newFieldProfile(originatingWorkflowStep, fieldPredicate, inputType, usage, help, gloss, repeatable, overrideable, enabled, optional, hidden, flagged, logged, controlledVocabulary, mappedShibAttribute, defaultValue); } + @Override + @Transactional + public void delete(FieldProfile fieldProfile) { + super.delete(fieldProfile); + Optional slc = submissionListColumnRepo.findByTitleAndPredicateAndInputType(fieldProfile.getGloss(), fieldProfile.getFieldPredicate().getValue(), fieldProfile.getInputType()); + if (slc.isPresent()) { + submissionListColumnRepo.delete(slc.get()); + } + } + private synchronized FieldProfile newFieldProfile(WorkflowStep originatingWorkflowStep, FieldPredicate fieldPredicate, InputType inputType, String usage, String help, String gloss, Boolean repeatable, Boolean overrideable, Boolean enabled, Boolean optional, Boolean hidden, Boolean flagged, Boolean logged, ControlledVocabulary controlledVocabulary, ManagedConfiguration mappedShibAttribute, String defaultValue) { FieldProfile fieldProfile = fieldProfileRepo.save(new FieldProfile(originatingWorkflowStep, fieldPredicate, inputType, usage, help, gloss, repeatable, overrideable, enabled, optional, hidden, flagged, logged, controlledVocabulary, mappedShibAttribute, defaultValue)); originatingWorkflowStep.addOriginalFieldProfile(fieldProfile); diff --git a/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java b/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java index f4ab1d899d..ccfc6b859b 100644 --- a/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java @@ -228,8 +228,6 @@ public void testRemoveFieldProfile() throws JsonProcessingException, WorkflowSte when(workflowStepRepo.findById(any(Long.class))).thenReturn(Optional.of(workflowStep1)); when(fieldProfileRepo.findById(any(Long.class))).thenReturn(Optional.of(fieldProfile1)); doNothing().when(fieldProfileRepo).removeFromWorkflowStep(any(Organization.class), any(WorkflowStep.class), any(FieldProfile.class)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); ApiResponse response = fieldPredicateController.removeFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -254,8 +252,6 @@ public void testRemoveFieldProfileById() throws JsonProcessingException, Workflo when(workflowStepRepo.findById(any(Long.class))).thenReturn(Optional.of(workflowStep1)); when(fieldProfileRepo.findById(any(Long.class))).thenReturn(Optional.of(fieldProfile1)); doNothing().when(fieldProfileRepo).removeFromWorkflowStep(any(Organization.class), any(WorkflowStep.class), any(FieldProfile.class)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); ApiResponse response = fieldPredicateController.removeFieldProfileById(organization1.getId(), workflowStep1.getId(), fieldProfile1.getId()); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -270,9 +266,7 @@ public void testRemoveFieldProfileWithMatchingOriginatingWorkflowStep() throws J when(workflowStepRepo.findById(any(Long.class))).thenReturn(Optional.of(workflowStep1)); when(fieldProfileRepo.findById(any(Long.class))).thenReturn(Optional.of(fieldProfile1)); doNothing().when(fieldProfileRepo).removeFromWorkflowStep(any(Organization.class), any(WorkflowStep.class), any(FieldProfile.class)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(fieldProfileRepo).deleteById(anyLong()); - doNothing().when(organizationRepo).broadcast(anyList()); + doNothing().when(fieldProfileRepo).delete(any(FieldProfile.class)); ApiResponse response = fieldPredicateController.removeFieldProfileById(organization1.getId(), workflowStep1.getId(), fieldProfile1.getId()); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); diff --git a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java index 5f18cdee00..ec68f79453 100644 --- a/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/EmailWorkflowRulesIntegrationTest.java @@ -89,7 +89,8 @@ public void testEmailWorkflowRulePersistenceUponReload() throws Exception { assertEquals(3, org.getEmailWorkflowRules().size()); - this.setup(); + // reload system data + systemDataLoader.loadSystemData(); EmailWorkflowRule newWorkflowRule = emailWorkflowRuleRepo.getById(newlyCreatedEmailWorkflowRuleId); assertNotNull(newWorkflowRule); diff --git a/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java new file mode 100644 index 0000000000..e623ae793e --- /dev/null +++ b/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java @@ -0,0 +1,145 @@ +package org.tdl.vireo.integration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.tdl.vireo.model.FieldPredicate; +import org.tdl.vireo.model.FieldProfile; +import org.tdl.vireo.model.InputType; +import org.tdl.vireo.model.Organization; +import org.tdl.vireo.model.WorkflowStep; +import org.tdl.vireo.model.repo.FieldPredicateRepo; +import org.tdl.vireo.model.repo.FieldProfileRepo; +import org.tdl.vireo.model.repo.InputTypeRepo; +import org.tdl.vireo.model.repo.OrganizationRepo; +import org.tdl.vireo.model.repo.SubmissionListColumnRepo; + +import com.fasterxml.jackson.databind.JsonNode; + +public class WorkflowStepIntegrationTest extends AbstractIntegrationTest { + + @Autowired + private InputTypeRepo inputTypeRepo; + + @Autowired + private OrganizationRepo organizationRepo; + + @Autowired + private FieldPredicateRepo fieldPredicateRepo; + + @Autowired + private FieldProfileRepo fieldProfileRepo; + + @Autowired + private SubmissionListColumnRepo submissionListColumnRepo; + + @BeforeEach + public void setup() throws Exception { + // takes a long time, try not to add more tests in this class or switch to static @BeforeAll + systemDataLoader.loadSystemData(); + + entityControlledVocabularyService.scanForEntityControlledVocabularies(); + + mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); + } + + @Test + @WithMockUser(roles = { "MANAGER" }) + public void testSubmissionListColumnRemovedWhenRemovingFieldProfileFromWorkflowStep() throws Exception { + Organization org = organizationRepo.findAll().get(0); + + assertEquals(4, org.getAggregateWorkflowSteps().size()); + + WorkflowStep workflowStep = org.getAggregateWorkflowSteps().get(0); + + assertEquals(18, workflowStep.getAggregateFieldProfiles().size()); + + InputType inputType = inputTypeRepo.findByName("INPUT_TEXT"); + + assertNotNull(inputType.getName()); + + long initialFieldPredicateCount = fieldPredicateRepo.count(); + long initialFieldProfileCount = fieldProfileRepo.count(); + long initialSubmissionListColumnCount = submissionListColumnRepo.count(); + + Long orgId = org.getId(); + Long wsId = workflowStep.getId(); + + + // create field predicate + + FieldPredicate fieldPredicate = new FieldPredicate("test", false); + + MvcResult results = mockMvc.perform(post("/settings/field-predicates/create") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.convertValue(fieldPredicate, JsonNode.class).toString().getBytes("utf-8"))) + .andExpect(status().isOk()).andExpect(jsonPath("$.meta.status").value("SUCCESS")) + .andExpect(jsonPath("$.payload.FieldPredicate").exists()) + .andExpect(jsonPath("$.payload.FieldPredicate.id").isNumber()) + .andExpect(jsonPath("$.payload.FieldPredicate.value").value("test")) + .andReturn(); + + Long fieldPredicateId = objectMapper.readTree(results.getResponse().getContentAsString()) + .get("payload") + .get("FieldPredicate") + .get("id") + .asLong(); + + fieldPredicate.setId(fieldPredicateId); + + assertEquals(initialFieldPredicateCount + 1, fieldPredicateRepo.count()); + assertTrue(fieldPredicateRepo.existsById(fieldPredicateId)); + + // add field profile to workflow step + + FieldProfile fieldProfile = new FieldProfile(workflowStep, fieldPredicate, inputType, "Test", false, true, true, false, false, false, null); + + results = mockMvc.perform(post("/workflow-step/{requestingOrgId}/{workflowStepId}/add-field-profile", orgId, wsId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.convertValue(fieldProfile, JsonNode.class).toString().getBytes("utf-8"))) + .andExpect(status().isOk()).andExpect(jsonPath("$.meta.status").value("SUCCESS")) + .andExpect(jsonPath("$.payload.FieldProfile").exists()) + .andExpect(jsonPath("$.payload.FieldProfile.id").isNumber()) + .andExpect(jsonPath("$.payload.FieldProfile.gloss").value("Test")) + .andReturn(); + + Long fpId = objectMapper.readTree(results.getResponse().getContentAsString()) + .get("payload") + .get("FieldProfile") + .get("id") + .asLong(); + + assertEquals(initialFieldProfileCount + 1, fieldProfileRepo.count()); + assertTrue(fieldProfileRepo.existsById(fpId)); + + assertEquals(initialSubmissionListColumnCount + 1, submissionListColumnRepo.count()); + assertNotNull(submissionListColumnRepo.findByTitle("Test")); + + // remove field profile and assert submission list column not orphaned + + mockMvc.perform(post("/workflow-step/{requestingOrgId}/{workflowStepId}/remove-field-profile/{fieldProfileId}", orgId, wsId, fpId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.convertValue(fieldProfile, JsonNode.class).toString().getBytes("utf-8"))) + .andExpect(status().isOk()).andExpect(jsonPath("$.meta.status").value("SUCCESS")); + + assertEquals(initialFieldProfileCount, fieldProfileRepo.count()); + assertFalse(fieldProfileRepo.existsById(fpId)); + + assertEquals(initialSubmissionListColumnCount, submissionListColumnRepo.count()); + assertNull(submissionListColumnRepo.findByTitle("Test")); + } + +} From 635cca0c8fedec9cf5159485fdcb7fa5b4547dbf Mon Sep 17 00:00:00 2001 From: William Welling Date: Thu, 28 Dec 2023 22:57:17 -0600 Subject: [PATCH 28/48] Keyboard accessible organization triptych --- src/main/webapp/app/views/directives/triptych.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/views/directives/triptych.html b/src/main/webapp/app/views/directives/triptych.html index 7eec327419..a648dc4dea 100644 --- a/src/main/webapp/app/views/directives/triptych.html +++ b/src/main/webapp/app/views/directives/triptych.html @@ -37,8 +37,9 @@

{{attr.header}}

  • + ng-focus="selectOrganization(organization)" + ng-class="{'selected': panel.selected.organization.id == organization.id}" + tabindex="0">
    • From bfa6f926bda859aac428b7a5c8bc9ea021f97771 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 09:54:30 -0600 Subject: [PATCH 29/48] Use test resources and ignore environment specific config files --- .gitignore | 4 ++++ src/main/webapp/META-INF/context.xml | 2 +- .../resources/config/application.yml} | 4 +--- src/test/resources/{logback-test.xml => logback.xml} | 0 4 files changed, 6 insertions(+), 4 deletions(-) rename src/{main/resources/application-test.yml => test/resources/config/application.yml} (90%) rename src/test/resources/{logback-test.xml => logback.xml} (100%) diff --git a/.gitignore b/.gitignore index 17eca5e0b1..047fb79b21 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,7 @@ dist/ !**/src/test/** *.mv.db + +### Environment Specific ### +application-*.yml +logback-*.yml diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml index cfad55a68a..1c03c94dd7 100644 --- a/src/main/webapp/META-INF/context.xml +++ b/src/main/webapp/META-INF/context.xml @@ -1,4 +1,4 @@ - \ No newline at end of file + diff --git a/src/main/resources/application-test.yml b/src/test/resources/config/application.yml similarity index 90% rename from src/main/resources/application-test.yml rename to src/test/resources/config/application.yml index 70d002a31b..a079515a64 100644 --- a/src/main/resources/application-test.yml +++ b/src/test/resources/config/application.yml @@ -1,6 +1,4 @@ spring: - config: - import: file:src/main/resources/application.yml sql: init: platform: h2 @@ -13,7 +11,7 @@ spring: database-platform: org.hibernate.dialect.H2Dialect hibernate.ddl-auto: create-drop -# logging (is overwritten by logback-test.xml) +# logging (is overwritten by src/test/resources/logback.xml) logging: level: com.zaxxer: ERROR diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback.xml similarity index 100% rename from src/test/resources/logback-test.xml rename to src/test/resources/logback.xml From a51c6dedacab881719c0413e36fcc63533af6458 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 09:55:38 -0600 Subject: [PATCH 30/48] Print internal server error stack trace in debug --- src/main/java/org/tdl/vireo/controller/UserController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/controller/UserController.java b/src/main/java/org/tdl/vireo/controller/UserController.java index cd27b574b9..486a84f2f0 100644 --- a/src/main/java/org/tdl/vireo/controller/UserController.java +++ b/src/main/java/org/tdl/vireo/controller/UserController.java @@ -188,7 +188,8 @@ public ApiResponse updateSetting(@WeaverUser User user, @RequestBody Map Date: Fri, 29 Dec 2023 09:55:55 -0600 Subject: [PATCH 31/48] Switch to release of weaver and and compiler release property --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aef8ab23fd..be9de29703 100644 --- a/pom.xml +++ b/pom.xml @@ -20,12 +20,13 @@ edu.tamu.weaver webservice-parent - 2.1.1-RC19 + 2.1.1 11 + ${java.version} ${java.version} ${java.version} UTF-8 From d1a6ac1366cad60dab35f43b645153b6b8a71136 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 10:29:26 -0600 Subject: [PATCH 32/48] Remove overriding exception handlers causing all exceptions to be 500 responses --- .../controller/SubmissionController.java | 36 ++++++++----------- .../tdl/vireo/controller/UserController.java | 14 -------- .../CustomResponseEntityExceptionHandler.java | 28 +++++++++++++-- .../vireo/controller/UserControllerTest.java | 18 +++------- 4 files changed, 45 insertions(+), 51 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/SubmissionController.java b/src/main/java/org/tdl/vireo/controller/SubmissionController.java index 5ee324da76..58b9a0efab 100644 --- a/src/main/java/org/tdl/vireo/controller/SubmissionController.java +++ b/src/main/java/org/tdl/vireo/controller/SubmissionController.java @@ -4,16 +4,6 @@ import static edu.tamu.weaver.response.ApiStatus.INVALID; import static edu.tamu.weaver.response.ApiStatus.SUCCESS; -import com.fasterxml.jackson.annotation.JsonView; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.tamu.weaver.auth.annotation.WeaverCredentials; -import edu.tamu.weaver.auth.annotation.WeaverUser; -import edu.tamu.weaver.auth.model.Credentials; -import edu.tamu.weaver.data.model.ApiPage; -import edu.tamu.weaver.response.ApiResponse; -import edu.tamu.weaver.validation.results.ValidationResults; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -33,8 +23,10 @@ import java.util.concurrent.ExecutionException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; + import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.poi.hssf.usermodel.HSSFRow; @@ -49,11 +41,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.web.PageableDefault; -import org.springframework.http.HttpStatus; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -61,8 +51,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.tdl.vireo.exception.DepositException; @@ -102,6 +90,18 @@ import org.tdl.vireo.utility.TemplateUtility; import org.tdl.vireo.view.FieldValueSubmissionView; +import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import edu.tamu.weaver.auth.annotation.WeaverCredentials; +import edu.tamu.weaver.auth.annotation.WeaverUser; +import edu.tamu.weaver.auth.model.Credentials; +import edu.tamu.weaver.data.model.ApiPage; +import edu.tamu.weaver.response.ApiResponse; +import edu.tamu.weaver.validation.results.ValidationResults; + @RestController @RequestMapping("/submission") public class SubmissionController { @@ -1113,12 +1113,4 @@ private void processAdvisorStatusClear(String type, Boolean approvalState, Submi actionLogRepo.createAdvisorPublicLog(submission, clearAdvisorMessage); } - @ExceptionHandler(Exception.class) - @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) - @ResponseBody - public ApiResponse handleExceptions(Exception exception) { - LOG.error(exception.getMessage(), exception); - return new ApiResponse(ERROR, exception.getMessage()); - } - } diff --git a/src/main/java/org/tdl/vireo/controller/UserController.java b/src/main/java/org/tdl/vireo/controller/UserController.java index 486a84f2f0..f0aecdef0a 100644 --- a/src/main/java/org/tdl/vireo/controller/UserController.java +++ b/src/main/java/org/tdl/vireo/controller/UserController.java @@ -1,6 +1,5 @@ package org.tdl.vireo.controller; -import static edu.tamu.weaver.response.ApiStatus.ERROR; import static edu.tamu.weaver.response.ApiStatus.SUCCESS; import static edu.tamu.weaver.validation.model.BusinessValidationType.UPDATE; import static org.springframework.beans.BeanUtils.copyProperties; @@ -17,16 +16,12 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.web.PageableDefault; -import org.springframework.http.HttpStatus; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.tdl.vireo.model.Role; import org.tdl.vireo.model.User; @@ -184,13 +179,4 @@ public ApiResponse updateSetting(@WeaverUser User user, @RequestBody Map Date: Fri, 29 Dec 2023 11:47:54 -0600 Subject: [PATCH 33/48] Move modal service to app to fix close modal - issue 1682 These changes can be undone if and when https://github.com/TAMULib/Weaver-UI-Core/pull/241 is approved, merged, and released. --- .wvr/build-config.js | 2 +- src/main/webapp/app/services/modalService.js | 47 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/main/webapp/app/services/modalService.js diff --git a/.wvr/build-config.js b/.wvr/build-config.js index 2c3b7708d5..6556e2f0c7 100644 --- a/.wvr/build-config.js +++ b/.wvr/build-config.js @@ -99,7 +99,7 @@ const config = { './node_modules/@wvr/core/app/services/alertService.js', './node_modules/@wvr/core/app/services/validationStore.js', './node_modules/@wvr/core/app/services/userService.js', - './node_modules/@wvr/core/app/services/modalService.js', + // './node_modules/@wvr/core/app/services/modalService.js', './node_modules/@wvr/core/app/services/modelCache.js', './node_modules/@wvr/core/app/services/modelUpdateService.js', './node_modules/@wvr/core/app/repo/abstractRepo.js', diff --git a/src/main/webapp/app/services/modalService.js b/src/main/webapp/app/services/modalService.js new file mode 100644 index 0000000000..17859af401 --- /dev/null +++ b/src/main/webapp/app/services/modalService.js @@ -0,0 +1,47 @@ +vireo.service("ModalService", function ($timeout) { + + var ModalService = this; + + var bodyElement = angular.element('body'); + + bodyElement.on('keydown', function (event) { + if (modalElement) { + if (event.code === 'Tab') { + $timeout(function () { + if (!modalElement.has(angular.element(':focus')).length) { + modalElement.find(':input:first').focus(); + } + }); + } else if (event.code === 'Escape') { + event.preventDefault(); + ModalService.closeModal(); + } + } + }); + + var modalElement; + + ModalService.openModal = function (id) { + modalElement = angular.element(id); + modalElement.modal('show'); + modalElement.on('shown.bs.modal', function (e) { + modalElement.find(':input:not(:button):visible:enabled:not([readonly]):first, :input:first').focus(); + }); + }; + + ModalService.closeModal = function () { + if (modalElement) { + modalElement.modal('hide'); + modalElement.off('shown.bs.modal'); + modalElement = undefined; + } + + // forcefully restore the body element + var body = angular.element('body'); + body.removeClass('modal-open'); + body.css('padding-right', ''); + }; + + return ModalService; + +}); From 56672ca09c9c7f636fc06b7b657bf7aabbc67d57 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 11:48:15 -0600 Subject: [PATCH 34/48] Remove unused dependency injection and scope variable --- src/main/webapp/app/controllers/abstractController.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/webapp/app/controllers/abstractController.js b/src/main/webapp/app/controllers/abstractController.js index 30fb931307..e4f591a848 100644 --- a/src/main/webapp/app/controllers/abstractController.js +++ b/src/main/webapp/app/controllers/abstractController.js @@ -1,9 +1,7 @@ -vireo.controller('AbstractController', function ($scope, $window, ModalService, StorageService, RestApi) { +vireo.controller('AbstractController', function ($scope, $window, ModalService, RestApi) { angular.extend($scope, ModalService); - $scope.modals = ModalService; - $scope.isAnonymous = function () { return sessionStorage.token === undefined || sessionStorage.role === appConfig.anonymousRole; }; From 4fc58ebf2d76e6e4322f363309e33510d1a96eb7 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 12:07:13 -0600 Subject: [PATCH 35/48] Close modal and wait before location change on submission delete This works okay but may have different experiences on different browsers. --- .../controllers/submission/adminSubmissionViewController.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/app/controllers/submission/adminSubmissionViewController.js b/src/main/webapp/app/controllers/submission/adminSubmissionViewController.js index 1f9ca1f9ba..139eedcedc 100644 --- a/src/main/webapp/app/controllers/submission/adminSubmissionViewController.js +++ b/src/main/webapp/app/controllers/submission/adminSubmissionViewController.js @@ -654,7 +654,10 @@ vireo.controller("AdminSubmissionViewController", function ($anchorScroll, $cont "deleteSubmission": function () { $scope.submission.delete().then(function () { $scope.submissionStatusBox.deleteWorking = false; - $location.path("/admin/list"); + $scope.closeModal(); + $timeout(function () { + $location.path("/admin/list"); + }, 250); }); }, "changeAssignee": function (assignee) { From 086d593519b756f9240065f166ba53555bdbc559 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 12:10:10 -0600 Subject: [PATCH 36/48] Remove modal backdrop manually - issue 1879 App ModelService can be removed and update .wvr/build-config.js to include @wvr/core ModelService if and when https://github.com/TAMULib/Weaver-UI-Core/pull/241 is approved, merged, and released. --- src/main/webapp/app/services/modalService.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/services/modalService.js b/src/main/webapp/app/services/modalService.js index 17859af401..eb308124f6 100644 --- a/src/main/webapp/app/services/modalService.js +++ b/src/main/webapp/app/services/modalService.js @@ -30,16 +30,21 @@ vireo.service("ModalService", function ($timeout) { }; ModalService.closeModal = function () { - if (modalElement) { + if (!!modalElement) { modalElement.modal('hide'); modalElement.off('shown.bs.modal'); modalElement = undefined; } // forcefully restore the body element - var body = angular.element('body'); - body.removeClass('modal-open'); - body.css('padding-right', ''); + bodyElement.removeClass('modal-open'); + bodyElement.css('padding-right', ''); + + // forcefully remove modal-backdrop div with + var backdropElement = angular.element('div.modal-backdrop'); + if (!!backdropElement) { + backdropElement.remove(); + } }; return ModalService; From 5d03e49d0abdb95c221a6a8221aba24170b84fe3 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 12:22:23 -0600 Subject: [PATCH 37/48] Update file upload to large message with max file size - issue 1883 --- .../advice/CustomResponseEntityExceptionHandler.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java b/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java index c7e7864470..f239d4deff 100644 --- a/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java +++ b/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java @@ -1,11 +1,13 @@ package org.tdl.vireo.controller.advice; import static edu.tamu.weaver.response.ApiStatus.ERROR; +import static java.lang.String.format; import javax.persistence.EntityNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -36,6 +38,11 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio private static final Logger logger = LoggerFactory.getLogger(CustomResponseEntityExceptionHandler.class); + private static final String PAYLOAD_TOO_LARGE_TEMPLATE = "File exceeds max size %s"; + + @Value("${spring.servlet.multipart.max-file-size:20MB}") + private String maxFileSize; + @ExceptionHandler(EntityNotFoundException.class) @ResponseStatus(value = HttpStatus.NOT_FOUND) @ResponseBody @@ -49,9 +56,10 @@ public ApiResponse handleEntityNotFoundException(EntityNotFoundException excepti @ResponseStatus(value = HttpStatus.PAYLOAD_TOO_LARGE) @ResponseBody public ApiResponse handleMultipartException(MultipartException exception) { + String message = format(PAYLOAD_TOO_LARGE_TEMPLATE, maxFileSize); logger.error(exception.getMessage()); - logger.debug("File size limit exceeded", exception); - return new ApiResponse(ERROR, "File size limit exceeded"); + logger.debug(message, exception); + return new ApiResponse(ERROR, message); } @ExceptionHandler(SwordDepositBadGatewayException.class) From 07e1d7ae393b69267850db0b6c274e36b518c509 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 12:27:53 -0600 Subject: [PATCH 38/48] Adjust line height of drop zone message --- src/main/webapp/app/resources/styles/sass/app.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/webapp/app/resources/styles/sass/app.scss b/src/main/webapp/app/resources/styles/sass/app.scss index efa7378053..26835eb8c2 100644 --- a/src/main/webapp/app/resources/styles/sass/app.scss +++ b/src/main/webapp/app/resources/styles/sass/app.scss @@ -717,6 +717,7 @@ h4 { color: #696969; border-radius: 5px; transition: all 0.35s ease-in; + line-height: 18px; } .upload-drop-zone.dragging-accept { From 33a88f73c906947990eabf5ac61c7578a9663d9d Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 12:46:51 -0600 Subject: [PATCH 39/48] Fix student submission select icon vertical centering --- .../styles/sass/views/submission/_studentSubmission.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss b/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss index 30e3dbd11a..ec2e637de0 100644 --- a/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss +++ b/src/main/webapp/app/resources/styles/sass/views/submission/_studentSubmission.scss @@ -139,6 +139,7 @@ display: flex; width: unset; min-height: 34px; + align-items: center; } .submission-input-select .btn-default.opaque { From 2452c217154a5aa4f45e6bb3340baaf4225f769d Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 12:58:45 -0600 Subject: [PATCH 40/48] Fix conditional textarea input template --- .../webapp/app/views/inputtype/input-conditional_textarea.html | 2 +- src/main/webapp/app/views/inputtype/input-textarea.html | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/views/inputtype/input-conditional_textarea.html b/src/main/webapp/app/views/inputtype/input-conditional_textarea.html index e894a13866..ae0f6c0f52 100644 --- a/src/main/webapp/app/views/inputtype/input-conditional_textarea.html +++ b/src/main/webapp/app/views/inputtype/input-conditional_textarea.html @@ -17,7 +17,7 @@ ng-required="!profile.optional" ng-model="fieldValue.value" ng-blur="saveConditionalTextArea(fieldValue)" - ng-disabled="fieldValue.updating" + ng-disabled="fieldValue.updating"> diff --git a/src/main/webapp/app/views/inputtype/input-textarea.html b/src/main/webapp/app/views/inputtype/input-textarea.html index a027a6d4ea..f81b248f69 100644 --- a/src/main/webapp/app/views/inputtype/input-textarea.html +++ b/src/main/webapp/app/views/inputtype/input-textarea.html @@ -4,7 +4,8 @@ ng-required="!profile.optional" ng-model="fieldValue.value" ng-blur="save(fieldValue)" - ng-disabled="fieldValue.updating"> + ng-disabled="fieldValue.updating"> + From fc8c0b078add5be1c12cb155d03f315358dbc054 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 14:33:21 -0600 Subject: [PATCH 41/48] Refactor test and test entity controlled vocabulary --- .../EntityControlledVocabularyService.java | 10 ++--- ...ava => ApplicationInitializationTest.java} | 45 ++++++++++++++++--- 2 files changed, 44 insertions(+), 11 deletions(-) rename src/test/java/org/tdl/vireo/{service/SystemDataLoaderTest.java => ApplicationInitializationTest.java} (66%) diff --git a/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java b/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java index d58d1a45fb..6f6b56eb0d 100644 --- a/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java +++ b/src/main/java/org/tdl/vireo/service/EntityControlledVocabularyService.java @@ -41,10 +41,10 @@ public EntityControlledVocabularyService() { entityControlledVocabularyRepos = new HashMap>(); } - @SuppressWarnings("unchecked") public void scanForEntityControlledVocabularies() throws ClassNotFoundException { for (String name : applicationContext.getBeanNamesForType(EntityControlledVocabularyRepo.class)) { Object bean = applicationContext.getBean(name); + @SuppressWarnings("unchecked") EntityControlledVocabularyRepo entityControlledVoabularyRepo = (EntityControlledVocabularyRepo) bean; String entityName = getEntity(entityControlledVoabularyRepo).getSimpleName(); List subsetAnnotations = getEntityControlledVocabularySubsets(entityControlledVoabularyRepo); @@ -96,7 +96,7 @@ public List getControlledVocabularyWords(String name) throws Cla return dictionary; } - public List getEntityControlledVocabularySubsets(EntityControlledVocabularyRepo repo) throws ClassNotFoundException { + private List getEntityControlledVocabularySubsets(EntityControlledVocabularyRepo repo) throws ClassNotFoundException { List subsets = new ArrayList(); EntityCV annotation = Class.forName(getGenericType(repo.getClass())[0].getTypeName()).getDeclaredAnnotation(EntityCV.class); if (annotation != null) { @@ -105,7 +105,7 @@ public List getEntityControlledVocabularySubsets(EntityControll return subsets; } - public Optional getEntityControlledVocabularyName(EntityControlledVocabularyRepo repo) throws ClassNotFoundException { + private Optional getEntityControlledVocabularyName(EntityControlledVocabularyRepo repo) throws ClassNotFoundException { Optional name = Optional.empty(); EntityCV annotation = Class.forName(getGenericType(repo.getClass())[0].getTypeName()).getDeclaredAnnotation(EntityCV.class); if (annotation != null) { @@ -116,13 +116,13 @@ public Optional getEntityControlledVocabularyName(EntityControlledVocabu return name; } - public Class getEntity(EntityControlledVocabularyRepo repo) { + private Class getEntity(EntityControlledVocabularyRepo repo) { Type type = getGenericType(repo.getClass())[0]; Type[] types = getGenericType(getClass(type)); return getClass(((ParameterizedType) types[0]).getActualTypeArguments()[0]); } - public Type[] getGenericType(Class target) { + private Type[] getGenericType(Class target) { Type[] types = new Type[0]; if (target != null) { types = target.getGenericInterfaces(); diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/ApplicationInitializationTest.java similarity index 66% rename from src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java rename to src/test/java/org/tdl/vireo/ApplicationInitializationTest.java index 2eea2026d0..f72b37c1cc 100644 --- a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java +++ b/src/test/java/org/tdl/vireo/ApplicationInitializationTest.java @@ -1,8 +1,10 @@ -package org.tdl.vireo.service; +package org.tdl.vireo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -11,16 +13,28 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import org.tdl.vireo.Application; +import org.tdl.vireo.model.ControlledVocabulary; +import org.tdl.vireo.model.VocabularyWord; +import org.tdl.vireo.model.repo.ControlledVocabularyRepo; +import org.tdl.vireo.service.DefaultFiltersService; +import org.tdl.vireo.service.DefaultSettingsService; +import org.tdl.vireo.service.DefaultSubmissionListColumnService; +import org.tdl.vireo.service.DepositorService; +import org.tdl.vireo.service.EntityControlledVocabularyService; +import org.tdl.vireo.service.ProquestCodesService; +import org.tdl.vireo.service.SystemDataLoader; @ActiveProfiles(value = { "test" }) @SpringBootTest(classes = { Application.class }) @Transactional(propagation = Propagation.REQUIRES_NEW) -public class SystemDataLoaderTest { +public class ApplicationInitializationTest { @Autowired private SystemDataLoader systemDataLoader; + @Autowired + private EntityControlledVocabularyService entityControlledVocabularyService; + @Autowired private DefaultSettingsService defaultSettingsService; @@ -36,16 +50,26 @@ public class SystemDataLoaderTest { @Autowired private ProquestCodesService proquesteCodesService; + @Autowired + private ControlledVocabularyRepo controlledVocabularyRepo; + @Test public void testLoadSystemData() throws Exception { - assertPersistedSystemData(false); + assertInMemorySystemData(false); // reload to ensure nothing changes systemDataLoader.loadSystemData(); - assertPersistedSystemData(true); + entityControlledVocabularyService.scanForEntityControlledVocabularies(); + assertInMemorySystemData(true); } - private void assertPersistedSystemData(boolean isReload) { + private void assertInMemorySystemData(boolean isReload) throws ClassNotFoundException { + assertEntityControlledVocabulary(48, "Degrees"); + assertEntityControlledVocabulary(3, "Graduation Months"); + assertEntityControlledVocabulary(5, "Proquest Embargos"); + assertEntityControlledVocabulary(1, "Languages"); + assertEntityControlledVocabulary(4, "Default Embargos"); + assertEquals(8, this.defaultSettingsService.getTypes().size(), isReload ? "Incorrect number of default setting types after reload" @@ -80,6 +104,15 @@ private void assertPersistedSystemData(boolean isReload) { assertProquestCodes(288, "subjects", isReload); } + private void assertEntityControlledVocabulary(int expected, String name) throws ClassNotFoundException { + List dictionary = entityControlledVocabularyService.getControlledVocabularyWords(name); + assertEquals(expected, dictionary.size()); + ControlledVocabulary cv = controlledVocabularyRepo.findByName(name); + assertNotNull(cv); + assertTrue(cv.getIsEntityProperty()); + assertEquals(expected, cv.getDictionary().size()); + } + private void assertSettingsType(int expected, String type, boolean isReload) { assertEquals(expected, this.defaultSettingsService.getSettingsByType(type).size(), isReload From 78d4559186c3a01eb6e9dbc60ba88f61a93b23e8 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 14:38:30 -0600 Subject: [PATCH 42/48] Remove empty tests --- .../vireo/service/EntityCVServiceTest.java | 69 ------------------- .../service/OrderedEntityServiceTest.java | 49 ------------- 2 files changed, 118 deletions(-) delete mode 100644 src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java delete mode 100644 src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java diff --git a/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java b/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java deleted file mode 100644 index 8e1915dc4b..0000000000 --- a/src/test/java/org/tdl/vireo/service/EntityCVServiceTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.tdl.vireo.service; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.tdl.vireo.Application; - -@ActiveProfiles(value = { "test", "isolated-test" }) -@SpringBootTest(classes = { Application.class }) -public class EntityCVServiceTest { - - @BeforeEach - public void setup() { - - } - - @Test - public void testAddEntityToWhitelist() { - - } - - @Test - public void testRemoveEntityFromWhitelist() { - - } - - @Test - public void testAddEntityPropertyToWhitelist() { - - } - - @Test - public void testRemoveEntityPropertyFromWhitelist() { - - } - - @Test - public void testGetControlledVocabulary() { - - } - - @Test - public void testGetEntityNames() { - - } - - @Test - public void testGetAllEntityPropertyNames() { - - } - - @Test - public void testGetPropertyNames() { - - } - - @Test - public void testGetWhitelist() { - - } - - @AfterEach - public void cleanup() { - - } - -} diff --git a/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java b/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java deleted file mode 100644 index 5c716b64fe..0000000000 --- a/src/test/java/org/tdl/vireo/service/OrderedEntityServiceTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.tdl.vireo.service; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.tdl.vireo.Application; - -@ActiveProfiles(value = { "test", "isolated-test" }) -@SpringBootTest(classes = { Application.class }) -public class OrderedEntityServiceTest { - - @BeforeEach - public void setup() { - - } - - @Test - public void testFindByOrder() { - - } - - @Test - public void testSwap() { - - } - - @Test - public void testDelete() { - - } - - @Test - public void testReorder() { - - } - - @Test - public void testRemove() { - - } - - @AfterEach - public void cleanup() { - - } - -} From 3aeea30a707939b48fe81810e2731242f6b865cb Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 14:45:09 -0600 Subject: [PATCH 43/48] Add test messages to application initialization tests --- .../vireo/ApplicationInitializationTest.java | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/test/java/org/tdl/vireo/ApplicationInitializationTest.java b/src/test/java/org/tdl/vireo/ApplicationInitializationTest.java index f72b37c1cc..1e2e6074a9 100644 --- a/src/test/java/org/tdl/vireo/ApplicationInitializationTest.java +++ b/src/test/java/org/tdl/vireo/ApplicationInitializationTest.java @@ -64,11 +64,11 @@ public void testLoadSystemData() throws Exception { } private void assertInMemorySystemData(boolean isReload) throws ClassNotFoundException { - assertEntityControlledVocabulary(48, "Degrees"); - assertEntityControlledVocabulary(3, "Graduation Months"); - assertEntityControlledVocabulary(5, "Proquest Embargos"); - assertEntityControlledVocabulary(1, "Languages"); - assertEntityControlledVocabulary(4, "Default Embargos"); + assertEntityControlledVocabulary(48, "Degrees", isReload); + assertEntityControlledVocabulary(3, "Graduation Months", isReload); + assertEntityControlledVocabulary(5, "Proquest Embargos", isReload); + assertEntityControlledVocabulary(1, "Languages", isReload); + assertEntityControlledVocabulary(4, "Default Embargos", isReload); assertEquals(8, this.defaultSettingsService.getTypes().size(), isReload @@ -104,13 +104,25 @@ private void assertInMemorySystemData(boolean isReload) throws ClassNotFoundExce assertProquestCodes(288, "subjects", isReload); } - private void assertEntityControlledVocabulary(int expected, String name) throws ClassNotFoundException { + private void assertEntityControlledVocabulary(int expected, String name, boolean isReload) throws ClassNotFoundException { List dictionary = entityControlledVocabularyService.getControlledVocabularyWords(name); - assertEquals(expected, dictionary.size()); + assertEquals(expected, dictionary.size(), + isReload + ? String.format("Incorrect number of words in %s dictionary after reload", name) + : String.format("Incorrect number of words in %s dictionary", name)); ControlledVocabulary cv = controlledVocabularyRepo.findByName(name); - assertNotNull(cv); - assertTrue(cv.getIsEntityProperty()); - assertEquals(expected, cv.getDictionary().size()); + assertNotNull(cv, + isReload + ? String.format("%s dictionary not found after reload", name) + : String.format("%s dictionary not found", name)); + assertTrue(cv.getIsEntityProperty(), + isReload + ? String.format("%s dictionary is not entity property after reload", name) + : String.format("%s dictionary is not entity property", name)); + assertEquals(expected, cv.getDictionary().size(), + isReload + ? String.format("Controlled vocabulary %s dictionary has incorrect number of words after reload", name) + : String.format("Controlled vocabulary %s dictionary has incorrect number of words", name)); } private void assertSettingsType(int expected, String type, boolean isReload) { From 16e320dce3b0adba1d30ea0317fd6c0ff2801d8b Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 16:54:15 -0600 Subject: [PATCH 44/48] Cleanup system data loader and rollback on IOException --- .../tdl/vireo/service/SystemDataLoader.java | 535 +++++++----------- 1 file changed, 217 insertions(+), 318 deletions(-) diff --git a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java index 5851fa4ff6..45f6092a14 100644 --- a/src/main/java/org/tdl/vireo/service/SystemDataLoader.java +++ b/src/main/java/org/tdl/vireo/service/SystemDataLoader.java @@ -69,9 +69,7 @@ import org.tdl.vireo.model.repo.VocabularyWordRepo; import org.tdl.vireo.model.repo.WorkflowStepRepo; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -161,8 +159,8 @@ public class SystemDataLoader { @Autowired private ProquestCodesService proquesteCodesService; - @Transactional - public void loadSystemData() { + @Transactional(rollbackFor = IOException.class) + public void loadSystemData() throws IOException { logger.info("Loading system languages"); loadLanguages(); @@ -203,56 +201,46 @@ public void loadSystemData() { logger.info("Loading system Proquest subject codes controlled vocabulary"); loadProquestSubjectCodesControlledVocabulary(); - logger.info("Loading system Submission List Columns"); + logger.info("Loading system submission list columns"); loadSubmissionListColumns(); - logger.info("Loading system Packagers"); + logger.info("Loading system packagers"); loadPackagers(); logger.info("Finished loading system data"); } - private void loadLanguages() { - try { - List languages = objectMapper.readValue(getInputStreamFromResource("classpath:/languages/SYSTEM_Languages.json"), new TypeReference>() {}); + private void loadLanguages() throws IOException { + List languages = objectMapper.readValue(getInputStreamFromResource("classpath:/languages/SYSTEM_Languages.json"), new TypeReference>() {}); - for (Language language : languages) { - Language persistedLanguage = languageRepo.findByName(language.getName()); + for (Language language : languages) { + Language persistedLanguage = languageRepo.findByName(language.getName()); - if (persistedLanguage == null) { - persistedLanguage = languageRepo.create(language.getName()); - } else { - persistedLanguage.setName(language.getName()); - persistedLanguage = languageRepo.save(persistedLanguage); - } + if (persistedLanguage == null) { + persistedLanguage = languageRepo.create(language.getName()); + } else { + persistedLanguage.setName(language.getName()); + persistedLanguage = languageRepo.save(persistedLanguage); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default languages. ", e); } } - private void loadInputTypes() { - try { - List inputTypes = objectMapper.readValue(getInputStreamFromResource("classpath:/input_types/SYSTEM_Input_Types.json"), new TypeReference>() {}); + private void loadInputTypes() throws IOException { + List inputTypes = objectMapper.readValue(getInputStreamFromResource("classpath:/input_types/SYSTEM_Input_Types.json"), new TypeReference>() {}); - for (InputType inputType : inputTypes) { - InputType persistedInputType = inputTypeRepo.findByName(inputType.getName()); + for (InputType inputType : inputTypes) { + InputType persistedInputType = inputTypeRepo.findByName(inputType.getName()); - if (persistedInputType == null) { - persistedInputType = inputTypeRepo.create(inputType); - } else { - persistedInputType.setName(inputType.getName()); - persistedInputType = inputTypeRepo.save(persistedInputType); - } + if (persistedInputType == null) { + persistedInputType = inputTypeRepo.create(inputType); + } else { + persistedInputType.setName(inputType.getName()); + persistedInputType = inputTypeRepo.save(persistedInputType); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default input types. ", e); } } - private void loadEmailTemplates() { + private void loadEmailTemplates() throws IOException { for (String name : getAllSystemEmailTemplateNames()) { // try to see if it already exists in the DB @@ -300,21 +288,15 @@ private void loadEmailTemplates() { } } - private List getAllSystemEmailTemplateNames() { - try { - - List names = new ArrayList(); - for (Resource resource : resourcePatternResolver.getResources("classpath:/emails/*.email")) { - String fileName = resource.getFilename(); - String templateName = decodeTemplateName(fileName); - names.add(templateName); - } - - return names; - - } catch (IOException e) { - throw new IllegalStateException("Unable to get emails directory from classpath."); + private List getAllSystemEmailTemplateNames() throws IOException { + List names = new ArrayList(); + for (Resource resource : resourcePatternResolver.getResources("classpath:/emails/*.email")) { + String fileName = resource.getFilename(); + String templateName = decodeTemplateName(fileName); + names.add(templateName); } + + return names; } private String decodeTemplateName(String path) { @@ -324,173 +306,137 @@ private String decodeTemplateName(String path) { return path.replaceAll("_", " "); } - private EmailTemplate loadSystemEmailTemplate(String name) { - try { - - Resource resource = resourcePatternResolver.getResource("classpath:/emails/" + encodeTemplateName(name)); - String data = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8); + private EmailTemplate loadSystemEmailTemplate(String name) throws IOException { + Resource resource = resourcePatternResolver.getResource("classpath:/emails/" + encodeTemplateName(name)); + String data = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8); - // Remove any comment lines - data = data.replaceAll("\\s*#.*[\\n\\r]{1}", ""); + // Remove any comment lines + data = data.replaceAll("\\s*#.*[\\n\\r]{1}", ""); - // Extract the subject - Matcher subjectMatcher = SUBJECT_PATTERN.matcher(data); - if (!subjectMatcher.find()) { - throw new IllegalStateException("Unable to identify the template's subject."); - } - String subject = subjectMatcher.group(1).trim(); - - // Trim the subject leaving just the body. - int index = data.indexOf("\n"); - if (index < 0) { - index = data.indexOf("\r"); - } - - String message = data.substring(index); + // Extract the subject + Matcher subjectMatcher = SUBJECT_PATTERN.matcher(data); + if (!subjectMatcher.find()) { + throw new IllegalStateException("Unable to identify the template's subject."); + } + String subject = subjectMatcher.group(1).trim(); - if (subject == null || subject.length() == 0) { - throw new IllegalStateException("Unable to identify the template's subject."); - } + // Trim the subject leaving just the body. + int index = data.indexOf("\n"); + if (index < 0) { + index = data.indexOf("\r"); + } - if (message == null || message.length() == 0) { - throw new IllegalStateException("Unable to identify the template's message."); - } + String message = data.substring(index); - EmailTemplate template = emailTemplateRepo.findByNameAndSystemRequired(name, true); + if (subject == null || subject.length() == 0) { + throw new IllegalStateException("Unable to identify the template's subject."); + } - if (template == null) { - template = emailTemplateRepo.create(name, subject, message); - template.setSystemRequired(true); - } else { - template.setSubject(subject); - template.setMessage(message); - } + if (message == null || message.length() == 0) { + throw new IllegalStateException("Unable to identify the template's message."); + } - return emailTemplateRepo.save(template); + EmailTemplate template = emailTemplateRepo.findByNameAndSystemRequired(name, true); - } catch (IOException e) { - throw new IllegalStateException("Unable to generate system email template: " + name, e); + if (template == null) { + template = emailTemplateRepo.create(name, subject, message); + template.setSystemRequired(true); + } else { + template.setSubject(subject); + template.setMessage(message); } + + return emailTemplateRepo.save(template); } private static String encodeTemplateName(String name) { return name.replaceAll(" ", "_") + ".email"; } - private void loadDegreeLevels() { - try { - - List degreeLevels = objectMapper.readValue(getInputStreamFromResource("classpath:/degree_levels/SYSTEM_Degree_Levels.json"), new TypeReference>() {}); - - for (DegreeLevel degreeLevel : degreeLevels) { - DegreeLevel dbDegreeLevel = degreeLevelRepo.findByName(degreeLevel.getName()); + private void loadDegreeLevels() throws IOException { + List degreeLevels = objectMapper.readValue(getInputStreamFromResource("classpath:/degree_levels/SYSTEM_Degree_Levels.json"), new TypeReference>() {}); - if (dbDegreeLevel == null) { - dbDegreeLevel = degreeLevelRepo.create(degreeLevel.getName()); - } + for (DegreeLevel degreeLevel : degreeLevels) { + DegreeLevel dbDegreeLevel = degreeLevelRepo.findByName(degreeLevel.getName()); + if (dbDegreeLevel == null) { + dbDegreeLevel = degreeLevelRepo.create(degreeLevel.getName()); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default degree levels.", e); + } } - private void loadDegrees() { - try { - - List degrees = objectMapper.readValue(getInputStreamFromResource("classpath:/degrees/SYSTEM_Degrees.json"), new TypeReference>() {}); + private void loadDegrees() throws IOException { + List degrees = objectMapper.readValue(getInputStreamFromResource("classpath:/degrees/SYSTEM_Degrees.json"), new TypeReference>() {}); - for (Degree degree : degrees) { + for (Degree degree : degrees) { - DegreeLevel degreeLevel = degreeLevelRepo.findByName(degree.getLevel().getName()); + DegreeLevel degreeLevel = degreeLevelRepo.findByName(degree.getLevel().getName()); - if (degreeLevel == null) { - degreeLevel = degreeLevelRepo.create(degree.getLevel().getName()); - } else { - degreeLevel.setName(degree.getLevel().getName()); - degreeLevel = degreeLevelRepo.save(degreeLevel); - } - - Degree dbDegree = degreeRepo.findByNameAndLevel(degree.getName(), degreeLevel); + if (degreeLevel == null) { + degreeLevel = degreeLevelRepo.create(degree.getLevel().getName()); + } else { + degreeLevel.setName(degree.getLevel().getName()); + degreeLevel = degreeLevelRepo.save(degreeLevel); + } - if (dbDegree == null) { - dbDegree = degreeRepo.create(degree.getName(), degreeLevel); - } else { - dbDegree.setName(degree.getName()); - dbDegree.setLevel(degreeLevel); - dbDegree = degreeRepo.save(dbDegree); - } + Degree dbDegree = degreeRepo.findByNameAndLevel(degree.getName(), degreeLevel); + if (dbDegree == null) { + dbDegree = degreeRepo.create(degree.getName(), degreeLevel); + } else { + dbDegree.setName(degree.getName()); + dbDegree.setLevel(degreeLevel); + dbDegree = degreeRepo.save(dbDegree); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default degrees.", e); + } } - private void loadGraduationMonths() { - try { + private void loadGraduationMonths() throws IOException { + List graduationMonths = objectMapper.readValue(getInputStreamFromResource("classpath:/graduation_months/SYSTEM_Graduation_Months.json"), new TypeReference>() {}); - List graduationMonths = objectMapper.readValue(getInputStreamFromResource("classpath:/graduation_months/SYSTEM_Graduation_Months.json"), new TypeReference>() {}); - - for (GraduationMonth graduationMonth : graduationMonths) { - GraduationMonth persistedGraduationMonth = graduationMonthRepo.findByMonth(graduationMonth.getMonth()); - - if (persistedGraduationMonth == null) { - persistedGraduationMonth = graduationMonthRepo.create(graduationMonth.getMonth()); - } + for (GraduationMonth graduationMonth : graduationMonths) { + GraduationMonth persistedGraduationMonth = graduationMonthRepo.findByMonth(graduationMonth.getMonth()); + if (persistedGraduationMonth == null) { + persistedGraduationMonth = graduationMonthRepo.create(graduationMonth.getMonth()); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default graduation months.", e); + } } - private void loadEmbargos() { - try { - - List embargoDefinitions = objectMapper.readValue(getInputStreamFromResource("classpath:/embargos/SYSTEM_Embargo_Definitions.json"), new TypeReference>() {}); + private void loadEmbargos() throws IOException { + List embargoDefinitions = objectMapper.readValue(getInputStreamFromResource("classpath:/embargos/SYSTEM_Embargo_Definitions.json"), new TypeReference>() {}); - for (Embargo embargoDefinition : embargoDefinitions) { - Embargo dbEmbargo = embargoRepo.findByNameAndGuarantorAndSystemRequired(embargoDefinition.getName(), embargoDefinition.getGuarantor(), true); + for (Embargo embargoDefinition : embargoDefinitions) { + Embargo dbEmbargo = embargoRepo.findByNameAndGuarantorAndSystemRequired(embargoDefinition.getName(), embargoDefinition.getGuarantor(), true); - if (dbEmbargo == null) { - dbEmbargo = embargoRepo.create(embargoDefinition.getName(), embargoDefinition.getDescription(), embargoDefinition.getDuration(), embargoDefinition.getGuarantor(), embargoDefinition.isActive()); - dbEmbargo.setSystemRequired(true); - embargoRepo.save(dbEmbargo); - } else { - dbEmbargo.setDescription(embargoDefinition.getDescription()); - dbEmbargo.setDuration(embargoDefinition.getDuration()); - dbEmbargo.setGuarantor(embargoDefinition.getGuarantor()); - dbEmbargo.isActive(embargoDefinition.isActive()); - dbEmbargo.setSystemRequired(embargoDefinition.getSystemRequired()); - embargoRepo.save(dbEmbargo); - } + if (dbEmbargo == null) { + dbEmbargo = embargoRepo.create(embargoDefinition.getName(), embargoDefinition.getDescription(), embargoDefinition.getDuration(), embargoDefinition.getGuarantor(), embargoDefinition.isActive()); + dbEmbargo.setSystemRequired(true); + embargoRepo.save(dbEmbargo); + } else { + dbEmbargo.setDescription(embargoDefinition.getDescription()); + dbEmbargo.setDuration(embargoDefinition.getDuration()); + dbEmbargo.setGuarantor(embargoDefinition.getGuarantor()); + dbEmbargo.isActive(embargoDefinition.isActive()); + dbEmbargo.setSystemRequired(embargoDefinition.getSystemRequired()); + embargoRepo.save(dbEmbargo); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default embargos. ", e); } } - private void loadSubmissionStatuses() { - - try { - // read System Submission Status as JsonNode - JsonNode systemSubmissionStatus = objectMapper.readTree(getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Status.json")); + private void loadSubmissionStatuses() throws IOException { + // read System Submission Status as JsonNode + JsonNode systemSubmissionStatus = objectMapper.readTree(getInputStreamFromResource("classpath:/submission_statuses/SYSTEM_Submission_Status.json")); - // check to see if the SubmissionStatus exists - SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(systemSubmissionStatus.get("name").asText()); - - // recursively find or create new SubmissionStatus if not already exists - if (newSubmissionStatus == null) { - recursivelyFindOrCreateSubmissionStatus(systemSubmissionStatus); - } + // check to see if the SubmissionStatus exists + SubmissionStatus newSubmissionStatus = submissionStatusRepo.findByName(systemSubmissionStatus.get("name").asText()); - } catch (IOException e) { - throw new IllegalStateException("Unable to generate system submission status", e); + // recursively find or create new SubmissionStatus if not already exists + if (newSubmissionStatus == null) { + recursivelyFindOrCreateSubmissionStatus(systemSubmissionStatus); } } @@ -526,6 +472,7 @@ private SubmissionStatus recursivelyFindOrCreateSubmissionStatus(JsonNode submis } private SubmissionStatus createSubmissionStatus(JsonNode submissionStatus) { + JsonNode isActive = submissionStatus.get("isActive"); return submissionStatusRepo.create( submissionStatus.get("name").asText(), submissionStatus.get("isArchived").asBoolean(), @@ -533,99 +480,77 @@ private SubmissionStatus createSubmissionStatus(JsonNode submissionStatus) { submissionStatus.get("isDeletable").asBoolean(), submissionStatus.get("isEditableByReviewer").asBoolean(), submissionStatus.get("isEditableByStudent").asBoolean(), - submissionStatus.get("isActive").asBoolean(), + isActive.isNull() ? null : isActive.asBoolean(), SubmissionState.from(submissionStatus.get("submissionState").asInt()) ); } - private void loadOrganizationCategories() { - try { + private void loadOrganizationCategories() throws IOException { + List organizationCategories = objectMapper.readValue(getInputStreamFromResource("classpath:/organization_categories/SYSTEM_Organizaiton_Categories.json"), new TypeReference>() {}); - List organizationCategories = objectMapper.readValue(getInputStreamFromResource("classpath:/organization_categories/SYSTEM_Organizaiton_Categories.json"), new TypeReference>() {}); - - for (OrganizationCategory organizationCategory : organizationCategories) { - OrganizationCategory dbOrganizationCategory = organizationCategoryRepo.findByName(organizationCategory.getName()); - - if (dbOrganizationCategory == null) { - dbOrganizationCategory = organizationCategoryRepo.create(organizationCategory.getName()); - } + for (OrganizationCategory organizationCategory : organizationCategories) { + OrganizationCategory dbOrganizationCategory = organizationCategoryRepo.findByName(organizationCategory.getName()); + if (dbOrganizationCategory == null) { + dbOrganizationCategory = organizationCategoryRepo.create(organizationCategory.getName()); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default embargos. ", e); } } - private void loadDocumentTypes() { - try { + private void loadDocumentTypes() throws IOException { + List documentTypes = objectMapper.readValue(getInputStreamFromResource("classpath:/document_types/SYSTEM_Document_Types.json"), new TypeReference>() {}); - List documentTypes = objectMapper.readValue(getInputStreamFromResource("classpath:/document_types/SYSTEM_Document_Types.json"), new TypeReference>() {}); + for (DocumentType documentType : documentTypes) { - for (DocumentType documentType : documentTypes) { + FieldPredicate fieldPredicate = documentType.getFieldPredicate(); - FieldPredicate fieldPredicate = documentType.getFieldPredicate(); - - FieldPredicate dbFieldPredicate = fieldPredicateRepo.findByValue(fieldPredicate.getValue()); - if (dbFieldPredicate == null) { - dbFieldPredicate = fieldPredicateRepo.create(fieldPredicate.getValue(), Boolean.valueOf(true)); - } else { - dbFieldPredicate.setValue(fieldPredicate.getValue()); - dbFieldPredicate.setDocumentTypePredicate(fieldPredicate.getDocumentTypePredicate()); - dbFieldPredicate = fieldPredicateRepo.save(dbFieldPredicate); - } + FieldPredicate dbFieldPredicate = fieldPredicateRepo.findByValue(fieldPredicate.getValue()); + if (dbFieldPredicate == null) { + dbFieldPredicate = fieldPredicateRepo.create(fieldPredicate.getValue(), Boolean.valueOf(true)); + } else { + dbFieldPredicate.setValue(fieldPredicate.getValue()); + dbFieldPredicate.setDocumentTypePredicate(fieldPredicate.getDocumentTypePredicate()); + dbFieldPredicate = fieldPredicateRepo.save(dbFieldPredicate); + } - DocumentType dbDocumentType = documentTypeRepo.findByNameAndFieldPredicate(documentType.getName(), dbFieldPredicate); + DocumentType dbDocumentType = documentTypeRepo.findByNameAndFieldPredicate(documentType.getName(), dbFieldPredicate); - if (dbDocumentType == null) { - dbDocumentType = documentTypeRepo.create(documentType.getName(), dbFieldPredicate); - } else { - dbDocumentType.setName(documentType.getName()); - dbDocumentType.setFieldPredicate(dbFieldPredicate); - documentTypeRepo.save(dbDocumentType); - } + if (dbDocumentType == null) { + dbDocumentType = documentTypeRepo.create(documentType.getName(), dbFieldPredicate); + } else { + dbDocumentType.setName(documentType.getName()); + dbDocumentType.setFieldPredicate(dbFieldPredicate); + documentTypeRepo.save(dbDocumentType); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default document types. ", e); } } - private void loadOrganization() { - - Organization organization = null; + private void loadOrganization() throws IOException { + // read and map json to Organization + Organization systemOrganization = objectMapper.readValue(getInputStreamFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); - try { - // read and map json to Organization - Organization systemOrganization = objectMapper.readValue(getInputStreamFromResource("classpath:/organization/SYSTEM_Organization_Definition.json"), Organization.class); + // check to see if organization category exists + OrganizationCategory category = organizationCategoryRepo.findByName(systemOrganization.getCategory().getName()); - // check to see if organization category exists - OrganizationCategory category = organizationCategoryRepo.findByName(systemOrganization.getCategory().getName()); - - // create organization category if does not already exists - if (category == null) { - category = organizationCategoryRepo.create(systemOrganization.getCategory().getName()); - } - - // check to see if organization with organization category exists - organization = organizationRepo.findByNameAndCategory(systemOrganization.getName(), category); - - // create new organization if not already exists - if (organization == null) { - organization = organizationRepo.create(systemOrganization.getName(), category); - organization.setAcceptsSubmissions(systemOrganization.getAcceptsSubmissions()); - } + // create organization category if does not already exists + if (category == null) { + category = organizationCategoryRepo.create(systemOrganization.getCategory().getName()); + } - processWorkflowSteps(organization, systemOrganization); + // check to see if organization with organization category exists + Organization organization = organizationRepo.findByNameAndCategory(systemOrganization.getName(), category); - processEmailWorflowRules(organization, systemOrganization); + // create new organization if not already exists + if (organization == null) { + organization = organizationRepo.create(systemOrganization.getName(), category); + organization.setAcceptsSubmissions(systemOrganization.getAcceptsSubmissions()); + } - organization = organizationRepo.save(organization); + processWorkflowSteps(organization, systemOrganization); - } catch (IOException e) { - throw new IllegalStateException("Unable to generate system organization", e); - } + processEmailWorflowRules(organization, systemOrganization); + organizationRepo.save(organization); } private void processWorkflowSteps(Organization organization, Organization systemOrganization) { @@ -777,45 +702,31 @@ private void processEmailWorflowRules(Organization organization, Organization sy organization.setEmailWorkflowRules(emailWorkflowRules); } - private void loadControlledVocabularies() { - try { - for (Resource vocabularyResourceJson : resourcePatternResolver.getResources("classpath:/controlled_vocabularies/*.json")) { - try { - ControlledVocabulary cv = objectMapper.readValue(vocabularyResourceJson.getInputStream(), ControlledVocabulary.class); - - // check to see if Controlled Vocabulary exists, and if so, merge up with it - ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName(cv.getName()); + private void loadControlledVocabularies() throws IOException { + for (Resource vocabularyResourceJson : resourcePatternResolver.getResources("classpath:/controlled_vocabularies/*.json")) { + ControlledVocabulary cv = objectMapper.readValue(vocabularyResourceJson.getInputStream(), ControlledVocabulary.class); - if (persistedCV == null) { - persistedCV = controlledVocabularyRepo.create(cv.getName()); - } + // check to see if Controlled Vocabulary exists, and if so, merge up with it + ControlledVocabulary persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - for (VocabularyWord vw : cv.getDictionary()) { + if (persistedCV == null) { + persistedCV = controlledVocabularyRepo.create(cv.getName()); + } - VocabularyWord persistedVW = vocabularyRepo.findByNameAndControlledVocabulary(vw.getName(), persistedCV); + for (VocabularyWord vw : cv.getDictionary()) { - if (persistedVW == null) { - persistedVW = vocabularyRepo.create(persistedCV, vw.getName(), vw.getDefinition(), vw.getIdentifier(), vw.getContacts()); - persistedCV = controlledVocabularyRepo.findByName(cv.getName()); - } else { - persistedVW.setDefinition(vw.getDefinition()); - persistedVW.setIdentifier(vw.getIdentifier()); - persistedVW.setContacts(vw.getContacts()); - persistedVW = vocabularyRepo.save(persistedVW); - } - } + VocabularyWord persistedVW = vocabularyRepo.findByNameAndControlledVocabulary(vw.getName(), persistedCV); - } catch (JsonParseException e) { - e.printStackTrace(); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + if (persistedVW == null) { + persistedVW = vocabularyRepo.create(persistedCV, vw.getName(), vw.getDefinition(), vw.getIdentifier(), vw.getContacts()); + persistedCV = controlledVocabularyRepo.findByName(cv.getName()); + } else { + persistedVW.setDefinition(vw.getDefinition()); + persistedVW.setIdentifier(vw.getIdentifier()); + persistedVW.setContacts(vw.getContacts()); + persistedVW = vocabularyRepo.save(persistedVW); } - } - } catch (IOException e) { - e.printStackTrace(); } } @@ -846,63 +757,51 @@ private void loadProquestSubjectCodesControlledVocabulary() { } } - private void loadSubmissionListColumns() { - try { + private void loadSubmissionListColumns() throws IOException { + List submissionListColumns = objectMapper.readValue(getInputStreamFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json"), new TypeReference>() {}); - List submissionListColumns = objectMapper.readValue(getInputStreamFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Columns.json"), new TypeReference>() {}); + for (SubmissionListColumn submissionListColumn : submissionListColumns) { + SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(submissionListColumn.getTitle()); - for (SubmissionListColumn submissionListColumn : submissionListColumns) { - SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(submissionListColumn.getTitle()); + // check to see if the InputType exists + InputType inputType = inputTypeRepo.findByName(submissionListColumn.getInputType().getName()); - // check to see if the InputType exists - InputType inputType = inputTypeRepo.findByName(submissionListColumn.getInputType().getName()); + if (inputType == null) { + inputType = inputTypeRepo.create(submissionListColumn.getInputType().getName()); + } else { + inputType.setName(submissionListColumn.getInputType().getName()); + inputType = inputTypeRepo.save(inputType); + } - if (inputType == null) { - inputType = inputTypeRepo.create(submissionListColumn.getInputType().getName()); + if (dbSubmissionListColumn == null) { + if (submissionListColumn.getPredicate() != null) { + submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getPredicate(), inputType); } else { - inputType.setName(submissionListColumn.getInputType().getName()); - inputType = inputTypeRepo.save(inputType); + submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getValuePath(), inputType); } - - if (dbSubmissionListColumn == null) { - if (submissionListColumn.getPredicate() != null) { - submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getPredicate(), inputType); - } else { - submissionListColumnRepo.create(submissionListColumn.getTitle(), submissionListColumn.getSort(), submissionListColumn.getValuePath(), inputType); - } - } else { - dbSubmissionListColumn.setSort(submissionListColumn.getSort()); - if (submissionListColumn.getPredicate() != null) { - dbSubmissionListColumn.setPredicate(submissionListColumn.getPredicate()); - } - dbSubmissionListColumn.setValuePath(submissionListColumn.getValuePath()); - submissionListColumnRepo.save(dbSubmissionListColumn); + } else { + dbSubmissionListColumn.setSort(submissionListColumn.getSort()); + if (submissionListColumn.getPredicate() != null) { + dbSubmissionListColumn.setPredicate(submissionListColumn.getPredicate()); } + dbSubmissionListColumn.setValuePath(submissionListColumn.getValuePath()); + submissionListColumnRepo.save(dbSubmissionListColumn); } - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize submission list columns. ", e); - } - - try { - String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getInputStreamFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); - int count = 0; - for (String defaultTitle : defaultSubmissionListColumnTitles) { - SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); - if (dbSubmissionListColumn != null) { - if (dbSubmissionListColumn.getSort() != Sort.NONE) { - logger.warn("Updating sort order for default submission list column with title " + defaultTitle); - dbSubmissionListColumn.setSortOrder(++count); - submissionListColumnRepo.update(dbSubmissionListColumn); - } - } else { - logger.warn("Unable to find submission list column with title " + defaultTitle); + } + + String[] defaultSubmissionListColumnTitles = objectMapper.readValue(getInputStreamFromResource("classpath:/submission_list_columns/SYSTEM_Default_Submission_List_Column_Titles.json"), new TypeReference() { }); + int count = 0; + for (String defaultTitle : defaultSubmissionListColumnTitles) { + SubmissionListColumn dbSubmissionListColumn = submissionListColumnRepo.findByTitle(defaultTitle); + if (dbSubmissionListColumn != null) { + if (dbSubmissionListColumn.getSort() != Sort.NONE) { + logger.warn("Updating sort order for default submission list column with title " + defaultTitle); + dbSubmissionListColumn.setSortOrder(++count); + submissionListColumnRepo.update(dbSubmissionListColumn); } + } else { + logger.warn("Unable to find submission list column with title " + defaultTitle); } - - } catch (RuntimeException | IOException e) { - e.printStackTrace(); - logger.debug("Unable to initialize default submission list column titles. ", e); } } From 1c576cf0dba8000d46ea8b90116a4bcc035821af Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 16:54:30 -0600 Subject: [PATCH 45/48] Add system data loader test --- .../vireo/service/SystemDataLoaderTest.java | 508 ++++++++++++++++++ 1 file changed, 508 insertions(+) create mode 100644 src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java diff --git a/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java new file mode 100644 index 0000000000..50232fbe9d --- /dev/null +++ b/src/test/java/org/tdl/vireo/service/SystemDataLoaderTest.java @@ -0,0 +1,508 @@ +package org.tdl.vireo.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.tdl.vireo.Application; +import org.tdl.vireo.model.Organization; +import org.tdl.vireo.model.SubmissionState; +import org.tdl.vireo.model.SubmissionStatus; +import org.tdl.vireo.model.WorkflowStep; +import org.tdl.vireo.model.repo.AbstractEmailRecipientRepo; +import org.tdl.vireo.model.repo.AbstractPackagerRepo; +import org.tdl.vireo.model.repo.ConfigurationRepo; +import org.tdl.vireo.model.repo.ControlledVocabularyRepo; +import org.tdl.vireo.model.repo.DegreeLevelRepo; +import org.tdl.vireo.model.repo.DegreeRepo; +import org.tdl.vireo.model.repo.DocumentTypeRepo; +import org.tdl.vireo.model.repo.EmailTemplateRepo; +import org.tdl.vireo.model.repo.EmailWorkflowRuleRepo; +import org.tdl.vireo.model.repo.EmbargoRepo; +import org.tdl.vireo.model.repo.FieldPredicateRepo; +import org.tdl.vireo.model.repo.FieldProfileRepo; +import org.tdl.vireo.model.repo.GraduationMonthRepo; +import org.tdl.vireo.model.repo.InputTypeRepo; +import org.tdl.vireo.model.repo.LanguageRepo; +import org.tdl.vireo.model.repo.NoteRepo; +import org.tdl.vireo.model.repo.OrganizationCategoryRepo; +import org.tdl.vireo.model.repo.OrganizationRepo; +import org.tdl.vireo.model.repo.SubmissionListColumnRepo; +import org.tdl.vireo.model.repo.SubmissionStatusRepo; +import org.tdl.vireo.model.repo.VocabularyWordRepo; +import org.tdl.vireo.model.repo.WorkflowStepRepo; + +@ActiveProfiles(value = { "test", "isolated-test" }) +@SpringBootTest(classes = { Application.class }) +@Transactional(propagation = Propagation.REQUIRES_NEW) +public class SystemDataLoaderTest { + + @Autowired + private SystemDataLoader systemDataLoader; + + @Autowired + private EntityControlledVocabularyService entityControlledVocabularyService; + + @Autowired + private InputTypeRepo inputTypeRepo; + + @Autowired + private EmailTemplateRepo emailTemplateRepo; + + @Autowired + private AbstractEmailRecipientRepo abstractEmailRecipientRepo; + + @Autowired + private EmbargoRepo embargoRepo; + + @Autowired + private OrganizationRepo organizationRepo; + + @Autowired + private OrganizationCategoryRepo organizationCategoryRepo; + + @Autowired + private WorkflowStepRepo workflowStepRepo; + + @Autowired + private NoteRepo noteRepo; + + @Autowired + private FieldProfileRepo fieldProfileRepo; + + @Autowired + private ConfigurationRepo configurationRepo; + + @Autowired + private FieldPredicateRepo fieldPredicateRepo; + + @Autowired + private ControlledVocabularyRepo controlledVocabularyRepo; + + @Autowired + private VocabularyWordRepo vocabularyRepo; + + @Autowired + private LanguageRepo languageRepo; + + @Autowired + private DegreeRepo degreeRepo; + + @Autowired + private DegreeLevelRepo degreeLevelRepo; + + @Autowired + private GraduationMonthRepo graduationMonthRepo; + + @Autowired + private DocumentTypeRepo documentTypeRepo; + + @Autowired + private EmailWorkflowRuleRepo emailWorkflowRuleRepo; + + @Autowired + private SubmissionStatusRepo submissionStatusRepo; + + @Autowired + private SubmissionListColumnRepo submissionListColumnRepo; + + @Autowired + private AbstractPackagerRepo abstractPackagerRepo; + + @Test + public void testLoadSystemData() throws Exception { + assertBeforeLoadSystemData(); + + systemDataLoader.loadSystemData(); + entityControlledVocabularyService.scanForEntityControlledVocabularies(); + assertAfterLoadSystemData(false); + + // reload to ensure nothing changes + systemDataLoader.loadSystemData(); + entityControlledVocabularyService.scanForEntityControlledVocabularies(); + assertAfterLoadSystemData(true); + } + + private void assertBeforeLoadSystemData() { + assertEquals(0, inputTypeRepo.count()); + assertEquals(0, emailTemplateRepo.count()); + assertEquals(0, abstractEmailRecipientRepo.count()); + assertEquals(0, embargoRepo.count()); + assertEquals(0, organizationRepo.count()); + assertEquals(0, organizationCategoryRepo.count()); + assertEquals(0, workflowStepRepo.count()); + assertEquals(0, noteRepo.count()); + assertEquals(0, fieldProfileRepo.count()); + assertEquals(0, configurationRepo.count()); + assertEquals(0, fieldPredicateRepo.count()); + assertEquals(0, controlledVocabularyRepo.count()); + assertEquals(0, vocabularyRepo.count()); + assertEquals(0, languageRepo.count()); + assertEquals(0, degreeRepo.count()); + assertEquals(0, degreeLevelRepo.count()); + assertEquals(0, graduationMonthRepo.count()); + assertEquals(0, documentTypeRepo.count()); + assertEquals(0, emailWorkflowRuleRepo.count()); + assertEquals(0, submissionStatusRepo.count()); + assertEquals(0, submissionListColumnRepo.count()); + assertEquals(0, abstractPackagerRepo.count()); + } + + private void assertAfterLoadSystemData(boolean isReload) { + assertInputType(isReload); + assertEmailTemplate(isReload); + assertAbstractEmailRecipient(isReload); + assertEmbargo(isReload); + assertOrganization(isReload); + assertOrganizationCategory(isReload); + assertWorkflowStep(isReload); + assertNote(isReload); + assertFieldProfile(isReload); + assertConfiguration(isReload); + assertFieldPredicate(isReload); + assertControlledVocabulary(isReload); + assertVocabulary(isReload); + assertLanguage(isReload); + assertDegree(isReload); + assertDegreeLevel(isReload); + assertGraduationMonth(isReload); + assertDocumentType(isReload); + assertEmailWorkflowRule(isReload); + assertSubmissionStatus(isReload); + assertSubmissionListColumn(isReload); + assertAbstractPackager(isReload); + } + + private void assertInputType(boolean isReload) { + assertEquals(18, inputTypeRepo.count(), + isReload + ? "Incorrect number of inputType found after reload" + : "Incorrect number of inputType found"); + } + + private void assertEmailTemplate(boolean isReload) { + assertEquals(7, emailTemplateRepo.count(), + isReload + ? "Incorrect number of emailTemplate found after reload" + : "Incorrect number of emailTemplate found"); + } + + private void assertAbstractEmailRecipient(boolean isReload) { + assertEquals(2, abstractEmailRecipientRepo.count(), + isReload + ? "Incorrect number of abstractEmailRecipient found after reload" + : "Incorrect number of abstractEmailRecipient found"); + } + + private void assertEmbargo(boolean isReload) { + assertEquals(9, embargoRepo.count(), + isReload + ? "Incorrect number of embargo found after reload" + : "Incorrect number of embargo found"); + } + + private void assertOrganization(boolean isReload) { + assertEquals(1, organizationRepo.count(), + isReload + ? "Incorrect number of organization found after reload" + : "Incorrect number of organization found"); + + Organization institution = organizationRepo.findAll().get(0); + + assertEquals(false, institution.getAcceptsSubmissions(), + isReload + ? "Organization has incorrect accepts submission flag after reload" + : "Organization has incorrect accepts submission flag"); + + assertEquals(4, institution.getOriginalWorkflowSteps().size(), + isReload + ? "Organization has incorrect number original workflow steps after reload" + : "Organization has incorrect number original workflow steps"); + + assertEquals(4, institution.getAggregateWorkflowSteps().size(), + isReload + ? "Organization has incorrect number aggregate workflow steps after reload" + : "Organization has incorrect number aggregate workflow steps"); + + assertEquals(0, institution.getAncestorOrganizations().size(), + isReload + ? "Organization has ancestor organizations after reload" + : "Organization has ancestor organizations"); + + assertNull(institution.getParentOrganization(), + isReload + ? "Organization has parent organization after reload" + : "Organization has parent organization"); + + assertEquals(0, institution.getChildrenOrganizations().size(), + isReload + ? "Organization has children organizations after reload" + : "Organization has children organizations"); + + assertEquals(0, institution.getEmails().size(), + isReload + ? "Organization has emails after reload" + : "Organization has emails"); + + assertEquals(2, institution.getEmailWorkflowRules().size(), + isReload + ? "Organization has incorrect number email workflow rules after reload" + : "Organization has incorrect number email workflow rules"); + + assertEquals(2, institution.getAggregateEmailWorkflowRules().size(), + isReload + ? "Organization has incorrect number aggregate email workflow rules after reload" + : "Organization has incorrect number aggregate email workflow rules"); + } + + private void assertOrganizationCategory(boolean isReload) { + assertEquals(7, organizationCategoryRepo.count(), + isReload + ? "Incorrect number of organizationCategory found after reload" + : "Incorrect number of organizationCategory found"); + } + + private void assertWorkflowStep(boolean isReload) { + assertEquals(4, workflowStepRepo.count(), + isReload + ? "Incorrect number of workflowStep found after reload" + : "Incorrect number of workflowStep found"); + + + assertWorkflowStepHeritableProperties(new int[] { 3, 18 }, "Personal Information", isReload); + assertWorkflowStepHeritableProperties(new int[] { 0, 2 }, "License Agreement", isReload); + assertWorkflowStepHeritableProperties(new int[] { 4, 13 }, "Document Information", isReload); + assertWorkflowStepHeritableProperties(new int[] { 2, 8 }, "File Upload", isReload); + } + + private void assertWorkflowStepHeritableProperties(int[] expected, String name, boolean isReload) { + WorkflowStep workflowStep = workflowStepRepo.findByName(name).get(0); + assertEquals(expected[0], workflowStep.getOriginalNotes().size(), + isReload + ? String.format("%s workflow step has incorrect number of original notes after reload", name) + : String.format("%s workflow step has incorrect number of original notes", name)); + assertEquals(expected[0], workflowStep.getAggregateNotes().size(), + isReload + ? String.format("%s workflow step has incorrect number of aggregate notes after reload", name) + : String.format("%s workflow step has incorrect number of aggregate notes", name)); + assertEquals(expected[1], workflowStep.getOriginalFieldProfiles().size(), + isReload + ? String.format("%s workflow step has incorrect number of original field profiles after reload", name) + : String.format("%s workflow step has incorrect number of original field profiles", name)); + assertEquals(expected[1], workflowStep.getAggregateFieldProfiles().size(), + isReload + ? String.format("%s workflow step has incorrect number of aggregate field profiles after reload", name) + : String.format("%s workflow step has incorrect number of aggregate field profiles", name)); + } + + private void assertNote(boolean isReload) { + assertEquals(9, noteRepo.count(), + isReload + ? "Incorrect number of note found after reload" + : "Incorrect number of note found"); + } + + private void assertFieldProfile(boolean isReload) { + assertEquals(41, fieldProfileRepo.count(), + isReload + ? "Incorrect number of fieldProfile found after reload" + : "Incorrect number of fieldProfile found"); + } + + private void assertConfiguration(boolean isReload) { + assertEquals(2, configurationRepo.count(), + isReload + ? "Incorrect number of configuration found after reload" + : "Incorrect number of configuration found"); + } + + private void assertFieldPredicate(boolean isReload) { + assertEquals(41, fieldPredicateRepo.count(), + isReload + ? "Incorrect number of fieldPredicate found after reload" + : "Incorrect number of fieldPredicate found"); + } + + private void assertControlledVocabulary(boolean isReload) { + assertEquals(14, controlledVocabularyRepo.count(), + isReload + ? "Incorrect number of controlledVocabulary found after reload" + : "Incorrect number of controlledVocabulary found"); + } + + private void assertVocabulary(boolean isReload) { + assertEquals(559, vocabularyRepo.count(), + isReload + ? "Incorrect number of vocabulary found after reload" + : "Incorrect number of vocabulary found"); + } + + private void assertLanguage(boolean isReload) { + assertEquals(1, languageRepo.count(), + isReload + ? "Incorrect number of language found after reload" + : "Incorrect number of language found"); + } + + private void assertDegree(boolean isReload) { + assertEquals(48, degreeRepo.count(), + isReload + ? "Incorrect number of degree found after reload" + : "Incorrect number of degree found"); + } + + private void assertDegreeLevel(boolean isReload) { + assertEquals(4, degreeLevelRepo.count(), + isReload + ? "Incorrect number of degreeLevel found after reload" + : "Incorrect number of degreeLevel found"); + } + + private void assertGraduationMonth(boolean isReload) { + assertEquals(3, graduationMonthRepo.count(), + isReload + ? "Incorrect number of graduationMonth found after reload" + : "Incorrect number of graduationMonth found"); + } + + private void assertDocumentType(boolean isReload) { + assertEquals(8, documentTypeRepo.count(), + isReload + ? "Incorrect number of documentType found after reload" + : "Incorrect number of documentType found"); + } + + private void assertEmailWorkflowRule(boolean isReload) { + assertEquals(2, emailWorkflowRuleRepo.count(), + isReload + ? "Incorrect number of emailWorkflowRule found after reload" + : "Incorrect number of emailWorkflowRule found"); + } + + private void assertSubmissionStatus(boolean isReload) { + assertEquals(12, submissionStatusRepo.count(), + isReload + ? "Incorrect number of submissionStatus found after reload" + : "Incorrect number of submissionStatus found"); + + SubmissionStatus inProgress = submissionStatusRepo.findByName("In Progress"); + SubmissionStatus submitted = submissionStatusRepo.findByName("Submitted"); + SubmissionStatus underReview = submissionStatusRepo.findByName("Under Review"); + SubmissionStatus needsCorrection = submissionStatusRepo.findByName("Needs Correction"); + SubmissionStatus correctionsReceived = submissionStatusRepo.findByName("Corrections Received"); + SubmissionStatus waitingOnRequirements = submissionStatusRepo.findByName("Waiting On Requirements"); + SubmissionStatus approved = submissionStatusRepo.findByName("Approved"); + SubmissionStatus pendingPublication = submissionStatusRepo.findByName("Pending Publication"); + SubmissionStatus published = submissionStatusRepo.findByName("Published"); + SubmissionStatus onHold = submissionStatusRepo.findByName("On Hold"); + SubmissionStatus withdrawn = submissionStatusRepo.findByName("Withdrawn"); + SubmissionStatus cancelled = submissionStatusRepo.findByName("Cancelled"); + + assertSubmissionStatusState(SubmissionState.IN_PROGRESS, inProgress, isReload); + assertSubmissionStatusState(SubmissionState.SUBMITTED, submitted, isReload); + assertSubmissionStatusState(SubmissionState.UNDER_REVIEW, underReview, isReload); + assertSubmissionStatusState(SubmissionState.NEEDS_CORRECTIONS, needsCorrection, isReload); + assertSubmissionStatusState(SubmissionState.CORRECTIONS_RECIEVED, correctionsReceived, isReload); + assertSubmissionStatusState(SubmissionState.WAITING_ON_REQUIREMENTS, waitingOnRequirements, isReload); + assertSubmissionStatusState(SubmissionState.APPROVED, approved, isReload); + assertSubmissionStatusState(SubmissionState.PENDING_PUBLICATION, pendingPublication, isReload); + assertSubmissionStatusState(SubmissionState.PUBLISHED, published, isReload); + assertSubmissionStatusState(SubmissionState.ON_HOLD, onHold, isReload); + assertSubmissionStatusState(SubmissionState.WITHDRAWN, withdrawn, isReload); + assertSubmissionStatusState(SubmissionState.CANCELED, cancelled, isReload); + + assertSubmissionStatusTransitions(new String[] { "Submitted", "On Hold", "Withdrawn", "Cancelled" }, inProgress, isReload); + assertSubmissionStatusTransitions(new String[] { "Under Review" }, submitted, isReload); + assertSubmissionStatusTransitions(new String[] { "Needs Correction", "Waiting On Requirements", "Approved" }, underReview, isReload); + assertSubmissionStatusTransitions(new String[] { "Corrections Received" }, needsCorrection, isReload); + assertSubmissionStatusTransitions(new String[] { "Under Review", "Waiting On Requirements", "Approved" }, correctionsReceived, isReload); + assertSubmissionStatusTransitions(new String[] { "Under Review", "Approved" }, waitingOnRequirements, isReload); + assertSubmissionStatusTransitions(new String[] { "Pending Publication" }, approved, isReload); + assertSubmissionStatusTransitions(new String[] { "Published" }, pendingPublication, isReload); + assertSubmissionStatusTransitions(new String[] { "Pending Publication" }, published, isReload); + assertSubmissionStatusTransitions(new String[] { }, onHold, isReload); + assertSubmissionStatusTransitions(new String[] { }, withdrawn, isReload); + assertSubmissionStatusTransitions(new String[] { }, cancelled, isReload); + + assertSubmissionStatusState(new Boolean[] { false, false, false, false, false, null }, inProgress, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, false, true }, submitted, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, false, true }, underReview, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, true, true }, needsCorrection, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, false, true }, correctionsReceived, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, false, true }, waitingOnRequirements, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, false, true }, approved, isReload); + assertSubmissionStatusState(new Boolean[] { true, false, false, true, false, false }, pendingPublication, isReload); + assertSubmissionStatusState(new Boolean[] { true, false, false, true, false, false }, published, isReload); + assertSubmissionStatusState(new Boolean[] { false, false, false, true, false, true }, onHold, isReload); + assertSubmissionStatusState(new Boolean[] { true, false, false, true, false, false }, withdrawn, isReload); + assertSubmissionStatusState(new Boolean[] { true, false, true, true, false, false }, cancelled, isReload); + } + + private void assertSubmissionStatusState(Boolean[] expected, SubmissionStatus actual, boolean isReload) { + assertEquals(expected[0], actual.isArchived(), + isReload + ? String.format("%s submission status has incorrect isArchived flag after reload", actual.getName()) + : String.format("%s submission status has incorrect isArchived flag", actual.getName())); + assertEquals(expected[1], actual.isPublishable(), + isReload + ? String.format("%s submission status has incorrect isPublishable flag after reload", actual.getName()) + : String.format("%s submission status has incorrect isPublishable flag", actual.getName())); + assertEquals(expected[2], actual.isDeletable(), + isReload + ? String.format("%s submission status has incorrect isDeletable flag after reload", actual.getName()) + : String.format("%s submission status has incorrect isDeletable flag", actual.getName())); + assertEquals(expected[3], actual.isEditableByReviewer(), + isReload + ? String.format("%s submission status has incorrect isEditableByReviewer flag after reload", actual.getName()) + : String.format("%s submission status has incorrect isEditableByReviewer flag", actual.getName())); + assertEquals(expected[4], actual.isEditableByStudent(), + isReload + ? String.format("%s submission status has incorrect isEditableByStudent flag after reload", actual.getName()) + : String.format("%s submission status has incorrect isEditableByStudent flag", actual.getName())); + assertEquals(expected[5], actual.isActive(), + isReload + ? String.format("%s submission status has incorrect isActive flag after reload", actual.getName()) + : String.format("%s submission status has incorrect isActive flag", actual.getName())); + } + + private void assertSubmissionStatusState(SubmissionState expected, SubmissionStatus actual, boolean isReload) { + assertEquals(expected, actual.getSubmissionState(), + isReload + ? String.format("%s submission status has incorrect submission state after reload", actual.getName()) + : String.format("%s submission status has incorrect submission state", actual.getName())); + } + + private void assertSubmissionStatusTransitions(String[] expected, SubmissionStatus actual, boolean isReload) { + assertEquals(expected.length, actual.getTransitionSubmissionStatuses().size(), + isReload + ? String.format("%s submission status has incorrect number of transition status after reload", actual.getName()) + : String.format("%s submission status has incorrect number of transition status", actual.getName())); + for (String name : expected) { + assertTrue(actual.getTransitionSubmissionStatuses().stream().anyMatch(ts -> ts.getName().equals(name)), + isReload + ? String.format("%s submission status is missing %s transition status after reload", actual.getName(), name) + : String.format("%s submission status is missing %s transition status", actual.getName(), name)); + } + } + + private void assertSubmissionListColumn(boolean isReload) { + assertEquals(59, submissionListColumnRepo.count(), + isReload + ? "Incorrect number of submissionListColumn found after reload" + : "Incorrect number of submissionListColumn found"); + } + + private void assertAbstractPackager(boolean isReload) { + assertEquals(6, abstractPackagerRepo.count(), + isReload + ? "Incorrect number of abstractPackager found after reload" + : "Incorrect number of abstractPackager found"); + } + +} From a4f2f70faa43feff7fe7c748eca178cabf5d1c6d Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 19:46:04 -0600 Subject: [PATCH 46/48] Update submission list column when field profile gloss updated --- .../controller/WorkflowStepController.java | 8 ++--- .../vireo/model/repo/FieldProfileRepo.java | 5 +++ .../model/repo/impl/FieldProfileRepoImpl.java | 26 ++++++++++++++ .../WorkflowStepControllerTest.java | 14 ++------ .../WorkflowStepIntegrationTest.java | 35 +++++++++++++++++++ 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java b/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java index 1322b318bf..ea20e863d0 100644 --- a/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java +++ b/src/main/java/org/tdl/vireo/controller/WorkflowStepController.java @@ -75,7 +75,7 @@ public ApiResponse createFieldProfile(@PathVariable Long requestingOrgId, @PathV workflowStep = workflowStepRepo.update(workflowStep, requestingOrganization); } FieldProfile fp = fieldProfileRepo.create(workflowStep, fieldProfile.getFieldPredicate(), fieldProfile.getInputType(), fieldProfile.getUsage(), fieldProfile.getHelp(), fieldProfile.getGloss(), fieldProfile.getRepeatable(), fieldProfile.getOverrideable(), fieldProfile.getEnabled(), fieldProfile.getOptional(), fieldProfile.getFlagged(), fieldProfile.getLogged(), fieldProfile.getControlledVocabulary(), fieldProfile.getDefaultValue()); - organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); + return new ApiResponse(SUCCESS, fp); } @@ -91,9 +91,9 @@ public ApiResponse updateFieldProfile(@PathVariable Long requestingOrgId, @PathV } fieldProfile.setMappedShibAttribute(persistedMappedShibAttribute); } - fieldProfileRepo.update(fieldProfile, organizationRepo.findById(requestingOrgId).get()); - organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); - return new ApiResponse(SUCCESS); + FieldProfile fp = fieldProfileRepo.update(fieldProfile, organizationRepo.findById(requestingOrgId).get()); + + return new ApiResponse(SUCCESS, fp); } @Deprecated diff --git a/src/main/java/org/tdl/vireo/model/repo/FieldProfileRepo.java b/src/main/java/org/tdl/vireo/model/repo/FieldProfileRepo.java index d59b529fe7..f526dee55b 100644 --- a/src/main/java/org/tdl/vireo/model/repo/FieldProfileRepo.java +++ b/src/main/java/org/tdl/vireo/model/repo/FieldProfileRepo.java @@ -2,6 +2,8 @@ import java.util.List; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.tdl.vireo.model.FieldPredicate; import org.tdl.vireo.model.FieldProfile; import org.tdl.vireo.model.WorkflowStep; @@ -16,4 +18,7 @@ public interface FieldProfileRepo extends HeritableRepo, FieldProf public List findByOriginating(FieldProfile originatingFieldProfile); + @Query(value = "SELECT fp.gloss FROM FieldProfile fp WHERE fp_type = 'Org' AND fp.id = :id") + public String findGlossById(@Param("id") Long id); + } diff --git a/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java b/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java index e25aef0519..800256618c 100644 --- a/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java +++ b/src/main/java/org/tdl/vireo/model/repo/impl/FieldProfileRepoImpl.java @@ -4,11 +4,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; +import org.tdl.vireo.exception.ComponentNotPresentOnOrgException; +import org.tdl.vireo.exception.HeritableModelNonOverrideableException; +import org.tdl.vireo.exception.WorkflowStepNonOverrideableException; import org.tdl.vireo.model.ControlledVocabulary; import org.tdl.vireo.model.FieldPredicate; import org.tdl.vireo.model.FieldProfile; import org.tdl.vireo.model.InputType; import org.tdl.vireo.model.ManagedConfiguration; +import org.tdl.vireo.model.Organization; import org.tdl.vireo.model.Sort; import org.tdl.vireo.model.SubmissionListColumn; import org.tdl.vireo.model.WorkflowStep; @@ -69,10 +73,27 @@ public FieldProfile create(WorkflowStep originatingWorkflowStep, FieldPredicate return newFieldProfile(originatingWorkflowStep, fieldPredicate, inputType, usage, help, gloss, repeatable, overrideable, enabled, optional, hidden, flagged, logged, controlledVocabulary, mappedShibAttribute, defaultValue); } + @Override + @Transactional + public FieldProfile update(FieldProfile fieldProfile, Organization requestingOrganization) throws ComponentNotPresentOnOrgException, WorkflowStepNonOverrideableException, HeritableModelNonOverrideableException { + String originalGloss = fieldProfileRepo.findGlossById(fieldProfile.getId()); + + FieldProfile updatedFieldProfile = super.update(fieldProfile, requestingOrganization); + + Optional slc = submissionListColumnRepo.findByTitleAndPredicateAndInputType(originalGloss, fieldProfile.getFieldPredicate().getValue(), fieldProfile.getInputType()); + if (slc.isPresent()) { + slc.get().setTitle(updatedFieldProfile.getGloss()); + submissionListColumnRepo.update(slc.get()); + } + + return updatedFieldProfile; + } + @Override @Transactional public void delete(FieldProfile fieldProfile) { super.delete(fieldProfile); + Optional slc = submissionListColumnRepo.findByTitleAndPredicateAndInputType(fieldProfile.getGloss(), fieldProfile.getFieldPredicate().getValue(), fieldProfile.getInputType()); if (slc.isPresent()) { submissionListColumnRepo.delete(slc.get()); @@ -81,13 +102,18 @@ public void delete(FieldProfile fieldProfile) { private synchronized FieldProfile newFieldProfile(WorkflowStep originatingWorkflowStep, FieldPredicate fieldPredicate, InputType inputType, String usage, String help, String gloss, Boolean repeatable, Boolean overrideable, Boolean enabled, Boolean optional, Boolean hidden, Boolean flagged, Boolean logged, ControlledVocabulary controlledVocabulary, ManagedConfiguration mappedShibAttribute, String defaultValue) { FieldProfile fieldProfile = fieldProfileRepo.save(new FieldProfile(originatingWorkflowStep, fieldPredicate, inputType, usage, help, gloss, repeatable, overrideable, enabled, optional, hidden, flagged, logged, controlledVocabulary, mappedShibAttribute, defaultValue)); + originatingWorkflowStep.addOriginalFieldProfile(fieldProfile); + workflowStepRepo.save(originatingWorkflowStep); + Optional slc = submissionListColumnRepo.findByTitleAndPredicateAndInputType(gloss, fieldPredicate.getValue(), inputType); if (!slc.isPresent()) { submissionListColumnRepo.create(gloss, Sort.NONE, fieldPredicate.getValue(), inputType); } + organizationRepo.broadcast(organizationRepo.findAllByOrderByIdAsc()); + return fieldProfileRepo.findById(fieldProfile.getId()).get(); } diff --git a/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java b/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java index ccfc6b859b..6a3d945ec2 100644 --- a/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java +++ b/src/test/java/org/tdl/vireo/controller/WorkflowStepControllerTest.java @@ -150,8 +150,6 @@ public void testCreateFieldProfile() throws JsonProcessingException, WorkflowSte when(workflowStepRepo.findById(any(Long.class))).thenReturn(Optional.of(workflowStep1)); when(organizationRepo.findById(any(Long.class))).thenReturn(Optional.of(organization1)); when(fieldProfileRepo.create(any(WorkflowStep.class), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(fieldProfile1); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); ApiResponse response = fieldPredicateController.createFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -163,8 +161,6 @@ public void testCreateFieldProfileUpdatingOrganization() throws JsonProcessingEx when(organizationRepo.findById(any(Long.class))).thenReturn(Optional.of(organization1)); when(workflowStepRepo.update(any(WorkflowStep.class), any(Organization.class))).thenReturn(workflowStep2); when(fieldProfileRepo.create(any(WorkflowStep.class), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(fieldProfile1); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); ApiResponse response = fieldPredicateController.createFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -173,8 +169,7 @@ public void testCreateFieldProfileUpdatingOrganization() throws JsonProcessingEx @Test public void testUpdateFieldProfile() throws JsonProcessingException, WorkflowStepNonOverrideableException, HeritableModelNonOverrideableException, ComponentNotPresentOnOrgException { when(organizationRepo.findById(any(Long.class))).thenReturn(Optional.of(organization1)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); + when(fieldProfileRepo.update(any(FieldProfile.class), any(Organization.class))).thenReturn(fieldProfile1); ApiResponse response = fieldPredicateController.updateFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -185,8 +180,7 @@ public void testUpdateFieldProfileWithNullShibAttribute() throws JsonProcessingE managedConfiguration1 = null; when(organizationRepo.findById(any(Long.class))).thenReturn(Optional.of(organization1)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); + when(fieldProfileRepo.update(any(FieldProfile.class), any(Organization.class))).thenReturn(fieldProfile1); ApiResponse response = fieldPredicateController.updateFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -199,8 +193,6 @@ public void testUpdateFieldProfileWithNullShibAttributeId() throws JsonProcessin when(configurationRepo.findByNameAndType(anyString(), anyString())).thenReturn(managedConfiguration1); when(fieldProfileRepo.update(any(FieldProfile.class), any(Organization.class))).thenReturn(fieldProfile1); when(organizationRepo.findById(any(Long.class))).thenReturn(Optional.of(organization1)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); ApiResponse response = fieldPredicateController.updateFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); @@ -215,8 +207,6 @@ public void testUpdateFieldProfileWithNullShibAttributeIDAndNullPersistedAttribu when(fieldProfileRepo.update(any(FieldProfile.class), any(Organization.class))).thenReturn(fieldProfile1); when(configurationRepo.create(any(ManagedConfiguration.class))).thenReturn(managedConfiguration1); when(organizationRepo.findById(any(Long.class))).thenReturn(Optional.of(organization1)); - when(organizationRepo.findAllByOrderByIdAsc()).thenReturn(organizations); - doNothing().when(organizationRepo).broadcast(anyList()); ApiResponse response = fieldPredicateController.updateFieldProfile(organization1.getId(), workflowStep1.getId(), fieldProfile1); assertEquals(ApiStatus.SUCCESS, response.getMeta().getStatus()); diff --git a/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java b/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java index e623ae793e..f74e6638c5 100644 --- a/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java +++ b/src/test/java/org/tdl/vireo/integration/WorkflowStepIntegrationTest.java @@ -103,6 +103,7 @@ public void testSubmissionListColumnRemovedWhenRemovingFieldProfileFromWorkflowS assertEquals(initialFieldPredicateCount + 1, fieldPredicateRepo.count()); assertTrue(fieldPredicateRepo.existsById(fieldPredicateId)); + // add field profile to workflow step FieldProfile fieldProfile = new FieldProfile(workflowStep, fieldPredicate, inputType, "Test", false, true, true, false, false, false, null); @@ -128,6 +129,39 @@ public void testSubmissionListColumnRemovedWhenRemovingFieldProfileFromWorkflowS assertEquals(initialSubmissionListColumnCount + 1, submissionListColumnRepo.count()); assertNotNull(submissionListColumnRepo.findByTitle("Test")); + + // rename field profile and assert submission list column updated accordingly + + fieldProfile.setId(fpId); + fieldProfile.setGloss("Tested"); + + try { + results = mockMvc.perform(post("/workflow-step/{requestingOrgId}/{workflowStepId}/update-field-profile", orgId, wsId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.convertValue(fieldProfile, JsonNode.class).toString().getBytes("utf-8"))) + .andExpect(status().isOk()).andExpect(jsonPath("$.meta.status").value("SUCCESS")) + .andExpect(jsonPath("$.payload.FieldProfile").exists()) + .andExpect(jsonPath("$.payload.FieldProfile.id").isNumber()) + .andExpect(jsonPath("$.payload.FieldProfile.gloss").value("Tested")) + .andReturn(); + + fpId = objectMapper.readTree(results.getResponse().getContentAsString()) + .get("payload") + .get("FieldProfile") + .get("id") + .asLong(); + } catch (Exception e) { + e.printStackTrace(); + } + + assertEquals(initialFieldProfileCount + 1, fieldProfileRepo.count()); + assertTrue(fieldProfileRepo.existsById(fpId)); + + assertEquals(initialSubmissionListColumnCount + 1, submissionListColumnRepo.count()); + assertNull(submissionListColumnRepo.findByTitle("Test")); + assertNotNull(submissionListColumnRepo.findByTitle("Tested")); + + // remove field profile and assert submission list column not orphaned mockMvc.perform(post("/workflow-step/{requestingOrgId}/{workflowStepId}/remove-field-profile/{fieldProfileId}", orgId, wsId, fpId) @@ -140,6 +174,7 @@ public void testSubmissionListColumnRemovedWhenRemovingFieldProfileFromWorkflowS assertEquals(initialSubmissionListColumnCount, submissionListColumnRepo.count()); assertNull(submissionListColumnRepo.findByTitle("Test")); + assertNull(submissionListColumnRepo.findByTitle("Tested")); } } From ab9375a41ff47500fb23fc067c44de31ce67efee Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 20:07:55 -0600 Subject: [PATCH 47/48] Add data integrity violation exception handler --- .../advice/CustomResponseEntityExceptionHandler.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java b/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java index f239d4deff..39ed909f28 100644 --- a/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java +++ b/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java @@ -8,6 +8,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -43,6 +44,15 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio @Value("${spring.servlet.multipart.max-file-size:20MB}") private String maxFileSize; + @ExceptionHandler(DataIntegrityViolationException.class) + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ResponseBody + public ApiResponse handleDataIntegrityViolationException(DataIntegrityViolationException exception) { + logger.error(exception.getMessage()); + logger.debug(exception.getMessage(), exception); + return new ApiResponse(ERROR, exception.getMessage()); + } + @ExceptionHandler(EntityNotFoundException.class) @ResponseStatus(value = HttpStatus.NOT_FOUND) @ResponseBody From b4406560779bc0c0416677f2b50b570c77a24847 Mon Sep 17 00:00:00 2001 From: William Welling Date: Fri, 29 Dec 2023 20:09:23 -0600 Subject: [PATCH 48/48] Have data integrity violation exception return conflict status --- .../controller/advice/CustomResponseEntityExceptionHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java b/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java index 39ed909f28..9d22a59237 100644 --- a/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java +++ b/src/main/java/org/tdl/vireo/controller/advice/CustomResponseEntityExceptionHandler.java @@ -45,7 +45,7 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio private String maxFileSize; @ExceptionHandler(DataIntegrityViolationException.class) - @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ResponseStatus(value = HttpStatus.CONFLICT) @ResponseBody public ApiResponse handleDataIntegrityViolationException(DataIntegrityViolationException exception) { logger.error(exception.getMessage());