001/*-
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2025 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.packages;
021
022import ca.uhn.fhir.model.api.annotation.ExampleSupplier;
023import com.fasterxml.jackson.annotation.JsonAutoDetect;
024import com.fasterxml.jackson.annotation.JsonIgnore;
025import com.fasterxml.jackson.annotation.JsonInclude;
026import com.fasterxml.jackson.annotation.JsonProperty;
027import com.fasterxml.jackson.annotation.JsonPropertyOrder;
028import io.swagger.v3.oas.annotations.media.Schema;
029
030import java.util.ArrayList;
031import java.util.List;
032import java.util.Set;
033import java.util.function.Supplier;
034
035@Schema(name = "PackageInstallationSpec", description = "Defines a set of instructions for package installation")
036@JsonPropertyOrder({
037        "name",
038        "version",
039        "packageUrl",
040        "installMode",
041        "installResourceTypes",
042        "validationMode",
043        "reloadExisting",
044        "additionalResourceFolders"
045})
046@ExampleSupplier({PackageInstallationSpec.ExampleSupplier.class, PackageInstallationSpec.ExampleSupplier2.class})
047@JsonInclude(JsonInclude.Include.NON_NULL)
048@JsonAutoDetect(
049                creatorVisibility = JsonAutoDetect.Visibility.NONE,
050                fieldVisibility = JsonAutoDetect.Visibility.NONE,
051                getterVisibility = JsonAutoDetect.Visibility.NONE,
052                isGetterVisibility = JsonAutoDetect.Visibility.NONE,
053                setterVisibility = JsonAutoDetect.Visibility.NONE)
054public class PackageInstallationSpec {
055
056        @Schema(description = "The direct package URL")
057        @JsonProperty("packageUrl")
058        private String myPackageUrl;
059
060        @Schema(description = "The NPM package Name")
061        @JsonProperty("name")
062        private String myName;
063
064        @Schema(description = "The direct package version")
065        @JsonProperty("version")
066        private String myVersion;
067
068        @Schema(
069                        description =
070                                        "Should resources from this package be extracted from the package and installed into the repository individually")
071        @JsonProperty("installMode")
072        private InstallModeEnum myInstallMode;
073
074        @Schema(
075                        description =
076                                        "If resources are being installed individually, this is list provides the resource types to install. By default, all conformance resources will be installed.")
077        @JsonProperty("installResourceTypes")
078        private List<String> myInstallResourceTypes;
079
080        @Schema(description = "Should dependencies be automatically resolved, fetched and installed with the same settings")
081        @JsonProperty("fetchDependencies")
082        private boolean myFetchDependencies;
083
084        @Schema(
085                        description =
086                                        "Should existing resources be reloaded. Defaults to true, but can be set to false to avoid re-index operations for existing search parameters")
087        @JsonProperty("reloadExisting")
088        private boolean myReloadExisting = true;
089
090        @Schema(
091                        description =
092                                        "Any values provided here will be interpreted as a regex. Dependencies with an ID matching any regex will be skipped.")
093        private List<String> myDependencyExcludes;
094
095        @Schema(
096                        description =
097                                        "List of folders in the package to extract additional resources from. Each folder listed will be scanned for resources which will be installed as part of package installation.")
098        @JsonProperty("additionalResourceFolders")
099        private Set<String> myAdditionalResourceFolders;
100
101        @JsonIgnore
102        private byte[] myPackageContents;
103
104        public List<String> getDependencyExcludes() {
105                if (myDependencyExcludes == null) {
106                        myDependencyExcludes = new ArrayList<>();
107                }
108                return myDependencyExcludes;
109        }
110
111        public void setDependencyExcludes(List<String> theDependencyExcludes) {
112                myDependencyExcludes = theDependencyExcludes;
113        }
114
115        public boolean isFetchDependencies() {
116                return myFetchDependencies;
117        }
118
119        public PackageInstallationSpec setFetchDependencies(boolean theFetchDependencies) {
120                myFetchDependencies = theFetchDependencies;
121                return this;
122        }
123
124        public String getPackageUrl() {
125                return myPackageUrl;
126        }
127
128        public PackageInstallationSpec setPackageUrl(String thePackageUrl) {
129                myPackageUrl = thePackageUrl;
130                return this;
131        }
132
133        public InstallModeEnum getInstallMode() {
134                return myInstallMode;
135        }
136
137        public PackageInstallationSpec setInstallMode(InstallModeEnum theInstallMode) {
138                myInstallMode = theInstallMode;
139                return this;
140        }
141
142        public List<String> getInstallResourceTypes() {
143                if (myInstallResourceTypes == null) {
144                        myInstallResourceTypes = new ArrayList<>();
145                }
146                return myInstallResourceTypes;
147        }
148
149        public void setInstallResourceTypes(List<String> theInstallResourceTypes) {
150                myInstallResourceTypes = theInstallResourceTypes;
151        }
152
153        public String getName() {
154                return myName;
155        }
156
157        public PackageInstallationSpec setName(String theName) {
158                myName = theName;
159                return this;
160        }
161
162        public String getVersion() {
163                return myVersion;
164        }
165
166        public PackageInstallationSpec setVersion(String theVersion) {
167                myVersion = theVersion;
168                return this;
169        }
170
171        public byte[] getPackageContents() {
172                return myPackageContents;
173        }
174
175        public PackageInstallationSpec setPackageContents(byte[] thePackageContents) {
176                myPackageContents = thePackageContents;
177                return this;
178        }
179
180        public boolean isReloadExisting() {
181                return myReloadExisting;
182        }
183
184        public void setReloadExisting(boolean reloadExisting) {
185                this.myReloadExisting = reloadExisting;
186        }
187
188        public Set<String> getAdditionalResourceFolders() {
189                return myAdditionalResourceFolders;
190        }
191
192        public void setAdditionalResourceFolders(Set<String> additionalResourceFolders) {
193                this.myAdditionalResourceFolders = additionalResourceFolders;
194        }
195
196        public PackageInstallationSpec addDependencyExclude(String theExclude) {
197                getDependencyExcludes().add(theExclude);
198                return this;
199        }
200
201        public PackageInstallationSpec addInstallResourceTypes(String... theResourceTypes) {
202                for (String next : theResourceTypes) {
203                        getInstallResourceTypes().add(next);
204                }
205                return this;
206        }
207
208        public enum InstallModeEnum {
209                STORE_ONLY,
210                STORE_AND_INSTALL
211        }
212
213        public enum ValidationModeEnum {
214                NOT_AVAILABLE,
215                AVAILABLE
216        }
217
218        public static class ExampleSupplier implements Supplier<PackageInstallationSpec> {
219
220                @Override
221                public PackageInstallationSpec get() {
222                        return new PackageInstallationSpec()
223                                        .setName("hl7.fhir.us.core")
224                                        .setVersion("3.1.0")
225                                        .setInstallMode(InstallModeEnum.STORE_ONLY)
226                                        .setFetchDependencies(true);
227                }
228        }
229
230        public static class ExampleSupplier2 implements Supplier<PackageInstallationSpec> {
231
232                @Override
233                public PackageInstallationSpec get() {
234                        return new PackageInstallationSpec()
235                                        .setName("com.example.my-resources")
236                                        .setVersion("1.0")
237                                        .setPackageUrl("classpath:/my-resources.tgz")
238                                        .setInstallMode(InstallModeEnum.STORE_AND_INSTALL)
239                                        .addInstallResourceTypes("Organization", "Medication", "PlanDefinition", "SearchParameter");
240                }
241        }
242}