1010import java .util .UUID ;
1111import life .qbic .application .commons .SortOrder ;
1212import life .qbic .projectmanagement .application .api .fair .DigitalObject ;
13+ import life .qbic .projectmanagement .application .ValidationResult ;
1314import life .qbic .projectmanagement .application .batch .SampleUpdateRequest .SampleInformation ;
1415import life .qbic .projectmanagement .application .confounding .ConfoundingVariableService .ConfoundingVariableInformation ;
1516import life .qbic .projectmanagement .application .sample .SamplePreview ;
@@ -224,6 +225,19 @@ Flux<SamplePreview> getSamplePreviews(String projectId, String experimentId, int
224225 */
225226 Mono <Sample > findSample (String projectId , String sampleId );
226227
228+ /**
229+ * Submits multiple validation requests in a single service call.
230+ *
231+ * @param requests a {@link Flux} providing {@link ValidationRequest}.
232+ * @return a {@link Flux} of {@link ValidationResponse}, providing the validation results for the
233+ * submitted requests. Exceptions are provided as {@link Flux#error(Throwable)}.
234+ * @throws UnknownRequestException if an unknown request has been used in the service call
235+ * @throws RequestFailedException if the request was not successfully executed
236+ * @throws AccessDeniedException if the user has insufficient rights
237+ * @since 1.10.0
238+ */
239+ Flux <ValidationResponse > validate (Flux <ValidationRequest > requests );
240+
227241 /**
228242 * Requests a sample registration template in a desired {@link MimeType}.
229243 * <p>
@@ -295,14 +309,33 @@ sealed interface ExperimentUpdateResponseBody permits ConfoundingVariables, Expe
295309
296310 }
297311
312+ /**
313+ * A validation request body for information that shall be validated by the service.
314+ * <p>
315+ * Currently, permits:
316+ *
317+ * <ul>
318+ * <li>{@link SampleMetadata}</li>
319+ * <li>{@link NGSMeasurementMetadata}</li>
320+ * <li>{@link ProteomicsMeasurementMetadata}</li>
321+ * </ul>
322+ *
323+ * @since 1.10.0
324+ */
325+ sealed interface ValidationRequestBody permits SampleMetadata , NGSMeasurementMetadata ,
326+ ProteomicsMeasurementMetadata {
327+
328+ }
329+
298330
299331 /**
300332 * Cacheable requests provide a unique identifier so cache implementations can unambiguously
301333 * manage the requests.
302334 *
303335 * @since 1.9.0
304336 */
305- sealed interface CacheableRequest permits ProjectUpdateRequest , ExperimentUpdateRequest {
337+ sealed interface CacheableRequest permits ExperimentUpdateRequest , ProjectUpdateRequest ,
338+ ValidationRequest {
306339
307340 /**
308341 * Returns an ID that is unique to the request.
@@ -590,16 +623,15 @@ public List<ConfoundingVariableInformation> confoundingVariables() {
590623 }
591624 }
592625
593-
594626 /**
595627 * A service request to update an experiment
596628 *
597629 * @param projectId the project's identifier. The project containing the experiment.
598630 * @param experimentId the experiment's identifier
599631 * @param body the request body containing information on what was updated
600- * @param requestId The identifier of the request. Please use
601- * {@link #ExperimentUpdateRequest(String, String ,
602- * ExperimentUpdateRequestBody)} if it is not determined yet.
632+ * @param requestId the request ID, needs to be provided by the client and will be referenced
633+ * in the response. If <code>null</code> or {@link String#isBlank()} is true ,
634+ * then a random UUID is assigned with {@link UUID#randomUUID()}
603635 * @since 1.9.0
604636 */
605637 record ExperimentUpdateRequest (String projectId , String experimentId ,
@@ -703,26 +735,41 @@ record ProjectCreationResponse(String projectId) {
703735 *
704736 * @param projectId the project's id
705737 * @param requestBody the information to be updated.
738+ * @param requestId the request ID, needs to be provided by the client and will be referenced in
739+ * the response. If <code>null</code> or {@link String#isBlank()} is true, then
740+ * a random UUID is assigned with {@link UUID#randomUUID()}.
706741 * @since 1.9.0
707742 */
708743 record ProjectUpdateRequest (String projectId , ProjectUpdateRequestBody requestBody ,
709- String id ) implements CacheableRequest {
744+ String requestId ) implements CacheableRequest {
745+
746+ public ProjectUpdateRequest {
747+ if (projectId == null ) {
748+ throw new IllegalArgumentException ("Project ID cannot be null" );
749+ }
750+ if (projectId .isBlank ()) {
751+ throw new IllegalArgumentException ("Project ID cannot be blank" );
752+ }
753+ if (requestId == null || requestId .isBlank ()) {
754+ requestId = UUID .randomUUID ().toString ();
755+ }
756+ }
757+
710758
711759 public ProjectUpdateRequest (String projectId , ProjectUpdateRequestBody requestBody ) {
712760 this (projectId , requestBody , UUID .randomUUID ().toString ());
713761 }
714762
715- @ Override
716- public String requestId () {
717- return id ;
718- }
719763 }
720764
721765 /**
722766 * A service response from an update project information request.
723767 *
724768 * @param projectId the project's id
725769 * @param responseBody the information that was updated.
770+ * @param requestId the request ID, needs to be provided by the client and will be referenced
771+ * in the response. If <code>null</code> or {@link String#isBlank()} is true,
772+ * then a random UUID is assigned with {@link UUID#randomUUID()}
726773 * @since 1.9.0
727774 */
728775 record ProjectUpdateResponse (String projectId , ProjectUpdateResponseBody responseBody ,
@@ -735,8 +782,9 @@ record ProjectUpdateResponse(String projectId, ProjectUpdateResponseBody respons
735782 if (projectId .isBlank ()) {
736783 throw new IllegalArgumentException ("Project ID cannot be blank" );
737784 }
738- if (requestId != null && requestId .isBlank ()) {
739- requestId = null ;
785+ if (requestId == null || requestId .isBlank ()) {
786+ requestId = UUID .randomUUID ().toString ();
787+ ;
740788 }
741789 }
742790
@@ -750,21 +798,59 @@ public Optional<String> retrieveRequestId() {
750798 return Optional .ofNullable (requestId );
751799 }
752800
753- /**
754- * Returns the requestId, can be null.
755- *
756- * @return Returns the requestId, if no requestId is set, returns null.
757- */
758- @ Override
759- public String requestId () {
760- return requestId ;
761- }
762-
763801 boolean hasRequestId () {
764802 return nonNull (requestId );
765803 }
766804 }
767805
806+ /**
807+ * The actual request container for metadata validation.
808+ * <p>
809+ * A validation request contains a {@link ValidationRequestBody} with the actual metadata to be
810+ * validated, next to the project ID and the request ID.
811+ *
812+ * @param projectId the project ID of the project the metadata shall be validated for
813+ * @param requestBody the actual metadata container with the information to be validated
814+ * @param requestId the request ID, needs to be provided by the client and will be referenced in
815+ * the response. If <code>null</code> or {@link String#isBlank()} is true, then
816+ * a random UUID is assigned with {@link UUID#randomUUID()}
817+ * @since 1.10.0
818+ */
819+ record ValidationRequest (String projectId , ValidationRequestBody requestBody ,
820+ String requestId ) implements CacheableRequest {
821+
822+ public ValidationRequest {
823+ if (projectId == null ) {
824+ throw new IllegalArgumentException ("Project ID cannot be null" );
825+ }
826+ if (projectId .isBlank ()) {
827+ throw new IllegalArgumentException ("Project ID cannot be blank" );
828+ }
829+ if (requestId == null || requestId .isBlank ()) {
830+ requestId = UUID .randomUUID ().toString ();
831+ }
832+ }
833+ }
834+
835+ /**
836+ * The response to a corresponding {@link ValidationRequest} with information about the actual
837+ * validation result.
838+ * <p>
839+ * The result itself is provided in the {@link ValidationResult} property.
840+ *
841+ * @param requestId the original ID of the request from {@link ValidationRequest}
842+ * @param result the validation report provided as {@link ValidationResult}
843+ * @since 1.10.0
844+ */
845+ record ValidationResponse (String requestId , ValidationResult result ) {
846+
847+ public ValidationResponse {
848+ if (requestId == null || requestId .isBlank ()) {
849+ throw new IllegalArgumentException ("Request ID cannot be null or blank" );
850+ }
851+ }
852+ }
853+
768854 /**
769855 * Exception to indicate that the service did not recognise the request.
770856 *
0 commit comments