|
36 | 36 | import org.springframework.data.domain.Sort;
|
37 | 37 | import org.springframework.data.mapping.MappingException;
|
38 | 38 | import org.springframework.data.mapping.PersistentProperty;
|
39 |
| -import org.springframework.data.neo4j.core.schema.Relationship.Direction; |
40 | 39 | import org.springframework.lang.NonNull;
|
41 | 40 | import org.springframework.lang.Nullable;
|
42 | 41 | import org.springframework.util.Assert;
|
43 | 42 |
|
44 | 43 | import java.util.ArrayList;
|
45 | 44 | import java.util.Arrays;
|
46 | 45 | import java.util.Collection;
|
47 |
| -import java.util.HashSet; |
48 | 46 | import java.util.List;
|
49 |
| -import java.util.Set; |
50 | 47 | import java.util.function.Predicate;
|
51 | 48 | import java.util.function.UnaryOperator;
|
52 |
| -import java.util.stream.Collectors; |
53 | 49 |
|
54 | 50 | import static org.neo4j.cypherdsl.core.Cypher.anyNode;
|
55 | 51 | import static org.neo4j.cypherdsl.core.Cypher.listBasedOn;
|
@@ -506,183 +502,13 @@ private MapProjection projectPropertiesAndRelationships(NodeDescription<?> nodeD
|
506 | 502 | List<Object> propertiesProjection = projectNodeProperties(nodeDescription, nodeName, includedProperties);
|
507 | 503 | List<Object> contentOfProjection = new ArrayList<>(propertiesProjection);
|
508 | 504 |
|
509 |
| - Collection<RelationshipDescription> relationships = getRelationshipDescriptionsUpAndDown(nodeDescription, includedProperties); |
| 505 | + Collection<RelationshipDescription> relationships = nodeDescription.getRelationshipsUpAndDown(includedProperties); |
510 | 506 | relationships.removeIf(r -> !includedProperties.test(r.getFieldName()));
|
511 | 507 |
|
512 | 508 | contentOfProjection.addAll(generateListsFor(relationships, nodeName, processedRelationships));
|
513 | 509 | return Cypher.anyNode(nodeName).project(contentOfProjection);
|
514 | 510 | }
|
515 | 511 |
|
516 |
| - @NonNull |
517 |
| - static Collection<RelationshipDescription> getRelationshipDescriptionsUpAndDown(NodeDescription<?> nodeDescription, |
518 |
| - Predicate<String> includedProperties) { |
519 |
| - |
520 |
| - Collection<RelationshipDescription> relationships = new HashSet<>(nodeDescription.getRelationships()); |
521 |
| - for (NodeDescription<?> childDescription : nodeDescription.getChildNodeDescriptionsInHierarchy()) { |
522 |
| - childDescription.getRelationships().forEach(concreteRelationship -> { |
523 |
| - |
524 |
| - String fieldName = concreteRelationship.getFieldName(); |
525 |
| - |
526 |
| - if (relationships.stream().noneMatch(relationship -> relationship.getFieldName().equals(fieldName))) { |
527 |
| - relationships.add(concreteRelationship); |
528 |
| - } |
529 |
| - }); |
530 |
| - } |
531 |
| - |
532 |
| - return relationships.stream().filter(relationshipDescription -> |
533 |
| - includedProperties.test(relationshipDescription.getFieldName())) |
534 |
| - .collect(Collectors.toSet()); |
535 |
| - } |
536 |
| - |
537 |
| - private RelationshipPattern createRelationships(Node node, Collection<RelationshipDescription> relationshipDescriptions) { |
538 |
| - RelationshipPattern relationship; |
539 |
| - |
540 |
| - Direction determinedDirection = determineDirection(relationshipDescriptions); |
541 |
| - if (Direction.OUTGOING.equals(determinedDirection)) { |
542 |
| - relationship = node.relationshipTo(anyNode(), collectFirstLevelRelationshipTypes(relationshipDescriptions)) |
543 |
| - .min(0).max(1); |
544 |
| - } else if (Direction.INCOMING.equals(determinedDirection)) { |
545 |
| - relationship = node.relationshipFrom(anyNode(), collectFirstLevelRelationshipTypes(relationshipDescriptions)) |
546 |
| - .min(0).max(1); |
547 |
| - } else { |
548 |
| - relationship = node.relationshipBetween(anyNode(), collectFirstLevelRelationshipTypes(relationshipDescriptions)) |
549 |
| - .min(0).max(1); |
550 |
| - } |
551 |
| - |
552 |
| - Set<RelationshipDescription> processedRelationshipDescriptions = new HashSet<>(relationshipDescriptions); |
553 |
| - for (RelationshipDescription relationshipDescription : relationshipDescriptions) { |
554 |
| - Collection<RelationshipDescription> relationships = relationshipDescription.getTarget().getRelationships(); |
555 |
| - if (relationships.size() > 0) { |
556 |
| - relationship = createRelationships(relationship, relationships, processedRelationshipDescriptions) |
557 |
| - .relationship; |
558 |
| - } |
559 |
| - } |
560 |
| - |
561 |
| - return relationship; |
562 |
| - } |
563 |
| - |
564 |
| - private RelationshipProcessState createRelationships(RelationshipPattern existingRelationship, |
565 |
| - Collection<RelationshipDescription> relationshipDescriptions, |
566 |
| - Set<RelationshipDescription> processedRelationshipDescriptions) { |
567 |
| - |
568 |
| - RelationshipPattern relationship = existingRelationship; |
569 |
| - String[] relationshipTypes = collectAllRelationshipTypes(relationshipDescriptions); |
570 |
| - if (processedRelationshipDescriptions.containsAll(relationshipDescriptions)) { |
571 |
| - return new RelationshipProcessState( |
572 |
| - relationship.relationshipBetween(anyNode(), |
573 |
| - relationshipTypes).unbounded().min(0), true); |
574 |
| - } |
575 |
| - processedRelationshipDescriptions.addAll(relationshipDescriptions); |
576 |
| - |
577 |
| - // we can process through the path |
578 |
| - if (relationshipDescriptions.size() == 1) { |
579 |
| - RelationshipDescription relationshipDescription = relationshipDescriptions.iterator().next(); |
580 |
| - switch (relationshipDescription.getDirection()) { |
581 |
| - case OUTGOING: |
582 |
| - relationship = existingRelationship.relationshipTo(anyNode(), |
583 |
| - collectFirstLevelRelationshipTypes(relationshipDescriptions)).unbounded().min(0).max(1); |
584 |
| - break; |
585 |
| - case INCOMING: |
586 |
| - relationship = existingRelationship.relationshipFrom(anyNode(), |
587 |
| - collectFirstLevelRelationshipTypes(relationshipDescriptions)).unbounded().min(0).max(1); |
588 |
| - break; |
589 |
| - default: |
590 |
| - relationship = existingRelationship.relationshipBetween(anyNode(), |
591 |
| - collectFirstLevelRelationshipTypes(relationshipDescriptions)).unbounded().min(0).max(1); |
592 |
| - } |
593 |
| - |
594 |
| - RelationshipProcessState relationships = createRelationships(relationship, |
595 |
| - relationshipDescription.getTarget().getRelationships(), processedRelationshipDescriptions); |
596 |
| - |
597 |
| - if (!relationships.done) { |
598 |
| - relationship = relationships.relationship; |
599 |
| - } |
600 |
| - } else { |
601 |
| - Direction determinedDirection = determineDirection(relationshipDescriptions); |
602 |
| - if (Direction.OUTGOING.equals(determinedDirection)) { |
603 |
| - relationship = existingRelationship.relationshipTo(anyNode(), relationshipTypes).unbounded().min(0); |
604 |
| - } else if (Direction.INCOMING.equals(determinedDirection)) { |
605 |
| - relationship = existingRelationship.relationshipFrom(anyNode(), relationshipTypes).unbounded().min(0); |
606 |
| - } else { |
607 |
| - relationship = existingRelationship.relationshipBetween(anyNode(), relationshipTypes).unbounded().min(0); |
608 |
| - } |
609 |
| - return new RelationshipProcessState(relationship, true); |
610 |
| - } |
611 |
| - return new RelationshipProcessState(relationship, false); |
612 |
| - } |
613 |
| - |
614 |
| - @Nullable |
615 |
| - Direction determineDirection(Collection<RelationshipDescription> relationshipDescriptions) { |
616 |
| - |
617 |
| - Direction direction = null; |
618 |
| - for (RelationshipDescription relationshipDescription : relationshipDescriptions) { |
619 |
| - if (direction == null) { |
620 |
| - direction = relationshipDescription.getDirection(); |
621 |
| - } |
622 |
| - if (!direction.equals(relationshipDescription.getDirection())) { |
623 |
| - return null; |
624 |
| - } |
625 |
| - } |
626 |
| - return direction; |
627 |
| - } |
628 |
| - |
629 |
| - private String[] collectFirstLevelRelationshipTypes(Collection<RelationshipDescription> relationshipDescriptions) { |
630 |
| - Set<String> relationshipTypes = new HashSet<>(); |
631 |
| - |
632 |
| - for (RelationshipDescription relationshipDescription : relationshipDescriptions) { |
633 |
| - String relationshipType = relationshipDescription.getType(); |
634 |
| - if (relationshipTypes.contains(relationshipType)) { |
635 |
| - continue; |
636 |
| - } |
637 |
| - if (relationshipDescription.isDynamic()) { |
638 |
| - handleDynamicRelationship(relationshipTypes, (DefaultRelationshipDescription) relationshipDescription); |
639 |
| - continue; |
640 |
| - } |
641 |
| - relationshipTypes.add(relationshipType); |
642 |
| - } |
643 |
| - return relationshipTypes.toArray(new String[0]); |
644 |
| - } |
645 |
| - |
646 |
| - private String[] collectAllRelationshipTypes(Collection<RelationshipDescription> relationshipDescriptions) { |
647 |
| - Set<String> relationshipTypes = new HashSet<>(); |
648 |
| - |
649 |
| - for (RelationshipDescription relationshipDescription : relationshipDescriptions) { |
650 |
| - String relationshipType = relationshipDescription.getType(); |
651 |
| - if (relationshipDescription.isDynamic()) { |
652 |
| - handleDynamicRelationship(relationshipTypes, (DefaultRelationshipDescription) relationshipDescription); |
653 |
| - continue; |
654 |
| - } |
655 |
| - relationshipTypes.add(relationshipType); |
656 |
| - collectAllRelationshipTypes(relationshipDescription.getTarget(), relationshipTypes, new HashSet<>(relationshipDescriptions)); |
657 |
| - } |
658 |
| - return relationshipTypes.toArray(new String[0]); |
659 |
| - } |
660 |
| - |
661 |
| - private void handleDynamicRelationship(Set<String> relationshipTypes, DefaultRelationshipDescription relationshipDescription) { |
662 |
| - Class<?> componentType = relationshipDescription.getInverse().getComponentType(); |
663 |
| - if (componentType != null && componentType.isEnum()) { |
664 |
| - Arrays.stream(componentType.getEnumConstants()) |
665 |
| - .forEach(constantName -> relationshipTypes.add(constantName.toString())); |
666 |
| - } else { |
667 |
| - relationshipTypes.clear(); |
668 |
| - } |
669 |
| - } |
670 |
| - |
671 |
| - private void collectAllRelationshipTypes(NodeDescription<?> nodeDescription, Set<String> relationshipTypes, |
672 |
| - Collection<RelationshipDescription> processedRelationshipDescriptions) { |
673 |
| - |
674 |
| - for (RelationshipDescription relationshipDescription : nodeDescription.getRelationships()) { |
675 |
| - String relationshipType = relationshipDescription.getType(); |
676 |
| - if (processedRelationshipDescriptions.contains(relationshipDescription)) { |
677 |
| - continue; |
678 |
| - } |
679 |
| - relationshipTypes.add(relationshipType); |
680 |
| - processedRelationshipDescriptions.add(relationshipDescription); |
681 |
| - collectAllRelationshipTypes(relationshipDescription.getTarget(), relationshipTypes, |
682 |
| - processedRelationshipDescriptions); |
683 |
| - } |
684 |
| - } |
685 |
| - |
686 | 512 | /**
|
687 | 513 | * Creates a list of objects that represents a very basic of {@code MapEntry<String, Object>} with the exception that
|
688 | 514 | * this list can also contain two "keys" in a row. The {@link MapProjection} will take care to handle them as
|
|
0 commit comments