|
30 | 30 | import java.util.function.Function;
|
31 | 31 | import java.util.function.Predicate;
|
32 | 32 | import java.util.function.Supplier;
|
33 |
| -import java.util.stream.Collectors; |
34 | 33 | import java.util.stream.StreamSupport;
|
35 | 34 |
|
36 | 35 | import org.neo4j.driver.Value;
|
@@ -111,7 +110,12 @@ public <R> R read(Class<R> targetType, MapAccessor mapAccessor) {
|
111 | 110 | }
|
112 | 111 | }
|
113 | 112 |
|
114 |
| - private <R> MapAccessor determineQueryRoot(MapAccessor mapAccessor, Neo4jPersistentEntity<R> rootNodeDescription) { |
| 113 | + @Nullable |
| 114 | + private <R> MapAccessor determineQueryRoot(MapAccessor mapAccessor, @Nullable Neo4jPersistentEntity<R> rootNodeDescription) { |
| 115 | + |
| 116 | + if (rootNodeDescription == null) { |
| 117 | + return null; |
| 118 | + } |
115 | 119 |
|
116 | 120 | List<String> primaryLabels = new ArrayList<>();
|
117 | 121 | primaryLabels.add(rootNodeDescription.getPrimaryLabel());
|
@@ -354,7 +358,7 @@ private boolean containsOnePlainNode(MapAccessor queryResult) {
|
354 | 358 |
|
355 | 359 | private <ET> ET instantiate(Neo4jPersistentEntity<ET> nodeDescription, MapAccessor values, MapAccessor allValues,
|
356 | 360 | Collection<RelationshipDescription> relationships, Collection<String> surplusLabels,
|
357 |
| - Object lastMappedEntity) { |
| 361 | + @Nullable Object lastMappedEntity) { |
358 | 362 |
|
359 | 363 | ParameterValueProvider<Neo4jPersistentProperty> parameterValueProvider = new ParameterValueProvider<Neo4jPersistentProperty>() {
|
360 | 364 | @Override
|
@@ -459,22 +463,10 @@ private Optional<Object> createInstanceOfRelationships(Neo4jPersistentProperty p
|
459 | 463 |
|
460 | 464 | if (Values.NULL.equals(list)) {
|
461 | 465 |
|
462 |
| - Collection<Relationship> allMatchingTypeRelationshipsInResult = new ArrayList<>(); |
463 |
| - Collection<Node> allNodesWithMatchingLabelInResult = new ArrayList<>(); |
464 |
| - |
465 | 466 | // Retrieve all relationships from the result's list(s)
|
466 |
| - StreamSupport.stream(allValues.values().spliterator(), false) |
467 |
| - .filter(MappingSupport.isListContainingOnly(listType, this.relationshipType)) |
468 |
| - .flatMap(entry -> MappingSupport.extractRelationships(listType, entry).stream()) |
469 |
| - .filter(r -> r.type().equals(typeOfRelationship) || relationshipDescription.isDynamic()) |
470 |
| - .forEach(allMatchingTypeRelationshipsInResult::add); |
471 |
| - |
| 467 | + Collection<Relationship> allMatchingTypeRelationshipsInResult = extractMatchingRelationships(allValues, relationshipDescription, typeOfRelationship); |
472 | 468 | // Retrieve all nodes from the result's list(s)
|
473 |
| - StreamSupport.stream(allValues.values().spliterator(), false) |
474 |
| - .filter(MappingSupport.isListContainingOnly(listType, this.nodeType)) |
475 |
| - .flatMap(entry -> MappingSupport.extractNodes(listType, entry).stream()) |
476 |
| - .filter(n -> n.hasLabel(targetLabel)).collect(Collectors.toList()) |
477 |
| - .forEach(allNodesWithMatchingLabelInResult::add); |
| 469 | + Collection<Node> allNodesWithMatchingLabelInResult = extractMatchingNodes(allValues, targetLabel); |
478 | 470 |
|
479 | 471 | Function<Relationship, Long> targetIdSelector = relationshipDescription.isIncoming() ? Relationship::startNodeId : Relationship::endNodeId;
|
480 | 472 | Function<Relationship, Long> sourceIdSelector = relationshipDescription.isIncoming() ? Relationship::endNodeId : Relationship::startNodeId;
|
@@ -546,6 +538,48 @@ private Optional<Object> createInstanceOfRelationships(Neo4jPersistentProperty p
|
546 | 538 | }
|
547 | 539 | }
|
548 | 540 |
|
| 541 | + private Collection<Node> extractMatchingNodes(MapAccessor allValues, String targetLabel) { |
| 542 | + |
| 543 | + Collection<Node> allNodesWithMatchingLabelInResult = new ArrayList<>(); |
| 544 | + Predicate<Node> onlyWithMatchingLabels = n -> n.hasLabel(targetLabel); |
| 545 | + StreamSupport.stream(allValues.values().spliterator(), false) |
| 546 | + .filter(MappingSupport.isListContainingOnly(listType, this.nodeType)) |
| 547 | + .flatMap(entry -> MappingSupport.extractNodes(listType, entry).stream()) |
| 548 | + .filter(onlyWithMatchingLabels) |
| 549 | + .forEach(allNodesWithMatchingLabelInResult::add); |
| 550 | + |
| 551 | + if (allNodesWithMatchingLabelInResult.isEmpty()) { |
| 552 | + StreamSupport.stream(allValues.values().spliterator(), false) |
| 553 | + .filter(this.nodeType::isTypeOf) |
| 554 | + .map(Value::asNode) |
| 555 | + .filter(onlyWithMatchingLabels) |
| 556 | + .forEach(allNodesWithMatchingLabelInResult::add); |
| 557 | + } |
| 558 | + |
| 559 | + return allNodesWithMatchingLabelInResult; |
| 560 | + } |
| 561 | + |
| 562 | + private Collection<Relationship> extractMatchingRelationships(MapAccessor allValues, RelationshipDescription relationshipDescription, String typeOfRelationship) { |
| 563 | + |
| 564 | + Collection<Relationship> allMatchingTypeRelationshipsInResult = new ArrayList<>(); |
| 565 | + Predicate<Relationship> onlyWithMatchingType = r -> r.type().equals(typeOfRelationship) || relationshipDescription.isDynamic(); |
| 566 | + StreamSupport.stream(allValues.values().spliterator(), false) |
| 567 | + .filter(MappingSupport.isListContainingOnly(listType, this.relationshipType)) |
| 568 | + .flatMap(entry -> MappingSupport.extractRelationships(listType, entry).stream()) |
| 569 | + .filter(onlyWithMatchingType) |
| 570 | + .forEach(allMatchingTypeRelationshipsInResult::add); |
| 571 | + |
| 572 | + if (allMatchingTypeRelationshipsInResult.isEmpty()) { |
| 573 | + StreamSupport.stream(allValues.values().spliterator(), false) |
| 574 | + .filter(this.relationshipType::isTypeOf) |
| 575 | + .map(Value::asRelationship) |
| 576 | + .filter(onlyWithMatchingType) |
| 577 | + .forEach(allMatchingTypeRelationshipsInResult::add); |
| 578 | + } |
| 579 | + |
| 580 | + return allMatchingTypeRelationshipsInResult; |
| 581 | + } |
| 582 | + |
549 | 583 | private static Value extractValueOf(Neo4jPersistentProperty property, MapAccessor propertyContainer) {
|
550 | 584 | if (property.isInternalIdProperty()) {
|
551 | 585 | return propertyContainer instanceof Entity ? Values.value(((Entity) propertyContainer).id())
|
|
0 commit comments