Skip to content

Commit a66de09

Browse files
authored
Merge pull request #473 from qbicsoftware/release/0.34.0
Release 0.34.0
2 parents d7432cc + dcceede commit a66de09

File tree

74 files changed

+2385
-2703
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2385
-2703
lines changed

project-management-infrastructure/src/main/java/life/qbic/projectmanagement/infrastructure/ontology/OntologyTermJpaRepository.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,15 @@ public List<OntologyClassEntity> query(int offset, int limit) {
4141
private String buildSearchTerm(String searchString) {
4242
StringBuilder searchTermBuilder = new StringBuilder();
4343
for(String word : searchString.split(" ")) {
44-
searchTermBuilder.append(" +" + word);
44+
searchTermBuilder.append(" +").append(word);
4545
}
4646
searchTermBuilder.append("*");
4747
return searchTermBuilder.toString().trim();
4848
}
4949

5050
@Override
51-
public List<OntologyClassEntity> query(String searchString, List<String> ontologyAbbreviations,
51+
public List<OntologyClassEntity> query(String searchString,
52+
List<String> ontologyAbbreviations,
5253
int offset,
5354
int limit, List<SortOrder> sortOrders) {
5455
List<Order> orders = sortOrders.stream().map(it -> {

project-management-infrastructure/src/main/java/life/qbic/projectmanagement/infrastructure/ontology/OntologyTermRepository.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,5 @@ public interface OntologyTermRepository extends
1919
countQuery = "SELECT count(*) FROM ontology_classes WHERE MATCH(label) AGAINST(?1 IN BOOLEAN MODE) AND ontology in (?2);",
2020
nativeQuery = true)
2121
Page<OntologyClassEntity> findByLabelFulltextMatching(
22-
String termFilter, List<String> ontology, Pageable pageable);
23-
24-
Page<OntologyClassEntity> findByLabelNotNullAndOntologyIn(List<String> ontologies, Pageable pageable);
25-
26-
Page<OntologyClassEntity> findByLabelStartingWithIgnoreCaseAndOntologyIn(String filter, List<String> ontology, Pageable pageable);
22+
String termFilter, List<String> ontologyAbbreviations, Pageable pageable);
2723
}

project-management-infrastructure/src/main/java/life/qbic/projectmanagement/infrastructure/ontology/OntologyTermRepositoryImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public OntologyTermRepositoryImpl(QbicOntologyTermRepo ontologyTermRepo) {
3838

3939
@Override
4040
public List<OntologyClassEntity> find(String name) {
41-
return ontologyTermRepo.findOntologyTermByName(name);
41+
return ontologyTermRepo.findOntologyClassEntitiesByClassName(name);
4242
}
4343

4444
@Override

project-management-infrastructure/src/main/java/life/qbic/projectmanagement/infrastructure/ontology/QbicOntologyTermRepo.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@
1717
*/
1818
public interface QbicOntologyTermRepo extends CrudRepository<OntologyClassEntity, Long> {
1919

20-
List<OntologyClassEntity> findOntologyTermByName(String name);
20+
List<OntologyClassEntity> findOntologyClassEntitiesByClassName(String name);
2121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package life.qbic.projectmanagement.application;
2+
3+
import java.util.List;
4+
import life.qbic.projectmanagement.domain.model.project.Contact;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
public class ContactRepository {
9+
10+
public List<Contact> findAll() {
11+
//TODO implement
12+
return dummyContacts();
13+
}
14+
15+
private static List<Contact> dummyContacts() {
16+
return List.of(
17+
new Contact("Max Mustermann", "[email protected]"),
18+
new Contact("David Müller", "[email protected]"),
19+
new Contact("John Koch", "[email protected]"),
20+
new Contact("Trevor Noah", "[email protected]"),
21+
new Contact("Sarah Connor", "[email protected]"),
22+
new Contact("Anna Bell", "[email protected]"),
23+
new Contact("Sophia Turner", "[email protected]"),
24+
new Contact("Tylor Smith", "[email protected]")
25+
);
26+
}
27+
28+
29+
}

project-management/src/main/java/life/qbic/projectmanagement/application/DeletionService.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,19 @@ public BatchId deleteBatch(ProjectId projectId, BatchId batchId) {
9797
deletedBatchId.onError(error -> {
9898
throw new ApplicationException("Could not delete batch " + batchId);
9999
});
100-
deleteSamples(projectId, samples);
100+
deleteSamples(projectId, batchId, samples);
101101
return deletedBatchId.getValue();
102102
}
103103

104104

105105
@Transactional
106106
public void deleteSamples(
107-
ProjectId projectId, Collection<SampleId> samplesCollection) {
107+
ProjectId projectId, BatchId batchId, Collection<SampleId> samplesCollection) {
108108
var project = projectInformationService.find(projectId);
109109
if (project.isEmpty()) {
110110
throw new IllegalArgumentException("Could not find project " + projectId);
111111
}
112-
sampleDomainService.deleteSamples(project.get(), samplesCollection);
112+
sampleDomainService.deleteSamples(project.get(), batchId, samplesCollection);
113113
}
114114

115115
/**

project-management/src/main/java/life/qbic/projectmanagement/application/OntologyClassEntity.java

+35-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package life.qbic.projectmanagement.application;
22

3+
import jakarta.persistence.Column;
34
import jakarta.persistence.Entity;
45
import jakarta.persistence.GeneratedValue;
56
import jakarta.persistence.Id;
@@ -10,18 +11,19 @@
1011
@Table(name = "ontology_classes")
1112
public class OntologyClassEntity {
1213

13-
String ontology;
14-
14+
@Column(name = "ontology")
15+
String ontologyAbbreviation;
16+
@Column(name = "ontologyVersion")
1517
String ontologyVersion;
16-
18+
@Column(name = "ontologyIri")
1719
String ontologyIri;
18-
19-
String label;
20-
21-
String name;
22-
20+
@Column(name = "label")
21+
String classLabel;
22+
@Column(name = "name")
23+
String className;
24+
@Column(name = "description", length = 2000)
2325
String description;
24-
26+
@Column(name = "classIri")
2527
String classIri;
2628

2729
@Id
@@ -31,23 +33,24 @@ public class OntologyClassEntity {
3133
public OntologyClassEntity() {
3234
}
3335

34-
public OntologyClassEntity(String ontology, String ontologyVersion, String ontologyIri,
35-
String label, String name, String description, String classIri) {
36-
this.ontology = ontology;
36+
public OntologyClassEntity(String ontologyAbbreviation, String ontologyVersion,
37+
String ontologyIri,
38+
String classLabel, String className, String description, String classIri) {
39+
this.ontologyAbbreviation = ontologyAbbreviation;
3740
this.ontologyVersion = ontologyVersion;
3841
this.ontologyIri = ontologyIri;
39-
this.label = label;
40-
this.name = name;
42+
this.classLabel = classLabel;
43+
this.className = className;
4144
this.description = description;
4245
this.classIri = classIri;
4346
}
4447

45-
public String getOntology() {
46-
return ontology;
48+
public String getOntologyAbbreviation() {
49+
return ontologyAbbreviation;
4750
}
4851

49-
public void setOntology(String ontology) {
50-
this.ontology = ontology;
52+
public void setOntologyAbbreviation(String ontology) {
53+
this.ontologyAbbreviation = ontology;
5154
}
5255

5356
public String getOntologyVersion() {
@@ -66,20 +69,20 @@ public void setOntologyIri(String ontologyIri) {
6669
this.ontologyIri = ontologyIri;
6770
}
6871

69-
public String getLabel() {
70-
return label;
72+
public String getClassLabel() {
73+
return classLabel;
7174
}
7275

73-
public void setLabel(String label) {
74-
this.label = label;
76+
public void setClassLabel(String label) {
77+
this.classLabel = label;
7578
}
7679

77-
public String getName() {
78-
return name;
80+
public String getClassName() {
81+
return className;
7982
}
8083

81-
public void setName(String name) {
82-
this.name = name;
84+
public void setClassName(String name) {
85+
this.className = name;
8386
}
8487

8588
public String getDescription() {
@@ -107,16 +110,17 @@ public boolean equals(Object o) {
107110
return false;
108111
}
109112
OntologyClassEntity that = (OntologyClassEntity) o;
110-
return Objects.equals(ontology, that.ontology) && Objects.equals(
113+
return Objects.equals(ontologyAbbreviation, that.ontologyAbbreviation) && Objects.equals(
111114
ontologyVersion, that.ontologyVersion) && Objects.equals(ontologyIri,
112-
that.ontologyIri) && Objects.equals(label, that.label) && Objects.equals(
113-
name, that.name) && Objects.equals(description, that.description)
115+
that.ontologyIri) && Objects.equals(classLabel, that.classLabel) && Objects.equals(
116+
className, that.className) && Objects.equals(description, that.description)
114117
&& Objects.equals(classIri, that.classIri);
115118
}
116119

117120
@Override
118121
public int hashCode() {
119-
return Objects.hash(ontology, ontologyVersion, ontologyIri, label, name, description, classIri);
122+
return Objects.hash(ontologyAbbreviation, ontologyVersion, ontologyIri, classLabel, className,
123+
description, classIri);
120124
}
121125

122126
public Long getId() {
@@ -126,4 +130,4 @@ public Long getId() {
126130
public void setId(Long id) {
127131
this.id = id;
128132
}
129-
}
133+
}

project-management/src/main/java/life/qbic/projectmanagement/application/OntologyTermInformationService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public List<OntologyClassEntity> queryOntologyTerm(String termFilter, List<Strin
4545
int offset, int limit, List<SortOrder> sortOrders) {
4646
// returned by JPA -> UnmodifiableRandomAccessList
4747
List<OntologyClassEntity> termList = ontologyTermLookup.query(termFilter, ontologyAbbreviations, offset,
48-
50, sortOrders);
48+
limit, sortOrders);
4949
// the list must be modifiable for spring security to filter it
5050
return new ArrayList<>(termList);
5151
}

project-management/src/main/java/life/qbic/projectmanagement/application/batch/BatchRegistrationService.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,21 @@ public Result<BatchId, ResponseCode> addSampleToBatch(SampleId sampleId, BatchId
9898
}
9999
}
100100

101+
public Result<BatchId, ResponseCode> deleteSampleFromBatch(SampleId sampleId, BatchId batchId) {
102+
var searchResult = batchRepository.find(batchId);
103+
if (searchResult.isEmpty()) {
104+
return Result.fromError(ResponseCode.BATCHES_COULD_NOT_BE_RETRIEVED);
105+
} else {
106+
Batch batch = searchResult.get();
107+
batch.removeSample(sampleId);
108+
var result = batchRepository.update(batch);
109+
if (result.isError()) {
110+
return Result.fromError(ResponseCode.BATCH_UPDATE_FAILED);
111+
}
112+
return Result.fromValue(batch.batchId());
113+
}
114+
}
115+
101116
/**
102117
* Edits the information contained within a {@link Batch} and its corresponding registered
103118
* {@link Sample}
@@ -150,7 +165,7 @@ public Result<BatchId, ResponseCode> editBatch(BatchId batchId, String batchLabe
150165
sampleRegistrationService.updateSamples(projectId, editedSamples);
151166
}
152167
if (!deletedSamples.isEmpty()) {
153-
deletionService.deleteSamples(projectId, deletedSamples);
168+
deletionService.deleteSamples(projectId, batchId, deletedSamples);
154169
}
155170
return Result.fromValue(batch.batchId());
156171
}

project-management/src/main/java/life/qbic/projectmanagement/application/batch/SampleUpdateRequest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public record SampleUpdateRequest(SampleId sampleId, SampleInformation sampleInf
1919
* Sample update request.
2020
* <p>
2121
* @param sampleLabel a human-readable semantic descriptor of the sample
22+
* @param organismId optional identifier of the sample's source patient or organism
2223
* @param analysisMethod analysis method to be performed
2324
* @param biologicalReplicate the biological replicate the sample has been taken from
2425
* @param experimentalGroup the experimental group the sample is part of
@@ -27,7 +28,8 @@ public record SampleUpdateRequest(SampleId sampleId, SampleInformation sampleInf
2728
* @param analyte the analyte the sample belongs to
2829
* @param comment comment relating to the sample
2930
*/
30-
public record SampleInformation(String sampleLabel, AnalysisMethod analysisMethod,
31+
public record SampleInformation(String sampleLabel, String organismId,
32+
AnalysisMethod analysisMethod,
3133
BiologicalReplicate biologicalReplicate,
3234
ExperimentalGroup experimentalGroup, OntologyClassDTO species,
3335
OntologyClassDTO specimen, OntologyClassDTO analyte,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package life.qbic.projectmanagement.application.policy;
2+
3+
import life.qbic.domain.concepts.DomainEventDispatcher;
4+
import life.qbic.projectmanagement.application.policy.directive.DeleteSampleFromBatch;
5+
import life.qbic.projectmanagement.domain.model.batch.Batch;
6+
import life.qbic.projectmanagement.domain.model.sample.event.SampleDeleted;
7+
8+
/**
9+
* <b>Policy: Sample Deleted</b>
10+
* <p>
11+
* A collection of all directives that need to be executed after a sample has been deleted
12+
* <p>
13+
* The policy subscribes to events of type
14+
* {@link SampleDeleted} and ensures the
15+
* registration of all business required directives.
16+
*
17+
* @since 1.0.0
18+
*/
19+
public class SampleDeletedPolicy {
20+
21+
private final DeleteSampleFromBatch deleteSampleFromBatch;
22+
23+
/**
24+
* Creates an instance of a {@link SampleDeletedPolicy} object.
25+
* <p>
26+
* All directives will be created and subscribed upon instantiation.
27+
*
28+
* @param deleteSampleFromBatch directive to remove the affected sample from
29+
* {@link Batch}
30+
* @since 1.0.0
31+
*/
32+
public SampleDeletedPolicy(DeleteSampleFromBatch deleteSampleFromBatch) {
33+
this.deleteSampleFromBatch = deleteSampleFromBatch;
34+
DomainEventDispatcher.instance().subscribe(this.deleteSampleFromBatch);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package life.qbic.projectmanagement.application.policy.directive;
2+
3+
import static life.qbic.logging.service.LoggerFactory.logger;
4+
5+
import life.qbic.domain.concepts.DomainEvent;
6+
import life.qbic.domain.concepts.DomainEventSubscriber;
7+
import life.qbic.logging.api.Logger;
8+
import life.qbic.projectmanagement.application.batch.BatchRegistrationService;
9+
import life.qbic.projectmanagement.domain.model.batch.BatchId;
10+
import life.qbic.projectmanagement.domain.model.sample.SampleId;
11+
import life.qbic.projectmanagement.domain.model.sample.event.SampleDeleted;
12+
import org.jobrunr.jobs.annotations.Job;
13+
import org.jobrunr.scheduling.JobScheduler;
14+
import org.springframework.stereotype.Component;
15+
16+
/**
17+
* <b>Directive: Delete Sample from Batch</b>
18+
* <p>
19+
* After a sample has been deleted, we need to update the batch and remove
20+
* the sample reference of the deleted sample.
21+
*
22+
* @since 1.0.0
23+
*/
24+
@Component
25+
public class DeleteSampleFromBatch implements DomainEventSubscriber<SampleDeleted> {
26+
27+
private static final Logger log = logger(DeleteSampleFromBatch.class);
28+
private final BatchRegistrationService batchRegistrationService;
29+
private final JobScheduler jobScheduler;
30+
31+
public DeleteSampleFromBatch(BatchRegistrationService batchRegistrationService,
32+
JobScheduler jobScheduler) {
33+
this.batchRegistrationService = batchRegistrationService;
34+
this.jobScheduler = jobScheduler;
35+
}
36+
37+
@Override
38+
public Class<? extends DomainEvent> subscribedToEventType() {
39+
return SampleDeleted.class;
40+
}
41+
42+
@Override
43+
public void handleEvent(SampleDeleted event) {
44+
jobScheduler.enqueue(() -> deleteSampleFromBatch(event.deletedSample(), event.assignedBatch()));
45+
}
46+
47+
@Job(name = "Delete_Sample_From_Batch")
48+
public void deleteSampleFromBatch(SampleId sample, BatchId batch) throws RuntimeException {
49+
batchRegistrationService.deleteSampleFromBatch(sample, batch).onError(responseCode -> {
50+
throw new RuntimeException(
51+
String.format("Deletion of sample %s from batch %s failed, response code was %s ", sample,
52+
batch,
53+
responseCode));
54+
});
55+
}
56+
}

0 commit comments

Comments
 (0)