diff --git a/project-management/src/main/java/life/qbic/projectmanagement/application/measurement/MeasurementService.java b/project-management/src/main/java/life/qbic/projectmanagement/application/measurement/MeasurementService.java index 277436cb3e..b95270b77c 100644 --- a/project-management/src/main/java/life/qbic/projectmanagement/application/measurement/MeasurementService.java +++ b/project-management/src/main/java/life/qbic/projectmanagement/application/measurement/MeasurementService.java @@ -116,7 +116,7 @@ public Collection findProteomicsMeasurement(String filter } private Result registerNGS( - NGSMeasurementMetadata ngsMeasurementMetadata) { + ProjectId projectId, NGSMeasurementMetadata ngsMeasurementMetadata) { var associatedSampleCodes = ngsMeasurementMetadata.associatedSamples(); var selectedSampleCode = MeasurementCode.createNGS( @@ -134,6 +134,7 @@ private Result registerNGS( } var measurement = NGSMeasurement.create( + projectId, sampleIdCodeEntries.stream().map(SampleIdCodeEntry::sampleId).toList(), selectedSampleCode, instrumentQuery.get()); @@ -150,7 +151,7 @@ private Result registerNGS( } private Result registerPxP( - ProteomicsMeasurementMetadata metadata) { + ProjectId projectId, ProteomicsMeasurementMetadata metadata) { var associatedSampleCodes = metadata.associatedSamples(); var selectedSampleCode = MeasurementCode.createMS( String.valueOf(metadata.associatedSamples().get(0).code())); @@ -183,6 +184,7 @@ private Result registerPxP( label.sampleCode(), label.labelType(), label.label())).toList(); var measurement = ProteomicsMeasurement.create( + projectId, sampleIdCodeEntries.stream().map(SampleIdCodeEntry::sampleId).toList(), selectedSampleCode, organisationQuery.get(), @@ -213,10 +215,10 @@ public Result register(ProjectId projectId, return Result.fromError(ResponseCode.MISSING_ASSOCIATED_SAMPLES); } if (measurementMetadata instanceof ProteomicsMeasurementMetadata proteomicsMeasurementMetadata) { - return registerPxP(proteomicsMeasurementMetadata); + return registerPxP(projectId, proteomicsMeasurementMetadata); } if (measurementMetadata instanceof NGSMeasurementMetadata ngsMeasurementMetadata) { - return registerNGS(ngsMeasurementMetadata); + return registerNGS(projectId, ngsMeasurementMetadata); } return Result.fromError(ResponseCode.FAILED); } diff --git a/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/NGSMeasurement.java b/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/NGSMeasurement.java index ccadb18714..a18efe3c96 100644 --- a/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/NGSMeasurement.java +++ b/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/NGSMeasurement.java @@ -1,12 +1,21 @@ package life.qbic.projectmanagement.domain.model.measurement; -import jakarta.persistence.*; +import static java.util.Objects.requireNonNull; +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embedded; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; import java.util.ArrayList; import java.util.Collection; -import java.util.Objects; import life.qbic.projectmanagement.application.measurement.MeasurementMetadata; import life.qbic.projectmanagement.domain.model.OntologyTerm; +import life.qbic.projectmanagement.domain.model.project.ProjectId; import life.qbic.projectmanagement.domain.model.sample.SampleId; /** @@ -29,6 +38,10 @@ public class NGSMeasurement implements MeasurementMetadata { @AttributeOverride(name = "uuid", column = @Column(name = "measurement_id")) private MeasurementId id; + @Embedded + @Column(nullable = false) + private ProjectId projectId; + @Embedded private OntologyTerm instrument; @@ -44,9 +57,11 @@ protected NGSMeasurement() { // Needed for JPA } - private NGSMeasurement(Collection sampleIds, MeasurementCode measurementCode, OntologyTerm instrument) { + private NGSMeasurement(ProjectId projectId, Collection sampleIds, + MeasurementCode measurementCode, OntologyTerm instrument) { measuredSamples = new ArrayList<>(); measuredSamples.addAll(sampleIds); + this.projectId = requireNonNull(projectId, "projectId must not be null"); this.instrument = instrument; this.measurementCode = measurementCode; } @@ -55,6 +70,7 @@ private NGSMeasurement(Collection sampleIds, MeasurementCode measureme * Creates a new {@link NGSMeasurement} object instance, that describes an NGS measurement entity * with many describing properties about provenance and instrumentation. * + * @param projectId * @param sampleIds the sample ids of the samples the measurement was performed on. If more than * one sample id is provided, the measurement is considered to be performed on a * pooled sample @@ -63,17 +79,18 @@ private NGSMeasurement(Collection sampleIds, MeasurementCode measureme * @return * @since 1.0.0 */ - public static NGSMeasurement create(Collection sampleIds, MeasurementCode measurementCode, OntologyTerm instrument) { + public static NGSMeasurement create(ProjectId projectId, Collection sampleIds, + MeasurementCode measurementCode, OntologyTerm instrument) { if (sampleIds.isEmpty()) { throw new IllegalArgumentException( "No sample ids provided. At least one sample id must provided for a measurement."); } - Objects.requireNonNull(instrument); - Objects.requireNonNull(measurementCode); + requireNonNull(instrument); + requireNonNull(measurementCode); if (!measurementCode.isNGSDomain()) { throw new IllegalArgumentException("NGSMeasurementMetadata code is not from the NGS domain for: \"" + measurementCode + "\""); } - return new NGSMeasurement(sampleIds, measurementCode, instrument); + return new NGSMeasurement(projectId, sampleIds, measurementCode, instrument); } /** diff --git a/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/ProteomicsMeasurement.java b/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/ProteomicsMeasurement.java index 2881ee325c..33c2f460ec 100644 --- a/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/ProteomicsMeasurement.java +++ b/project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/ProteomicsMeasurement.java @@ -1,5 +1,7 @@ package life.qbic.projectmanagement.domain.model.measurement; +import static java.util.Objects.requireNonNull; + import jakarta.persistence.AttributeOverride; import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; @@ -14,13 +16,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Objects; import java.util.Optional; import java.util.Set; import life.qbic.projectmanagement.application.measurement.MeasurementMetadata; import life.qbic.projectmanagement.domain.Organisation; import life.qbic.projectmanagement.domain.model.OntologyTerm; import life.qbic.projectmanagement.domain.model.measurement.MeasurementCode.MeasurementCodeConverter; +import life.qbic.projectmanagement.domain.model.project.ProjectId; import life.qbic.projectmanagement.domain.model.sample.SampleId; /** @@ -43,6 +45,10 @@ public class ProteomicsMeasurement implements MeasurementMetadata { @AttributeOverride(name = "uuid", column = @Column(name = "measurement_id")) private MeasurementId id; + @Embedded + @Column(nullable = false) + ProjectId projectId; + @Column(name = "instrument", columnDefinition = "longtext CHECK (json_valid(`instrument`))") private OntologyTerm instrument; @@ -97,9 +103,11 @@ protected ProteomicsMeasurement() { // Needed for JPA } - private ProteomicsMeasurement(MeasurementId id, Collection sampleIds, + private ProteomicsMeasurement(ProjectId projectId, MeasurementId id, + Collection sampleIds, MeasurementCode measurementCode, Organisation organisation, ProteomicsMethodMetadata method, Instant registration) { + this.projectId = requireNonNull(projectId, "projectId must not be null"); evaluateMandatorMetadata( method); // throws IllegalArgumentException if required properties are missing measuredSamples = new ArrayList<>(); @@ -155,6 +163,7 @@ private static void evaluateMandatorMetadata(ProteomicsMethodMetadata method) * Creates a new {@link ProteomicsMeasurement} object instance, that describes an NGS measurement * entity with many describing properties about provenance and instrumentation. * + * @param projectId * @param sampleIds the sample ids of the samples the measurement was performed on. If more than * one sample id is provided, the measurement is considered to be performed on a * pooled sample @@ -162,28 +171,30 @@ private static void evaluateMandatorMetadata(ProteomicsMethodMetadata method) * @throws IllegalArgumentException in case there are missing required metadata. * @since 1.0.0 */ - public static ProteomicsMeasurement create(Collection sampleIds, + public static ProteomicsMeasurement create(ProjectId projectId, Collection sampleIds, MeasurementCode measurementCode, Organisation organisation, ProteomicsMethodMetadata method) throws IllegalArgumentException { if (sampleIds.isEmpty()) { throw new IllegalArgumentException( "No sample ids provided. At least one sample id must provided for a measurement."); } - Objects.requireNonNull(method.instrument()); - Objects.requireNonNull(measurementCode); + requireNonNull(method.instrument()); + requireNonNull(measurementCode); if (!measurementCode.isMSDomain()) { throw new IllegalArgumentException( "Proteomics code is not from the Proteomics domain for: \"" + measurementCode + "\""); } var measurementId = MeasurementId.create(); - return new ProteomicsMeasurement(measurementId, sampleIds, measurementCode, organisation, + return new ProteomicsMeasurement(projectId, measurementId, sampleIds, measurementCode, + organisation, method, Instant.now()); } - public static ProteomicsMeasurement create(Collection sampleIds, MeasurementCode code, + public static ProteomicsMeasurement create(ProjectId projectId, Collection sampleIds, + MeasurementCode code, Organisation organisation, ProteomicsMethodMetadata method, ProteomicsSamplePreparation samplePreparation) { - var measurement = create(sampleIds, code, organisation, method); + var measurement = create(projectId, sampleIds, code, organisation, method); measurement.setSamplePreparation(samplePreparation); return measurement; }