UrlsController/src/main/java/eu/openaire/urls_controller/models/BulkImportReport.java

129 lines
4.4 KiB
Java
Raw Permalink Normal View History

package eu.openaire.urls_controller.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.gson.Gson;
import eu.openaire.urls_controller.util.GenericUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BulkImportReport {
private static final Logger logger = LoggerFactory.getLogger(BulkImportReport.class);
private static final Gson gson = new Gson(); // This is "transient" by default. It won't be included in any json object.
@JsonProperty
private String provenance;
@JsonProperty
private String reportLocation;
@JsonProperty
private String reportID;
// This will not be serialized, since Gson cannot serialize Multimaps. Instead, it will be converted to the "simpler" map below.
transient private SetMultimap<String, String> eventsMultimap = Multimaps.synchronizedSetMultimap(LinkedHashMultimap.create());
// We need a "LinkedHashMultimap", se that the order of the keys (timestamps) stay ascending, so the final report makes sense in chronological order.
// We need for one key (timestamp) to have multiple values (events), in order to not lose events happening at the same time.
@JsonProperty
private Map<String, Collection<String>> eventsMap;
transient private final Lock reportLock = new ReentrantLock(true);
public BulkImportReport(String provenance, String reportLocation, String reportID) {
this.provenance = provenance;
this.reportLocation = reportLocation;
this.reportID = reportID;
}
public void addEvent(String event) {
eventsMultimap.put(GenericUtils.getReadableCurrentTimeAndZone(), event); // This is synchronized.
}
/**
* Synchronize it with a lock, to avoid concurrency issues when concurrent calls are made to the same bulkImport-Report object.
* */
public String getJsonReport()
{
String reportToReturn = null;
reportLock.lock();
try {
//Convert the SetMultimap<String, String> to Map<String, Collection<String>>, since Gson cannot serialize Multimaps.
eventsMap = new LinkedHashMap<>(eventsMultimap.asMap()); // Make sure we use a clone of the original data, in order to avoid any exception in the "gson.toJson()" method, when at the same time another thread modifies the "eventsMultimap".
reportToReturn = gson.toJson(this, BulkImportReport.class);
} catch (Exception e) {
logger.error("Problem when producing the JSON-string with the BulkImportReport! | reportID: '" + reportID + "'", e);
} finally {
reportLock.unlock();
}
return reportToReturn; // It may be null.
}
public String getProvenance() {
return provenance;
}
public void setProvenance(String provenance) {
this.provenance = provenance;
}
public String getReportLocation() {
return reportLocation;
}
public void setReportLocation(String reportLocation) {
this.reportLocation = reportLocation;
}
public String getReportID() {
return reportID;
}
public void setReportID(String reportID) {
this.reportID = reportID;
}
public SetMultimap<String, String> getEventsMultimap() {
return eventsMultimap;
}
public void setEventsMultimap(SetMultimap<String, String> eventsMultimap) {
this.eventsMultimap = eventsMultimap;
}
public Map<String, Collection<String>> getEventsMap() {
return eventsMap;
}
public void setEventsMap(Map<String, Collection<String>> eventsMap) {
this.eventsMap = eventsMap;
}
@Override
public String toString() {
return "BulkImportReport{" +
"provenance='" + provenance + '\'' +
", reportLocation='" + reportLocation + '\'' +
", reportID='" + reportID + '\'' +
", eventsMultimap=" + eventsMultimap +
", eventsMap=" + eventsMap +
'}';
}
}