Doc updates
This commit is contained in:
parent
81b2b1cc50
commit
f7a4b48e07
|
@ -264,8 +264,10 @@
|
|||
var pres = elements[i].getElementsByTagName("pre");
|
||||
for (var j = 0; j < pres.length; j++) {
|
||||
var pre = pres[j];
|
||||
if (pre.innerHTML.match(/\\\*/)) {
|
||||
if (pre.innerHTML.match(/\/\*/)) {
|
||||
pre.className = 'brush: java';
|
||||
} else if (pre.innerHTML.match(/^\#/)) {
|
||||
pre.className = 'brush: bash';
|
||||
} else if (pre.innerHTML.match(/\<\;\//)) {
|
||||
pre.className = 'brush: xml';
|
||||
} else {
|
||||
|
|
|
@ -51,15 +51,20 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
private HashMap<String, String> myProfileToNarrativeName;
|
||||
private HashMap<Class<?>, String> myClassToNarrativeName;
|
||||
private HashMap<String, String> myNameToNarrativeTemplate;
|
||||
|
||||
private boolean myApplyDefaultDatatypeTemplates=true;
|
||||
private volatile boolean myInitialized;
|
||||
|
||||
@Override
|
||||
public NarrativeDt generateNarrative(IResource theResource) {
|
||||
return generateNarrative(null, theResource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NarrativeDt generateNarrative(String theProfile, IResource theResource) {
|
||||
if (!myInitialized) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
String name = null;
|
||||
if (StringUtils.isNotBlank(theProfile)) {
|
||||
name = myProfileToNarrativeName.get(theProfile);
|
||||
|
@ -80,7 +85,7 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
try {
|
||||
Context context = new Context();
|
||||
context.setVariable("resource", theResource);
|
||||
|
||||
|
||||
String result = myProfileTemplateEngine.process(name, context);
|
||||
|
||||
if (myCleanWhitespace) {
|
||||
|
@ -113,8 +118,11 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
if (isBlank(propFileName)) {
|
||||
throw new ConfigurationException("Property file name can not be null");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
if (myApplyDefaultDatatypeTemplates) {
|
||||
loadProperties(DefaultThymeleafNarrativeGenerator.NARRATIVES_PROPERTIES);
|
||||
}
|
||||
loadProperties(propFileName);
|
||||
} catch (IOException e) {
|
||||
throw new ConfigurationException("Can not load property file " + propFileName, e);
|
||||
|
@ -139,9 +147,12 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
protected abstract String getPropertyFile();
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (which is the default), most whitespace will be trimmed from the generated narrative before it is returned.
|
||||
* If set to <code>true</code> (which is the default), most whitespace will
|
||||
* be trimmed from the generated narrative before it is returned.
|
||||
* <p>
|
||||
* Note that in order to preserve formatting, not all whitespace is trimmed. Repeated whitespace characters (e.g. "\n \n ") will be trimmed to a single space.
|
||||
* Note that in order to preserve formatting, not all whitespace is trimmed.
|
||||
* Repeated whitespace characters (e.g. "\n \n ") will be
|
||||
* trimmed to a single space.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isCleanWhitespace() {
|
||||
|
@ -149,24 +160,30 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
}
|
||||
|
||||
/**
|
||||
* If set to <code>true</code>, which is the default, if any failure occurs during narrative generation the generator will suppress any generated exceptions, and simply return a default narrative
|
||||
* indicating that no narrative is available.
|
||||
* If set to <code>true</code>, which is the default, if any failure occurs
|
||||
* during narrative generation the generator will suppress any generated
|
||||
* exceptions, and simply return a default narrative indicating that no
|
||||
* narrative is available.
|
||||
*/
|
||||
public boolean isIgnoreFailures() {
|
||||
return myIgnoreFailures;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to true, will return an empty narrative block for any profiles where no template is available
|
||||
* If set to true, will return an empty narrative block for any profiles
|
||||
* where no template is available
|
||||
*/
|
||||
public boolean isIgnoreMissingTemplates() {
|
||||
return myIgnoreMissingTemplates;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (which is the default), most whitespace will be trimmed from the generated narrative before it is returned.
|
||||
* If set to <code>true</code> (which is the default), most whitespace will
|
||||
* be trimmed from the generated narrative before it is returned.
|
||||
* <p>
|
||||
* Note that in order to preserve formatting, not all whitespace is trimmed. Repeated whitespace characters (e.g. "\n \n ") will be trimmed to a single space.
|
||||
* Note that in order to preserve formatting, not all whitespace is trimmed.
|
||||
* Repeated whitespace characters (e.g. "\n \n ") will be
|
||||
* trimmed to a single space.
|
||||
* </p>
|
||||
*/
|
||||
public void setCleanWhitespace(boolean theCleanWhitespace) {
|
||||
|
@ -174,15 +191,18 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
}
|
||||
|
||||
/**
|
||||
* If set to <code>true</code>, which is the default, if any failure occurs during narrative generation the generator will suppress any generated exceptions, and simply return a default narrative
|
||||
* indicating that no narrative is available.
|
||||
* If set to <code>true</code>, which is the default, if any failure occurs
|
||||
* during narrative generation the generator will suppress any generated
|
||||
* exceptions, and simply return a default narrative indicating that no
|
||||
* narrative is available.
|
||||
*/
|
||||
public void setIgnoreFailures(boolean theIgnoreFailures) {
|
||||
myIgnoreFailures = theIgnoreFailures;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to true, will return an empty narrative block for any profiles where no template is available
|
||||
* If set to true, will return an empty narrative block for any profiles
|
||||
* where no template is available
|
||||
*/
|
||||
public void setIgnoreMissingTemplates(boolean theIgnoreMissingTemplates) {
|
||||
myIgnoreMissingTemplates = theIgnoreMissingTemplates;
|
||||
|
@ -261,11 +281,11 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
} else if (name.startsWith("file:")) {
|
||||
File file = new File(name.substring("file:".length()));
|
||||
if (file.exists() == false) {
|
||||
throw new IOException("Can not read file: " + file.getAbsolutePath());
|
||||
throw new IOException("File not found: " + file.getAbsolutePath());
|
||||
}
|
||||
return new FileInputStream(file);
|
||||
} else {
|
||||
throw new IOException("Invalid resource name: '" + name + "'");
|
||||
throw new IOException("Invalid resource name: '" + name + "' (must start with classpath: or file: )");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,11 +357,14 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
final IStandardExpression expression = expressionParser.parseExpression(configuration, theArguments, attributeValue);
|
||||
final Object value = expression.execute(configuration, theArguments);
|
||||
|
||||
|
||||
theElement.removeAttribute(theAttributeName);
|
||||
theElement.clearChildren();
|
||||
|
||||
Context context = new Context();
|
||||
context.setVariable("resource", value);
|
||||
|
||||
|
||||
String name = myClassToNarrativeName.get(value.getClass());
|
||||
|
||||
if (name == null) {
|
||||
if (myIgnoreMissingTemplates) {
|
||||
ourLog.debug("No narrative template available for type: {}", value.getClass());
|
||||
|
@ -354,9 +377,6 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
|||
String result = myProfileTemplateEngine.process(name, context);
|
||||
Document dom = DOMUtils.getXhtmlDOMFor(new StringReader(result));
|
||||
|
||||
theElement.removeAttribute(theAttributeName);
|
||||
theElement.clearChildren();
|
||||
|
||||
Element firstChild = (Element) dom.getFirstChild();
|
||||
for (Node next : firstChild.getChildren()) {
|
||||
theElement.addChild(next);
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
package ca.uhn.fhir.narrative;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DefaultThymeleafNarrativeGenerator extends BaseThymeleafNarrativeGenerator implements INarrativeGenerator {
|
||||
|
||||
public DefaultThymeleafNarrativeGenerator() throws IOException {
|
||||
super();
|
||||
}
|
||||
static final String NARRATIVES_PROPERTIES = "classpath:ca/uhn/fhir/narrative/narratives.properties";
|
||||
|
||||
@Override
|
||||
protected String getPropertyFile() {
|
||||
return "classpath:ca/uhn/fhir/narrative/narratives.properties";
|
||||
return NARRATIVES_PROPERTIES;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import ca.uhn.fhir.parser.DataFormatException;
|
|||
|
||||
public interface INarrativeGenerator {
|
||||
|
||||
public NarrativeDt generateNarrative(String theProfile, IResource theResource) throws DataFormatException;
|
||||
|
||||
NarrativeDt generateNarrative(String theProfile, IResource theResource) throws DataFormatException;
|
||||
|
||||
NarrativeDt generateNarrative(IResource theResource);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package example;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.narrative.CustomThymeleafNarrativeGenerator;
|
||||
|
||||
public class NarrativeGenerator {
|
||||
|
||||
@Test
|
||||
public void testGenerator() throws IOException {
|
||||
|
||||
//START SNIPPET: gen
|
||||
String propFile = "classpath:/com/foo/customnarrative.properties";
|
||||
CustomThymeleafNarrativeGenerator gen = new CustomThymeleafNarrativeGenerator(propFile);
|
||||
|
||||
FhirContext ctx = new FhirContext();
|
||||
ctx.setNarrativeGenerator(gen);
|
||||
//END SNIPPET: gen
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@
|
|||
<script type="text/javascript" src="syntaxhighlighter/shCore.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushJScript.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushJava.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushBash.js"></script>
|
||||
<script type="text/javascript" src="syntaxhighlighter/shBrushXml.js"></script>
|
||||
<link href="syntaxhighlighter/shCore.css" rel="stylesheet" type="text/css" />
|
||||
<link href="syntaxhighlighter/shThemeDefault.css" rel="stylesheet" type="text/css" />
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||
|
||||
<properties>
|
||||
<title>Download - HAPI FHIR</title>
|
||||
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
|
||||
</properties>
|
||||
|
||||
<body>
|
||||
|
||||
<section name="Downloading HAPI FHIR">
|
||||
|
||||
<p>
|
||||
The easiest way to get started with HAPI-FHIR is to either download the
|
||||
source code from our
|
||||
<a href="https://sourceforge.net/p/hl7api/fhircode/ci/master/tree/">Git Repository</a>
|
||||
, or to use Maven:
|
||||
</p>
|
||||
<source><![CDATA[<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>]]></source>
|
||||
|
||||
<subsection name="Non-Maven Users">
|
||||
|
||||
<p>
|
||||
Non-maven users can grab the files from the
|
||||
<a href="https://sourceforge.net/projects/hl7api/files/hapi-fhir/">Sourceforge File Release System</a>.
|
||||
</p>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
</document>
|
|
@ -9,7 +9,7 @@
|
|||
<body>
|
||||
|
||||
<!-- The body of the document contains a number of sections -->
|
||||
<section name="Developing using FHIR-HAPI">
|
||||
<section name="Developing using HAPI FHIR">
|
||||
|
||||
<macro name="toc">
|
||||
</macro>
|
||||
|
@ -45,24 +45,10 @@
|
|||
<section name="Getting Started">
|
||||
|
||||
<p>
|
||||
The easiest way to get started with HAPI-FHIR is to either download the
|
||||
source code from our
|
||||
<a href="https://sourceforge.net/p/hl7api/fhircode/ci/master/tree/">Git Repository</a>
|
||||
, or to use Maven:
|
||||
</p>
|
||||
<source><![CDATA[<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>]]></source>
|
||||
|
||||
<p>
|
||||
If you are not using Maven, you can download the latest version
|
||||
of the snapshot JAR (and optionally the Javadoc and Sources JAR) from the Maven
|
||||
repo here: <a href="http://oss.sonatype.org/content/repositories/snapshots/ca/uhn/hapi/fhir/hapi-fhir-base/1.0-SNAPSHOT/">download</a>.
|
||||
Once a formal release has been created, it will be uploaded through the Sourceforge
|
||||
file release system (as the HAPI v2 libraries are).
|
||||
</p>
|
||||
To get started with HAPI FHIR, first download a copy and add it
|
||||
to your project. See the <a href="doc_download.html">Download Page</a>
|
||||
for instructions.
|
||||
</p>
|
||||
|
||||
<subsection name="Introcuding the FHIR Context">
|
||||
|
||||
|
|
|
@ -111,6 +111,63 @@
|
|||
|
||||
</section>
|
||||
|
||||
<section name="Creating your own Templates">
|
||||
|
||||
<p>
|
||||
To use your own templates for narrative generation,
|
||||
simply create one or more templates, using the Thymeleaf
|
||||
HTML based syntax.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="file" value="src/test/resources/narrative/Practitioner.html" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Then create a properties file which describes your
|
||||
templates. In this properties file, each resource to
|
||||
be defined has a pair or properties.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The first (name.class) defines the class name of the resource to define a
|
||||
template for. The second (name.narrative) defines the path/classpath to the
|
||||
template file. The format of this path is <code>file:/path/foo.html</code> or <code>classpath:/com/classpath/foo.html</code>
|
||||
</p>
|
||||
|
||||
<source><![CDATA[# Two property lines in the file per template
|
||||
practitioner.class=ca.uhn.fhir.model.dstu.resource.Practitioner
|
||||
practitioner.narrative=file:src/test/resources/narrative/Practitioner.html
|
||||
|
||||
observation.class=ca.uhn.fhir.model.dstu.resource.Observation
|
||||
observation.narrative=file:src/test/resources/narrative/Observation.html
|
||||
|
||||
# etc...]]></source>
|
||||
|
||||
<p>
|
||||
You may also override/define behaviour for datatypes. These datatype narrative
|
||||
definitions will be used as content within <code>th:narrative</code> blocks
|
||||
in resource templates. See the example resource template above for an example.
|
||||
</p>
|
||||
|
||||
<source><![CDATA[# datatypes use the same format as resources
|
||||
humanname.class=ca.uhn.fhir.model.dstu.composite.HumanNameDt
|
||||
humanname.narrative=classpath:ca/uhn/fhir/narrative/HumanNameDt.html]]></source>
|
||||
|
||||
<p>
|
||||
Finally, use the
|
||||
<a href="./apidocs/ca/uhn/fhir/narrative/CustomThymeleafNarrativeGenerator.html">CustomThymeleafNarrativeGenerator</a>
|
||||
and provide it
|
||||
to the FhirContext.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="gen" />
|
||||
<param name="file" value="src/site/example/java/example/NarrativeGenerator.java" />
|
||||
</macro>
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
</document>
|
||||
|
|
|
@ -1,18 +1,36 @@
|
|||
package ca.uhn.fhir.narrative;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Practitioner;
|
||||
|
||||
public class CustomThymeleafNarrativeGeneratorTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomThymeleafNarrativeGeneratorTest.class);
|
||||
|
||||
@Test
|
||||
public void testGenerator() throws IOException {
|
||||
|
||||
CustomThymeleafNarrativeGenerator gen = new CustomThymeleafNarrativeGenerator("src/test/resources/narrative/customnarrative.properties");
|
||||
|
||||
|
||||
|
||||
CustomThymeleafNarrativeGenerator gen = new CustomThymeleafNarrativeGenerator("file:src/test/resources/narrative/customnarrative.properties");
|
||||
|
||||
Practitioner p = new Practitioner();
|
||||
p.addIdentifier("sys", "val1");
|
||||
p.addIdentifier("sys", "val2");
|
||||
p.getAddress().addLine("line1").addLine("line2");
|
||||
p.getName().addFamily("fam1").addGiven("given");
|
||||
|
||||
NarrativeDt narrative = gen.generateNarrative(p);
|
||||
|
||||
String actual = narrative.getDiv().getValueAsString();
|
||||
ourLog.info(actual);
|
||||
|
||||
assertThat(actual, containsString("<h1>Name</h1><div> given <b>FAM1 </b></div><h1>Address</h1><div><span>line1 </span><br/><span>line2 </span><br/></div></div>"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
|||
private DefaultThymeleafNarrativeGenerator gen;
|
||||
|
||||
@Before
|
||||
public void before() throws IOException {
|
||||
public void before() {
|
||||
gen = new DefaultThymeleafNarrativeGenerator();
|
||||
gen.setIgnoreFailures(false);
|
||||
gen.setIgnoreMissingTemplates(false);
|
||||
|
|
|
@ -10,12 +10,10 @@
|
|||
HAPI also defines a custom tag, th:narrative="value", which is
|
||||
used to render a datatype.
|
||||
-->
|
||||
<div th:narrative="${resource.addressFirstRep}"></div>
|
||||
<h1>Name</h1>
|
||||
<div th:narrative="${resource.name}"></div>
|
||||
<h1>Address</h1>
|
||||
<div th:narrative="${resource.address}"></div>
|
||||
|
||||
<!--
|
||||
HAPI also defines a custom tag, th:narrative="value", which is
|
||||
used to render a datatype.
|
||||
-->
|
||||
<div th:narrative="${resource.nameFirstRep}"></div>
|
||||
|
||||
</div>
|
|
@ -9,7 +9,7 @@
|
|||
# Format is file:/path/foo.html or classpath:/com/classpath/foo.html
|
||||
#
|
||||
practitioner.class=ca.uhn.fhir.model.dstu.resource.Practitioner
|
||||
practitioner.narrative=file:src/test/resource/narrative/Practitioner.html
|
||||
practitioner.narrative=file:src/test/resources/narrative/Practitioner.html
|
||||
|
||||
# You may also override/define behaviour for datatypes
|
||||
humanname.class=ca.uhn.fhir.model.dstu.composite.HumanNameDt
|
Loading…
Reference in New Issue