All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencds.cqf.processor.IGProcessor Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
package org.opencds.cqf.processor;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.io.FilenameUtils;
import org.opencds.cqf.parameter.RefreshIGParameters;
import org.opencds.cqf.utilities.IOUtils;
import org.opencds.cqf.utilities.IOUtils.Encoding;
import org.opencds.cqf.utilities.LogUtils;

import ca.uhn.fhir.context.FhirContext;

public class IGProcessor {
    public enum IGVersion {
        FHIR3("fhir3"), FHIR4("fhir4");

        private String string;

        public String toString() {
            return this.string;
        }

        private IGVersion(String string) {
            this.string = string;
        }

        public static IGVersion parse(String value) {
            switch (value) {
            case "fhir3":
                return FHIR3;
            case "fhir4":
                return FHIR4;
            default:
                throw new RuntimeException("Unable to parse IG version value:" + value);
            }
        }
    }

    //mega ig method
    public static void publishIG(RefreshIGParameters params) {
        String igPath = params.igPath;
        String igResourcePath = params.igResourcePath;
        IGVersion igVersion = params.igVersion;
        Encoding encoding = params.outputEncoding;
        Boolean includeELM = params.includeELM;
        Boolean includeDependencies = params.includeDependencies;
        Boolean includeTerminology = params.includeTerminology;
        Boolean includePatientScenarios = params.includePatientScenarios;
        Boolean versioned = params.versioned;
        Boolean cdsHooksIg = params.cdsHooksIg;
        String fhirUri = params.fhirUri;
        String measureToRefreshPath = params.measureToRefreshPath;
        ArrayList resourceDirs = params.resourceDirs;

        IOUtils.resourceDirectories.addAll(resourceDirs);

        FhirContext fhirContext = IGProcessor.getIgFhirContext(igVersion);

        igPath = Paths.get(igPath).toAbsolutePath().toString();

        //Use case 1
        //scafold basic templating for the type of content, Measure, PlanDefinition, or Questionnaire
        //Give it a name and generate all the files, cql, library, measure... should be very basic template
        //ScaffoldProcessor.scaffold(ScaffoldParameters);

        //Use case 2 while developing in Atom refresh content and run tests for either entire IG or targeted Artifact
        //refreshcontent
        LogUtils.info("IGProcessor.publishIG - refreshIG");
        IGRefreshProcessor.refreshIG(params);
        //validate
        //ValidateProcessor.validate(ValidateParameters);
        //run all tests
        //IGTestProcessor.testIg(IGTestParameters);

        //Use case 3
        //package everything
        LogUtils.info("IGProcessor.publishIG - bundleIg");
        IGBundleProcessor.bundleIg(IGRefreshProcessor.refreshedResourcesNames, igPath, encoding, includeELM, includeDependencies, includeTerminology, includePatientScenarios,
        versioned, cdsHooksIg, fhirContext, fhirUri);
        //test everything
        //IGTestProcessor.testIg(IGTestParameters);
        //Publish?
    }

    
    public static FhirContext getIgFhirContext(IGVersion igVersion)
    {
        switch (igVersion) {
            case FHIR3:
                return FhirContext.forDstu3();
            case FHIR4:
                return FhirContext.forR4();
            default:
                throw new IllegalArgumentException("Unknown IG version: " + igVersion);
        }     
    }
    
    public static IGVersion getIgVersion(String igPath){
        IGVersion igVersion = null;
        List igPathFiles = IOUtils.getFilePaths(igPath, false).stream()
            .map(path -> new File(path))
            .collect(Collectors.toList());
        for (File file : igPathFiles) {
            if (FilenameUtils.getExtension(file.getName()).equals("ini")) {
                igVersion = tryToReadIni(file);
            }
        }
        if (igVersion == null) {
            throw new IllegalArgumentException("IG version must be configured in ig.ini or provided as an argument.");
        }
        else return igVersion;
    }

    private static IGVersion tryToReadIni(File file) {
        try {
            InputStream inputStream = new FileInputStream(file);
            String igIniContent = new BufferedReader(new InputStreamReader(inputStream))
                .lines().collect(Collectors.joining("\n"));
            String[] contentLines = igIniContent.split("\n");
            inputStream.close();
            return parseVersion(contentLines);
        } catch (Exception e) {
                System.out.println(e.getMessage());
                return null;
            }
    }

    static final String STU3SPECIFIER = "stu3";
    static final String DSTU3SPECIFIER = "dstu3";
    static final String R4SPECIFIER = "r4";
    private static IGVersion parseVersion(String[] contentLines) {
        for (String line : contentLines) {
            if (line.toLowerCase().startsWith("fhirspec"))
            {
                if (line.toLowerCase().contains(R4SPECIFIER)){
                    return IGVersion.FHIR4;
                }
                else if (line.toLowerCase().contains(STU3SPECIFIER) || line.toLowerCase().contains(DSTU3SPECIFIER)) {
                    return IGVersion.FHIR3;
                }
            }
        }
        return null;
    }

    public static final String bundlePathElement = "bundles/";
    public static String getBundlesPath(String igPath) {
        return FilenameUtils.concat(igPath, bundlePathElement);
    }
    public static final String cqlLibraryPathElement = "input/pagecontent/cql/";
    public static final String libraryPathElement = "input/resources/library/";
    public static final String measurePathElement = "input/resources/measure/";
    public static final String valuesetsPathElement = "input/vocabulary/valueset/";
    public static final String testCasePathElement = "input/tests/";
    
    public static void ensure(String igPath, Boolean includePatientScenarios, Boolean includeTerminology, ArrayList resourcePaths) {                
        File directory = new File(getBundlesPath(igPath));
        if (!directory.exists()) {
            directory.mkdir();
        }        
        if (resourcePaths.isEmpty()) {
            ensureDirectory(igPath, IGProcessor.cqlLibraryPathElement);
            ensureDirectory(igPath, IGProcessor.libraryPathElement);
            ensureDirectory(igPath, IGProcessor.measurePathElement);
            ensureDirectory(igPath, IGProcessor.valuesetsPathElement);
            ensureDirectory(igPath, IGProcessor.testCasePathElement);
        }
        else {
            checkForDirectory(igPath, IGProcessor.cqlLibraryPathElement);
            checkForDirectory(igPath, IGProcessor.libraryPathElement);
            checkForDirectory(igPath, IGProcessor.measurePathElement);
            checkForDirectory(igPath, IGProcessor.valuesetsPathElement);
            checkForDirectory(igPath, IGProcessor.testCasePathElement);
        }
        HashSet cqlContentPaths = IOUtils.getCqlLibraryPaths();
        for (String cqlContentPath : cqlContentPaths) {
            String cqlLibraryContent = IOUtils.getCqlString(cqlContentPath);
            if (!cqlLibraryContent.startsWith("library ")) {
                throw new RuntimeException("Unable to refresh IG.  All Libraries must begin with \"library \": " + cqlContentPath);
            }
            String strippedLibraryName = FilenameUtils.getBaseName(cqlContentPath);
            for (IGProcessor.IGVersion igVersion : IGVersion.values()) {                
                String igVersionToken = "_" + igVersion.toString().toUpperCase();
               
                if (strippedLibraryName.contains(igVersionToken)) {
                    strippedLibraryName = strippedLibraryName.replace(igVersionToken, "");
                    if (strippedLibraryName.contains("_")) {
                        throw new RuntimeException("Convention only allows a single \"_\" and it must be preceeding the IG Version: " + cqlContentPath);
                    }
                }    
            }
            if (strippedLibraryName.contains("_")) {
                throw new RuntimeException("Convention only allows a single \"_\" and it must be preceeding the IG Version: " + cqlContentPath);
            }
        }
    }

    private static void ensureDirectory(String igPath, String pathElement) {
        File directory = new File(FilenameUtils.concat(igPath, pathElement));
        if (!directory.exists()) {
            throw new RuntimeException("Convention requires the following directory:" + pathElement);
        }
        // TODO: This is a concept different from "resource directories". It is expected elsewhere (e.g., IOUtils.setupActivityDefinitionPaths)
        // that resourceDirectories contains a set of proper "resource" directories. Adding non-resource directories
        // leads to surprising results when bundling like picking up resources from the /tests directory.
        IOUtils.resourceDirectories.add(FilenameUtils.concat(igPath, pathElement));
    }

    private static void checkForDirectory(String igPath, String pathElement) {
        File directory = new File(FilenameUtils.concat(igPath, pathElement));
        if (!directory.exists()) {
            System.out.println("No directory found by convention for: " + directory.getName());
        }
        else {
            // TODO: This is a concept different from "resource directories". It is expected elsewhere (e.g., IOUtils.setupActivityDefinitionPaths)
            // that resourceDirectories contains a set of proper "resource" directories. Adding non-resource directories
            // leads to surprising results when bundling like picking up resources from the /tests directory.
            IOUtils.resourceDirectories.add(FilenameUtils.concat(igPath, pathElement));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy