private void acceptInvitation(String bucket, String location, Invitation invitation) {
        List<SharedResource> resourceLinks = invitation.getResources();
        String resourceOwnerLocation = null;
        for (SharedResource link : resourceLinks) {
            String url = link.getUrl();
            ResourceDescriptor resourceDescriptor = ResourceDescriptorFactory.fromPrivateUrl(url, encryptionService);
            if (resourceDescriptor.getBucketName().equals(bucket)) {
                throw new IllegalArgumentException("Resource %s already belong to you".formatted(url));
            }
            if (resourceOwnerLocation == null) {
                resourceOwnerLocation = resourceDescriptor.getBucketLocation();
            }
        }

        // group resources with the same type to reduce resource transformations
        Map<ResourceTypes, List<SharedResource>> resourceGroups = resourceLinks.stream()
                .collect(Collectors.groupingBy(sharedResource -> getResourceType(sharedResource.getUrl())));
        lockService.underBucketLock(resourceOwnerLocation, () -> {
            List<Pair<ResourceDescriptor, SharedByMeDto>> resourcesToBeUpdated = new ArrayList<>();
            resourceGroups.forEach((resourceType, links) -> {
                String ownerBucket = getBucket(links.get(0).getUrl());
                String ownerLocation = encryptionService.decrypt(ownerBucket);

                // write user location to the resource owner
                ResourceDescriptor sharedByMe = getShareResource(ResourceTypes.SHARED_BY_ME, resourceType, ownerBucket, ownerLocation);
                String state = resourceService.getResource(sharedByMe);
                SharedByMeDto dto = ProxyUtil.convertToObject(state, SharedByMeDto.class);
                if (dto == null) {
                    dto = new SharedByMeDto(new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>());
                }

                // add user location for each link
                for (SharedResource resource : links) {
                    int numOfAcceptedUsers = dto.getNumOfAcceptedUsers(resource.getUrl());
                    ShareResourceLimit limit = dto.getLimits().getOrDefault(resource.getUrl(), DEFAULT_LIMITS.get(resourceType));
                    if (limit == null) {
                        throw new IllegalArgumentException("Limit is not found for the resource:" + resource.getUrl());
                    }
                    if (numOfAcceptedUsers >= limit.getMaxAcceptedUsers()) {
                        throw new IllegalArgumentException("Limit is exceeded on the number of accepted users for the resource: " + resource.getUrl());
                    }
                    dto.addUserToResource(resource, location);
                }
                resourcesToBeUpdated.add(Pair.of(sharedByMe, dto));
            });
            for (Pair<ResourceDescriptor, SharedByMeDto> pair : resourcesToBeUpdated) {
                resourceService.putResource(pair.getKey(), ProxyUtil.convertToString(pair.getValue()), EtagHeader.ANY);
            }
            return null;
        });
        lockService.underBucketLock(location, () -> {
            resourceGroups.forEach((resourceType, links) -> {
                ResourceDescriptor sharedWithMe = getShareResource(ResourceTypes.SHARED_WITH_ME, resourceType, bucket, location);
                String state = resourceService.getResource(sharedWithMe);
                SharedResources sharedResources = ProxyUtil.convertToObject(state, SharedResources.class);
                if (sharedResources == null) {
                    sharedResources = new SharedResources(new ArrayList<>());
                }

                // add all links to the user
                sharedResources.addSharedResources(links);

                resourceService.putResource(sharedWithMe, ProxyUtil.convertToString(sharedResources), EtagHeader.ANY);
            });
            return null;
        });
    }
Accept an invitation to grand share access for provided resources

@param invitationId - invitation ID
server/src/main/java/com/epam/aidial/core/server/service/ShareService.java