Skip to content

Commit

Permalink
Add initial implementation of Ehr service gen tool
Browse files Browse the repository at this point in the history
  • Loading branch information
sameeragunarathne committed Feb 6, 2024
1 parent cee4b0d commit ea665eb
Show file tree
Hide file tree
Showing 29 changed files with 1,610 additions and 38 deletions.
24 changes: 24 additions & 0 deletions native/ehr-prebuilt-services/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.ballerina</groupId>
<artifactId>health-tools</artifactId>
<version>2.1.2</version>
<relativePath>../../pom.xml</relativePath>
</parent>

<artifactId>ehr-prebuilt-services</artifactId>
<version>2.1.2</version>

<dependencies>
<dependency>
<groupId>io.ballerina</groupId>
<artifactId>fhir-to-bal-template</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.healthcare.fhir.ballerina.prebuiltservicegen.tool;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.healthcare.codegen.tool.framework.commons.config.ToolConfig;
import org.wso2.healthcare.codegen.tool.framework.commons.core.AbstractToolContext;
import org.wso2.healthcare.codegen.tool.framework.commons.core.TemplateGenerator;
import org.wso2.healthcare.codegen.tool.framework.commons.core.ToolContext;
import org.wso2.healthcare.codegen.tool.framework.commons.exception.CodeGenException;
import org.wso2.healthcare.codegen.tool.framework.fhir.core.AbstractFHIRTool;
import org.wso2.healthcare.fhir.codegen.ballerina.project.tool.BallerinaProjectConstants;
import org.wso2.healthcare.fhir.codegen.ballerina.project.tool.model.BallerinaService;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
* This tool is used to generate a prebuilt service for a FHIR server.
*/
public class ServiceGenTool extends AbstractFHIRTool {

private static final Log LOG = LogFactory.getLog(ServiceGenTool.class);
private ServiceGenToolConfig prebuiltFhirServiceGenToolConfig;

@Override
public void initialize(ToolConfig toolConfig) throws CodeGenException {
this.prebuiltFhirServiceGenToolConfig = (ServiceGenToolConfig) toolConfig;
}

@Override
public TemplateGenerator execute(ToolContext toolContext) throws CodeGenException {
Properties toolProperties = ((AbstractToolContext) toolContext).getCustomToolProperties();
Map<String, Object> toolPropertiesMap = (Map<String, Object>) toolProperties.get("ehrServiceGenProperties");
if (toolPropertiesMap != null) {
Map<String, BallerinaService> serviceMap = (Map<String, BallerinaService>) toolPropertiesMap.get("serviceMap");
int servicePort = 9090;
for (Map.Entry<String, BallerinaService> entry : serviceMap.entrySet()) {
String resourceType = entry.getKey();
BallerinaService service = entry.getValue();
Map<String, Object> projectProperties = new HashMap<>();
projectProperties.put("service", service);
projectProperties.put("resourceType", resourceType);
projectProperties.put("config", toolPropertiesMap.get("config"));
if (!service.getImportsList().contains(BallerinaProjectConstants.INTERNATIONAL_PACKAGE_IMPORT_SUFFIX)) {
((Map<String, String>) toolPropertiesMap.get("dependenciesMap")).remove("dependentPackage");
service.getImportsList().remove(BallerinaProjectConstants.INTERNATIONAL_PACKAGE_IMPORT_SUFFIX);
}
projectProperties.put("dependencies", toolPropertiesMap.get("dependenciesMap"));
Map<String, String> dependenciesMap = (Map<String, String>) toolPropertiesMap.get("dependenciesMap");
String dependentPackage = dependenciesMap.get("dependentPackage");

String basePackage = dependenciesMap.get("basePackage");
String servicePackage = dependenciesMap.get("servicePackage");
String igPackage = dependenciesMap.get("igPackage");
projectProperties.put("basePackageImportIdentifier", basePackage.substring(
basePackage.lastIndexOf(".") + 1));
projectProperties.put("servicePackageImportIdentifier", servicePackage.substring(
servicePackage.lastIndexOf(".") + 1));
projectProperties.put("igPackageImportIdentifier", igPackage.substring(
igPackage.lastIndexOf(".") + 1));
if (dependentPackage != null) {
projectProperties.put("dependentPackageImportIdentifier", dependentPackage.substring(
dependentPackage.lastIndexOf(".") + 1));
}
projectProperties.put("serviceFileName", service.getName().toLowerCase() + "_service.bal");
projectProperties.put("apiConfigFileName", service.getName().toLowerCase() + "_api_config.bal");
projectProperties.put("projectAPIPath", prebuiltFhirServiceGenToolConfig.getTargetDir() + File.separator
+ prebuiltFhirServiceGenToolConfig.getProjectName());
projectProperties.put("apiConfName", service.getName().toLowerCase().concat("ApiConfig"));
projectProperties.put("servicePort", servicePort);
projectProperties.put("ehrName", prebuiltFhirServiceGenToolConfig.getEhrName());
projectProperties.put("authMethod", prebuiltFhirServiceGenToolConfig.getAuthMethod());
projectProperties.put("disablePackageMd", true);
projectProperties.put("templateName", prebuiltFhirServiceGenToolConfig.getProjectName());
if (service.getProfileList().size() > 0) {
projectProperties.put("profileList", service.getProfileList());
}
Map<String, String> interactionMethods = new HashMap<>();
projectProperties.put("interactionMethods", interactionMethods);
try {
ServiceInteractionMethodGenerator serviceInteractionMethodContentGenerator =
new ServiceInteractionMethodGenerator(prebuiltFhirServiceGenToolConfig.getTargetDir());
for (String interactionType : ToolConstants.SUPPORTED_INTERACTIONS) {
projectProperties.put("interactionType", interactionType);
serviceInteractionMethodContentGenerator.generate(toolContext, projectProperties);
String interactionMethodContent = serviceInteractionMethodContentGenerator.getInteractionMethodContent(
interactionType);
service.getFhirInteractionMethodsContent().setInteractionContentByType(
interactionType, interactionMethodContent);
}

ServiceGenerator serviceGenerator = new ServiceGenerator(
prebuiltFhirServiceGenToolConfig.getTargetDir());
serviceGenerator.generate(toolContext, projectProperties);
} catch (CodeGenException e) {
LOG.error("Error occurred while generation EHR prebuilt service.", e);
}
servicePort++;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.healthcare.fhir.ballerina.prebuiltservicegen.tool;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.wso2.healthcare.codegen.tool.framework.commons.Constants;
import org.wso2.healthcare.codegen.tool.framework.commons.config.AbstractToolConfig;
import org.wso2.healthcare.codegen.tool.framework.commons.exception.CodeGenException;
import org.wso2.healthcare.codegen.tool.framework.commons.model.ConfigType;
import org.wso2.healthcare.codegen.tool.framework.commons.model.JsonConfigType;
import org.wso2.healthcare.fhir.ballerina.prebuiltservicegen.tool.config.PackageInfo;

import java.util.HashMap;
import java.util.Map;

/**
* Holds the configuration for the FHIR prebuilt service gen tool.
*/
public class ServiceGenToolConfig extends AbstractToolConfig {

private static final Log LOG = LogFactory.getLog(ServiceGenToolConfig.class);
private boolean isEnabled;
private String ehrName;
private String projectName;
private IBaseResource capabilityStatement;
private String authMethod;
private final Map<String, PackageInfo> packageInfoMap = new HashMap<>();

@Override
public void configure(ConfigType<?> configObj) throws CodeGenException {
if (Constants.JSON_CONFIG_TYPE.equals(configObj.getType())) {
JsonObject jsonConfigObj = ((JsonConfigType) configObj).getConfigObj();
this.isEnabled = jsonConfigObj.getAsJsonPrimitive(ToolConstants.CONFIG_ENABLE).getAsBoolean();
jsonConfigObj.getAsJsonObject("igPackageInfo").entrySet().forEach(entry -> {
String key = entry.getKey();
JsonObject value = entry.getValue().getAsJsonObject();
PackageInfo packageInfo = new PackageInfo(value.get("packagePrefix").getAsString(),
value.get("importStatement").getAsString());
packageInfoMap.putIfAbsent(key, packageInfo);
});
}
}

@Override
public void overrideConfig(String jsonPath, JsonElement jsonElement) {
switch (jsonPath) {
case "servicegen.config.projectName":
this.projectName = jsonElement.getAsString();
break;
//TODO: change config name
case "servicegen.config.ehrName":
this.ehrName = jsonElement.getAsString();
break;
case "servicegen.config.authMethod":
this.authMethod = jsonElement.getAsString();
break;
default:
LOG.warn("Invalid config path: " + jsonPath);
break;
}
}

public String getEhrName() {
return ehrName;
}

public String getProjectName() {
if (projectName == null) {
projectName = ehrName.concat("-service");
}
return projectName;
}

public IBaseResource getCapabilityStatement() {
return capabilityStatement;
}

public void setCapabilityStatement(IBaseResource capabilityStatement) {
this.capabilityStatement = capabilityStatement;
}

public String getAuthMethod() {
return authMethod;
}

public Map<String, PackageInfo> getPackageInfoMap() {
return packageInfoMap;
}

public boolean isEnabled() {
return isEnabled;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.healthcare.fhir.ballerina.prebuiltservicegen.tool;

import org.wso2.healthcare.codegen.tool.framework.commons.core.TemplateContext;
import org.wso2.healthcare.codegen.tool.framework.commons.core.ToolContext;
import org.wso2.healthcare.codegen.tool.framework.commons.exception.CodeGenException;
import org.wso2.healthcare.codegen.tool.framework.fhir.core.AbstractFHIRTemplateGenerator;
import org.wso2.healthcare.fhir.codegen.ballerina.project.tool.BallerinaProjectConstants;
import org.wso2.healthcare.fhir.codegen.ballerina.project.tool.generator.MetaGenerator;
import org.wso2.healthcare.fhir.codegen.ballerina.project.tool.generator.TomlGenerator;

import java.io.File;
import java.util.Calendar;
import java.util.Map;

/**
* FHIR prebuilt service generator class.
*/
public class ServiceGenerator extends AbstractFHIRTemplateGenerator {
public ServiceGenerator(String targetDir) throws CodeGenException {
super(targetDir);
}

@Override
public void generate(ToolContext toolContext, Map<String, Object> generatorProperties) throws CodeGenException {
//generation of fhir service files by reusing the template gen tool lib
org.wso2.healthcare.fhir.codegen.ballerina.project.tool.generator.ServiceGenerator balServiceGenerator = new org.wso2.healthcare.fhir.codegen.ballerina.project.tool.generator.ServiceGenerator(this.getTargetDir());
balServiceGenerator.generate(toolContext, generatorProperties);
TomlGenerator tomlGenerator = new TomlGenerator(this.getTargetDir());
tomlGenerator.generate(toolContext, generatorProperties);
MetaGenerator metaFilesGenerator = new MetaGenerator(this.getTargetDir());
metaFilesGenerator.generate(toolContext, generatorProperties);
//generation of prebuilt service specific files.
String directoryPath = generatorProperties.get("projectAPIPath") + File.separator;
String initFileName = "connection_config.bal";
String serviceUtilsFileName = "serviceUtils.bal";
this.getTemplateEngine().generateOutputAsFile(BallerinaProjectConstants.RESOURCE_PATH_TEMPLATES +
File.separator + "connection_config.vm", createTemplateContext(
generatorProperties), directoryPath, initFileName);
this.getTemplateEngine().generateOutputAsFile(BallerinaProjectConstants.RESOURCE_PATH_TEMPLATES +
File.separator + "service_utils.vm", createTemplateContext(
generatorProperties), directoryPath, serviceUtilsFileName);
}

private TemplateContext createTemplateContext(Map<String, Object> generatorProperties) {
TemplateContext templateContext = this.getNewTemplateContext();
templateContext.setProperty("ehrName", generatorProperties.get("ehrName"));
templateContext.setProperty("currentYear", Calendar.getInstance().get(Calendar.YEAR));
templateContext.setProperty("authMethod", generatorProperties.get("authMethod"));
return templateContext;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.healthcare.fhir.ballerina.prebuiltservicegen.tool;

import org.wso2.healthcare.codegen.tool.framework.commons.core.TemplateContext;
import org.wso2.healthcare.codegen.tool.framework.commons.core.ToolContext;
import org.wso2.healthcare.codegen.tool.framework.commons.exception.CodeGenException;
import org.wso2.healthcare.codegen.tool.framework.fhir.core.AbstractFHIRTemplateGenerator;
import org.wso2.healthcare.fhir.codegen.ballerina.project.tool.BallerinaProjectConstants;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* This generates FHIR service interaction method content.
*/
public class ServiceInteractionMethodGenerator extends AbstractFHIRTemplateGenerator {

private final Map<String, String> interactionMethodContent = new HashMap<>();

public ServiceInteractionMethodGenerator(String targetDir) throws CodeGenException {
super(targetDir);
}

@Override
public void generate(ToolContext toolContext, Map<String, Object> generatorProperties) throws CodeGenException {
if (generatorProperties.containsKey("interactionType")) {
String content = this.getTemplateEngine().generateOutputAsString(BallerinaProjectConstants.RESOURCE_PATH_TEMPLATES +
File.separator + "interaction_method_content.vm", createTemplateContext(generatorProperties));
if (!Objects.equals(content, "")) {
interactionMethodContent.put((String) generatorProperties.get("interactionType"), content);
}
}
}

private TemplateContext createTemplateContext(Map<String, Object> generatorProperties) {
TemplateContext templateContext = this.getNewTemplateContext();
templateContext.setProperty("resourceType", generatorProperties.get("resourceType"));
templateContext.setProperty("interactionType", generatorProperties.get("interactionType"));
templateContext.setProperty("profileList", generatorProperties.get("profileList"));
return templateContext;
}

public String getInteractionMethodContent(String interactionType) {
return interactionMethodContent.get(interactionType);
}
}
Loading

0 comments on commit ea665eb

Please sign in to comment.