Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IPS Generator #4438

Merged
merged 32 commits into from Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e9e98ec
Begin IPS refactor
jamesagnew Jan 14, 2023
1b72a53
Commit work so far
jamesagnew Jan 14, 2023
fa77a60
Fix test bug
jamesagnew Jan 14, 2023
8909460
Fix typo
jamesagnew Jan 14, 2023
6c101da
Fix typo
jamesagnew Jan 14, 2023
811f728
Narrative generator cleanup
jamesagnew Jan 14, 2023
a67e0c1
Narrative generator working
jamesagnew Jan 15, 2023
9e5a1dc
Add test for bad reference in narrative
jamesagnew Jan 15, 2023
51d1f82
Tests passing
jamesagnew Jan 16, 2023
7f4aa48
Start docs
jamesagnew Jan 17, 2023
b0c1e65
Tests passing
jamesagnew Jan 18, 2023
36dc1cd
Merge branch 'master' into ja_20230113_ips
jamesagnew Jan 18, 2023
0fc4479
Cleanup
jamesagnew Jan 19, 2023
d6d6b7c
Update cyangelog
jamesagnew Jan 19, 2023
145ca8d
Doc tweaks
jamesagnew Jan 20, 2023
c0d6ef8
Merge branch 'master' into ja_20230113_ips
jamesagnew Jan 20, 2023
0cfaa6c
Version bump
jamesagnew Jan 20, 2023
2f56dd1
Address review comments
jamesagnew Jan 21, 2023
03c7f85
Address review comments
jamesagnew Jan 21, 2023
0d0556a
Merge branch 'master' into ja_20230113_ips
jamesagnew Jan 21, 2023
9f7ab23
Build fix
jamesagnew Jan 21, 2023
2acdf38
Cleanup
jamesagnew Jan 21, 2023
d4636c5
Compile fix
jamesagnew Jan 21, 2023
e47aaa0
Test fix
jamesagnew Jan 22, 2023
e382361
Test fix
jamesagnew Jan 22, 2023
a9407ae
Version bump
jamesagnew Jan 23, 2023
727ddcb
Build update
jamesagnew Jan 23, 2023
7be8b8a
Test fix
jamesagnew Jan 23, 2023
b5fa756
Merge branch 'ja_20230113_ips' of github.com:hapifhir/hapi-fhir into …
jamesagnew Jan 23, 2023
2b34d1f
Test fix
jamesagnew Jan 24, 2023
6542123
Add one utility method
jamesagnew Jan 24, 2023
4fab7c9
Add doc
jamesagnew Jan 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions azure-pipelines.yml
Expand Up @@ -59,6 +59,8 @@ stages:
# module: hapi-fhir-jpaserver-base
- name: hapi_fhir_jpaserver_elastic_test_utilities
module: hapi-fhir-jpaserver-elastic-test-utilities
- name: hapi_fhir_jpaserver_ips
module: hapi-fhir-jpaserver-ips
- name: hapi_fhir_jpaserver_mdm
module: hapi-fhir-jpaserver-mdm
- name: hapi_fhir_jpaserver_model
Expand Down
12 changes: 12 additions & 0 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/fhirpath/IFhirPath.java
Expand Up @@ -22,6 +22,7 @@

import org.hl7.fhir.instance.model.api.IBase;

import javax.annotation.Nonnull;
import java.util.List;
import java.util.Optional;

Expand Down Expand Up @@ -52,4 +53,15 @@ public interface IFhirPath {
* Parses the expression and throws an exception if it can not parse correctly
*/
void parse(String theExpression) throws Exception;


/**
* This method can be used optionally to supply an evaluation context for the
* FHIRPath evaluator instance. The context can be used to supply data needed by
* specific functions, e.g. allowing the <code>resolve()</code> function to
* fetch referenced resources.
*
* @since 6.4.0
*/
void setEvaluationContext(@Nonnull IFhirPathEvaluationContext theEvaluationContext);
}
@@ -0,0 +1,41 @@
package ca.uhn.fhir.fhirpath;

/*-
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed 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.
* #L%
*/

import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IIdType;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public interface IFhirPathEvaluationContext {
jamesagnew marked this conversation as resolved.
Show resolved Hide resolved

/**
* Evaluates the <code>resolve()</code> function and returns the target
* of the resolution.
*
* @param theReference The reference
* @param theContext The entity containing the reference. Note that this will be <code>null</code> for FHIR versions R4 and below.
*/
default IBase resolveReference(@Nonnull IIdType theReference, @Nullable IBase theContext) {
jamesagnew marked this conversation as resolved.
Show resolved Hide resolved
return null;
}
}
Expand Up @@ -37,7 +37,7 @@
* upgrading servers.
* </p>
* <p>
* Note on thrwead safety: This class is not thread safe.
* Note on thread safety: This class is not thread safe.
* </p>
*/
public class Include implements Serializable {
Expand Down
Expand Up @@ -22,17 +22,21 @@

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.narrative2.BaseNarrativeGenerator;
import ca.uhn.fhir.narrative2.INarrativeTemplate;
import ca.uhn.fhir.narrative2.NarrativeTemplateManifest;
import ca.uhn.fhir.narrative2.ThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;

public abstract class BaseThymeleafNarrativeGenerator extends ThymeleafNarrativeGenerator {

private boolean myInitialized;
private volatile boolean myInitialized;

/**
* Constructor
Expand All @@ -43,11 +47,21 @@ protected BaseThymeleafNarrativeGenerator() {

@Override
public boolean populateResourceNarrative(FhirContext theFhirContext, IBaseResource theResource) {
initializeIfNecessary();
super.populateResourceNarrative(theFhirContext, theResource);
return false;
}

@Override
public String generateResourceNarrative(FhirContext theFhirContext, IBaseResource theResource) {
initializeIfNecessary();
return super.generateResourceNarrative(theFhirContext, theResource);
}

protected void initializeIfNecessary() {
if (!myInitialized) {
initialize();
}
super.populateResourceNarrative(theFhirContext, theResource);
return false;
}

protected abstract List<String> getPropertyFile();
jamesagnew marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Expand Up @@ -32,16 +32,30 @@ public class CustomThymeleafNarrativeGenerator extends BaseThymeleafNarrativeGen
/**
* Create a new narrative generator
*
* @param thePropertyFile
* @param theNarrativePropertyFiles
* The name of the property file, in one of the following formats:
* <ul>
* <li>file:/path/to/file/file.properties</li>
* <li>classpath:/com/package/file.properties</li>
* </ul>
*/
public CustomThymeleafNarrativeGenerator(String... thePropertyFile) {
public CustomThymeleafNarrativeGenerator(String... theNarrativePropertyFiles) {
super();
setPropertyFile(thePropertyFile);
setPropertyFile(theNarrativePropertyFiles);
}

/**
* Create a new narrative generator
*
* @param theNarrativePropertyFiles
* The name of the property file, in one of the following formats:
* <ul>
* <li>file:/path/to/file/file.properties</li>
* <li>classpath:/com/package/file.properties</li>
* </ul>
*/
public CustomThymeleafNarrativeGenerator(List<String> theNarrativePropertyFiles) {
this(theNarrativePropertyFiles.toArray(new String[0]));
}

/**
Expand Down
Expand Up @@ -35,4 +35,8 @@ public interface INarrativeGenerator {
*/
boolean populateResourceNarrative(FhirContext theFhirContext, IBaseResource theResource);

/**
* Generates the narrative for the given resource and returns it as a string
*/
String generateResourceNarrative(FhirContext theFhirContext, IBaseResource theResource);
}
Expand Up @@ -31,6 +31,8 @@
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.INarrative;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.EnumSet;
Expand Down Expand Up @@ -64,7 +66,18 @@ public boolean populateResourceNarrative(FhirContext theFhirContext, IBaseResour
return false;
}

private List<INarrativeTemplate> getTemplateForElement(FhirContext theFhirContext, IBase theElement) {
@Override
public String generateResourceNarrative(FhirContext theFhirContext, IBaseResource theResource) {
List<INarrativeTemplate> templates = getTemplateForElement(theFhirContext, theResource);
if (templates.size() > 0) {
String narrative = applyTemplate(theFhirContext, templates.get(0), (IBase)theResource);
jamesagnew marked this conversation as resolved.
Show resolved Hide resolved
return cleanWhitespace(narrative);
}

return null;
}

protected List<INarrativeTemplate> getTemplateForElement(FhirContext theFhirContext, IBase theElement) {
return myManifest.getTemplateByElement(theFhirContext, getStyle(), theElement);
}

Expand Down
Expand Up @@ -23,13 +23,17 @@
import ca.uhn.fhir.context.FhirContext;
import org.hl7.fhir.instance.model.api.IBase;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;

public interface INarrativeTemplateManifest {
List<INarrativeTemplate> getTemplateByResourceName(FhirContext theFhirContext, EnumSet<TemplateTypeEnum> theStyles, String theResourceName);
List<INarrativeTemplate> getTemplateByResourceName(@Nonnull FhirContext theFhirContext, @Nonnull EnumSet<TemplateTypeEnum> theStyles, @Nonnull String theResourceName, @Nonnull Collection<String> theProfiles);

List<INarrativeTemplate> getTemplateByName(FhirContext theFhirContext, EnumSet<TemplateTypeEnum> theStyles, String theName);
List<INarrativeTemplate> getTemplateByName(@Nonnull FhirContext theFhirContext, @Nonnull EnumSet<TemplateTypeEnum> theStyles, @Nonnull String theName);

List<INarrativeTemplate> getTemplateByElement(FhirContext theFhirContext, EnumSet<TemplateTypeEnum> theStyles, IBase theElementValue);
List<INarrativeTemplate> getTemplateByElement(@Nonnull FhirContext theFhirContext, @Nonnull EnumSet<TemplateTypeEnum> theStyles, @Nonnull IBase theElementValue);

List<INarrativeTemplate> getTemplateByFragmentName(@Nonnull FhirContext theFhirContext, @Nonnull EnumSet<TemplateTypeEnum> theStyles, @Nonnull String theFragmentName);
}
Expand Up @@ -32,10 +32,11 @@
public class NarrativeTemplate implements INarrativeTemplate {

private String myTemplateFileName;
private Set<String> myAppliesToProfiles = new HashSet<>();
private Set<String> myAppliesToResourceTypes = new HashSet<>();
private Set<String> myAppliesToDataTypes = new HashSet<>();
private Set<Class<? extends IBase>> myAppliesToClasses = new HashSet<>();
private final Set<String> myAppliesToProfiles = new HashSet<>();
private final Set<String> myAppliesToResourceTypes = new HashSet<>();
private final Set<String> myAppliesToDataTypes = new HashSet<>();
private final Set<Class<? extends IBase>> myAppliesToClasses = new HashSet<>();
private final Set<String> myAppliesToFragmentNames = new HashSet<>();
private TemplateTypeEnum myTemplateType = TemplateTypeEnum.THYMELEAF;
private String myContextPath;
private String myTemplateName;
Expand All @@ -44,6 +45,14 @@ public Set<String> getAppliesToDataTypes() {
return Collections.unmodifiableSet(myAppliesToDataTypes);
}

public Set<String> getAppliesToFragmentNames() {
return Collections.unmodifiableSet(myAppliesToFragmentNames);
}

void addAppliesToFragmentName(String theAppliesToFragmentName) {
myAppliesToFragmentNames.add(theAppliesToFragmentName);
}

@Override
public String getContextPath() {
return myContextPath;
Expand Down