14
14
import static org .folio .harvesteradmin .dataaccess .statics .RequestParameters .supportedGetRequestParameters ;
15
15
import static org .folio .okapi .common .HttpResponse .responseText ;
16
16
17
+ import io .vertx .core .AsyncResult ;
18
+ import io .vertx .core .CompositeFuture ;
17
19
import io .vertx .core .Future ;
18
20
import io .vertx .core .Promise ;
19
21
import io .vertx .core .Vertx ;
@@ -140,7 +142,7 @@ public Future<ProcessedHarvesterResponseGetById> getConfigRecordById(
140
142
return promise .future ();
141
143
}
142
144
143
- private Future <ProcessedHarvesterResponse > getConfigRecordByIdOrName (
145
+ private Future <ProcessedHarvesterResponse > getUniqueConfigRecordByIdOrName (
144
146
String harvesterPath , String id , String name ) {
145
147
Promise <ProcessedHarvesterResponse > promise = Promise .promise ();
146
148
if (id == null || id .isEmpty ()) {
@@ -160,13 +162,13 @@ private Future<ProcessedHarvesterResponse> getConfigRecordByIdOrName(
160
162
promise .complete (
161
163
new ProcessedHarvesterResponseGetUniqueByName (
162
164
recordsByName .jsonObject (),
163
- 422 ,
165
+ 404 ,
164
166
"Record with name \" " + name + "\" not found" , recordsFoundByName ));
165
167
} else {
166
168
promise .complete (
167
169
new ProcessedHarvesterResponseGetUniqueByName (
168
170
recordsByName .jsonObject (),
169
- 422 ,
171
+ 404 ,
170
172
"Found multiple records with name \" " + name + "\" " , recordsFoundByName ));
171
173
}
172
174
return promise .future ();
@@ -249,7 +251,7 @@ public Future<ProcessedHarvesterResponsePost> resolveReferencedEntities(
249
251
final String transformationId = entity .getJsonObject ("transformation" ).getString ("id" );
250
252
final String storageName = entity .getJsonObject ("storage" ).getString ("name" );
251
253
final String transformationName = entity .getJsonObject ("transformation" ).getString ("name" );
252
- getConfigRecordByIdOrName (HARVESTER_STORAGES_PATH , storageId , storageName )
254
+ getUniqueConfigRecordByIdOrName (HARVESTER_STORAGES_PATH , storageId , storageName )
253
255
.onComplete (storage -> {
254
256
if (storage .succeeded ()) {
255
257
if (storage .result ().wasOK ()) {
@@ -265,7 +267,7 @@ public Future<ProcessedHarvesterResponsePost> resolveReferencedEntities(
265
267
fatalError .add ("Error looking up storage by id or name "
266
268
+ storage .cause ().getMessage ());
267
269
}
268
- getConfigRecordByIdOrName (HARVESTER_TRANSFORMATIONS_PATH ,
270
+ getUniqueConfigRecordByIdOrName (HARVESTER_TRANSFORMATIONS_PATH ,
269
271
transformationId , transformationName )
270
272
.onComplete (transformation -> {
271
273
if (transformation .succeeded ()) {
@@ -278,7 +280,7 @@ public Future<ProcessedHarvesterResponsePost> resolveReferencedEntities(
278
280
constraintViolation .add (transformation .result ().errorMessage ());
279
281
280
282
}
281
- if (constraintViolation .size () > 0 ) {
283
+ if (! constraintViolation .isEmpty () ) {
282
284
promise .complete (
283
285
new ProcessedHarvesterResponsePost (422 , constraintViolation .toString ())
284
286
);
@@ -292,7 +294,7 @@ public Future<ProcessedHarvesterResponsePost> resolveReferencedEntities(
292
294
+ transformation .cause ().getMessage ());
293
295
}
294
296
});
295
- if (fatalError .size () > 0 ) {
297
+ if (! fatalError .isEmpty () ) {
296
298
promise .complete (new ProcessedHarvesterResponsePost (500 ,fatalError .toString ()));
297
299
}
298
300
});
@@ -408,8 +410,12 @@ public Future<ProcessedHarvesterResponsePut> putConfigRecord(RoutingContext rout
408
410
String harvesterPath = mapToHarvesterPath (routingContext );
409
411
JsonObject jsonToPut = routingContext .body ().asJsonObject ();
410
412
String id = routingContext .request ().getParam ("id" );
411
- if (harvesterPath != null && harvesterPath .equals (HARVESTER_HARVESTABLES_PATH )) {
412
- jsonToPut .put ("lastUpdated" , iso_instant .format (Instant .now ()));
413
+ if (harvesterPath != null ) {
414
+ if (harvesterPath .equals (HARVESTER_TRANSFORMATIONS_PATH )) {
415
+ return putTransformation (routingContext );
416
+ } else if (harvesterPath .equals (HARVESTER_HARVESTABLES_PATH )) {
417
+ jsonToPut .put ("lastUpdated" , iso_instant .format (Instant .now ()));
418
+ }
413
419
}
414
420
return putConfigRecord (routingContext , harvesterPath , jsonToPut , id );
415
421
}
@@ -580,12 +586,41 @@ public Future<Integer> checkForReferencingEntities(String api, String id) {
580
586
return promise .future ();
581
587
}
582
588
583
-
584
-
585
- private Future <ProcessedHarvesterResponsePost > doPostAndPutTransformation (
586
- RoutingContext routingContext ) {
589
+ private Future <ProcessedHarvesterResponsePut > putTransformation (RoutingContext routingContext ) {
587
590
JsonObject transformationJson = routingContext .body ().asJsonObject ();
588
- logger .debug ("About to POST-then-PUT " + transformationJson .encodePrettily ());
591
+ logger .debug ("About to PUT " + transformationJson .encodePrettily ());
592
+ List <Future <ProcessedHarvesterResponse >> stepFutures = getStepLookupFutures (transformationJson );
593
+ Promise <ProcessedHarvesterResponsePut > promise = Promise .promise ();
594
+ GenericCompositeFuture .all (stepFutures ).onComplete (steps -> {
595
+ if (steps .succeeded ()) {
596
+ boolean allStepsFound = true ;
597
+ for (int h = 0 ; h < steps .result ().size (); h ++) {
598
+ ProcessedHarvesterResponse stepResponse = steps .result ().resultAt (h );
599
+ if (stepResponse .statusCode () == NOT_FOUND ) {
600
+ allStepsFound = false ;
601
+ promise .complete (new ProcessedHarvesterResponsePut (422 ,
602
+ "Uniquely referenced step not found, cannot store transformation pipeline: "
603
+ + stepResponse .errorMessage ()));
604
+ break ;
605
+ }
606
+ }
607
+ if (allStepsFound ) {
608
+ expandAssociatedSteps (steps , transformationJson );
609
+ putConfigRecord (
610
+ routingContext ,
611
+ HARVESTER_TRANSFORMATIONS_PATH ,
612
+ transformationJson ,
613
+ transformationJson .getString ("id" )).onComplete (response ->
614
+ promise .complete (response .result ())
615
+ );
616
+ }
617
+ }
618
+ });
619
+ return promise .future ();
620
+ }
621
+
622
+ private List <Future <ProcessedHarvesterResponse >> getStepLookupFutures (
623
+ JsonObject transformationJson ) {
589
624
JsonArray stepsIdsJson =
590
625
transformationJson .containsKey ("stepAssociations" ) ? transformationJson .getJsonArray (
591
626
"stepAssociations" ).copy () : new JsonArray ();
@@ -599,19 +634,32 @@ private Future<ProcessedHarvesterResponsePost> doPostAndPutTransformation(
599
634
String stepName = step .containsKey ("step" )
600
635
? step .getJsonObject ("step" ).getString ("name" )
601
636
: step .getString ("stepName" );
602
- stepFutures .add (getConfigRecordByIdOrName (HARVESTER_STEPS_PATH , stepId , stepName ));
637
+ stepFutures .add (getUniqueConfigRecordByIdOrName (HARVESTER_STEPS_PATH , stepId , stepName ));
603
638
}
639
+ return stepFutures ;
640
+ }
641
+
642
+ /**
643
+ * Checks that referenced steps exist, POSTs the transformation without the steps,
644
+ * creates schema compliant step associations in the transformation object,
645
+ * PUTs the transformation, checks that a transformation with the given ID exists.
646
+ * @return response structure
647
+ */
648
+ private Future <ProcessedHarvesterResponsePost > doPostAndPutTransformation (
649
+ RoutingContext routingContext ) {
650
+ JsonObject transformationJson = routingContext .body ().asJsonObject ();
651
+ logger .debug ("About to POST-then-PUT " + transformationJson .encodePrettily ());
652
+ List <Future <ProcessedHarvesterResponse >> stepFutures = getStepLookupFutures (transformationJson );
604
653
Promise <ProcessedHarvesterResponsePost > promise = Promise .promise ();
605
654
GenericCompositeFuture .all (stepFutures ).onComplete (steps -> {
606
655
if (steps .succeeded ()) {
607
656
boolean allStepsFound = true ;
608
657
for (int h = 0 ; h < steps .result ().size (); h ++) {
609
- ProcessedHarvesterResponseGetById stepResponse = steps .result ().resultAt (h );
658
+ ProcessedHarvesterResponse stepResponse = steps .result ().resultAt (h );
610
659
if (stepResponse .statusCode () == NOT_FOUND ) {
611
- logger .info ("Step not found: " + stepResponse .errorMessage ());
612
660
allStepsFound = false ;
613
661
promise .complete (new ProcessedHarvesterResponsePost (422 ,
614
- "Referenced step not found, cannot store transformation pipeline: "
662
+ "Uniquely referenced step not found, cannot store transformation pipeline: "
615
663
+ stepResponse .errorMessage ()));
616
664
break ;
617
665
}
@@ -625,21 +673,7 @@ private Future<ProcessedHarvesterResponsePost> doPostAndPutTransformation(
625
673
if (transformationPost .succeeded ()
626
674
&& transformationPost .result ().statusCode () == CREATED ) {
627
675
JsonObject createdTransformation = transformationPost .result ().jsonObject ();
628
- createdTransformation .put ("stepAssociations" , new JsonArray ());
629
- for (int i = 0 ; i < steps .result ().size (); i ++) {
630
- ProcessedHarvesterResponseGetById stepResponse = steps .result ().resultAt (i );
631
- final JsonObject stepJson = stepResponse .jsonObject ();
632
- JsonObject tsaJson = new JsonObject ();
633
- tsaJson .put ("id" , getRandomFifteenDigitString ());
634
- tsaJson .put ("position" , Integer .toString (i + 1 ));
635
- tsaJson .put ("step" , new JsonObject ());
636
- tsaJson .getJsonObject ("step" )
637
- .put ("entityType" ,
638
- typeToEmbeddedTypeMap .get (stepJson .getString ("type" )));
639
- tsaJson .getJsonObject ("step" ).put ("id" , stepJson .getString ("id" ));
640
- tsaJson .put ("transformation" , createdTransformation .getString ("id" ));
641
- createdTransformation .getJsonArray ("stepAssociations" ).add (tsaJson );
642
- }
676
+ expandAssociatedSteps (steps , createdTransformation );
643
677
putConfigRecord (
644
678
routingContext ,
645
679
HARVESTER_TRANSFORMATIONS_PATH ,
@@ -687,6 +721,25 @@ private Future<ProcessedHarvesterResponsePost> doPostAndPutTransformation(
687
721
return promise .future ();
688
722
}
689
723
724
+ private static void expandAssociatedSteps (AsyncResult <CompositeFuture > steps ,
725
+ JsonObject createdTransformation ) {
726
+ createdTransformation .put ("stepAssociations" , new JsonArray ());
727
+ for (int i = 0 ; i < steps .result ().size (); i ++) {
728
+ ProcessedHarvesterResponse stepResponse = steps .result ().resultAt (i );
729
+ final JsonObject stepJson = stepResponse .jsonObject ();
730
+ JsonObject tsaJson = new JsonObject ();
731
+ tsaJson .put ("id" , getRandomFifteenDigitString ());
732
+ tsaJson .put ("position" , Integer .toString (i + 1 ));
733
+ tsaJson .put ("step" , new JsonObject ());
734
+ tsaJson .getJsonObject ("step" )
735
+ .put ("entityType" ,
736
+ typeToEmbeddedTypeMap .get (stepJson .getString ("type" )));
737
+ tsaJson .getJsonObject ("step" ).put ("id" , stepJson .getString ("id" ));
738
+ tsaJson .put ("transformation" , createdTransformation .getString ("id" ));
739
+ createdTransformation .getJsonArray ("stepAssociations" ).add (tsaJson );
740
+ }
741
+ }
742
+
690
743
private Future <ProcessedHarvesterResponsePost > doPostTsaPutTransformation (
691
744
RoutingContext routingContext ) {
692
745
JsonObject incomingTsa = routingContext .body ().asJsonObject ();
@@ -695,7 +748,7 @@ private Future<ProcessedHarvesterResponsePost> doPostTsaPutTransformation(
695
748
String stepId = incomingTsa .getJsonObject ("step" ).getString ("id" );
696
749
String stepName = incomingTsa .getJsonObject ("step" ).getString ("name" );
697
750
Promise <ProcessedHarvesterResponsePost > promise = Promise .promise ();
698
- getConfigRecordByIdOrName (HARVESTER_TRANSFORMATIONS_PATH , transId , transName ).onComplete (
751
+ getUniqueConfigRecordByIdOrName (HARVESTER_TRANSFORMATIONS_PATH , transId , transName ).onComplete (
699
752
theTransformation -> {
700
753
if (theTransformation .failed ()) {
701
754
promise .complete (
@@ -710,7 +763,7 @@ private Future<ProcessedHarvesterResponsePost> doPostTsaPutTransformation(
710
763
+ transId + " not found." ));
711
764
} else {
712
765
JsonObject transformationFound = theTransformation .result ().jsonObject ();
713
- getConfigRecordByIdOrName (HARVESTER_STEPS_PATH , stepId , stepName ).onComplete (
766
+ getUniqueConfigRecordByIdOrName (HARVESTER_STEPS_PATH , stepId , stepName ).onComplete (
714
767
theStep -> {
715
768
if (!theStep .result ().found ()) {
716
769
promise .complete (
0 commit comments