|
34 | 34 | import java.util.function.Supplier;
|
35 | 35 | import java.util.stream.Collectors;
|
36 | 36 |
|
| 37 | +import org.eclipse.collections.api.RichIterable; |
| 38 | +import org.eclipse.collections.api.bag.ImmutableBag; |
| 39 | +import org.eclipse.collections.api.bag.MutableBag; |
| 40 | +import org.eclipse.collections.api.factory.Bags; |
| 41 | +import org.eclipse.collections.api.factory.Lists; |
| 42 | +import org.eclipse.collections.api.factory.Maps; |
| 43 | +import org.eclipse.collections.api.factory.Sets; |
| 44 | +import org.eclipse.collections.api.list.ImmutableList; |
| 45 | +import org.eclipse.collections.api.list.MutableList; |
| 46 | +import org.eclipse.collections.api.map.ImmutableMap; |
| 47 | +import org.eclipse.collections.api.map.MapIterable; |
| 48 | +import org.eclipse.collections.api.map.MutableMap; |
| 49 | +import org.eclipse.collections.api.set.ImmutableSet; |
| 50 | +import org.eclipse.collections.api.set.MutableSet; |
37 | 51 | import org.springframework.core.convert.TypeDescriptor;
|
| 52 | +import org.springframework.core.convert.converter.ConditionalConverter; |
38 | 53 | import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
| 54 | +import org.springframework.core.convert.converter.Converter; |
39 | 55 | import org.springframework.core.convert.converter.ConverterRegistry;
|
40 | 56 | import org.springframework.core.io.support.SpringFactoriesLoader;
|
41 | 57 | import org.springframework.lang.NonNull;
|
@@ -488,4 +504,232 @@ public Object convert(@Nullable Object source, TypeDescriptor sourceDescriptor,
|
488 | 504 | }
|
489 | 505 | }
|
490 | 506 | }
|
| 507 | + |
| 508 | + static class EclipseCollections implements CustomCollectionRegistrar { |
| 509 | + |
| 510 | + /* |
| 511 | + * (non-Javadoc) |
| 512 | + * @see org.springframework.data.util.CustomCollectionRegistrar#isAvailable() |
| 513 | + */ |
| 514 | + @Override |
| 515 | + public boolean isAvailable() { |
| 516 | + return ClassUtils.isPresent("org.eclipse.collections.api.list.ImmutableList", |
| 517 | + EclipseCollections.class.getClassLoader()); |
| 518 | + } |
| 519 | + |
| 520 | + /* |
| 521 | + * (non-Javadoc) |
| 522 | + * @see org.springframework.data.util.CustomCollectionRegistrar#getCollectionTypes() |
| 523 | + */ |
| 524 | + @Override |
| 525 | + public Collection<Class<?>> getCollectionTypes() { |
| 526 | + return Arrays.asList(ImmutableList.class, ImmutableSet.class, ImmutableBag.class, // |
| 527 | + MutableList.class, MutableSet.class, MutableBag.class); |
| 528 | + } |
| 529 | + |
| 530 | + /* |
| 531 | + * (non-Javadoc) |
| 532 | + * @see org.springframework.data.util.CustomCollectionRegistrar#getMapTypes() |
| 533 | + */ |
| 534 | + @Override |
| 535 | + public Collection<Class<?>> getMapTypes() { |
| 536 | + return Arrays.asList(ImmutableMap.class, MutableMap.class); |
| 537 | + } |
| 538 | + |
| 539 | + /* |
| 540 | + * (non-Javadoc) |
| 541 | + * @see org.springframework.data.util.CustomCollectionRegistrar#getAllowedPaginationReturnTypes() |
| 542 | + */ |
| 543 | + @Override |
| 544 | + public Collection<Class<?>> getAllowedPaginationReturnTypes() { |
| 545 | + return Arrays.asList(ImmutableList.class, MutableList.class); |
| 546 | + } |
| 547 | + |
| 548 | + /* |
| 549 | + * (non-Javadoc) |
| 550 | + * @see org.springframework.data.util.CustomCollectionRegistrar#toJavaNativeCollection() |
| 551 | + */ |
| 552 | + @Override |
| 553 | + public Function<Object, Object> toJavaNativeCollection() { |
| 554 | + |
| 555 | + return source -> source instanceof RichIterable |
| 556 | + ? EclipseToJavaConverter.INSTANCE.convert(source) |
| 557 | + : source; |
| 558 | + } |
| 559 | + |
| 560 | + /* |
| 561 | + * (non-Javadoc) |
| 562 | + * @see org.springframework.data.util.CustomCollectionRegistrar#registerConvertersIn(org.springframework.core.convert.converter.ConverterRegistry) |
| 563 | + */ |
| 564 | + @Override |
| 565 | + public void registerConvertersIn(ConverterRegistry registry) { |
| 566 | + |
| 567 | + registry.addConverter(EclipseToJavaConverter.INSTANCE); |
| 568 | + registry.addConverter(JavaToEclipseConverter.INSTANCE); |
| 569 | + } |
| 570 | + |
| 571 | + enum EclipseToJavaConverter implements Converter<Object, Object>, ConditionalConverter { |
| 572 | + |
| 573 | + INSTANCE; |
| 574 | + |
| 575 | + private static final TypeDescriptor RICH_ITERABLE_DESCRIPTOR = TypeDescriptor.valueOf(RichIterable.class); |
| 576 | + |
| 577 | + /* |
| 578 | + * (non-Javadoc) |
| 579 | + * @see org.springframework.core.convert.converter.ConditionalConverter#matches(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor) |
| 580 | + */ |
| 581 | + @Override |
| 582 | + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { |
| 583 | + |
| 584 | + return sourceType.isAssignableTo(RICH_ITERABLE_DESCRIPTOR) |
| 585 | + && COLLECTIONS_AND_MAP.contains(targetType.getType()); |
| 586 | + } |
| 587 | + |
| 588 | + /* |
| 589 | + * (non-Javadoc) |
| 590 | + * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object) |
| 591 | + */ |
| 592 | + @Nullable |
| 593 | + @Override |
| 594 | + public Object convert(@Nullable Object source) { |
| 595 | + |
| 596 | + if (source instanceof ImmutableList) { |
| 597 | + return ((ImmutableList<?>) source).toList(); |
| 598 | + } |
| 599 | + |
| 600 | + if (source instanceof ImmutableBag) { |
| 601 | + return ((ImmutableBag<?>) source).toList(); |
| 602 | + } |
| 603 | + |
| 604 | + if (source instanceof ImmutableSet) { |
| 605 | + return ((ImmutableSet<?>) source).toSet(); |
| 606 | + } |
| 607 | + |
| 608 | + if (source instanceof ImmutableMap) { |
| 609 | + return ((ImmutableMap<?, ?>) source).toMap(); |
| 610 | + } |
| 611 | + |
| 612 | + return source; |
| 613 | + } |
| 614 | + } |
| 615 | + |
| 616 | + enum JavaToEclipseConverter implements ConditionalGenericConverter { |
| 617 | + |
| 618 | + INSTANCE; |
| 619 | + |
| 620 | + private static final Set<ConvertiblePair> CONVERTIBLE_PAIRS; |
| 621 | + |
| 622 | + static { |
| 623 | + |
| 624 | + Set<ConvertiblePair> pairs = new HashSet<>(); |
| 625 | + pairs.add(new ConvertiblePair(Collection.class, RichIterable.class)); |
| 626 | + |
| 627 | + pairs.add(new ConvertiblePair(Set.class, MutableSet.class)); |
| 628 | + pairs.add(new ConvertiblePair(Set.class, MutableList.class)); |
| 629 | + pairs.add(new ConvertiblePair(Set.class, ImmutableSet.class)); |
| 630 | + pairs.add(new ConvertiblePair(Set.class, ImmutableList.class)); |
| 631 | + |
| 632 | + pairs.add(new ConvertiblePair(List.class, MutableList.class)); |
| 633 | + pairs.add(new ConvertiblePair(List.class, ImmutableList.class)); |
| 634 | + |
| 635 | + pairs.add(new ConvertiblePair(Map.class, RichIterable.class)); |
| 636 | + pairs.add(new ConvertiblePair(Map.class, MutableMap.class)); |
| 637 | + pairs.add(new ConvertiblePair(Map.class, ImmutableMap.class)); |
| 638 | + |
| 639 | + CONVERTIBLE_PAIRS = Collections.unmodifiableSet(pairs); |
| 640 | + } |
| 641 | + |
| 642 | + /* |
| 643 | + * (non-Javadoc) |
| 644 | + * @see org.springframework.core.convert.converter.GenericConverter#getConvertibleTypes() |
| 645 | + */ |
| 646 | + @NonNull |
| 647 | + @Override |
| 648 | + public Set<ConvertiblePair> getConvertibleTypes() { |
| 649 | + return CONVERTIBLE_PAIRS; |
| 650 | + } |
| 651 | + |
| 652 | + /* |
| 653 | + * (non-Javadoc) |
| 654 | + * @see org.springframework.core.convert.converter.ConditionalConverter#matches(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor) |
| 655 | + */ |
| 656 | + @Override |
| 657 | + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { |
| 658 | + |
| 659 | + // Prevent collections to be mapped to maps |
| 660 | + if (sourceType.isCollection() && MapIterable.class.isAssignableFrom(targetType.getType())) { |
| 661 | + return false; |
| 662 | + } |
| 663 | + |
| 664 | + // Prevent maps to be mapped to collections |
| 665 | + if (sourceType.isMap() // |
| 666 | + && !(MapIterable.class.isAssignableFrom(targetType.getType()) |
| 667 | + || targetType.getType().equals(RichIterable.class))) { |
| 668 | + return false; |
| 669 | + } |
| 670 | + |
| 671 | + return true; |
| 672 | + } |
| 673 | + |
| 674 | + /* |
| 675 | + * (non-Javadoc) |
| 676 | + * @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor) |
| 677 | + */ |
| 678 | + @Nullable |
| 679 | + @Override |
| 680 | + public Object convert(@Nullable Object source, TypeDescriptor sourceDescriptor, TypeDescriptor targetDescriptor) { |
| 681 | + |
| 682 | + Class<?> targetType = targetDescriptor.getType(); |
| 683 | + |
| 684 | + if (ImmutableList.class.isAssignableFrom(targetType)) { |
| 685 | + return Lists.immutable.ofAll((Iterable<?>) source); |
| 686 | + } |
| 687 | + |
| 688 | + if (ImmutableSet.class.isAssignableFrom(targetType)) { |
| 689 | + return Sets.immutable.ofAll((Iterable<?>) source); |
| 690 | + } |
| 691 | + |
| 692 | + if (ImmutableBag.class.isAssignableFrom(targetType)) { |
| 693 | + return Bags.immutable.ofAll((Iterable<?>) source); |
| 694 | + } |
| 695 | + |
| 696 | + if (ImmutableMap.class.isAssignableFrom(targetType)) { |
| 697 | + return Maps.immutable.ofAll((Map<?, ?>) source); |
| 698 | + } |
| 699 | + |
| 700 | + if (MutableList.class.isAssignableFrom(targetType)) { |
| 701 | + return Lists.mutable.ofAll((Iterable<?>) source); |
| 702 | + } |
| 703 | + |
| 704 | + if (MutableSet.class.isAssignableFrom(targetType)) { |
| 705 | + return Sets.mutable.ofAll((Iterable<?>) source); |
| 706 | + } |
| 707 | + |
| 708 | + if (MutableBag.class.isAssignableFrom(targetType)) { |
| 709 | + return Bags.mutable.ofAll((Iterable<?>) source); |
| 710 | + } |
| 711 | + |
| 712 | + if (MutableMap.class.isAssignableFrom(targetType)) { |
| 713 | + return Maps.mutable.ofMap((Map<?, ?>) source); |
| 714 | + } |
| 715 | + |
| 716 | + // No dedicated type asked for, probably RichIterable. |
| 717 | + // Try to stay as close to the source value. |
| 718 | + |
| 719 | + if (source instanceof List) { |
| 720 | + return Lists.mutable.ofAll((Iterable<?>) source); |
| 721 | + } |
| 722 | + |
| 723 | + if (source instanceof Set) { |
| 724 | + return Sets.mutable.ofAll((Iterable<?>) source); |
| 725 | + } |
| 726 | + |
| 727 | + if (source instanceof Map) { |
| 728 | + return Maps.mutable.ofMap((Map<?, ?>) source); |
| 729 | + } |
| 730 | + |
| 731 | + return source; |
| 732 | + } |
| 733 | + } |
| 734 | + } |
491 | 735 | }
|
0 commit comments