Skip to content

Commit

Permalink
Merge pull request #7 from DiSSCo/feature/add-rollback
Browse files Browse the repository at this point in the history
Add rollback functionality and remove duplication
  • Loading branch information
samleeflang authored Nov 11, 2022
2 parents 16f351d + 165ba83 commit f3bef1c
Show file tree
Hide file tree
Showing 22 changed files with 948 additions and 190 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
</dependencies>

<build>
<defaultGoal>clean package</defaultGoal>
<defaultGoal>-B verify</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Random;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

Expand All @@ -24,7 +26,16 @@ public Random random() {
@Bean
public DocumentBuilder documentBuilder() throws ParserConfigurationException {
var docFactory = DocumentBuilderFactory.newInstance();
docFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
return docFactory.newDocumentBuilder();
}

@Bean
public TransformerFactory transformerFactory() {
var factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
return factory;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
package eu.dissco.core.digitalspecimenprocessor.domain;

import java.util.Arrays;
import java.util.Objects;

public record HandleAttribute(int index, String type, byte[] data) {

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
HandleAttribute that = (HandleAttribute) o;
return index == that.index && Objects.equals(type, that.type)
&& Arrays.equals(data, that.data);
}

@Override
public int hashCode() {
int result = Objects.hash(index, type);
result = 31 * result + Arrays.hashCode(data);
return result;
}

@Override
public String toString() {
return "HandleAttribute{" +
"index=" + index +
", type='" + type + '\'' +
", data=" + Arrays.toString(data) +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package eu.dissco.core.digitalspecimenprocessor.domain;

import java.util.List;

public record UpdatedDigitalSpecimenRecord(DigitalSpecimenRecord digitalSpecimenRecord,
List<String> enrichment,
DigitalSpecimenRecord currentDigitalSpecimen) {

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package eu.dissco.core.digitalspecimenprocessor.domain;

public record UpdatedDigitalSpecimenTuple(DigitalSpecimenRecord currentSpecimen,
DigitalSpecimen digitalSpecimen) {
DigitalSpecimenEvent digitalSpecimenEvent) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package eu.dissco.core.digitalspecimenprocessor.exception;

import org.springframework.dao.DataAccessException;

public class DisscoJsonBMappingException extends DataAccessException {

public DisscoJsonBMappingException(String msg, Throwable cause) {
super(msg, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package eu.dissco.core.digitalspecimenprocessor.exception;

public class DisscoRepositoryException extends Exception{

public DisscoRepositoryException(String message) {
super(message);
}

public DisscoRepositoryException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import static eu.dissco.core.digitalspecimenprocessor.database.jooq.Tables.NEW_DIGITAL_SPECIMEN;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.dissco.core.digitalspecimenprocessor.domain.DigitalSpecimen;
import eu.dissco.core.digitalspecimenprocessor.domain.DigitalSpecimenRecord;
import eu.dissco.core.digitalspecimenprocessor.exception.DisscoJsonBMappingException;
import eu.dissco.core.digitalspecimenprocessor.exception.DisscoRepositoryException;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
Expand All @@ -14,6 +17,7 @@
import org.jooq.JSONB;
import org.jooq.Query;
import org.jooq.Record;
import org.jooq.exception.DataAccessException;
import org.springframework.stereotype.Repository;

@Repository
Expand All @@ -25,21 +29,18 @@ public class DigitalSpecimenRepository {

private DigitalSpecimenRecord mapDigitalSpecimen(Record dbRecord) {
DigitalSpecimen digitalSpecimen = null;
try {
digitalSpecimen = new DigitalSpecimen(dbRecord.get(NEW_DIGITAL_SPECIMEN.TYPE),
dbRecord.get(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_ID),
dbRecord.get(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_TYPE),
dbRecord.get(NEW_DIGITAL_SPECIMEN.SPECIMEN_NAME),
dbRecord.get(NEW_DIGITAL_SPECIMEN.ORGANIZATION_ID),
dbRecord.get(NEW_DIGITAL_SPECIMEN.DATASET),
dbRecord.get(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_COLLECTION),
dbRecord.get(NEW_DIGITAL_SPECIMEN.SOURCE_SYSTEM_ID),
mapper.readTree(dbRecord.get(NEW_DIGITAL_SPECIMEN.DATA).data()),
mapper.readTree(dbRecord.get(NEW_DIGITAL_SPECIMEN.ORIGINAL_DATA).data()),
dbRecord.get(NEW_DIGITAL_SPECIMEN.DWCA_ID));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
digitalSpecimen = new DigitalSpecimen(dbRecord.get(NEW_DIGITAL_SPECIMEN.TYPE),
dbRecord.get(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_ID),
dbRecord.get(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_TYPE),
dbRecord.get(NEW_DIGITAL_SPECIMEN.SPECIMEN_NAME),
dbRecord.get(NEW_DIGITAL_SPECIMEN.ORGANIZATION_ID),
dbRecord.get(NEW_DIGITAL_SPECIMEN.DATASET),
dbRecord.get(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_COLLECTION),
dbRecord.get(NEW_DIGITAL_SPECIMEN.SOURCE_SYSTEM_ID),
mapToJson(dbRecord.get(NEW_DIGITAL_SPECIMEN.DATA)),
mapToJson(dbRecord.get(NEW_DIGITAL_SPECIMEN.ORIGINAL_DATA)),
dbRecord.get(NEW_DIGITAL_SPECIMEN.DWCA_ID));

return new DigitalSpecimenRecord(
dbRecord.get(NEW_DIGITAL_SPECIMEN.ID),
dbRecord.get(NEW_DIGITAL_SPECIMEN.MIDSLEVEL),
Expand All @@ -48,6 +49,16 @@ private DigitalSpecimenRecord mapDigitalSpecimen(Record dbRecord) {
digitalSpecimen);
}

private JsonNode mapToJson(JSONB jsonb) {
try {
return mapper.readTree(jsonb.data());
} catch (JsonProcessingException e) {
throw new DisscoJsonBMappingException(
"Failed to parse jsonb field to json: " + jsonb.data(), e);
}
}


public int[] createDigitalSpecimenRecord(
Collection<DigitalSpecimenRecord> digitalSpecimenRecords) {
var queries = digitalSpecimenRecords.stream().map(this::specimenToQuery).toList();
Expand Down Expand Up @@ -89,12 +100,31 @@ public int updateLastChecked(List<String> currentDigitalSpecimen) {
.execute();
}

public List<DigitalSpecimenRecord> getDigitalSpecimens(List<String> specimenList) {
return context.select(NEW_DIGITAL_SPECIMEN.asterisk())
.distinctOn(NEW_DIGITAL_SPECIMEN.ID)
.from(NEW_DIGITAL_SPECIMEN)
.where(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_ID.in(specimenList))
.orderBy(NEW_DIGITAL_SPECIMEN.ID, NEW_DIGITAL_SPECIMEN.VERSION.desc())
.fetch(this::mapDigitalSpecimen);
public List<DigitalSpecimenRecord> getDigitalSpecimens(List<String> specimenList)
throws DisscoRepositoryException {
try {
return context.select(NEW_DIGITAL_SPECIMEN.asterisk())
.distinctOn(NEW_DIGITAL_SPECIMEN.ID)
.from(NEW_DIGITAL_SPECIMEN)
.where(NEW_DIGITAL_SPECIMEN.PHYSICAL_SPECIMEN_ID.in(specimenList))
.orderBy(NEW_DIGITAL_SPECIMEN.ID, NEW_DIGITAL_SPECIMEN.VERSION.desc())
.fetch(this::mapDigitalSpecimen);
} catch (DataAccessException ex) {
throw new DisscoRepositoryException(
"Failed to get specimen from repository: " + specimenList);
}
}

public void rollbackSpecimen(String handle) {
context.delete(NEW_DIGITAL_SPECIMEN)
.where(NEW_DIGITAL_SPECIMEN.ID.eq(handle))
.execute();
}

public void deleteVersion(DigitalSpecimenRecord digitalSpecimenRecord) {
context.delete(NEW_DIGITAL_SPECIMEN)
.where(NEW_DIGITAL_SPECIMEN.ID.eq(digitalSpecimenRecord.id()))
.and(NEW_DIGITAL_SPECIMEN.VERSION.eq(digitalSpecimenRecord.version()))
.execute();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.DeleteResponse;
import eu.dissco.core.digitalspecimenprocessor.domain.DigitalSpecimenRecord;
import eu.dissco.core.digitalspecimenprocessor.property.ElasticSearchProperties;
import java.io.IOException;
Expand Down Expand Up @@ -30,4 +31,14 @@ public BulkResponse indexDigitalSpecimen(Collection<DigitalSpecimenRecord> digit
}
return client.bulk(bulkRequest.build());
}

public DeleteResponse rollbackSpecimen(DigitalSpecimenRecord digitalSpecimenRecord)
throws IOException {
return client.delete(d -> d.index(properties.getIndexName()).id(digitalSpecimenRecord.id()));
}

public void rollbackVersion(DigitalSpecimenRecord currentDigitalSpecimen) throws IOException {
client.index(i -> i.index(properties.getIndexName()).id(currentDigitalSpecimen.id())
.document(currentDigitalSpecimen));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void createHandle(String handle, Instant recordTimestamp,
}

public void updateHandleAttributes(String id, Instant recordTimestamp,
List<HandleAttribute> handleAttributes) {
List<HandleAttribute> handleAttributes, boolean versionIncrement) {
var queryList = new ArrayList<Query>();
for (var handleAttribute : handleAttributes) {
var query = context.update(HANDLES)
Expand All @@ -49,24 +49,37 @@ public void updateHandleAttributes(String id, Instant recordTimestamp,
.and(HANDLES.IDX.eq(handleAttribute.index()));
queryList.add(query);
}
queryList.add(versionIncrement(id, recordTimestamp));
queryList.add(versionIncrement(id, recordTimestamp, versionIncrement));
context.batch(queryList).execute();
}

private Query versionIncrement(String pid, Instant recordTimestamp) {
private Query versionIncrement(String pid, Instant recordTimestamp, boolean versionIncrement) {
var currentVersion =
Integer.parseInt(context.select(HANDLES.DATA)
.from(HANDLES)
.where(HANDLES.HANDLE.eq(pid.getBytes(
StandardCharsets.UTF_8)))
.and(HANDLES.TYPE.eq("issueNumber".getBytes(StandardCharsets.UTF_8)))
.fetchOne(dbRecord -> new String(dbRecord.value1())));
var version = currentVersion + 1;
int version;
if (versionIncrement){
version = currentVersion + 1;
} else {
version = currentVersion - 1;
}

return context.update(HANDLES)
.set(HANDLES.DATA, String.valueOf(version).getBytes(StandardCharsets.UTF_8))
.set(HANDLES.TIMESTAMP, recordTimestamp.getEpochSecond())
.where(HANDLES.HANDLE.eq(pid.getBytes(
StandardCharsets.UTF_8)))
.and(HANDLES.TYPE.eq("issueNumber".getBytes(StandardCharsets.UTF_8)));
}

public void rollbackHandleCreation(String id) {
context.delete(HANDLES)
.where(HANDLES.HANDLE.eq(id.getBytes(StandardCharsets.UTF_8)))
.execute();
}

}
Loading

0 comments on commit f3bef1c

Please sign in to comment.