Skip to content

Commit

Permalink
Merge branch 'master' into feature-445-cqlOptions-support
Browse files Browse the repository at this point in the history
  • Loading branch information
JPercival authored Nov 28, 2023
2 parents c42a154 + 8b356fd commit e1401fc
Show file tree
Hide file tree
Showing 186 changed files with 70,864 additions and 2,166 deletions.
17 changes: 11 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@

<groupId>org.opencds.cqf</groupId>
<artifactId>tooling-parent</artifactId>
<version>2.5.0-SNAPSHOT</version>

<version>2.6.0-SNAPSHOT</version>

<packaging>pom</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<cql-engine.version>2.9.0-SNAPSHOT</cql-engine.version>
<cql-engine.version>3.3.2</cql-engine.version>
<cql-evaluator.version>2.6.0</cql-evaluator.version>
<cqframework.version>2.9.0-SNAPSHOT</cqframework.version>
<hapi.version>6.0.1</hapi.version>
<core.version>5.6.36</core.version>
<cqframework.version>3.3.2</cqframework.version>
<hapi.version>6.8.0</hapi.version>
<core.version>6.0.22</core.version>
<spring-boot.version>2.1.5.RELEASE</spring-boot.version>
</properties>

Expand Down Expand Up @@ -217,6 +216,11 @@
<artifactId>FastInfoset</artifactId>
<version>1.2.18</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down Expand Up @@ -351,6 +355,7 @@
<version>3.0.0-M5</version>
<configuration>
<argLine>-Xmx4096m</argLine>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
</configuration>
<executions>
<execution>
Expand Down
21 changes: 16 additions & 5 deletions tooling-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
<parent>
<groupId>org.opencds.cqf</groupId>
<artifactId>tooling-parent</artifactId>
<version>2.5.0-SNAPSHOT</version>
<version>2.6.0-SNAPSHOT</version>
</parent>

<groupId>org.opencds.cqf</groupId>
<artifactId>tooling-cli</artifactId>
<version>2.5.0-SNAPSHOT</version>
<version>2.6.0-SNAPSHOT</version>
<packaging>jar</packaging>

<description>CQF Tooling CLI</description>
Expand All @@ -20,8 +19,7 @@
<dependency>
<groupId>org.opencds.cqf</groupId>
<artifactId>tooling</artifactId>
<version>2.5.0-SNAPSHOT</version>
<!-- <packaging>jar</packaging> -->
<version>2.6.0-SNAPSHOT</version>
</dependency>

<dependency>
Expand All @@ -35,6 +33,19 @@
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.7.7</version>
</dependency>

<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>

<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.7.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
66 changes: 59 additions & 7 deletions tooling-cli/src/main/java/org/opencds/cqf/tooling/cli/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,14 @@
- This tooling decomposes a Bundle entry into separate resource files
- Accepts Bundles with .json or .xml extensions
- MAT Bundle extraction
- mvn exec:java -Dexec.args="[-ExtractMatBundle] [Bundle file path] (-v)
- Example: mvn exec:java -Dexec.args="-ExtractMatBundle /Users/mholck/Development/ecqm-content-r4/bundles/mat/EXM124/EXM124.json -v=r4"
- This tooling extracts out the resources and CQL from a MAT export bundle and puts them in the appropriate directories
- Accepts Bundles with .json or .xml extensions
- version = FHIR version { stu3, r4 }
Default version: r4
- MAT Bundle extraction
- mvn exec:java -Dexec.args="[-ExtractMatBundle] [Bundle file path] (-v) (-dir)
- Example: mvn exec:java -Dexec.args="-ExtractMatBundle /Users/mholck/Development/ecqm-content-r4/bundles/mat/EXM124/EXM124.json -v=r4"
- This tooling extracts out the resources and CQL from a MAT export bundle and puts them in the appropriate directories
- Accepts Bundles with .json or .xml extensions
- version = FHIR version { stu3, r4 }
Default version: r4
- dir = Directory indicator. To process the input location as a directory of files, the input should point to a valid directory and the -dir flag should be present in the arguments list.
- Generate StructureDefinitions from ModelInfo
- command: mvn exec:java -Dexec.args="[-GenerateSDs] [path to modelinfo xml] (-outputpath | -op) (-encoding | -e)"
Expand Down Expand Up @@ -218,7 +219,58 @@
*/

//import org.opencds.cqf.tooling.exception.InvalidOperationArgs;
//import org.opencds.cqf.tooling.exception.InvalidOperationInitialization;
//import org.opencds.cqf.tooling.exception.OperationNotFound;
//import org.opencds.cqf.tooling.operations.ExecutableOperation;
//import org.opencds.cqf.tooling.operations.Operation;
//import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import java.lang.reflect.InvocationTargetException;
//import java.util.HashMap;
//import java.util.Map;
//import java.util.Set;

public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);

// TODO: Uncomment this block and imports once operation refactor is ready
// private static Map<String, Class<?>> operationClassMap;
//
// public static void main(String[] args) {
// if (args == null || args.length == 0) {
// logger.error("cqf-tooling version: {}", Main.class.getPackage().getImplementationVersion());
// throw new OperationNotFound(
// "Requests must include which operation to run as a command line argument. See docs for examples on how to use this project.");
// }
//
// // NOTE: we may want to use the Spring Context Library to find the annotated classes
// if (operationClassMap == null) {
// operationClassMap = new HashMap<>();
// Reflections reflections = new Reflections("org.opencds.cqf.tooling.operations");
// Set<Class<?>> operationClasses = reflections
// .getTypesAnnotatedWith(Operation.class);
// operationClasses.forEach(clazz -> operationClassMap.put(clazz.getAnnotation(Operation.class).name(), clazz));
// }
//
// String operation = args[0];
// if (!operation.startsWith("-")) {
// throw new InvalidOperationArgs(
// "Invalid operation syntax: " + operation + ". Operations must be declared with a \"-\" prefix");
// }
//
// try {
// ExecutableOperation executableOperation = OperationFactory.createOperation(
// operation, operationClassMap.get(operation.substring(1)), args);
// if (executableOperation != null) {
// executableOperation.execute();
// }
// } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException e) {
// throw new InvalidOperationInitialization(e.getMessage(), e);
// }
// }

public static void main(String[] args) {
if (args.length == 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package org.opencds.cqf.tooling.cli;

//import org.opencds.cqf.tooling.jsonschema.SchemaGenerator;
import org.opencds.cqf.tooling.casereporting.transformer.ErsdTransformer;
import org.opencds.cqf.tooling.dateroller.DataDateRollerOperation;
import org.opencds.cqf.tooling.exception.InvalidOperationArgs;
import org.opencds.cqf.tooling.exception.OperationNotFound;
import org.opencds.cqf.tooling.operations.ExecutableOperation;
import org.opencds.cqf.tooling.operations.OperationParam;
import org.opencds.cqf.tooling.terminology.templateToValueSetGenerator.TemplateToValueSetGenerator;
import org.apache.commons.lang3.NotImplementedException;
import org.opencds.cqf.tooling.Operation;
Expand Down Expand Up @@ -40,9 +43,92 @@
import org.opencds.cqf.tooling.terminology.VSACBatchValueSetGenerator;
import org.opencds.cqf.tooling.terminology.VSACValueSetGenerator;
import org.opencds.cqf.tooling.terminology.distributable.DistributableValueSetGenerator;
import org.opencds.cqf.tooling.utilities.OperationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;


class OperationFactory {
private static final Logger logger = LoggerFactory.getLogger(OperationFactory.class);
private static String operationName;
private static Map<String, String> paramMap;
private static boolean showHelpMenu = false;

private OperationFactory() {

}

private static void processArgs(String[] args) {
paramMap = new HashMap<>();
for (int i = 1; i < args.length; ++i) {
if (OperationUtils.isHelpArg(args[i])) {
showHelpMenu = true;
return;
}
String[] argAndValue = args[i].split("=", 2);
if (argAndValue.length == 2) {
paramMap.put(argAndValue[0].replace("-", ""), argAndValue[1]);
}
else {
throw new InvalidOperationArgs(String.format(
"Invalid argument: %s found for operation: %s", args[i], operationName));
}
}
}

private static ExecutableOperation initialize(ExecutableOperation operation)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
for (Field field : operation.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(OperationParam.class)) {
boolean isInitialized = false;
for (String alias : field.getAnnotation(OperationParam.class).alias()) {
if (paramMap.containsKey(alias)) {
Class<?> paramType = OperationUtils.getParamType(operation,
field.getAnnotation(OperationParam.class).setter());
operation.getClass().getDeclaredMethod(
field.getAnnotation(OperationParam.class).setter(), paramType
).invoke(operation, OperationUtils.mapParamType(paramMap.get(alias), paramType));
isInitialized = true;
}
}
if (!isInitialized) {
if (field.getAnnotation(OperationParam.class).required()) {
throw new InvalidOperationArgs("Missing required argument: " + field.getName());
}
else if (!field.getAnnotation(OperationParam.class).defaultValue().isEmpty()) {
Class<?> paramType = OperationUtils.getParamType(operation,
field.getAnnotation(OperationParam.class).setter());
operation.getClass().getDeclaredMethod(
field.getAnnotation(OperationParam.class).setter(), paramType
).invoke(operation, OperationUtils.mapParamType(
field.getAnnotation(OperationParam.class).defaultValue(), paramType));
}
}
}
}
return operation;
}

static ExecutableOperation createOperation(String operationName, Class<?> operationClass, String[] args)
throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if (operationClass == null) {
throw new OperationNotFound("Unable to resolve operation: " + operationName);
}
OperationFactory.operationName = operationName;
processArgs(args);
if (showHelpMenu) {
logger.info(OperationUtils.getHelpMenu(
(ExecutableOperation) operationClass.getDeclaredConstructor().newInstance()));
showHelpMenu = false;
return null;
}
return initialize((ExecutableOperation) operationClass.getDeclaredConstructor().newInstance());
}

static Operation createOperation(String operationName) {
switch (operationName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.opencds.cqf.tooling.cli;

import org.opencds.cqf.tooling.exception.InvalidOperationArgs;
import org.opencds.cqf.tooling.exception.OperationNotFound;
import org.testng.Assert;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;

public class OperationInitializationIT {
@Test
@Ignore("Skipped until operation refactor is ready")
void missingOperationName() {
String[] args = new String[]{};
Assert.assertThrows(OperationNotFound.class, () -> Main.main(args));
}

@Test
@Ignore("Skipped until operation refactor is ready")
void invalidOperationName() {
String[] args = new String[]{ "-NonexistentOperationName" };
Assert.assertThrows(OperationNotFound.class, () -> Main.main(args));
}

@Test
@Ignore("Skipped until operation refactor is ready")
void InvalidOperationDeclaration() {
String[] args = new String[]{ "BundleResources", "-ptr=some/directory/path" };
Assert.assertThrows(InvalidOperationArgs.class, () -> Main.main(args));
}

@Test
@Ignore("Skipped until operation refactor is ready")
void missingRequiredOperationArgs() {
String[] args = new String[]{ "-BundleResources" };
Assert.assertThrows(InvalidOperationArgs.class, () -> Main.main(args));
}
}
Loading

0 comments on commit e1401fc

Please sign in to comment.