001/*-
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2023 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.search.builder;
021
022import ca.uhn.fhir.jpa.model.dao.JpaPid;
023import org.apache.commons.lang3.Validate;
024
025import java.util.Iterator;
026import java.util.List;
027import javax.annotation.Nonnull;
028
029public class SearchQueryExecutors {
030
031        public static ISearchQueryExecutor limited(ISearchQueryExecutor theExecutor, long theLimit) {
032                Validate.isTrue(theLimit >= 0, "limit must be non-negative");
033
034                return new ISearchQueryExecutor() {
035                        long myCount = 0;
036
037                        @Override
038                        public void close() {
039                                theExecutor.close();
040                        }
041
042                        @Override
043                        public boolean hasNext() {
044                                return theExecutor.hasNext() && myCount < theLimit;
045                        }
046
047                        @Override
048                        public Long next() {
049                                myCount += 1;
050                                return theExecutor.next();
051                        }
052                };
053        }
054
055        @Nonnull
056        public static ISearchQueryExecutor from(List<Long> rawPids) {
057                return new ResolvedSearchQueryExecutor(rawPids);
058        }
059
060        /**
061         * Adapt bare Iterator to our internal query interface.
062         */
063        static class ResolvedSearchQueryExecutor implements ISearchQueryExecutor {
064                private final Iterator<Long> myIterator;
065
066                ResolvedSearchQueryExecutor(Iterable<Long> theIterable) {
067                        this(theIterable.iterator());
068                }
069
070                ResolvedSearchQueryExecutor(Iterator<Long> theIterator) {
071                        myIterator = theIterator;
072                }
073
074                @Nonnull
075                public static ResolvedSearchQueryExecutor from(List<Long> rawPids) {
076                        return new ResolvedSearchQueryExecutor(rawPids);
077                }
078
079                @Override
080                public boolean hasNext() {
081                        return myIterator.hasNext();
082                }
083
084                @Override
085                public Long next() {
086                        return myIterator.next();
087                }
088
089                @Override
090                public void close() {
091                        // empty
092                }
093        }
094
095        public static ISearchQueryExecutor from(Iterator<JpaPid> theIterator) {
096                return new JpaPidQueryAdaptor(theIterator);
097        }
098
099        public static ISearchQueryExecutor from(Iterable<JpaPid> theIterable) {
100                return new JpaPidQueryAdaptor(theIterable.iterator());
101        }
102
103        static class JpaPidQueryAdaptor implements ISearchQueryExecutor {
104                final Iterator<JpaPid> myIterator;
105
106                JpaPidQueryAdaptor(Iterator<JpaPid> theIterator) {
107                        myIterator = theIterator;
108                }
109
110                @Override
111                public void close() {}
112
113                @Override
114                public boolean hasNext() {
115                        return myIterator.hasNext();
116                }
117
118                @Override
119                public Long next() {
120                        JpaPid next = myIterator.next();
121                        return next == null ? null : next.getId();
122                }
123        }
124}