diff --git a/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java b/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java index b6c7e310adb..4fe0fb04c15 100644 --- a/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java +++ b/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java @@ -6,10 +6,12 @@ public interface EmailDomainManager { EmailDomainEntity createEmailDomain(String emailDomain, EmailDomainEntity.DomainCategory category); - + boolean updateCategory(long id, EmailDomainEntity.DomainCategory category); EmailDomainEntity findByEmailDoman(String emailDomain); List findByCategory(EmailDomainEntity.DomainCategory category); + + EmailDomainEntity createOrUpdateEmailDomain(String emailDomain, String rorId); } diff --git a/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java b/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java index b5950fb9f91..d096f255f04 100644 --- a/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java +++ b/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java @@ -19,14 +19,18 @@ public class EmailDomainManagerImpl implements EmailDomainManager { @Resource(name = "emailDomainDaoReadOnly") private EmailDomainDao emailDomainDaoReadOnly; - @Override - public EmailDomainEntity createEmailDomain(String emailDomain, DomainCategory category) { + private void validateEmailDomain(String emailDomain) { if (emailDomain == null || emailDomain.isBlank()) { throw new IllegalArgumentException("Email Domain must not be empty"); } if(!InternetDomainName.isValid(emailDomain)) { throw new IllegalArgumentException("Email Domain '" + emailDomain + "' is invalid"); } + } + + @Override + public EmailDomainEntity createEmailDomain(String emailDomain, DomainCategory category) { + validateEmailDomain(emailDomain); if (category == null) { throw new IllegalArgumentException("Category must not be empty"); } @@ -57,4 +61,17 @@ public List findByCategory(DomainCategory category) { return emailDomainDaoReadOnly.findByCategory(category); } + @Override + public EmailDomainEntity createOrUpdateEmailDomain(String emailDomain, String rorId) { + EmailDomainEntity existingEntity = emailDomainDaoReadOnly.findByEmailDoman(emailDomain); + if(existingEntity != null) { + if(!rorId.equals(existingEntity.getRorId())) { + emailDomainDao.updateRorId(existingEntity.getId(), rorId); + } + } else { + return emailDomainDao.createEmailDomain(emailDomain, DomainCategory.PROFESSIONAL, rorId); + } + return existingEntity; + } + } diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java b/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java index bb5c5730a53..93ea7a3bc35 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java @@ -6,8 +6,12 @@ public interface EmailDomainDao extends GenericDao { EmailDomainEntity createEmailDomain(String emailDomain, EmailDomainEntity.DomainCategory category); + + EmailDomainEntity createEmailDomain(String emailDomain, EmailDomainEntity.DomainCategory category, String rorId); boolean updateCategory(long id, EmailDomainEntity.DomainCategory category); + + boolean updateRorId(long id, String rorId); EmailDomainEntity findByEmailDoman(String emailDomain); diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java b/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java index 5a8416d1e3c..6c75eec184f 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java @@ -31,6 +31,18 @@ public EmailDomainEntity createEmailDomain(String emailDomain, DomainCategory ca entityManager.persist(e); return e; } + + @Override + @Transactional + public EmailDomainEntity createEmailDomain(String emailDomain, DomainCategory category, String rorId) { + LOG.debug("Creating domain {} with category {} and ror Id {}", emailDomain, category, rorId); + EmailDomainEntity e = new EmailDomainEntity(); + e.setEmailDomain(emailDomain); + e.setCategory(category); + e.setRorId(rorId); + entityManager.persist(e); + return e; + } @Override @Transactional @@ -42,6 +54,16 @@ public boolean updateCategory(long id, DomainCategory category) { return query.executeUpdate() > 0; } + @Override + @Transactional + public boolean updateRorId(long id, String rorId) { + LOG.debug("Updating domain with id {} with rorId {}", id, rorId); + Query query = entityManager.createNativeQuery("UPDATE email_domain SET ror_id=:rorId WHERE id = :id"); + query.setParameter("id", id); + query.setParameter("rorId", rorId.toString()); + return query.executeUpdate() > 0; + } + @Override public EmailDomainEntity findByEmailDoman(String emailDomain) { TypedQuery query = entityManager.createQuery("from EmailDomainEntity where emailDomain = :emailDomain", EmailDomainEntity.class); diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/jpa/entities/EmailDomainEntity.java b/orcid-persistence/src/main/java/org/orcid/persistence/jpa/entities/EmailDomainEntity.java index 06ea938e449..c676f19cea8 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/jpa/entities/EmailDomainEntity.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/jpa/entities/EmailDomainEntity.java @@ -28,6 +28,7 @@ public static enum DomainCategory {PERSONAL, PROFESSIONAL, UNDEFINED} private Long id; private String emailDomain; private DomainCategory category; + private String rorId; public EmailDomainEntity() { @@ -38,6 +39,12 @@ public EmailDomainEntity(String emailDomain, DomainCategory category) { this.category = category; } + public EmailDomainEntity(String emailDomain, DomainCategory category, String rorId) { + this.emailDomain = emailDomain; + this.category = category; + this.rorId = rorId; + } + @Override @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "email_domain_seq") @@ -70,9 +77,18 @@ public void setEmailDomain(String emailDomain) { this.emailDomain = emailDomain; } + @Column(name = "ror_id") + public String getRorId() { + return rorId; + } + + public void setRorId(String rorId) { + this.rorId = rorId; + } + @Override public int hashCode() { - return Objects.hash(category, emailDomain, id); + return Objects.hash(category, emailDomain, id, rorId); } @Override @@ -84,6 +100,6 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; EmailDomainEntity other = (EmailDomainEntity) obj; - return category == other.category && Objects.equals(emailDomain, other.emailDomain) && Objects.equals(id, other.id); - } + return category == other.category && Objects.equals(emailDomain, other.emailDomain) && Objects.equals(id, other.id) && Objects.equals(rorId, other.rorId); + } } diff --git a/orcid-persistence/src/main/resources/db/updates/create_email_domain_mapping_tables.xml b/orcid-persistence/src/main/resources/db/updates/create_email_domain_mapping_tables.xml index 02d6c9d413a..5e5832934af 100644 --- a/orcid-persistence/src/main/resources/db/updates/create_email_domain_mapping_tables.xml +++ b/orcid-persistence/src/main/resources/db/updates/create_email_domain_mapping_tables.xml @@ -20,53 +20,25 @@ - - - - - - - - - - - - - - - - - - - - - + + - - ALTER TABLE email_domain_to_org_id ADD CONSTRAINT email_domain_fk FOREIGN KEY (email_domian_id) REFERENCES email_domain (id); - ALTER TABLE email_domain_to_org_id ADD CONSTRAINT org_disambiguated_id_fk FOREIGN KEY (org_disambiguated_id) REFERENCES org_disambiguated (id); - create index email_domain_to_org_id_domain_index on email_domain_to_org_id(email_domian_id); - create index email_domain_to_org_id_org_index on email_domain_to_org_id(org_disambiguated_id); - + - - - @@ -76,11 +48,11 @@ create index email_domain_domain_index on email_domain(email_domain); + create index email_domain_domain_index on email_domain(ror); - GRANT SELECT ON email_domain to orcidro; - GRANT SELECT ON email_domain_to_org_id to orcidro; + GRANT SELECT ON email_domain to orcidro; \ No newline at end of file diff --git a/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainToRorLoader.java b/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainToRorLoader.java new file mode 100644 index 00000000000..6260f2e7adc --- /dev/null +++ b/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainToRorLoader.java @@ -0,0 +1,149 @@ +package org.orcid.scheduler.loader.cli; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.AbstractMap; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.orcid.core.common.manager.EmailDomainManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import com.fasterxml.jackson.databind.MappingIterator; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvParser; + +public class EmailDomainToRorLoader { + + private static final Logger LOG = LoggerFactory.getLogger(EmailDomainToRorLoader.class); + + private String filePath; + private EmailDomainManager emailDomainManager; + List> csvData; + + List invalidDomains = new ArrayList(); + + Map map = new HashMap(); + + public EmailDomainToRorLoader(String filePath) { + this.filePath = filePath; + init(filePath); + } + + public void execute() throws IOException { + load(this.filePath); + processCsvData(); + } + + private void init(String filePath) { + Path path = Paths.get(filePath); + if(!Files.exists(path)) { + LOG.error("File does not exists: '{}'", filePath); + System.exit(1); + } + + @SuppressWarnings("resource") + ApplicationContext context = new ClassPathXmlApplicationContext("orcid-core-context.xml"); + emailDomainManager = (EmailDomainManager) context.getBean("emailDomainManager"); + } + + private void load(String filePath) throws IOException { + LOG.info("Reading file {}", filePath); + FileReader fileReader = new FileReader(filePath); + CsvMapper csvMapper = new CsvMapper(); + csvMapper.enable(CsvParser.Feature.WRAP_AS_ARRAY); + MappingIterator> it = csvMapper.readerForListOf(String.class).readValues(fileReader); + + if (it != null) { + csvData = new ArrayList>(); + while(it.hasNext()) { + List r = it.next(); + csvData.add(r); + } + } + } + + private void processCsvData() { + for (List row : csvData) { + String domain = row.get(0); + String rorId = row.get(1); + boolean hasParent = false; + try { + String hasParentField = row.get(2); + hasParent = hasParentField == null ? false : Boolean.valueOf(hasParentField); + } catch(IndexOutOfBoundsException eoob) { + // Leave the hasParent as false + } + + if(!map.containsKey(domain)) { + DomainToRorMap dtrm = new DomainToRorMap(); + dtrm.setDomain(domain); + if(hasParent) { + dtrm.addIdWithParent(rorId); + } else { + dtrm.addIdWithNoParent(rorId); + } + map.put(rorId, dtrm); + } else { + DomainToRorMap dtrm = map.get(rorId); + if(hasParent) { + dtrm.addIdWithParent(rorId); + } else { + dtrm.addIdWithNoParent(rorId); + } + } + } + } + + private void storeDomainToRorMap() { + for(DomainToRorMap element : map.values()) { + // If the domain has only one entry with no parent, store that one + if(element.getIdsWithNoParent().size() == 1) { + + } else if(element.getIdsWithParent().size() == 1) { + // Else, if the domain has only one entry with parent, store that one + } else { + // Else log a warning because there is no way to provide a suggestion + } + } + } + + private class DomainToRorMap { + private String domain; + private List idsWithParent = new ArrayList(); + private List idsWithNoParent = new ArrayList(); + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getDomain() { + return this.domain; + } + + public void addIdWithParent(String rorId) { + idsWithParent.add(rorId); + } + + public List getIdsWithParent() { + return this.idsWithParent; + } + + public void addIdWithNoParent(String rorId) { + idsWithNoParent.add(rorId); + } + + public List getIdsWithNoParent() { + return this.idsWithNoParent; + } + } +} diff --git a/orcid-web/src/main/java/org/orcid/frontend/web/controllers/EmailDomainController.java b/orcid-web/src/main/java/org/orcid/frontend/web/controllers/EmailDomainController.java index e42dd146931..76c33f8d640 100644 --- a/orcid-web/src/main/java/org/orcid/frontend/web/controllers/EmailDomainController.java +++ b/orcid-web/src/main/java/org/orcid/frontend/web/controllers/EmailDomainController.java @@ -27,7 +27,7 @@ public class EmailDomainController { ObjectMapper mapper = new ObjectMapper(); if(domain == null || domain.isBlank() || domain.length() > 254) { ObjectNode response = mapper.createObjectNode(); - response.put("error", "domain lenght too long or invalid"); + response.put("error", "Domain lenght too long, empty or invalid"); return response; } domain = OrcidStringUtils.stripHtml(domain);