Skip to content

Commit 6cacd84

Browse files
Copilothmiguim
andcommitted
Implement requested changes: JobStats columns, StepReport entity, fix line separator
Co-authored-by: hmiguim <1252710+hmiguim@users.noreply.github.com>
1 parent 7cb08a2 commit 6cacd84

5 files changed

Lines changed: 513 additions & 12 deletions

File tree

roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/jobs/Job.java

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.roda.core.data.v2.ip.HasId;
2323
import org.roda.core.data.v2.ip.HasInstanceID;
2424
import org.roda.core.data.v2.ip.HasInstanceName;
25-
import org.roda.core.data.v2.jpa.JobStatsConverter;
2625
import org.roda.core.data.v2.jpa.JobUserDetailsListConverter;
2726
import org.roda.core.data.v2.jpa.ObjectMapConverter;
2827
import org.roda.core.data.v2.jpa.SelectedItemsConverter;
@@ -96,10 +95,29 @@ public enum JOB_STATE {
9695
@Column(name = "instance_name")
9796
private String instanceName = null;
9897

99-
// job statistics (total source objects, etc.)
100-
@Column(name = "job_stats", columnDefinition = "TEXT")
101-
@Convert(converter = JobStatsConverter.class)
102-
JobStats jobStats = new JobStats();
98+
// job statistics - expanded into separate columns
99+
@Column(name = "stats_completion_percentage")
100+
private int statsCompletionPercentage = 0;
101+
@Column(name = "stats_source_objects_count")
102+
private int statsSourceObjectsCount = 0;
103+
@Column(name = "stats_source_objects_being_processed")
104+
private int statsSourceObjectsBeingProcessed = 0;
105+
@Column(name = "stats_source_objects_waiting_to_be_processed")
106+
private int statsSourceObjectsWaitingToBeProcessed = 0;
107+
@Column(name = "stats_source_objects_processed_with_success")
108+
private int statsSourceObjectsProcessedWithSuccess = 0;
109+
@Column(name = "stats_source_objects_processed_with_partial_success")
110+
private int statsSourceObjectsProcessedWithPartialSuccess = 0;
111+
@Column(name = "stats_source_objects_processed_with_failure")
112+
private int statsSourceObjectsProcessedWithFailure = 0;
113+
@Column(name = "stats_source_objects_processed_with_skipped")
114+
private int statsSourceObjectsProcessedWithSkipped = 0;
115+
@Column(name = "stats_outcome_objects_with_manual_intervention")
116+
private int statsOutcomeObjectsWithManualIntervention = 0;
117+
118+
// Transient jobStats field for backwards compatibility with existing code
119+
@Transient
120+
private JobStats jobStats = null;
103121

104122
// plugin full class (e.g. org.roda.core.plugins.plugins.base.FixityPlugin)
105123
@Column(name = "plugin")
@@ -258,11 +276,36 @@ public void setStateDetails(String stateDetails) {
258276
}
259277

260278
public JobStats getJobStats() {
279+
// Build JobStats from individual columns for backwards compatibility
280+
if (jobStats == null) {
281+
jobStats = new JobStats();
282+
}
283+
jobStats.setCompletionPercentage(statsCompletionPercentage);
284+
jobStats.setSourceObjectsCount(statsSourceObjectsCount);
285+
jobStats.setSourceObjectsBeingProcessed(statsSourceObjectsBeingProcessed);
286+
jobStats.setSourceObjectsWaitingToBeProcessed(statsSourceObjectsWaitingToBeProcessed);
287+
jobStats.setSourceObjectsProcessedWithSuccess(statsSourceObjectsProcessedWithSuccess);
288+
jobStats.setSourceObjectsProcessedWithPartialSuccess(statsSourceObjectsProcessedWithPartialSuccess);
289+
jobStats.setSourceObjectsProcessedWithFailure(statsSourceObjectsProcessedWithFailure);
290+
jobStats.setSourceObjectsProcessedWithSkipped(statsSourceObjectsProcessedWithSkipped);
291+
jobStats.setOutcomeObjectsWithManualIntervention(statsOutcomeObjectsWithManualIntervention);
261292
return jobStats;
262293
}
263294

264295
public void setJobStats(JobStats jobStats) {
265296
this.jobStats = jobStats;
297+
// Sync to individual columns
298+
if (jobStats != null) {
299+
this.statsCompletionPercentage = jobStats.getCompletionPercentage();
300+
this.statsSourceObjectsCount = jobStats.getSourceObjectsCount();
301+
this.statsSourceObjectsBeingProcessed = jobStats.getSourceObjectsBeingProcessed();
302+
this.statsSourceObjectsWaitingToBeProcessed = jobStats.getSourceObjectsWaitingToBeProcessed();
303+
this.statsSourceObjectsProcessedWithSuccess = jobStats.getSourceObjectsProcessedWithSuccess();
304+
this.statsSourceObjectsProcessedWithPartialSuccess = jobStats.getSourceObjectsProcessedWithPartialSuccess();
305+
this.statsSourceObjectsProcessedWithFailure = jobStats.getSourceObjectsProcessedWithFailure();
306+
this.statsSourceObjectsProcessedWithSkipped = jobStats.getSourceObjectsProcessedWithSkipped();
307+
this.statsOutcomeObjectsWithManualIntervention = jobStats.getOutcomeObjectsWithManualIntervention();
308+
}
266309
}
267310

268311
public String getPlugin() {

roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/jobs/Report.java

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@
1717
import org.roda.core.data.v2.ip.HasId;
1818
import org.roda.core.data.v2.ip.HasInstanceID;
1919
import org.roda.core.data.v2.ip.SIPInformation;
20-
import org.roda.core.data.v2.jpa.ReportListConverter;
2120
import org.roda.core.data.v2.jpa.StringListConverter;
2221

2322
import com.fasterxml.jackson.annotation.JsonIgnore;
2423
import com.fasterxml.jackson.annotation.JsonInclude;
2524
import com.fasterxml.jackson.annotation.JsonProperty;
2625

26+
import jakarta.persistence.CascadeType;
2727
import jakarta.persistence.Column;
2828
import jakarta.persistence.Convert;
2929
import jakarta.persistence.Entity;
3030
import jakarta.persistence.EnumType;
3131
import jakarta.persistence.Enumerated;
32+
import jakarta.persistence.FetchType;
3233
import jakarta.persistence.Id;
3334
import jakarta.persistence.Index;
35+
import jakarta.persistence.OneToMany;
36+
import jakarta.persistence.OrderBy;
3437
import jakarta.persistence.Table;
3538
import jakarta.persistence.Temporal;
3639
import jakarta.persistence.TemporalType;
@@ -111,9 +114,13 @@ public class Report implements IsModelObject, HasId, HasInstanceID {
111114
@JsonIgnore
112115
private SIPInformation sipInformation = new SIPInformation();
113116

114-
@Column(name = "reports", columnDefinition = "TEXT")
115-
@Convert(converter = ReportListConverter.class)
116-
private List<Report> reports = new ArrayList<>();
117+
@OneToMany(mappedBy = "parentReportId", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
118+
@OrderBy("stepOrder ASC")
119+
private List<StepReport> stepReports = new ArrayList<>();
120+
121+
// Transient field for backwards compatibility with existing code that uses List<Report>
122+
@Transient
123+
private List<Report> reports = null;
117124

118125
@Column(name = "line_separator")
119126
private String lineSeparator = "";
@@ -152,7 +159,8 @@ public Report(Report report) {
152159
this.pluginIsMandatory = report.getPluginIsMandatory();
153160
this.pluginDetails = report.getPluginDetails();
154161
this.htmlPluginDetails = report.isHtmlPluginDetails();
155-
this.reports = new ArrayList<>();
162+
this.reports = null;
163+
this.stepReports = new ArrayList<>();
156164
this.instanceId = report.getInstanceId();
157165
this.transactionId = report.getTransactionId();
158166
}
@@ -472,12 +480,25 @@ public Report addReport(Report report, boolean updateReportItemDateUpdated) {
472480
ReportUtils.calculatePluginState(getPluginState(), report.getPluginState(), report.getPluginIsMandatory()));
473481

474482
if (!"".equals(report.getPluginDetails()) && !getPluginDetails().equals(report.getPluginDetails())) {
483+
// Fix: avoid adding repeated line separators
484+
String separator = (lineSeparator != null && !lineSeparator.isEmpty()) ? lineSeparator : "\n";
475485
setPluginDetails(
476-
(!"".equals(getPluginDetails()) ? getPluginDetails() + lineSeparator : "") + report.getPluginDetails());
486+
(!"".equals(getPluginDetails()) ? getPluginDetails() + separator : "") + report.getPluginDetails());
477487
}
478488
setOutcomeObjectState(report.getOutcomeObjectState());
479489

490+
// Add to both stepReports (JPA entity) and reports (backwards compatibility)
491+
if (reports == null) {
492+
reports = new ArrayList<>();
493+
}
480494
reports.add(report);
495+
496+
// Also add as StepReport
497+
if (stepReports == null) {
498+
stepReports = new ArrayList<>();
499+
}
500+
stepReports.add(new StepReport(report, this.id, stepReports.size()));
501+
481502
return this;
482503
}
483504

@@ -497,15 +518,50 @@ public Report addReport(Report report, boolean updateReportItemDateUpdated) {
497518
* return newPluginState; }
498519
*/
499520

521+
/**
522+
* Get the step reports as a list of Report objects for backwards compatibility.
523+
* If reports is null, builds it from stepReports.
524+
*/
500525
public List<Report> getReports() {
501-
return reports;
526+
if (reports == null && stepReports != null) {
527+
reports = new ArrayList<>();
528+
for (StepReport stepReport : stepReports) {
529+
reports.add(stepReport.toReport());
530+
}
531+
}
532+
return reports != null ? reports : new ArrayList<>();
502533
}
503534

504535
public Report setReports(List<Report> reports) {
505536
this.reports = reports;
537+
// Sync to stepReports
538+
if (reports != null) {
539+
this.stepReports = new ArrayList<>();
540+
int order = 0;
541+
for (Report report : reports) {
542+
this.stepReports.add(new StepReport(report, this.id, order++));
543+
}
544+
}
506545
return this;
507546
}
508547

548+
/**
549+
* Get the underlying StepReport entities.
550+
*/
551+
@JsonIgnore
552+
public List<StepReport> getStepReports() {
553+
return stepReports;
554+
}
555+
556+
/**
557+
* Set the underlying StepReport entities.
558+
*/
559+
@JsonIgnore
560+
public void setStepReports(List<StepReport> stepReports) {
561+
this.stepReports = stepReports;
562+
this.reports = null; // Reset cached reports
563+
}
564+
509565
@JsonProperty("lineSeparator")
510566
public void injectLineSeparator(String lineSeparator) {
511567
this.lineSeparator = lineSeparator;

0 commit comments

Comments
 (0)