001package ca.uhn.fhir.cql.common.provider;
002
003/*-
004 * #%L
005 * HAPI FHIR JPA Server - Clinical Quality Language
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.rest.api.server.RequestDetails;
024
025import java.util.function.Function;
026
027public interface LibraryResolutionProvider<LibraryType> {
028        static int compareVersions(String version1, String version2) {
029                // Treat null as MAX VERSION
030                if (version1 == null && version2 == null) {
031                        return 0;
032                }
033
034                if (version1 != null && version2 == null) {
035                        return -1;
036                }
037
038                if (version1 == null && version2 != null) {
039                        return 1;
040                }
041
042                String[] string1Vals = version1.split("\\.");
043                String[] string2Vals = version2.split("\\.");
044
045                int length = Math.max(string1Vals.length, string2Vals.length);
046
047                for (int i = 0; i < length; i++)
048                {
049                        Integer v1 = (i < string1Vals.length)?Integer.parseInt(string1Vals[i]):0;
050                        Integer v2 = (i < string2Vals.length)?Integer.parseInt(string2Vals[i]):0;
051
052                        //Making sure Version1 bigger than version2
053                        if (v1 > v2)
054                        {
055                                return 1;
056                        }
057                        //Making sure Version1 smaller than version2
058                        else if (v1 < v2) {
059                                return -1;
060                        }
061                }
062
063                //Both are equal
064                return 0;
065        }
066
067        LibraryType resolveLibraryById(String libraryId, RequestDetails theRequestDetails);
068
069        LibraryType resolveLibraryByName(String libraryName, String libraryVersion);
070
071        LibraryType resolveLibraryByCanonicalUrl(String libraryUrl, RequestDetails theRequestDetails);
072
073
074        // This function assumes that you're selecting from a set of libraries with the same name.
075        // It returns the closest matching version, or the max version if no version is specified.
076        static <LibraryType> LibraryType selectFromList(Iterable<LibraryType> libraries, String libraryVersion, Function<LibraryType, String> getVersion) {
077                LibraryType library = null;
078                LibraryType maxVersion = null;
079                for (LibraryType l : libraries) {
080                        String currentVersion = getVersion.apply(l);
081                        if ((libraryVersion != null && currentVersion.equals(libraryVersion)) ||
082                                (libraryVersion == null && currentVersion == null)) {
083                                library = l;
084                        }
085
086                        if (maxVersion == null || compareVersions(
087                                getVersion.apply(maxVersion),
088                                getVersion.apply(l)) < 0) {
089                                maxVersion = l;
090                        }
091                }
092
093                // If we were not given a version, return the highest found
094                if (libraryVersion == null && maxVersion != null) {
095                        return maxVersion;
096                }
097
098                return library;
099        }
100
101        // Hmmm... Probably need to think through this use case a bit more.
102        // Should we throw an exception? Should this be a different interface?
103        void update(LibraryType library);
104}