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.context.FhirContext;
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.parser.IParser;
025import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
026import ca.uhn.fhir.util.BundleBuilder;
027import jakarta.annotation.Nonnull;
028import org.hl7.fhir.instance.model.api.IBaseBundle;
029import org.hl7.fhir.instance.model.api.IBaseResource;
030import org.hl7.fhir.utilities.npm.NpmPackage;
031
032import java.io.ByteArrayInputStream;
033import java.io.IOException;
034import java.util.Collection;
035import java.util.LinkedList;
036import java.util.List;
037import java.util.Objects;
038import java.util.Set;
039import java.util.stream.Collectors;
040
041public class AdditionalResourcesParser {
042
043        public static IBaseBundle bundleAdditionalResources(
044                        Set<String> additionalResources, PackageInstallationSpec packageInstallationSpec, FhirContext fhirContext) {
045                NpmPackage npmPackage;
046                try {
047                        npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(packageInstallationSpec.getPackageContents()));
048                } catch (IOException e) {
049                        throw new InternalErrorException(Msg.code(2765) + e);
050                }
051                List<IBaseResource> resources = getAdditionalResources(additionalResources, npmPackage, fhirContext);
052
053                BundleBuilder bundleBuilder = new BundleBuilder(fhirContext);
054                resources.forEach(bundleBuilder::addTransactionUpdateEntry);
055                return bundleBuilder.getBundle();
056        }
057
058        @Nonnull
059        public static List<IBaseResource> getAdditionalResources(
060                        Set<String> folderNames, NpmPackage npmPackage, FhirContext fhirContext) {
061
062                List<NpmPackage.NpmPackageFolder> npmFolders = folderNames.stream()
063                                .map(name -> npmPackage.getFolders().get(name))
064                                .filter(Objects::nonNull)
065                                .collect(Collectors.toList());
066
067                List<IBaseResource> resources = new LinkedList<>();
068                IParser parser = fhirContext.newJsonParser().setSuppressNarratives(true);
069
070                for (NpmPackage.NpmPackageFolder folder : npmFolders) {
071                        List<String> fileNames;
072                        try {
073                                fileNames = folder.getTypes().values().stream()
074                                                .flatMap(Collection::stream)
075                                                .collect(Collectors.toList());
076                        } catch (IOException e) {
077                                throw new InternalErrorException(Msg.code(2766) + e.getMessage(), e);
078                        }
079
080                        resources.addAll(fileNames.stream()
081                                        .map(fileName -> {
082                                                try {
083                                                        return new String(folder.fetchFile(fileName));
084                                                } catch (IOException e) {
085                                                        throw new InternalErrorException(Msg.code(2767) + e.getMessage(), e);
086                                                }
087                                        })
088                                        .map(parser::parseResource)
089                                        .collect(Collectors.toList()));
090                }
091                return resources;
092        }
093}