Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
amontenegro committed Oct 19, 2023
1 parent b0016f3 commit a2944e7
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<EmailDomainEntity> findByCategory(EmailDomainEntity.DomainCategory category);

EmailDomainEntity createOrUpdateEmailDomain(String emailDomain, String rorId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -57,4 +61,17 @@ public List<EmailDomainEntity> 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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@

public interface EmailDomainDao extends GenericDao<EmailDomainEntity, Long> {
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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<EmailDomainEntity> query = entityManager.createQuery("from EmailDomainEntity where emailDomain = :emailDomain", EmailDomainEntity.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {

Expand All @@ -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")
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,53 +20,25 @@
<column name="category" type="VARCHAR(16)">
<constraints nullable="false" />
</column>
<column name="date_created" type="TIMESTAMP WITH TIME ZONE" />
<column name="last_modified" type="TIMESTAMP WITH TIME ZONE" />
</createTable>
</changeSet>

<changeSet author="Angel Montenegro" id="CREATE-EMAIL-DOMAIN-TO-ORG-ID-TABLE">
<preConditions onFail="MARK_RAN">
<not>
<tableExists tableName="email_domain_to_org_id" />
</not>
</preConditions>

<createTable tableName="email_domain_to_org_id">
<column name="id" type="bigint">
<constraints nullable="false" primaryKey="true"
primaryKeyName="email_domain_to_org_id_pkey" />
</column>
<column name="email_domian_id" type="bigint">
<constraints nullable="false" />
</column>
<column name="org_disambiguated_id" type="bigint">
<constraints nullable="false" />
<column name="ror_id" type="VARCHAR(30)">
<constraints nullable="true" />
</column>
<column name="date_created" type="TIMESTAMP WITH TIME ZONE" />
<column name="last_modified" type="TIMESTAMP WITH TIME ZONE" />
</createTable>

<sql>ALTER TABLE email_domain_to_org_id ADD CONSTRAINT email_domain_fk FOREIGN KEY (email_domian_id) REFERENCES email_domain (id);</sql>
<sql>ALTER TABLE email_domain_to_org_id ADD CONSTRAINT org_disambiguated_id_fk FOREIGN KEY (org_disambiguated_id) REFERENCES org_disambiguated (id);</sql>
<sql>create index email_domain_to_org_id_domain_index on email_domain_to_org_id(email_domian_id);</sql>
<sql>create index email_domain_to_org_id_org_index on email_domain_to_org_id(org_disambiguated_id);</sql>
</changeSet>

<changeSet id="CREATE-SEQUENCES" author="Angel Montenegro" dbms="postgresql">
<preConditions onFail="MARK_RAN">
<not>
<sequenceExists sequenceName="email_domain_seq"/>
<sequenceExists sequenceName="email_domain_to_org_id_seq"/>
</not>
</preConditions>
<createSequence sequenceName="email_domain_seq" startValue="1000" />
<createSequence sequenceName="email_domain_to_org_id_seq" startValue="1000" />
</changeSet>

<changeSet id="CREATE-AUTOCOLS" author="Angel Montenegro" dbms="hsqldb">
<addAutoIncrement tableName="email_domain" columnName="id" columnDataType="bigint"/>
<addAutoIncrement tableName="email_domain_to_org_id" columnName="id" columnDataType="bigint"/>
</changeSet>

<changeSet id="EMAIL-DOMAIN-INDEX" author="Angel Montenegro" dbms="postgresql">
Expand All @@ -76,11 +48,11 @@
</not>
</preConditions>
<sql>create index email_domain_domain_index on email_domain(email_domain);</sql>
<sql>create index email_domain_domain_index on email_domain(ror);</sql>
</changeSet>

<changeSet id="GRANT-READ-PERMISSIONS-TO-ORCIDRO" author="Angel Montenegro" dbms="postgresql">
<sql>GRANT SELECT ON email_domain to orcidro;</sql>
<sql>GRANT SELECT ON email_domain_to_org_id to orcidro;</sql>
<sql>GRANT SELECT ON email_domain to orcidro;</sql>
</changeSet>

</databaseChangeLog>
Original file line number Diff line number Diff line change
@@ -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<List<String>> csvData;

List<String> invalidDomains = new ArrayList<String>();

Map<String, DomainToRorMap> map = new HashMap<String, DomainToRorMap>();

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<List<String>> it = csvMapper.readerForListOf(String.class).readValues(fileReader);

if (it != null) {
csvData = new ArrayList<List<String>>();
while(it.hasNext()) {
List<String> r = it.next();
csvData.add(r);
}
}
}

private void processCsvData() {
for (List<String> 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<String> idsWithParent = new ArrayList<String>();
private List<String> idsWithNoParent = new ArrayList<String>();

public void setDomain(String domain) {
this.domain = domain;
}

public String getDomain() {
return this.domain;
}

public void addIdWithParent(String rorId) {
idsWithParent.add(rorId);
}

public List<String> getIdsWithParent() {
return this.idsWithParent;
}

public void addIdWithNoParent(String rorId) {
idsWithNoParent.add(rorId);
}

public List<String> getIdsWithNoParent() {
return this.idsWithNoParent;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit a2944e7

Please sign in to comment.