-
Notifications
You must be signed in to change notification settings - Fork 1
Implement missing eperimental variable functionality #1274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 78 commits
6ff8af9
f7b340d
9b0e84c
bdca38b
bda4861
3103d69
0d0cb6f
faec88b
4fa7603
9ff8c33
5926d06
e542fb0
e78f5d1
3d56282
5c95256
643e8a7
1b5e9f8
f9ea42c
d58801c
f1746f5
41a1630
621a146
0ce5a9c
eecadeb
cea127e
0f5fa65
cf8b3d5
73a0224
e3cc6c7
2cf58c9
72261de
67031e3
099ce4f
f0602d4
4bed019
7857d7f
6cefc83
c1ec84c
10e708f
fde84e6
8d5aff9
cc9dd3e
3dd52b8
14b65e8
7804482
f9ef3e1
bb6e4c3
c649bba
72c3290
17de7d3
a4d131a
9402809
2da3926
0baad2f
3b0ef2f
51a7e6b
4b065eb
3ace81e
d434724
d877a75
ef71332
e935fce
bd811f5
02f66da
1672d30
70cbc59
fc66f8a
8ebf805
2a3e038
87c5e4c
9529ca0
912c08b
13abd2a
ac82503
c6ae679
bdfd01b
9d7d112
bc00aa4
15efb17
aba4aa2
d707acf
bbe23b3
a58da23
4333831
55aab8e
2fb4110
069746c
915aa18
cafb294
2ef7467
b87ee8c
48e46db
6e014ed
18944e9
82786fb
885521d
da74ce4
d779b62
2f4b39a
37a5bec
5b7f063
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package life.qbic.application.commons; | ||
|
|
||
| /** | ||
| * Interface to implement the Memento/Snapshot pattern. <a | ||
| * href="https://refactoring.guru/design-patterns/memento">Memento Pattern</a> Originators of | ||
| * Mementos or Creators of Snapshots should implement this interface. | ||
| */ | ||
| public interface CanSnapshot { | ||
|
|
||
| /** | ||
| * Capture the internal state and expose it as a Snapshot. | ||
| * | ||
| * @return the created snapshot | ||
| */ | ||
| Snapshot snapshot(); | ||
|
|
||
| /** | ||
| * Adapts the internal state to match the information provided by the snapshot. The method can | ||
| * fail throwing a {@link SnapshotRestorationException} for unknown types of Snapshots. | ||
| * <p> | ||
| * It is the responsibility of the implementation to make sure after successful application or | ||
| * failure, the internal state of the object is valid. | ||
| * <p> | ||
| * After snapshot restoration failure. The object is expected to revert all modifications made by | ||
| * the attempt. | ||
| * | ||
| * @param snapshot the snapshot to be restored | ||
| * @throws SnapshotRestorationException thrown when snapshot restoration failed. | ||
| */ | ||
| void restore(Snapshot snapshot) throws SnapshotRestorationException; | ||
|
|
||
| /** | ||
| * Indicates that a snapshot cannot be used to restore the state of the originator. | ||
| */ | ||
| class SnapshotRestorationException extends RuntimeException { | ||
|
|
||
| public SnapshotRestorationException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public SnapshotRestorationException(String message, Throwable cause) { | ||
| super(message, cause); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package life.qbic.application.commons; | ||
|
|
||
| import java.io.Serializable; | ||
|
|
||
| /** | ||
| * Interface for the Memento in the <a | ||
| * href="https://refactoring.guru/design-patterns/memento">Memento Pattern</a> | ||
| */ | ||
| public interface Snapshot extends Serializable { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -706,7 +706,9 @@ public ExperimentalVariable(String name, List<String> levels) { | |
| } | ||
|
|
||
| public ExperimentalVariable { | ||
| levels = List.copyOf(levels); | ||
| levels = levels.stream() | ||
| .distinct() | ||
KochTobi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| .toList(); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -958,33 +960,62 @@ public ExperimentalVariablesCreationRequest(String projectId, String experimentI | |
| } | ||
| } | ||
|
|
||
| record ExperimentalVariablesUpdateRequest(String projectId, String experimentId, | ||
| List<ExperimentalVariable> experimentalVariables, | ||
| String requestId) implements CacheableRequest { | ||
| record ExperimentalVariableUpdateRequest(String projectId, String experimentId, | ||
| ExperimentalVariable experimentalVariable, | ||
| String requestId) implements CacheableRequest { | ||
|
|
||
| public ExperimentalVariablesUpdateRequest { | ||
| public ExperimentalVariableUpdateRequest { | ||
| requireNonNull(projectId); | ||
| requireNonNull(experimentId); | ||
| requireNonNull(experimentalVariables); | ||
| requireNonNull(experimentalVariable); | ||
| requireNonNull(requestId); | ||
| experimentalVariables = List.copyOf(experimentalVariables); | ||
| } | ||
|
|
||
| public ExperimentalVariablesUpdateRequest(String projectId, String experimentId, | ||
| List<ExperimentalVariable> experimentalVariables) { | ||
| this(projectId, experimentId, experimentalVariables, UUID.randomUUID().toString()); | ||
| public ExperimentalVariableUpdateRequest(String projectId, String experimentId, | ||
sven1103 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ExperimentalVariable experimentalVariable) { | ||
| this(projectId, experimentId, experimentalVariable, UUID.randomUUID().toString()); | ||
| } | ||
| } | ||
|
|
||
| record ExperimentalVariablesUpdateResponse(String projectId, | ||
| List<ExperimentalVariable> experimentalVariables, | ||
| String requestId) { | ||
| record ExperimentalVariableUpdateResponse(String projectId, | ||
| ExperimentalVariable experimentalVariable, | ||
| String requestId) { | ||
|
|
||
| public ExperimentalVariablesUpdateResponse { | ||
| public ExperimentalVariableUpdateResponse { | ||
| requireNonNull(projectId); | ||
| requireNonNull(requestId); | ||
| requireNonNull(experimentalVariables); | ||
| experimentalVariables = List.copyOf(experimentalVariables); | ||
| requireNonNull(experimentalVariable); | ||
| } | ||
| } | ||
|
|
||
| record ExperimentalVariableRenameRequest(String projectId, String experimentId, | ||
| String currentVariableName, String futureVariableName, | ||
| String requestId) implements CacheableRequest { | ||
|
|
||
| public ExperimentalVariableRenameRequest { | ||
| requireNonNull(projectId); | ||
| requireNonNull(experimentId); | ||
| requireNonNull(currentVariableName); | ||
| requireNonNull(futureVariableName); | ||
| requireNonNull(requestId); | ||
| } | ||
|
|
||
| public ExperimentalVariableRenameRequest(String newVariableName, String oldVariableName, | ||
| String experimentId, String projectId) { | ||
| this(projectId, experimentId, oldVariableName, newVariableName, UUID.randomUUID().toString()); | ||
| } | ||
| } | ||
|
|
||
| record ExperimentalVariableRenameResponse(String projectId, String experimentId, | ||
| String previousVariableName, String currentVariableName, | ||
| String requestId) { | ||
|
|
||
| public ExperimentalVariableRenameResponse { | ||
| requireNonNull(projectId); | ||
| requireNonNull(experimentId); | ||
| requireNonNull(previousVariableName); | ||
| requireNonNull(currentVariableName); | ||
| requireNonNull(requestId); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -1135,22 +1166,41 @@ record ExperimentalVariablesDeletionResponse(String projectId, String experiment | |
|
|
||
| /** | ||
| * Submits an experimental variable update request and returns a reactive | ||
| * {@link Mono<ExperimentalVariablesUpdateResponse>.} | ||
| * {@link Mono<ExperimentalVariableUpdateResponse>.} | ||
|
||
| * <p> | ||
| * <b>Exceptions</b> | ||
| * <p> | ||
| * Exceptions are wrapped as {@link Mono#error(Throwable)} and are one of the types described in | ||
| * the throw section below. | ||
| * | ||
| * @param request the request with information required for the experimental variable update | ||
| * @return a {@link Mono<ExperimentalVariableUpdateResponse>} object publishing a | ||
| * {@link ExperimentalVariableUpdateResponse} on success. | ||
| * @throws UnknownRequestException if an unknown request has been used in the service call | ||
| * @throws RequestFailedException if the request was not successfully executed | ||
| * @throws AccessDeniedException if the user has insufficient rights | ||
| * @since 1.10.0 | ||
| */ | ||
| Mono<ExperimentalVariableUpdateResponse> update(ExperimentalVariableUpdateRequest request); | ||
|
|
||
| /** | ||
| * Submits an experimental variable update request and returns a reactive | ||
| * {@link Mono<ExperimentalVariableUpdateResponse>.} | ||
|
||
| * <p> | ||
| * <b>Exceptions</b> | ||
| * <p> | ||
| * Exceptions are wrapped as {@link Mono#error(Throwable)} and are one of the types described in | ||
| * the throw section below. | ||
| * | ||
| * @param request the request with information required for the experimental variable update | ||
| * @return a {@link Mono<ExperimentalVariablesUpdateResponse>} object publishing a | ||
| * {@link ExperimentalVariablesUpdateResponse} on success. | ||
| * @return a {@link Mono<ExperimentalVariableUpdateResponse>} object publishing a | ||
| * {@link ExperimentalVariableUpdateResponse} on success. | ||
| * @throws UnknownRequestException if an unknown request has been used in the service call | ||
| * @throws RequestFailedException if the request was not successfully executed | ||
| * @throws AccessDeniedException if the user has insufficient rights | ||
| * @since 1.10.0 | ||
| */ | ||
| Mono<ExperimentalVariablesUpdateResponse> update(ExperimentalVariablesUpdateRequest request); | ||
| Mono<ExperimentalVariableRenameResponse> update(ExperimentalVariableRenameRequest request); | ||
|
|
||
| /** | ||
| * Submits an experimental variable deletion request and returns a reactive | ||
|
|
@@ -1658,10 +1708,11 @@ sealed interface ValidationRequestBody permits MeasurementRegistrationInformatio | |
| */ | ||
| sealed interface CacheableRequest permits ExperimentCreationRequest, ExperimentDeletionRequest, | ||
| ExperimentUpdateRequest, ExperimentalGroupCreationRequest, ExperimentalGroupDeletionRequest, | ||
| ExperimentalGroupUpdateRequest, ExperimentalVariablesDeletionRequest, | ||
| ExperimentalVariablesUpdateRequest, FundingInformationCreationRequest, | ||
| MeasurementRegistrationRequest, MeasurementUpdateRequest, ProjectResponsibleCreationRequest, | ||
| ProjectResponsibleDeletionRequest, ProjectUpdateRequest, ValidationRequest { | ||
| ExperimentalGroupUpdateRequest, ExperimentalVariableRenameRequest, | ||
| ExperimentalVariableUpdateRequest, ExperimentalVariablesDeletionRequest, | ||
| FundingInformationCreationRequest, MeasurementRegistrationRequest, MeasurementUpdateRequest, | ||
| ProjectResponsibleCreationRequest, ProjectResponsibleDeletionRequest, ProjectUpdateRequest, | ||
| ValidationRequest { | ||
|
|
||
| /** | ||
| * Returns an ID that is unique to the request. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |
| import java.nio.ByteBuffer; | ||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.Comparator; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.Set; | ||
|
|
@@ -30,7 +31,7 @@ | |
| import life.qbic.projectmanagement.application.api.fair.DigitalObjectFactory; | ||
| import life.qbic.projectmanagement.application.api.fair.ResearchProject; | ||
| import life.qbic.projectmanagement.application.api.template.TemplateService; | ||
| import life.qbic.projectmanagement.application.authorization.ReactiveSecurityContextUtils; | ||
| import life.qbic.projectmanagement.application.concurrent.VirtualThreadScheduler; | ||
| import life.qbic.projectmanagement.application.dataset.LocalRawDatasetLookupService; | ||
| import life.qbic.projectmanagement.application.experiment.ExperimentInformationService; | ||
| import life.qbic.projectmanagement.application.measurement.MeasurementService; | ||
|
|
@@ -994,7 +995,8 @@ public Flux<ExperimentalVariable> getExperimentalVariables(String projectId, | |
| () -> experimentInformationService.getVariablesOfExperiment(projectId, | ||
| ExperimentId.parse(experimentId)) | ||
| .stream() | ||
| .map(this::convertToApi)); | ||
| .map(this::convertToApi) | ||
| .sorted(Comparator.comparing(ExperimentalVariable::name))); | ||
sven1103 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return applySecurityContextMany(call) | ||
| .subscribeOn(scheduler) | ||
|
|
@@ -1007,6 +1009,7 @@ public Flux<ExperimentalVariable> getExperimentalVariables(String projectId, | |
| .retryWhen(defaultRetryStrategy()); | ||
| } | ||
|
|
||
| @Deprecated | ||
|
||
| private ExperimentalVariable convertToApi( | ||
| life.qbic.projectmanagement.domain.model.experiment.ExperimentalVariable experimentalVariable) { | ||
| return new ExperimentalVariable(experimentalVariable.name().value(), | ||
|
|
@@ -1039,10 +1042,46 @@ public Mono<ExperimentalVariablesCreationResponse> create( | |
| } | ||
|
|
||
| @Override | ||
| public Mono<ExperimentalVariablesUpdateResponse> update( | ||
| ExperimentalVariablesUpdateRequest request) { | ||
| // TODO implement | ||
| throw new RuntimeException("Not yet implemented"); | ||
| public Mono<ExperimentalVariableUpdateResponse> update( | ||
| ExperimentalVariableUpdateRequest request) { | ||
| //TODO implement | ||
| throw new RuntimeException("Not implemented"); | ||
sven1103 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| @Override | ||
| public Mono<ExperimentalVariableRenameResponse> update( | ||
| ExperimentalVariableRenameRequest request) { | ||
| var call = Mono.fromCallable(() -> { | ||
| ExperimentId experimentId = ExperimentId.parse(request.experimentId()); | ||
| experimentInformationService.renameExperimentalVariable(request.projectId(), | ||
| experimentId, request.currentVariableName(), request.futureVariableName()); | ||
|
|
||
| return new ExperimentalVariableRenameResponse(request.projectId(), | ||
| experimentId.value(), request.currentVariableName(), request.futureVariableName(), | ||
| request.requestId()); | ||
| }); | ||
| return applySecurityContext(call) | ||
| .subscribeOn(VirtualThreadScheduler.getScheduler()) | ||
| .contextWrite(reactiveSecurity(SecurityContextHolder.getContext())) | ||
| .doOnError(e -> log.error("Could not update experimental group", e)) | ||
| .retryWhen(defaultRetryStrategy()) | ||
| .onErrorMap(e -> mapToAPIException(e, | ||
| "Error renaming experimental variable " + request.currentVariableName() + " to " | ||
| + request.futureVariableName())); | ||
| } | ||
|
|
||
| private ExperimentalVariable convertToApi( | ||
| ExperimentInformationService.ExperimentalVariableInformation experimentalVariable) { | ||
| return new ExperimentalVariable(experimentalVariable.name(), experimentalVariable.levels(), | ||
| experimentalVariable.unit()); | ||
| } | ||
|
|
||
| private ExperimentInformationService.ExperimentalVariableInformation convertFromApi( | ||
|
||
| String experimentId, ExperimentalVariable experimentalVariable) { | ||
| return new ExperimentInformationService.ExperimentalVariableInformation(experimentId, | ||
| experimentalVariable.name(), | ||
| experimentalVariable.unit(), | ||
| experimentalVariable.levels()); | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.