12
12
import org .gridsuite .shortcircuit .server .dto .ResourceFilter ;
13
13
import org .gridsuite .shortcircuit .server .dto .ShortCircuitLimits ;
14
14
import org .gridsuite .shortcircuit .server .entities .*;
15
+ import org .gridsuite .shortcircuit .server .repositories .specifications .FaultResultSpecificationBuilder ;
15
16
import org .gridsuite .shortcircuit .server .service .ShortCircuitRunContext ;
16
- import org .gridsuite .shortcircuit .server .utils .FaultResultSpecificationBuilder ;
17
- import org .gridsuite .shortcircuit .server .utils .FeederResultSpecificationBuilder ;
17
+ import org .gridsuite .shortcircuit .server .repositories .specifications .FeederResultSpecificationBuilder ;
18
18
import org .slf4j .Logger ;
19
19
import org .slf4j .LoggerFactory ;
20
20
import org .springframework .beans .factory .annotation .Autowired ;
@@ -65,7 +65,7 @@ private static List<LimitViolationEmbeddable> extractLimitViolations(FaultResult
65
65
.map (limitViolation -> new LimitViolationEmbeddable (limitViolation .getSubjectId (),
66
66
limitViolation .getLimitType (), limitViolation .getLimit (),
67
67
limitViolation .getLimitName (), limitViolation .getValue ()))
68
- .collect ( Collectors . toList () );
68
+ .toList ();
69
69
}
70
70
71
71
public static ShortCircuitAnalysisResultEntity toResultEntity (UUID resultUuid , ShortCircuitAnalysisResult result , Map <String , ShortCircuitLimits > allShortCircuitLimits ) {
@@ -116,7 +116,7 @@ private static FaultResultEntity toMagnitudeFaultResultEntity(MagnitudeFaultResu
116
116
entity .setFeederResults (faultResult .getFeederResults ().stream ()
117
117
.map (feederResult -> new FeederResultEntity (feederResult .getConnectableId (),
118
118
((MagnitudeFeederResult ) feederResult ).getCurrent (), null ))
119
- .collect ( Collectors . toList () ));
119
+ .toList ());
120
120
if (shortCircuitLimits != null ) {
121
121
entity .setDeltaCurrentIpMin (current - entity .getIpMin () / 1000.0 );
122
122
entity .setDeltaCurrentIpMax (current - entity .getIpMax () / 1000.0 );
@@ -138,7 +138,7 @@ private static FaultResultEntity toFortescueFaultResultEntity(FortescueFaultResu
138
138
feederFortescueThreePhaseValue .getMagnitudeC (), feederFortescueThreePhaseValue .getAngleA (),
139
139
feederFortescueThreePhaseValue .getAngleB (), feederFortescueThreePhaseValue .getAngleC ()));
140
140
})
141
- .collect ( Collectors . toList () ));
141
+ .toList ());
142
142
143
143
final FortescueValue current = faultResult .getCurrent ();
144
144
if (shortCircuitLimits != null ) {
@@ -163,7 +163,7 @@ private static GlobalStatusEntity toStatusEntity(UUID resultUuid, String status)
163
163
public void insertStatus (List <UUID > resultUuids , String status ) {
164
164
Objects .requireNonNull (resultUuids );
165
165
globalStatusRepository .saveAll (resultUuids .stream ()
166
- .map (uuid -> toStatusEntity (uuid , status )).collect ( Collectors . toList () ));
166
+ .map (uuid -> toStatusEntity (uuid , status )).toList ());
167
167
}
168
168
169
169
@ Transactional
@@ -238,7 +238,7 @@ public Optional<ShortCircuitAnalysisResultEntity> findResultsWithLimitViolations
238
238
List <UUID > faultResultsUuidWithLimitViolations = result .get ().getFaultResults ().stream ()
239
239
.filter (fr -> !fr .getLimitViolations ().isEmpty ())
240
240
.map (FaultResultEntity ::getFaultResultUuid )
241
- .collect ( Collectors . toList () );
241
+ .toList ();
242
242
// using the Hibernate First-Level Cache or Persistence Context
243
243
// cf.https://vladmihalcea.com/spring-data-jpa-multiplebagfetchexception/
244
244
if (!result .get ().getFaultResults ().isEmpty ()) {
@@ -248,20 +248,70 @@ public Optional<ShortCircuitAnalysisResultEntity> findResultsWithLimitViolations
248
248
}
249
249
250
250
@ Transactional (readOnly = true )
251
- public Page <FaultResultEntity > findFaultResultsPage (ShortCircuitAnalysisResultEntity result , List <ResourceFilter > resourceFilters , Pageable pageable , FaultResultsMode mode ) {
251
+ public Page <FaultResultEntity > findFaultResultsPage (ShortCircuitAnalysisResultEntity result ,
252
+ List <ResourceFilter > resourceFilters ,
253
+ Pageable pageable ,
254
+ FaultResultsMode mode ) {
252
255
Objects .requireNonNull (result );
256
+
257
+ Optional <Sort .Order > childrenSort = extractChildrenSort (pageable );
258
+
259
+ Pageable modifiedPageable = addDefaultSort (filterOutChildrenSort (pageable , childrenSort ),
260
+ DEFAULT_FAULT_RESULT_SORT_COLUMN );
253
261
Specification <FaultResultEntity > specification = FaultResultSpecificationBuilder .buildSpecification (result .getResultUuid (), resourceFilters );
254
262
// WARN org.hibernate.hql.internal.ast.QueryTranslatorImpl -
255
263
// HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
256
264
// cf. https://vladmihalcea.com/fix-hibernate-hhh000104-entity-fetch-pagination-warning-message/
257
265
// We must separate in two requests, one with pagination the other one with Join Fetch
258
- Page <FaultResultEntity > faultResultsPage = faultResultRepository .findAll (specification , addDefaultSort (pageable , DEFAULT_FAULT_RESULT_SORT_COLUMN ));
259
- if (faultResultsPage .hasContent () && mode != FaultResultsMode .BASIC ) {
260
- appendLimitViolationsAndFeederResults (faultResultsPage );
266
+
267
+ Page <FaultResultRepository .EntityId > uuidPage = faultResultRepository .findBy (specification , q ->
268
+ q .project (FaultResultEntity .Fields .faultResultUuid )
269
+ .as (FaultResultRepository .EntityId .class )
270
+ .sortBy (modifiedPageable .getSort ())
271
+ .page (modifiedPageable )
272
+ );
273
+
274
+ if (!uuidPage .hasContent ()) {
275
+ return Page .empty ();
276
+ }
277
+
278
+ List <UUID > faultResultsUuids = uuidPage
279
+ .map (FaultResultRepository .EntityId ::getFaultResultUuid )
280
+ .toList ();
281
+ // Then we fetch the main entities data for each UUID
282
+ List <FaultResultEntity > faultResults = faultResultRepository .findAllByFaultResultUuidIn (faultResultsUuids );
283
+ faultResults .sort (Comparator .comparing (fault -> faultResultsUuids .indexOf (fault .getFaultResultUuid ())));
284
+ Page <FaultResultEntity > faultResultsPage = new PageImpl <>(faultResults , modifiedPageable , uuidPage .getTotalElements ());
285
+
286
+ if (mode != FaultResultsMode .BASIC ) {
287
+ // then we append the missing data, and filter some of the Lazy Loaded collections
288
+ appendLimitViolationsAndFeederResults (faultResultsPage , childrenSort , resourceFilters );
261
289
}
290
+
262
291
return faultResultsPage ;
263
292
}
264
293
294
+ private Pageable filterOutChildrenSort (Pageable pageable , Optional <Sort .Order > childrenSort ) {
295
+ if (childrenSort .isEmpty ()) {
296
+ return pageable ;
297
+ }
298
+ return PageRequest .of (
299
+ pageable .getPageNumber (),
300
+ pageable .getPageSize (),
301
+ Sort .by (pageable .getSort ().stream ().filter (sortOrder ->
302
+ !sortOrder .getProperty ().equals (childrenSort .get ().getProperty ())
303
+ ).toList ()
304
+ )
305
+ );
306
+ }
307
+
308
+ private Optional <Sort .Order > extractChildrenSort (Pageable pageable ) {
309
+ return pageable .getSort ().stream ()
310
+ .filter (sortOrder ->
311
+ sortOrder .getProperty ().contains (FeederResultEntity .Fields .connectableId ))
312
+ .findFirst ();
313
+ }
314
+
265
315
@ Transactional (readOnly = true )
266
316
public Page <FeederResultEntity > findFeederResultsPage (ShortCircuitAnalysisResultEntity result , List <ResourceFilter > resourceFilters , Pageable pageable ) {
267
317
Objects .requireNonNull (result );
@@ -270,30 +320,78 @@ public Page<FeederResultEntity> findFeederResultsPage(ShortCircuitAnalysisResult
270
320
}
271
321
272
322
@ Transactional (readOnly = true )
273
- public Page <FaultResultEntity > findFaultResultsWithLimitViolationsPage (ShortCircuitAnalysisResultEntity result , List <ResourceFilter > resourceFilters , Pageable pageable ) {
323
+ public Page <FaultResultEntity > findFaultResultsWithLimitViolationsPage (ShortCircuitAnalysisResultEntity result ,
324
+ List <ResourceFilter > resourceFilters ,
325
+ Pageable pageable ) {
274
326
Objects .requireNonNull (result );
327
+
328
+ Optional <Sort .Order > childrenSort = extractChildrenSort (pageable );
329
+
330
+ Pageable modifiedPageable = addDefaultSort (filterOutChildrenSort (pageable , childrenSort ),
331
+ DEFAULT_FAULT_RESULT_SORT_COLUMN );
275
332
Specification <FaultResultEntity > specification = FaultResultSpecificationBuilder .buildSpecification (result .getResultUuid (), resourceFilters );
276
333
specification = FaultResultSpecificationBuilder .appendWithLimitViolationsToSpecification (specification );
277
334
// WARN org.hibernate.hql.internal.ast.QueryTranslatorImpl -
278
335
// HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
279
336
// cf. https://vladmihalcea.com/fix-hibernate-hhh000104-entity-fetch-pagination-warning-message/
280
337
// We must separate in two requests, one with pagination the other one with Join Fetch
281
- Page <FaultResultEntity > faultResultsPage = faultResultRepository .findAll (specification , addDefaultSort (pageable , DEFAULT_FAULT_RESULT_SORT_COLUMN ));
282
- if (faultResultsPage .hasContent ()) {
283
- appendLimitViolationsAndFeederResults (faultResultsPage );
338
+
339
+ Page <FaultResultRepository .EntityId > uuidPage = faultResultRepository .findBy (specification , q ->
340
+ q .project (FaultResultEntity .Fields .faultResultUuid )
341
+ .as (FaultResultRepository .EntityId .class )
342
+ .sortBy (modifiedPageable .getSort ())
343
+ .page (modifiedPageable )
344
+ );
345
+
346
+ if (!uuidPage .hasContent ()) {
347
+ return Page .empty ();
284
348
}
349
+
350
+ List <UUID > faultResultsUuids = uuidPage
351
+ .map (FaultResultRepository .EntityId ::getFaultResultUuid )
352
+ .toList ();
353
+ // Then we fetch the main entities data for each UUID
354
+ List <FaultResultEntity > faultResults = faultResultRepository .findAllByFaultResultUuidIn (faultResultsUuids );
355
+ faultResults .sort (Comparator .comparing (fault -> faultResultsUuids .indexOf (fault .getFaultResultUuid ())));
356
+ Page <FaultResultEntity > faultResultsPage = new PageImpl <>(faultResults , modifiedPageable , uuidPage .getTotalElements ());
357
+
358
+ // then we append the missing data, and filter some of the Lazy Loaded collections
359
+ appendLimitViolationsAndFeederResults (faultResultsPage , childrenSort , resourceFilters );
360
+
285
361
return faultResultsPage ;
286
362
}
287
363
288
- private void appendLimitViolationsAndFeederResults (Page <FaultResultEntity > pagedFaultResults ) {
364
+ private void appendLimitViolationsAndFeederResults (Page <FaultResultEntity > pagedFaultResults ,
365
+ Optional <Sort .Order > childrenSort ,
366
+ List <ResourceFilter > resourceFilters ) {
289
367
// using the Hibernate First-Level Cache or Persistence Context
290
368
// cf.https://vladmihalcea.com/spring-data-jpa-multiplebagfetchexception/
291
369
if (!pagedFaultResults .isEmpty ()) {
292
370
List <UUID > faultResultsUuids = pagedFaultResults .stream ()
293
371
.map (FaultResultEntity ::getFaultResultUuid )
294
- .collect (Collectors .toList ());
372
+ .toList ();
373
+
374
+ Specification <FaultResultEntity > specification = FaultResultSpecificationBuilder .buildFeedersSpecification (faultResultsUuids , resourceFilters );
375
+ faultResultRepository .findAll (specification );
376
+
295
377
faultResultRepository .findAllWithLimitViolationsByFaultResultUuidIn (faultResultsUuids );
296
- faultResultRepository .findAllWithFeederResultsByFaultResultUuidIn (faultResultsUuids );
378
+
379
+ sortFeeders (pagedFaultResults , childrenSort );
380
+ }
381
+ }
382
+
383
+ private void sortFeeders (Page <FaultResultEntity > pagedFaultResults , Optional <Sort .Order > childrenSort ) {
384
+ // feeders may only be sorted by connectableId
385
+ if (childrenSort .isPresent ()) {
386
+ pagedFaultResults .forEach (res -> res .getFeederResults ().sort (
387
+ childrenSort .get ().isAscending () ?
388
+ Comparator .comparing (FeederResultEntity ::getConnectableId ) :
389
+ Comparator .comparing (FeederResultEntity ::getConnectableId ).reversed ()
390
+ ));
391
+ } else {
392
+ // otherwise by default feederResults (within each individual faultResult) are sorted by 'current' in descending order :
393
+ pagedFaultResults .forEach (res -> res .getFeederResults ().sort (
394
+ Comparator .comparingDouble (FeederResultEntity ::getCurrent ).reversed ()));
297
395
}
298
396
}
299
397
0 commit comments