001/*-
002 * #%L
003 * HAPI FHIR Storage api
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.api.pid;
021
022import ca.uhn.fhir.interceptor.model.RequestPartitionId;
023import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
024import org.apache.commons.lang3.Validate;
025
026import java.util.ArrayList;
027import java.util.Date;
028import java.util.HashSet;
029import java.util.LinkedHashSet;
030import java.util.List;
031import java.util.Set;
032
033public class ResourcePidListBuilder {
034        private static final IResourcePidList EMPTY_CHUNK = new EmptyResourcePidList();
035
036        public static IResourcePidList fromChunksAndDate(List<IResourcePidList> theChunks, Date theEnd) {
037                if (theChunks.isEmpty()) {
038                        return empty();
039                }
040
041                Set<IResourcePersistentId> ids = new LinkedHashSet<>();
042                RequestPartitionId requestPartitionId = null;
043
044                Date endDate = null;
045                Set<String> resourceTypes = new HashSet<>();
046                boolean containsMixed = false;
047                for (IResourcePidList chunk : theChunks) {
048
049                        Validate.isTrue(requestPartitionId == null || requestPartitionId == chunk.getRequestPartitionId());
050                        requestPartitionId = chunk.getRequestPartitionId();
051
052                        if (chunk.isEmpty()) {
053                                continue;
054                        }
055                        ids.addAll(chunk.getIds());
056                        endDate = getLatestDate(chunk, endDate, theEnd);
057                        if (chunk instanceof MixedResourcePidList) {
058                                containsMixed = true;
059                        } else {
060                                resourceTypes.add(chunk.getResourceType(0));
061                        }
062                }
063
064                if (containsMixed || resourceTypes.size() > 1) {
065                        List<String> types = new ArrayList<>();
066                        for (IResourcePidList chunk : theChunks) {
067                                for (int i = 0; i < chunk.size(); ++i) {
068                                        types.add(chunk.getResourceType(i));
069                                }
070                        }
071                        return new MixedResourcePidList(types, ids, endDate, requestPartitionId);
072                } else {
073                        IResourcePidList firstChunk = theChunks.get(0);
074                        String onlyResourceType = firstChunk.getResourceType(0);
075                        return new HomogeneousResourcePidList(onlyResourceType, ids, endDate, requestPartitionId);
076                }
077        }
078
079        private static Date getLatestDate(IResourcePidList theChunk, Date theCurrentEndDate, Date thePassedInEndDate) {
080                Date endDate = theCurrentEndDate;
081                if (theCurrentEndDate == null) {
082                        endDate = theChunk.getLastDate();
083                } else if (theChunk.getLastDate().after(endDate)
084                                && theChunk.getLastDate().before(thePassedInEndDate)) {
085                        endDate = theChunk.getLastDate();
086                }
087                return endDate;
088        }
089
090        private static IResourcePidList empty() {
091                return EMPTY_CHUNK;
092        }
093}