updated public logs api
This commit is contained in:
parent
e4cbfe863b
commit
a0e7425379
|
@ -1,35 +1,53 @@
|
|||
package eu.dnetlib.organizations.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import eu.dnetlib.organizations.model.view.ApiJournalView;
|
||||
import eu.dnetlib.organizations.repository.OrganizationRepository;
|
||||
import eu.dnetlib.organizations.repository.readonly.ApiJournalViewRepository;
|
||||
import eu.dnetlib.organizations.utils.DatabaseUtils;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/public-api")
|
||||
public class PublicApiController {
|
||||
|
||||
@Autowired
|
||||
private ApiJournalViewRepository apiJournalViewRepository;
|
||||
private DatabaseUtils dbUtils;
|
||||
|
||||
@Autowired
|
||||
private OrganizationRepository organizationRepository;
|
||||
@GetMapping("/logs/{year}/{month}/{country}")
|
||||
public void findJournalByCountry(@PathVariable final int year,
|
||||
@PathVariable final int month,
|
||||
@PathVariable final String country,
|
||||
final HttpServletResponse res) throws IOException {
|
||||
|
||||
@GetMapping("/logs")
|
||||
public ApiJournalView findJournalByDsId(@RequestParam final String id) {
|
||||
return apiJournalViewRepository.findById(id).orElse(organizationRepository.findById(id).map(ApiJournalView::new).orElse(new ApiJournalView()));
|
||||
if (month < 1 || month > 12) {
|
||||
res.sendError(HttpStatus.BAD_REQUEST.value(), "Invalid month");
|
||||
}
|
||||
if (year < 2020 || year > 2100) {
|
||||
res.sendError(HttpStatus.BAD_REQUEST.value(), "Invalid year");
|
||||
}
|
||||
|
||||
@GetMapping("/logs/{country}/{page}/{size}")
|
||||
public Page<ApiJournalView> findJournalByCountry(@PathVariable final String country, @PathVariable final int page, @PathVariable final int size) {
|
||||
return apiJournalViewRepository.findByCountry(country, PageRequest.of(page, size));
|
||||
res.setContentType(MediaType.TEXT_PLAIN.getType());
|
||||
final ServletOutputStream out = res.getOutputStream();
|
||||
|
||||
dbUtils.obtainLogEntries(year, month, country).forEach(s -> {
|
||||
try {
|
||||
IOUtils.write(s, out, StandardCharsets.UTF_8);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package eu.dnetlib.organizations.model.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class ApiOperation implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7111524441502889608L;
|
||||
|
||||
private String operation;
|
||||
private String description;
|
||||
private LocalDateTime date;
|
||||
|
||||
public String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setOperation(final String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(final String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public LocalDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(final LocalDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
package eu.dnetlib.organizations.model.view;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
import org.hibernate.annotations.TypeDefs;
|
||||
|
||||
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
|
||||
import com.vladmihalcea.hibernate.type.json.JsonStringType;
|
||||
|
||||
import eu.dnetlib.organizations.model.Organization;
|
||||
import eu.dnetlib.organizations.model.utils.ApiOperation;
|
||||
|
||||
@Entity
|
||||
@Table(name = "api_journal_view")
|
||||
@TypeDefs({
|
||||
@TypeDef(name = "json", typeClass = JsonStringType.class),
|
||||
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
|
||||
})
|
||||
public class ApiJournalView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1270660185726854334L;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private String id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "country")
|
||||
private String country;
|
||||
|
||||
@Type(type = "json")
|
||||
@Column(name = "logs", columnDefinition = "json")
|
||||
private List<ApiOperation> logs;
|
||||
|
||||
public ApiJournalView() {}
|
||||
|
||||
public ApiJournalView(final Organization o) {
|
||||
id = o.getId();
|
||||
name = o.getName();
|
||||
country = o.getCountry();
|
||||
logs = new ArrayList<>();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(final String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public List<ApiOperation> getLogs() {
|
||||
return logs;
|
||||
}
|
||||
|
||||
public void setLogs(final List<ApiOperation> logs) {
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package eu.dnetlib.organizations.repository.readonly;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import eu.dnetlib.organizations.model.view.ApiJournalView;
|
||||
|
||||
@Repository
|
||||
public interface ApiJournalViewRepository extends ReadOnlyRepository<ApiJournalView, String> {
|
||||
|
||||
Page<ApiJournalView> findByCountry(String country, Pageable page);
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package eu.dnetlib.organizations.utils;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -104,12 +105,7 @@ public class DatabaseUtils {
|
|||
private static final Log log = LogFactory.getLog(DatabaseUtils.class);
|
||||
|
||||
public enum VocabularyTable {
|
||||
languages,
|
||||
countries,
|
||||
org_types,
|
||||
id_types,
|
||||
rel_types,
|
||||
simrel_types
|
||||
languages, countries, org_types, id_types, rel_types, simrel_types
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
@ -194,7 +190,7 @@ public class DatabaseUtils {
|
|||
if (oldStatus == null) {
|
||||
op = JournalOperations.NEW_SUGG_ORG;
|
||||
message = "Created a new suggested org";
|
||||
} else if (oldStatus != null) {
|
||||
} else {
|
||||
op = JournalOperations.EDIT_SUGG_ORG;
|
||||
message = "Metadata updated";
|
||||
}
|
||||
|
@ -481,13 +477,12 @@ public class DatabaseUtils {
|
|||
final List<OrganizationView> views =
|
||||
similarIds.stream().map(organizationViewRepository::findById).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
|
||||
|
||||
final List<OrganizationView> persistents = views.stream().filter(v -> v.getPersistent()).collect(Collectors.toList());
|
||||
final List<OrganizationView> persistents = views.stream().filter(OrganizationView::getPersistent).collect(Collectors.toList());
|
||||
|
||||
final OrganizationView masterOrg = new OrganizationView();
|
||||
|
||||
if (persistents.size() > 1) {
|
||||
throw new RuntimeException("Too many persintent organizations");
|
||||
} else if (persistents.size() == 1) {
|
||||
if (persistents.size() > 1) { throw new RuntimeException("Too many persintent organizations"); }
|
||||
if (persistents.size() == 1) {
|
||||
backupOrg(persistents.get(0), user);
|
||||
masterOrg.setId(persistents.get(0).getId());
|
||||
masterOrg.setStatus(OrganizationStatus.approved.toString());
|
||||
|
@ -570,7 +565,7 @@ public class DatabaseUtils {
|
|||
final List<OpenaireDuplicate> newDuplicates = orgs.stream()
|
||||
.map(OrganizationView::getId)
|
||||
.map(openaireDuplicateRepository::findByLocalId)
|
||||
.flatMap(l -> l.stream())
|
||||
.flatMap(List::stream)
|
||||
.map(d -> new OpenaireDuplicate(masterId, d.getOaOriginalId(), d.getRelType(), d.getOaCollectedFrom()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
@ -633,11 +628,11 @@ public class DatabaseUtils {
|
|||
}
|
||||
|
||||
private <T> Set<T> findAll(final List<OrganizationView> views, final Function<OrganizationView, Set<T>> mapper) {
|
||||
return views.stream().map(mapper).flatMap(s -> s.stream()).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
return views.stream().map(mapper).flatMap(Set::stream).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
private <T> Set<T> findAll(final List<OrganizationView> views, final Function<OrganizationView, Set<T>> mapper, final Predicate<T> filter) {
|
||||
return views.stream().map(mapper).flatMap(s -> s.stream()).filter(filter).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
return views.stream().map(mapper).flatMap(Set::stream).filter(filter).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
private List<Relationship> hideConflictOrgs(final String masterId, final String otherId) {
|
||||
|
@ -679,13 +674,67 @@ public class DatabaseUtils {
|
|||
if (valid) {
|
||||
persistentOrganizationRepository.save(new PersistentOrganization(ooid));
|
||||
return ooid;
|
||||
} else {
|
||||
throw new RuntimeException("The ID does not refer to an approved Organization");
|
||||
}
|
||||
throw new RuntimeException("The ID does not refer to an approved Organization");
|
||||
}
|
||||
|
||||
public void deletePersistentOrgs(final String id) {
|
||||
persistentOrganizationRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public List<String> obtainLogEntries(final int year, final int month, final String country) {
|
||||
final String query = "SELECT o.id, o.name, j.operation, j.description, date(j.op_date) as op_date "
|
||||
+ "FROM organizations o JOIN journal j ON o.id = j.id "
|
||||
+ "WHERE o.country=? AND extract(year FROM j.op_date)=? AND extract(month FROM j.op_date)=? "
|
||||
+ "ORDER BY date(j.op_date), o,id";
|
||||
return jdbcTemplate.queryForList(query, country, year, month)
|
||||
.stream()
|
||||
.map(this::asLogEntry)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
private String asLogEntry(final Map<String, Object> map) {
|
||||
final JournalOperations op = JournalOperations.valueOf("" + map.get("operation"));
|
||||
|
||||
final StringWriter sw = new StringWriter();
|
||||
sw.write("On %s a curator ");
|
||||
|
||||
switch (op) {
|
||||
case APPROVE_SUGG_ORG:
|
||||
sw.write("approved the suggested organisation %s (ID: %s)");
|
||||
break;
|
||||
case NEW_ORG:
|
||||
sw.write("created the organisation %s (ID: %s)");
|
||||
break;
|
||||
case NEW_SUGG_ORG:
|
||||
sw.write("suggested the organisation %s (ID: %s)");
|
||||
break;
|
||||
case EDIT_ORG:
|
||||
sw.write("updated the metadata of %s (ID: %s)");
|
||||
break;
|
||||
case EDIT_SUGG_ORG:
|
||||
sw.write("updated the metadata of the suggested organisation %s (ID: %s)");
|
||||
break;
|
||||
case DUPLICATES:
|
||||
sw.write("updated the list of duplicates for %s (ID: %s)");
|
||||
break;
|
||||
case FIX_CONFLICT:
|
||||
sw.write("chose as master the organisation %s (id: %s), which has been involved in a conflict resolution");
|
||||
break;
|
||||
case NO_CONFLICT:
|
||||
sw.write("stated that the conflict where the organisation %s (id: %s) was involved was a false positive");
|
||||
break;
|
||||
case BACKUP_ORG:
|
||||
sw.write("resolved a conflict and the organisation %s (id: %s) involved has been hidden, because another organisation has been chosen as master");
|
||||
break;
|
||||
case UNKNOWN:
|
||||
default:
|
||||
sw.write("performed an unknown operation on %s (ID: %s)");
|
||||
}
|
||||
sw.write(". \"%s\"\n");
|
||||
|
||||
return String.format(sw.toString(), map.get("op_date"), map.get("name"), map.get("id"), map.get("description"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -749,4 +749,15 @@ $$;
|
|||
CREATE TRIGGER insert_or_update_index_search_trigger AFTER INSERT OR UPDATE ON organizations FOR EACH ROW EXECUTE PROCEDURE insert_or_update_index_search_trigger();
|
||||
CREATE TRIGGER delete_index_search_trigger BEFORE DELETE ON organizations FOR EACH ROW EXECUTE PROCEDURE delete_index_search();
|
||||
|
||||
-- PUBLIC VIEW
|
||||
|
||||
CREATE VIEW api_journal_view AS SELECT
|
||||
o.id AS org_id,
|
||||
o.name AS org_name,
|
||||
o.country AS country,
|
||||
j.operation AS operation,
|
||||
j.description AS description,
|
||||
j.op_date AS op_date
|
||||
FROM organizations o JOIN journal j ON o.id = j.id;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue