Remove dead modules (#3380)

* fix handling of common search parameters

* Revert "fix handling of common search parameters"

This reverts commit 89c45eebdc31c3dd9533570d9c709ecc7ed5a7a6.

* Fix implementation, add test (#3378)

* Fix implementation, add test

* Tighten test

* Rip out dead modules

* Add changelog

Co-authored-by: Jason Roberts <jason.roberts@smilecdr.com>
This commit is contained in:
Tadgh 2022-02-10 16:44:26 -05:00 committed by GitHub
parent ecdb8c2ce6
commit 38912423c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
304 changed files with 47 additions and 79222 deletions

View File

@ -0,0 +1,4 @@
---
type: change
issue: 3379
title: "Removed the following modules from the HAPI-FHIR project: `hapi-fhir-testpage-interceptor`, `hapi-fhir-structures-dstu`, `hapi-fhir-oauth2`, `hapi-fhir-narrativegenerator`."

View File

@ -2,13 +2,26 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.test.BaseTest;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import java.util.Date;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.slf4j.LoggerFactory.getLogger;
public class SearchParameterMapTest extends BaseTest {
private static final Logger ourLog = getLogger(SearchParameterMapTest.class);
private final FhirContext myContext = FhirContext.forR4Cached();
@ -19,4 +32,31 @@ public class SearchParameterMapTest extends BaseTest {
String criteria = params.toNormalizedQueryString(myContext);
assertEquals(criteria, "?_has:Observation:subject:identifier=urn%3Asystem%7CFOO");
}
@Test
public void testCloningRecreatesCorrectQueryString() {
SearchParameterMap params = new SearchParameterMap();
params.add("_id", new StringOrListParam().addOr(new StringParam("123")).addOr(new StringParam("456")));
params.add("given", new StringOrListParam().addOr(new StringParam("Gary")).addOr(new StringParam("Ken ")));
params.setSummaryMode(SummaryEnum.COUNT);
params.setSort(new SortSpec().setOrder(SortOrderEnum.DESC).setParamName("_id"));
params.setCount(10);
params.setLastUpdated(new DateRangeParam(new DateParam("2020-01-01")));
params.setSearchTotalMode(SearchTotalModeEnum.ACCURATE);
String originalQueryString = params.toNormalizedQueryString(myContext);
ourLog.info("Original query string: {}", originalQueryString);
SearchParameterMap params2 = params.clone();
String clonedQueryString = params2.toNormalizedQueryString(myContext);
ourLog.info("Cloned query string: {}", clonedQueryString);
assertEquals(originalQueryString, clonedQueryString);
}
}

View File

@ -124,6 +124,8 @@ public class SearchParameterMap implements Serializable {
map.put(entry.getKey(), newAndParams);
}
return map;
}

View File

@ -1,73 +0,0 @@
<?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>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>2.2-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-hapi-fhir-narrativegenerator</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - Narrative Generator</name>
<dependencies>
<!-- HAPI DEPENDENCIES -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>2.2-SNAPSHOT</version>
</dependency>
<!-- Unit test dependencies -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu3</artifactId>
<version>2.2-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr</artifactId>
<version>3.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<version>3.5.2</version>
<executions>
<execution>
<goals>
<goal>antlr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<dumpOnExit>true</dumpOnExit>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,274 +0,0 @@
/*
* Copyright (c) 2010 by Bart Kiers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Project : Liqp; a Liquid Template grammar/parser
* Developed by : Bart Kiers, bart@big-o.nl
*/
tree grammar LiquidWalker;
options {
tokenVocab=Liquid;
ASTLabelType=CommonTree;
}
@header {
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.parser.*;
import ca.uhn.fhir.narrative.template.tags.*;
import ca.uhn.fhir.narrative.template.filters.*;
import java.util.Map;
}
@members {
private Map<String, Tag> tags;
private Map<String, Filter> filters;
private Flavor flavor;
public LiquidWalker(TreeNodeStream nodes, Map<String, Tag> tags, Map<String, Filter> filters) {
this(nodes, tags, filters, Flavor.LIQUID);
}
public LiquidWalker(TreeNodeStream nodes, Map<String, Tag> tags, Map<String, Filter> filters, Flavor flavor) {
super(nodes);
this.tags = tags;
this.filters = filters;
this.flavor = flavor;
}
}
walk returns [LNode node]
: block {$node = $block.node;}
;
block returns [BlockNode node]
@init{$node = new BlockNode();}
: ^(BLOCK (atom {$node.add($atom.node);})*)
;
atom returns [LNode node]
: tag {$node = $tag.node;}
| output {$node = $output.node;}
| assignment {$node = $assignment.node;}
| PLAIN {$node = new AtomNode($PLAIN.text);}
;
tag returns [LNode node]
: raw_tag {$node = $raw_tag.node;}
| comment_tag {$node = $comment_tag.node;}
| if_tag {$node = $if_tag.node;}
| unless_tag {$node = $unless_tag.node;}
| case_tag {$node = $case_tag.node;}
| cycle_tag {$node = $cycle_tag.node;}
| for_tag {$node = $for_tag.node;}
| table_tag {$node = $table_tag.node;}
| capture_tag {$node = $capture_tag.node;}
| include_tag {$node = $include_tag.node;}
| custom_tag {$node = $custom_tag.node;}
| custom_tag_block {$node = $custom_tag_block.node;}
| break_tag {$node = $break_tag.node;}
| continue_tag {$node = $continue_tag.node;}
;
raw_tag returns [LNode node]
: RAW {$node = new TagNode("raw", tags.get("raw"), new AtomNode($RAW.text));}
;
comment_tag returns [LNode node]
: COMMENT {$node = new TagNode("comment", tags.get("comment"), new AtomNode($COMMENT.text));}
;
if_tag returns [LNode node]
@init{List<LNode> nodes = new ArrayList<LNode>();}
: ^(IF e1=expr b1=block {nodes.add($e1.node); nodes.add($b1.node);}
(^(ELSIF e2=expr b2=block {nodes.add($e2.node); nodes.add($b2.node);} ))*
^(ELSE (b3=block {nodes.add(new AtomNode("TRUE")); nodes.add($b3.node);} )?)
)
{$node = new TagNode("if", tags.get("if"), nodes.toArray(new LNode[nodes.size()]));}
;
unless_tag returns [LNode node]
@init{List<LNode> nodes = new ArrayList<LNode>();}
: ^(UNLESS expr b1=block {nodes.add($expr.node); nodes.add($b1.node);}
^(ELSE (b2=block {nodes.add(new AtomNode(null)); nodes.add($b2.node);})?))
{$node = new TagNode("unless", tags.get("unless"), nodes.toArray(new LNode[nodes.size()]));}
;
case_tag returns [LNode node]
@init{List<LNode> nodes = new ArrayList<LNode>();}
: ^(CASE expr {nodes.add($expr.node);}
(when_tag [nodes] )+
^(ELSE (block {nodes.add(nodes.get(0)); nodes.add($block.node);} )?))
{$node = new TagNode("case", tags.get("case"), nodes.toArray(new LNode[nodes.size()]));}
;
when_tag[List<LNode> nodes]
: ^(WHEN (expr {nodes.add($expr.node);})+ block) {nodes.add($block.node);}
;
cycle_tag returns [LNode node]
@init{List<LNode> nodes = new ArrayList<LNode>();}
: ^(CYCLE cycle_group {nodes.add($cycle_group.node);} (e=expr {nodes.add($e.node);})+)
{$node = new TagNode("cycle", tags.get("cycle"), nodes.toArray(new LNode[nodes.size()]));}
;
cycle_group returns [LNode node]
: ^(GROUP expr?) {$node = $expr.node;}
;
for_tag returns [LNode node]
: for_array {$node = $for_array.node;}
| for_range {$node = $for_range.node;}
;
for_array returns [LNode node]
@init{
List<LNode> expressions = new ArrayList<LNode>();
expressions.add(new AtomNode(true));
}
: ^(FOR_ARRAY Id lookup {expressions.add(new AtomNode($Id.text)); expressions.add($lookup.node);}
for_block {expressions.add($for_block.node1); expressions.add($for_block.node2);}
^(ATTRIBUTES (attribute {expressions.add($attribute.node);})*)
)
{$node = new TagNode("for", tags.get("for"), expressions.toArray(new LNode[expressions.size()]));}
;
for_range returns [LNode node]
@init{
List<LNode> expressions = new ArrayList<LNode>();
expressions.add(new AtomNode(false));
}
: ^(FOR_RANGE Id from=expr to=expr {expressions.add(new AtomNode($Id.text)); expressions.add($from.node); expressions.add($to.node);}
block {expressions.add($block.node);}
^(ATTRIBUTES (attribute {expressions.add($attribute.node);})*)
)
{$node = new TagNode("for", tags.get("for"), expressions.toArray(new LNode[expressions.size()]));}
;
for_block returns [LNode node1, LNode node2]
: ^(FOR_BLOCK n1=block n2=block?)
{
$node1 = $n1.node;
$node2 = $n2.node;
}
;
attribute returns [LNode node]
: ^(Id expr) {$node = new AttributeNode(new AtomNode($Id.text), $expr.node);}
;
table_tag returns [LNode node]
@init{
List<LNode> expressions = new ArrayList<LNode>();
}
: ^(TABLE
Id {expressions.add(new AtomNode($Id.text));}
lookup {expressions.add($lookup.node);}
block {expressions.add($block.node);}
^(ATTRIBUTES (attribute {expressions.add($attribute.node);})*)
)
{$node = new TagNode("tablerow", tags.get("tablerow"), expressions.toArray(new LNode[expressions.size()]));}
;
capture_tag returns [LNode node]
: ^(CAPTURE Id block) {$node = new TagNode("capture", tags.get("capture"), new AtomNode($Id.text), $block.node);}
;
include_tag returns [LNode node]
: ^(INCLUDE file=Str ^(WITH (with=Str)?))
{
if($with.text != null) {
$node = new TagNode("include", tags.get("include"), flavor, new AtomNode($file.text), new AtomNode($with.text));
} else {
$node = new TagNode("include", tags.get("include"), flavor, new AtomNode($file.text));
}
}
;
break_tag returns [LNode node]
: Break {$node = new AtomNode(Tag.Statement.BREAK);}
;
continue_tag returns [LNode node]
: Continue {$node = new AtomNode(Tag.Statement.CONTINUE);}
;
custom_tag returns [LNode node]
@init{List<LNode> expressions = new ArrayList<LNode>();}
: ^(CUSTOM_TAG Id (expr {expressions.add($expr.node);})*)
{$node = new TagNode($Id.text, tags.get($Id.text), expressions.toArray(new LNode[expressions.size()]));}
;
custom_tag_block returns [LNode node]
@init{List<LNode> expressions = new ArrayList<LNode>();}
: ^(CUSTOM_TAG_BLOCK Id (expr {expressions.add($expr.node);})* block {expressions.add($block.node);})
{$node = new TagNode($Id.text, tags.get($Id.text), expressions.toArray(new LNode[expressions.size()]));}
;
output returns [OutputNode node]
: ^(OUTPUT expr {$node = new OutputNode($expr.node);} ^(FILTERS (filter {$node.addFilter($filter.node);})*))
;
filter returns [FilterNode node]
: ^(FILTER Id {$node = new FilterNode($Id.text, filters.get($Id.text));} ^(PARAMS params[$node]?))
;
params[FilterNode node]
: (expr {$node.add($expr.node);})+
;
assignment returns [TagNode node]
: ^(ASSIGNMENT Id filter? expr) {$node = new TagNode("assign", tags.get("assign"), new AtomNode($Id.text), $filter.node, $expr.node);}
;
expr returns [LNode node]
: ^(Or a=expr b=expr) {$node = new OrNode($a.node, $b.node);}
| ^(And a=expr b=expr) {$node = new AndNode($a.node, $b.node);}
| ^(Eq a=expr b=expr) {$node = new EqNode($a.node, $b.node);}
| ^(NEq a=expr b=expr) {$node = new NEqNode($a.node, $b.node);}
| ^(LtEq a=expr b=expr) {$node = new LtEqNode($a.node, $b.node);}
| ^(Lt a=expr b=expr) {$node = new LtNode($a.node, $b.node);}
| ^(GtEq a=expr b=expr) {$node = new GtEqNode($a.node, $b.node);}
| ^(Gt a=expr b=expr) {$node = new GtNode($a.node, $b.node);}
| ^(Contains a=expr b=expr) {$node = new ContainsNode($a.node, $b.node);}
| LongNum {$node = new AtomNode(new Long($LongNum.text));}
| DoubleNum {$node = new AtomNode(new Double($DoubleNum.text));}
| Str {$node = new AtomNode($Str.text);}
| True {$node = new AtomNode(true);}
| False {$node = new AtomNode(false);}
| Nil {$node = new AtomNode(null);}
| NO_SPACE {$node = new AtomNode($NO_SPACE.text);}
| lookup {$node = $lookup.node;}
| Empty {$node = AtomNode.EMPTY;}
;
lookup returns [LookupNode node]
: ^(LOOKUP
FluentPathExpression {$node = new LookupNode($FluentPathExpression.text);}
)
;

View File

@ -1,545 +0,0 @@
/*
* Copyright (c) 2010 by Bart Kiers
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Project : Liqp; a Liquid Template grammar/parser
* Developed by : Bart Kiers, bart@big-o.nl
*/
grammar Liquid;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
ASSIGNMENT;
ATTRIBUTES;
BLOCK;
CAPTURE;
CASE;
COMMENT;
CYCLE;
ELSE;
FILTERS;
FILTER;
FOR_ARRAY;
FOR_BLOCK;
FOR_RANGE;
GROUP;
IF;
ELSIF;
INCLUDE;
LOOKUP;
OUTPUT;
PARAMS;
PLAIN;
RAW;
TABLE;
UNLESS;
WHEN;
WITH;
NO_SPACE;
CUSTOM_TAG;
CUSTOM_TAG_BLOCK;
}
@parser::header {
package ca.uhn.fhir.narrative.template.parser;
}
@lexer::header {
package ca.uhn.fhir.narrative.template.parser;
}
@parser::members {
private Flavor flavor = Flavor.LIQUID;
public LiquidParser(Flavor flavor, TokenStream input) {
this(input, new RecognizerSharedState());
this.flavor = flavor;
}
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException(e);
}
}
@lexer::members {
private boolean inTag = false;
private boolean inRaw = false;
private boolean openRawEndTagAhead() {
if(!openTagAhead()) {
return false;
}
int indexLA = 3;
while(Character.isSpaceChar(input.LA(indexLA))) {
indexLA++;
}
return input.LA(indexLA) == 'e' &&
input.LA(indexLA + 1) == 'n' &&
input.LA(indexLA + 2) == 'd' &&
input.LA(indexLA + 3) == 'r' &&
input.LA(indexLA + 4) == 'a' &&
input.LA(indexLA + 5) == 'w';
}
private boolean openTagAhead() {
return input.LA(1) == '{' && (input.LA(2) == '{' || input.LA(2) == '\u0025');
}
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException(e);
}
private String strip(String text, boolean singleQuoted) {
return text.substring(1, text.length() - 1);
}
}
/* parser rules */
parse
: block EOF -> block
//(t=. {System.out.printf("\%-20s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF
;
block
: (options{greedy=true;}: atom)* -> ^(BLOCK atom*)
;
atom
: tag
| output
| assignment
| Other -> PLAIN[$Other.text]
;
tag
: custom_tag
| raw_tag
| comment_tag
| if_tag
| unless_tag
| case_tag
| cycle_tag
| for_tag
| table_tag
| capture_tag
| include_tag
| break_tag
| continue_tag
;
custom_tag
: (TagStart Id (expr (Comma expr)*)? TagEnd -> ^(CUSTOM_TAG Id expr*))
((custom_tag_block)=> custom_tag_block -> ^(CUSTOM_TAG_BLOCK Id expr* custom_tag_block))?
;
custom_tag_block
: (options{greedy=false;}: atom)* TagStart EndId TagEnd -> ^(BLOCK atom*)
;
raw_tag
: TagStart RawStart TagEnd raw_body TagStart RawEnd TagEnd -> raw_body
;
raw_body
: other_than_tag_start -> RAW[$other_than_tag_start.text]
;
comment_tag
: TagStart CommentStart TagEnd comment_body TagStart CommentEnd TagEnd -> comment_body
;
comment_body
: other_than_tag_start -> COMMENT[$other_than_tag_start.text]
;
other_than_tag_start
: ~TagStart*
;
if_tag
: TagStart IfStart expr TagEnd block elsif_tag* else_tag? TagStart IfEnd TagEnd -> ^(IF expr block elsif_tag* ^(ELSE else_tag?))
;
elsif_tag
: TagStart Elsif expr TagEnd block -> ^(ELSIF expr block)
;
else_tag
: TagStart Else TagEnd block -> block
;
unless_tag
: TagStart UnlessStart expr TagEnd block else_tag? TagStart UnlessEnd TagEnd -> ^(UNLESS expr block ^(ELSE else_tag?))
;
case_tag
: TagStart CaseStart expr TagEnd Other? when_tag+ else_tag? TagStart CaseEnd TagEnd -> ^(CASE expr when_tag+ ^(ELSE else_tag?))
;
when_tag
: TagStart When term ((Or | Comma) term)* TagEnd block -> ^(WHEN term+ block)
;
cycle_tag
: TagStart Cycle cycle_group expr (Comma expr)* TagEnd -> ^(CYCLE cycle_group expr+)
;
cycle_group
: ((expr Col)=> expr Col)? -> ^(GROUP expr?)
;
for_tag
: for_array
| for_range
;
for_array
: TagStart ForStart Id In lookup attribute* TagEnd
for_block
TagStart ForEnd TagEnd
-> ^(FOR_ARRAY Id lookup for_block ^(ATTRIBUTES attribute*))
;
for_range
: TagStart ForStart Id In OPar expr DotDot expr CPar attribute* TagEnd
block
TagStart ForEnd TagEnd
-> ^(FOR_RANGE Id expr expr block ^(ATTRIBUTES attribute*))
;
for_block
: a=block (TagStart Else TagEnd b=block)? -> ^(FOR_BLOCK block block?)
;
attribute
: Id Col expr -> ^(Id expr)
;
table_tag
: TagStart TableStart Id In lookup attribute* TagEnd block TagStart TableEnd TagEnd -> ^(TABLE Id lookup block ^(ATTRIBUTES attribute*))
;
capture_tag
: TagStart CaptureStart ( Id TagEnd block TagStart CaptureEnd TagEnd -> ^(CAPTURE Id block)
| Str TagEnd block TagStart CaptureEnd TagEnd -> ^(CAPTURE Id[$Str.text] block)
)
;
include_tag
: TagStart Include ( {this.flavor == Flavor.JEKYLL}?=>
file_name_as_str TagEnd -> ^(INCLUDE file_name_as_str ^(WITH ))
| a=Str (With b=Str)? TagEnd -> ^(INCLUDE $a ^(WITH $b?))
)
;
break_tag
: TagStart Break TagEnd -> Break
;
continue_tag
: TagStart Continue TagEnd -> Continue
;
output
: OutStart expr filter* OutEnd -> ^(OUTPUT expr ^(FILTERS filter*))
;
filter
: Pipe Id params? -> ^(FILTER Id ^(PARAMS params?))
;
params
: Col expr (Comma expr)* -> expr+
;
assignment
: TagStart Assign Id EqSign expr filter? TagEnd -> ^(ASSIGNMENT Id filter? expr)
;
expr
: or_expr
;
or_expr
: and_expr (Or^ and_expr)*
;
and_expr
: contains_expr (And^ contains_expr)*
;
contains_expr
: eq_expr (Contains^ eq_expr)?
;
eq_expr
: rel_expr ((Eq | NEq)^ rel_expr)*
;
rel_expr
: term ((LtEq | Lt | GtEq | Gt)^ term)?
;
term
: DoubleNum
| LongNum
| Str
| True
| False
| Nil
| NoSpace+ -> NO_SPACE[$text]
| lookup
| Empty
| OPar expr CPar -> expr
;
lookup
: FluentPathExpression -> ^(LOOKUP FluentPathExpression)
;
id
: Id
| Continue -> Id[$Continue.text]
;
id2
: id
| Empty -> Id[$Empty.text]
| CaptureStart -> Id[$CaptureStart.text]
| CaptureEnd -> Id[$CaptureEnd.text]
| CommentStart -> Id[$CommentStart.text]
| CommentEnd -> Id[$CommentEnd.text]
| RawStart -> Id[$RawStart.text]
| RawEnd -> Id[$RawEnd.text]
| IfStart -> Id[$IfStart.text]
| Elsif -> Id[$Elsif.text]
| IfEnd -> Id[$IfEnd.text]
| UnlessStart -> Id[$UnlessStart.text]
| UnlessEnd -> Id[$UnlessEnd.text]
| Else -> Id[$Else.text]
| Contains -> Id[$Contains.text]
| CaseStart -> Id[$CaseStart.text]
| CaseEnd -> Id[$CaseEnd.text]
| When -> Id[$When.text]
| Cycle -> Id[$Cycle.text]
| ForStart -> Id[$ForStart.text]
| ForEnd -> Id[$ForEnd.text]
| In -> Id[$In.text]
| And -> Id[$And.text]
| Or -> Id[$Or.text]
| TableStart -> Id[$TableStart.text]
| TableEnd -> Id[$TableEnd.text]
| Assign -> Id[$Assign.text]
| True -> Id[$True.text]
| False -> Id[$False.text]
| Nil -> Id[$Nil.text]
| Include -> Id[$Include.text]
| With -> Id[$With.text]
| EndId -> Id[$EndId.text]
| Break -> Id[$Break.text]
;
file_name_as_str
: other_than_tag_end -> Str[$text]
;
other_than_tag_end
: ~TagEnd+
;
/* lexer rules */
OutStart : '{{' {inTag=true;};
OutEnd : '}}' {inTag=false;};
TagStart : '{%' {inTag=true;};
TagEnd : '%}' {inTag=false;};
Str : {inTag}?=> (SStr | DStr);
DotDot : {inTag}?=> '..';
Dot : {inTag}?=> '.';
NEq : {inTag}?=> '!=' | '<>';
Eq : {inTag}?=> '==';
EqSign : {inTag}?=> '=';
GtEq : {inTag}?=> '>=';
Gt : {inTag}?=> '>';
LtEq : {inTag}?=> '<=';
Lt : {inTag}?=> '<';
Minus : {inTag}?=> '-';
Pipe : {inTag}?=> '|';
Col : {inTag}?=> ':';
Comma : {inTag}?=> ',';
OPar : {inTag}?=> '(';
CPar : {inTag}?=> ')';
OBr : {inTag}?=> '[';
CBr : {inTag}?=> ']';
QMark : {inTag}?=> '?';
DoubleNum : {inTag}?=> '-'? Digit+ ( {input.LA(1) == '.' && input.LA(2) != '.'}?=> '.' Digit*
| {$type = LongNum;}
);
LongNum : {inTag}?=> '-'? Digit+;
WS : {inTag}?=> (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
FluentPathExpression
: {inTag}?=> (Letter | '_') (Letter | '_' | '-' | Digit | '.' | '[' | ']' | '(' | ')' )*
{
if($text.equals("capture")) $type = CaptureStart;
else if($text.equals("endcapture")) $type = CaptureEnd;
else if($text.equals("comment")) $type = CommentStart;
else if($text.equals("endcomment")) $type = CommentEnd;
else if($text.equals("raw")) { $type = RawStart; inRaw = true; }
else if($text.equals("endraw")) { $type = RawEnd; inRaw = false; }
else if($text.equals("if")) $type = IfStart;
else if($text.equals("elsif")) $type = Elsif;
else if($text.equals("endif")) $type = IfEnd;
else if($text.equals("unless")) $type = UnlessStart;
else if($text.equals("endunless")) $type = UnlessEnd;
else if($text.equals("else")) $type = Else;
else if($text.equals("contains")) $type = Contains;
else if($text.equals("case")) $type = CaseStart;
else if($text.equals("endcase")) $type = CaseEnd;
else if($text.equals("when")) $type = When;
else if($text.equals("cycle")) $type = Cycle;
else if($text.equals("for")) $type = ForStart;
else if($text.equals("endfor")) $type = ForEnd;
else if($text.equals("in")) $type = In;
else if($text.equals("and")) $type = And;
else if($text.equals("or")) $type = Or;
else if($text.equals("tablerow")) $type = TableStart;
else if($text.equals("endtablerow")) $type = TableEnd;
else if($text.equals("assign")) $type = Assign;
else if($text.equals("true")) $type = True;
else if($text.equals("false")) $type = False;
else if($text.equals("nil")) $type = Nil;
else if($text.equals("null")) $type = Nil;
else if($text.equals("include")) $type = Include;
else if($text.equals("with")) $type = With;
else if($text.startsWith("end")) $type = EndId;
else if($text.equals("break")) $type = Break;
else if($text.startsWith("continue")) $type = Continue;
else if($text.startsWith("empty")) $type = Empty;
}
;
Id
: {inTag}?=> (Letter | '_') (Letter | '_' | '-' | Digit)*
{
if($text.equals("capture")) $type = CaptureStart;
else if($text.equals("endcapture")) $type = CaptureEnd;
else if($text.equals("comment")) $type = CommentStart;
else if($text.equals("endcomment")) $type = CommentEnd;
else if($text.equals("raw")) { $type = RawStart; inRaw = true; }
else if($text.equals("endraw")) { $type = RawEnd; inRaw = false; }
else if($text.equals("if")) $type = IfStart;
else if($text.equals("elsif")) $type = Elsif;
else if($text.equals("endif")) $type = IfEnd;
else if($text.equals("unless")) $type = UnlessStart;
else if($text.equals("endunless")) $type = UnlessEnd;
else if($text.equals("else")) $type = Else;
else if($text.equals("contains")) $type = Contains;
else if($text.equals("case")) $type = CaseStart;
else if($text.equals("endcase")) $type = CaseEnd;
else if($text.equals("when")) $type = When;
else if($text.equals("cycle")) $type = Cycle;
else if($text.equals("for")) $type = ForStart;
else if($text.equals("endfor")) $type = ForEnd;
else if($text.equals("in")) $type = In;
else if($text.equals("and")) $type = And;
else if($text.equals("or")) $type = Or;
else if($text.equals("tablerow")) $type = TableStart;
else if($text.equals("endtablerow")) $type = TableEnd;
else if($text.equals("assign")) $type = Assign;
else if($text.equals("true")) $type = True;
else if($text.equals("false")) $type = False;
else if($text.equals("nil")) $type = Nil;
else if($text.equals("null")) $type = Nil;
else if($text.equals("include")) $type = Include;
else if($text.equals("with")) $type = With;
else if($text.startsWith("end")) $type = EndId;
else if($text.equals("break")) $type = Break;
else if($text.startsWith("continue")) $type = Continue;
else if($text.startsWith("empty")) $type = Empty;
}
;
Other
: ({!inTag && !openTagAhead()}?=> . )+
| ({!inTag && inRaw && !openRawEndTagAhead()}?=> . )+
;
NoSpace
: ~(' ' | '\t' | '\r' | '\n')
;
/* fragment rules */
fragment Letter : 'a'..'z' | 'A'..'Z';
fragment Digit : '0'..'9';
fragment SStr : '\'' ~'\''* '\'' {setText(strip($text, true));};
fragment DStr : '"' ~'"'* '"' {setText(strip($text, false));};
fragment CommentStart : 'CommentStart';
fragment CommentEnd : 'CommentEnd';
fragment RawStart : 'RawStart';
fragment RawEnd : 'RawEnd';
fragment IfStart : 'IfStart';
fragment IfEnd : 'IfEnd';
fragment Elsif : 'Elsif';
fragment UnlessStart : 'UnlessStart';
fragment UnlessEnd : 'UnlessEnd';
fragment Else : 'Else';
fragment Contains : 'contains';
fragment CaseStart : 'CaseStart';
fragment CaseEnd : 'CaseEnd';
fragment When : 'When';
fragment Cycle : 'Cycle';
fragment ForStart : 'ForStart';
fragment ForEnd : 'ForEnd';
fragment In : 'In';
fragment And : 'And';
fragment Or : 'Or';
fragment TableStart : 'TableStart';
fragment TableEnd : 'TableEnd';
fragment Assign : 'Assign';
fragment True : 'True';
fragment False : 'False';
fragment Nil : 'Nil';
fragment Include : 'Include';
fragment With : 'With';
fragment CaptureStart : 'CaptureStart';
fragment CaptureEnd : 'CaptureEnd';
fragment EndId : 'EndId';
fragment Break : 'Break';
fragment Continue : 'Continue';
fragment Empty : 'Empty';

View File

@ -1,248 +0,0 @@
package ca.uhn.fhir.narrative.template;
import java.util.Collection;
import java.util.List;
import ca.uhn.fhir.narrative.template.nodes.AtomNode;
/**
* An abstract class the Filter and Tag classes extend.
* <p/>
* It houses some utility methods easily available for said
* classes.
*/
public abstract class LValue {
/**
* Returns true iff a and b are equals, where (int) 1 is
* equals to (double) 1.0
*
* @param a
* the first object to compare.
* @param b
* the second object to compare.
*
* @return true iff a and b are equals, where (int) 1 is
* equals to (double) 1.0
*/
public static boolean areEqual(Object a, Object b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
// TODO refactor the instance-ofs below
if (a instanceof Number && b instanceof Number) {
double delta = ((Number) a).doubleValue() - ((Number) b).doubleValue();
// To account for floating point rounding errors, return true if
// the difference between double a and double b is very small.
return Math.abs(delta) < 0.00000000001;
}
if (AtomNode.isEmpty(a) && (b instanceof CharSequence)) {
return ((CharSequence)b).length() == 0;
}
if (AtomNode.isEmpty(b) && (a instanceof CharSequence)) {
return ((CharSequence)a).length() == 0;
}
if (AtomNode.isEmpty(a) && (b instanceof Collection)) {
return ((Collection)b).size() == 0;
}
if (AtomNode.isEmpty(b) && (a instanceof Collection)) {
return ((Collection)a).size() == 0;
}
if (AtomNode.isEmpty(a) && (b.getClass().isArray())) {
return ((Object[])b).length == 0;
}
if (AtomNode.isEmpty(b) && (a.getClass().isArray())) {
return ((Object[])a).length == 0;
}
return a.equals(b);
}
/**
* Returns this value as an array. If a value is already an array,
* it is casted to a `Object[]`, if it's a `java.util.List`, it is
* converted to an array and in all other cases, `value` is simply
* returned as an `Object[]` with a single value in it.
*
* @param value
* the value to convert/cast to an array.
*
* @return this value as an array.
*/
public Object[] asArray(Object value) {
if(value == null) {
return null;
}
if (value.getClass().isArray()) {
return (Object[]) value;
}
if (value instanceof List) {
return ((List) value).toArray();
}
return new Object[]{value};
}
/**
* Convert `value` to a boolean. Note that only `nil` and `false`
* are `false`, all other values are `true`.
*
* @param value
* the value to convert.
*
* @return `value` as a boolean.
*/
public boolean asBoolean(Object value) {
if (value == null) {
return false;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
return true;
}
/**
* Returns `value` as a Number. Strings will be coerced into
* either a Long or Double.
*
* @param value
* the value to cast to a Number.
*
* @return `value` as a Number.
*
* @throws NumberFormatException when `value` is a String which could
* not be parsed as a Long or Double.
*/
public Number asNumber(Object value) throws NumberFormatException {
if(value instanceof Number) {
return (Number) value;
}
String str = String.valueOf(value);
return str.matches("\\d+") ? Long.valueOf(str) : Double.valueOf(str);
}
/**
* Returns `value` as a String.
*
* @param value
* the value to convert to a String.
*
* @return `value` as a String.
*/
public String asString(Object value) {
if (value == null) {
return "";
}
if (!this.isArray(value)) {
return String.valueOf(value);
}
Object[] array = this.asArray(value);
StringBuilder builder = new StringBuilder();
for (Object obj : array) {
builder.append(this.asString(obj));
}
return builder.toString();
}
/**
* Returns true iff `value` is an array or a java.util.List.
*
* @param value
* the value to check.
*
* @return true iff `value` is an array or a java.util.List.
*/
public boolean isArray(Object value) {
return value != null && (value.getClass().isArray() || value instanceof List);
}
/**
* Returns true iff `value` is a whole number (Integer or Long).
*
* @param value
* the value to check.
*
* @return true iff `value` is a whole number (Integer or Long).
*/
public boolean isInteger(Object value) {
return value != null && (value instanceof Long || value instanceof Integer);
}
/**
* Returns true iff `value` is a Number.
*
* @param value
* the value to check.
*
* @return true iff `value` is a Number.
*/
public boolean isNumber(Object value) {
if(value == null) {
return false;
}
if(value instanceof Number) {
return true;
}
// valid Long?
if(String.valueOf(value).matches("\\d+")) {
return true;
}
try {
// valid Double?
Double.parseDouble(String.valueOf(value));
} catch(Exception e) {
return false;
}
return true;
}
/**
* Returns true iff `value` is a String.
*
* @param value
* the value to check.
*
* @return true iff `value` is a String.
*/
public boolean isString(Object value) {
return value != null && value instanceof CharSequence;
}
}

View File

@ -1,249 +0,0 @@
package ca.uhn.fhir.narrative.template;
import ca.uhn.fhir.i18n.Msg;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import ca.uhn.fhir.narrative.template.filters.Filter;
import ca.uhn.fhir.narrative.template.nodes.LNode;
import ca.uhn.fhir.narrative.template.nodes.LiquidWalker;
import ca.uhn.fhir.narrative.template.parser.Flavor;
import ca.uhn.fhir.narrative.template.parser.LiquidLexer;
import ca.uhn.fhir.narrative.template.parser.LiquidParser;
import ca.uhn.fhir.narrative.template.tags.Tag;
/**
* The main class of this library. Use one of its static
* <code>parse(...)</code> to get a hold of a reference.
* <p/>
* Also see: https://github.com/Shopify/liquid
*/
public class Template {
/**
* The root of the AST denoting the Liquid input source.
*/
private final CommonTree root;
/**
* This instance's tags.
*/
private final Map<String, Tag> tags;
/**
* This instance's filters.
*/
private final Map<String, Filter> filters;
private final Flavor flavor;
/**
* Creates a new Template instance from a given input.
* @param input
* the file holding the Liquid source.
* @param tags
* the tags this instance will make use of.
* @param filters
* the filters this instance will make use of.
*/
private Template(String input, Map<String, Tag> tags, Map<String, Filter> filters) {
this(input, tags, filters, Flavor.LIQUID);
}
private Template(String input, Map<String, Tag> tags, Map<String, Filter> filters, Flavor flavor) {
this.tags = tags;
this.filters = filters;
this.flavor = flavor;
LiquidLexer lexer = new LiquidLexer(new ANTLRStringStream(input));
LiquidParser parser = new LiquidParser(flavor, new CommonTokenStream(lexer));
try {
root = (CommonTree) parser.parse().getTree();
}
catch (RecognitionException e) {
throw new RuntimeException(Msg.code(712) + "could not parse input: " + input, e);
}
}
/**
* Creates a new Template instance from a given file.
*
* @param file
* the file holding the Liquid source.
*/
private Template(File file, Map<String, Tag> tags, Map<String, Filter> filters) throws IOException {
this(file, tags, filters, Flavor.LIQUID);
}
private Template(File file, Map<String, Tag> tags, Map<String, Filter> filters, Flavor flavor) throws IOException {
this.tags = tags;
this.filters = filters;
this.flavor = flavor;
try {
LiquidLexer lexer = new LiquidLexer(new ANTLRFileStream(file.getAbsolutePath()));
LiquidParser parser = new LiquidParser(flavor, new CommonTokenStream(lexer));
root = (CommonTree) parser.parse().getTree();
}
catch (RecognitionException e) {
throw new RuntimeException(Msg.code(713) + "could not parse input from " + file, e);
}
}
/**
* Returns the root of the AST of the parsed input.
*
* @return the root of the AST of the parsed input.
*/
public CommonTree getAST() {
return root;
}
/**
* Returns a new Template instance from a given input string.
*
* @param input
* the input string holding the Liquid source.
*
* @return a new Template instance from a given input string.
*/
public static Template parse(String input) {
return new Template(input, Tag.getTags(), Filter.getFilters());
}
/**
* Returns a new Template instance from a given input file.
*
* @param file
* the input file holding the Liquid source.
*
* @return a new Template instance from a given input file.
*/
public static Template parse(File file) throws IOException {
return parse(file, Flavor.LIQUID);
}
public static Template parse(File file, Flavor flavor) throws IOException {
return new Template(file, Tag.getTags(), Filter.getFilters(), flavor);
}
public Template with(Tag tag) {
this.tags.put(tag.name, tag);
return this;
}
public Template with(Filter filter) {
this.filters.put(filter.name, filter);
return this;
}
/**
* Renders the template.
*
* @param context
* a Map denoting the (possibly nested)
* variables that can be used in this
* Template.
*
* @return a string denoting the rendered template.
*/
public String render(Map<String, Object> context) {
LiquidWalker walker = new LiquidWalker(new CommonTreeNodeStream(root), this.tags, this.filters, this.flavor);
try {
LNode node = walker.walk();
Object rendered = node.render(context);
return rendered == null ? "" : String.valueOf(rendered);
}
catch (Exception e) {
throw new RuntimeException(Msg.code(714) + e);
}
}
/**
* Returns a string representation of the AST of the parsed
* input source.
*
* @return a string representation of the AST of the parsed
* input source.
*/
public String toStringAST() {
StringBuilder builder = new StringBuilder();
walk(root, builder);
return builder.toString();
}
/**
* Walks a (sub) tree of the root of the input source and builds
* a string representation of the structure of the AST.
* <p/>
* Note that line breaks and multiple white space characters are
* trimmed to a single white space character.
*
* @param tree
* the (sub) tree.
* @param builder
* the StringBuilder to fill.
*/
@SuppressWarnings("unchecked")
private void walk(CommonTree tree, StringBuilder builder) {
List<CommonTree> firstStack = new ArrayList<CommonTree>();
firstStack.add(tree);
List<List<CommonTree>> childListStack = new ArrayList<List<CommonTree>>();
childListStack.add(firstStack);
while (!childListStack.isEmpty()) {
List<CommonTree> childStack = childListStack.get(childListStack.size() - 1);
if (childStack.isEmpty()) {
childListStack.remove(childListStack.size() - 1);
}
else {
tree = childStack.remove(0);
String indent = "";
for (int i = 0; i < childListStack.size() - 1; i++) {
indent += (childListStack.get(i).size() > 0) ? "| " : " ";
}
String tokenName = LiquidParser.tokenNames[tree.getType()];
String tokenText = tree.getText().replaceAll("\\s+", " ").trim();
builder.append(indent)
.append(childStack.isEmpty() ? "'- " : "|- ")
.append(tokenName)
.append(!tokenName.equals(tokenText) ? "='" + tokenText + "'" : "")
.append("\n");
if (tree.getChildCount() > 0) {
childListStack.add(new ArrayList<CommonTree>((List<CommonTree>) tree.getChildren()));
}
}
}
}
}

View File

@ -1,102 +0,0 @@
package ca.uhn.fhir.narrative.template;
import ca.uhn.fhir.i18n.Msg;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.antlr.runtime.tree.CommonTree;
import org.hl7.fhir.dstu3.exceptions.FHIRException;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.model.Base;
import org.hl7.fhir.dstu3.utils.FluentPathEngine;
import org.hl7.fhir.dstu3.utils.IWorkerContext;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.INarrative;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.FhirTerser;
public class TemplateNarrativeGenerator implements INarrativeGenerator {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TemplateNarrativeGenerator.class);
private FhirContext myFhirContext = FhirContext.forDstu3();
private IContextValidationSupport myValidationSupport = new DefaultProfileValidationSupport();
@Override
public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) {
// TODO Auto-generated method stub
}
public String processLiquid(FhirContext theContext, String theTemplate, IBaseResource theResource) {
Template template = Template.parse(theTemplate);
ourLog.info(template.toStringAST());
IWorkerContext ctx = new HapiWorkerContext(myFhirContext, myValidationSupport);
FluentPathEngine fluentPathEngine = new FluentPathEngine(ctx);
FhirTerser terser = new FhirTerser(theContext);
HashMap<String, Object> context = new HashMap<String, Object>();
context.put("context", theResource);
context.put("terser", terser);
context.put("fpEngine", fluentPathEngine);
return template.render(context);
}
class MyContextMap extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
private List<Base> myContext;
private IBaseResource myResource;
MyContextMap(IBaseResource theResource) {
myResource = theResource;
myContext = null;
}
MyContextMap(Base theContext, IBaseResource theResource) {
myContext = Collections.singletonList(theContext);
myResource=theResource;
}
MyContextMap(List<Base> theContext, IBaseResource theResource) {
myContext = (theContext);
myResource=theResource;
}
@Override
public Object get(Object theKey) {
ourLog.info("Requesting key: {}", theKey);
if (theKey.equals("resource")) {
return new MyContextMap((Base) myResource, myResource);
}
IWorkerContext ctx = new HapiWorkerContext(myFhirContext, myValidationSupport);
try {
FluentPathEngine fluentPathEngine = new FluentPathEngine(ctx);
List<Base> evaluated = new ArrayList<Base>();
for (Base nextContext : myContext) {
evaluated.addAll(fluentPathEngine.evaluate(nextContext, (String)theKey));
}
return new MyContextMap(evaluated, myResource);
} catch (FHIRException e) {
throw new InternalErrorException(Msg.code(711) + "Failed to process expression: " + theKey, e);
}
}
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Append extends Filter {
/*
* (Object) append(input, string)
*
* add one string to another
*/
@Override
public Object apply(Object value, Object... params) {
return super.asString(value) + super.asString(super.get(0, params));
}
}

View File

@ -1,23 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Capitalize extends Filter {
/*
* (Object) capitalize(input)
*
* capitalize words in the input sentence
*/
@Override
public Object apply(Object value, Object... params) {
String original = super.asString(value);
if (original.isEmpty()) {
return original;
}
char first = original.charAt(0);
return Character.toUpperCase(first) + original.substring(1);
}
}

View File

@ -1,256 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import ca.uhn.fhir.i18n.Msg;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
class Date extends Filter {
private static Locale locale = Locale.ENGLISH;
private static Set<String> datePatterns = new HashSet<String>();
private final static java.util.Map<Character, SimpleDateFormat> LIQUID_TO_JAVA_FORMAT =
new java.util.HashMap<Character, SimpleDateFormat>();
static {
addDatePattern("yyyy-MM-dd HH:mm:ss");
addDatePattern("EEE MMM ddhh:mm:ss yyyy");
init();
}
/*
* (Object) date(input, format)
*
* Reformat a date
*
* %a - The abbreviated weekday name (``Sun'')
* %A - The full weekday name (``Sunday'')
* %b - The abbreviated month name (``Jan'')
* %B - The full month name (``January'')
* %c - The preferred local date and time representation
* %d - Day of the month (01..31)
* %H - Hour of the day, 24-hour clock (00..23)
* %I - Hour of the day, 12-hour clock (01..12)
* %j - Day of the year (001..366)
* %m - Month of the year (01..12)
* %M - Minute of the hour (00..59)
* %p - Meridian indicator (``AM'' or ``PM'')
* %S - Second of the minute (00..60)
* %U - Week number of the current year,
* starting with the first Sunday as the first
* day of the first week (00..53)
* %W - Week number of the current year,
* starting with the first Monday as the first
* day of the first week (00..53)
* %w - Day of the week (Sunday is 0, 0..6)
* %x - Preferred representation for the date alone, no time
* %X - Preferred representation for the time alone, no date
* %y - Year without a century (00..99)
* %Y - Year with century
* %Z - Time zone name
* %% - Literal ``%'' character
*/
@Override
public Object apply(Object value, Object... params) {
try {
final Long seconds;
if(super.asString(value).equals("now")) {
seconds = System.currentTimeMillis() / 1000L;
}
else if(super.isNumber(value)) {
// No need to divide this by 1000, the param is expected to be in seconds already!
seconds = super.asNumber(value).longValue();
}
else {
seconds = trySeconds(super.asString(value)); // formatter.parse(super.asString(value)).getTime() / 1000L;
if(seconds == null) {
return value;
}
}
final java.util.Date date = new java.util.Date(seconds * 1000L);
final String format = super.asString(super.get(0, params));
if(format == null || format.trim().isEmpty()) {
return value;
}
final java.util.Calendar calendar = java.util.Calendar.getInstance();
calendar.setTime(date);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < format.length(); i++) {
char ch = format.charAt(i);
if (ch == '%') {
i++;
if (i == format.length()) {
// a trailing (single) '%' sign: just append it
builder.append("%");
break;
}
char next = format.charAt(i);
SimpleDateFormat javaFormat = LIQUID_TO_JAVA_FORMAT.get(next);
if (javaFormat == null) {
// no valid date-format: append the '%' and the 'next'-char
builder.append("%").append(next);
}
else {
builder.append(javaFormat.format(date));
}
}
else {
builder.append(ch);
}
}
return builder.toString();
}
catch (Exception e) {
return value;
}
}
private static void init() {
// %% - Literal ``%'' character
LIQUID_TO_JAVA_FORMAT.put('%', new SimpleDateFormat("%", locale));
// %a - The abbreviated weekday name (``Sun'')
LIQUID_TO_JAVA_FORMAT.put('a', new SimpleDateFormat("EEE", locale));
// %A - The full weekday name (``Sunday'')
LIQUID_TO_JAVA_FORMAT.put('A', new SimpleDateFormat("EEEE", locale));
// %b - The abbreviated month name (``Jan'')
LIQUID_TO_JAVA_FORMAT.put('b', new SimpleDateFormat("MMM", locale));
LIQUID_TO_JAVA_FORMAT.put('h', new SimpleDateFormat("MMM", locale));
// %B - The full month name (``January'')
LIQUID_TO_JAVA_FORMAT.put('B', new SimpleDateFormat("MMMM", locale));
// %c - The preferred local date and time representation
LIQUID_TO_JAVA_FORMAT.put('c', new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", locale));
// %d - Day of the month (01..31)
LIQUID_TO_JAVA_FORMAT.put('d', new SimpleDateFormat("dd", locale));
// %H - Hour of the day, 24-hour clock (00..23)
LIQUID_TO_JAVA_FORMAT.put('H', new SimpleDateFormat("HH", locale));
// %I - Hour of the day, 12-hour clock (01..12)
LIQUID_TO_JAVA_FORMAT.put('I', new SimpleDateFormat("hh", locale));
// %j - Day of the year (001..366)
LIQUID_TO_JAVA_FORMAT.put('j', new SimpleDateFormat("DDD", locale));
// %m - Month of the year (01..12)
LIQUID_TO_JAVA_FORMAT.put('m', new SimpleDateFormat("MM", locale));
// %M - Minute of the hour (00..59)
LIQUID_TO_JAVA_FORMAT.put('M', new SimpleDateFormat("mm", locale));
// %p - Meridian indicator (``AM'' or ``PM'')
LIQUID_TO_JAVA_FORMAT.put('p', new SimpleDateFormat("a", locale));
// %S - Second of the minute (00..60)
LIQUID_TO_JAVA_FORMAT.put('S', new SimpleDateFormat("ss", locale));
// %U - Week number of the current year,
// starting with the first Sunday as the first
// day of the first week (00..53)
LIQUID_TO_JAVA_FORMAT.put('U', new SimpleDateFormat("ww", locale));
// %W - Week number of the current year,
// starting with the first Monday as the first
// day of the first week (00..53)
LIQUID_TO_JAVA_FORMAT.put('W', new SimpleDateFormat("ww", locale));
// %w - Day of the week (Sunday is 0, 0..6)
LIQUID_TO_JAVA_FORMAT.put('w', new SimpleDateFormat("F", locale));
// %x - Preferred representation for the date alone, no time
LIQUID_TO_JAVA_FORMAT.put('x', new SimpleDateFormat("MM/dd/yy", locale));
// %X - Preferred representation for the time alone, no date
LIQUID_TO_JAVA_FORMAT.put('X', new SimpleDateFormat("HH:mm:ss", locale));
// %y - Year without a century (00..99)
LIQUID_TO_JAVA_FORMAT.put('y', new SimpleDateFormat("yy", locale));
// %Y - Year with century
LIQUID_TO_JAVA_FORMAT.put('Y', new SimpleDateFormat("yyyy", locale));
// %Z - Time zone name
LIQUID_TO_JAVA_FORMAT.put('Z', new SimpleDateFormat("z", locale));
}
/**
* Changes the locale.
*
* @param locale the new locale.
*/
public static void setLocale(Locale locale) {
Date.locale = locale;
init();
}
/**
* Adds a new Date-pattern to be used when parsing a string to a Date.
*
* @param pattern the pattern.
*/
public static void addDatePattern(String pattern) {
if(pattern == null) {
throw new NullPointerException(Msg.code(725) + "date-pattern cannot be null");
}
datePatterns.add(pattern);
}
/**
* Removed a Date-pattern to be used when parsing a string to a Date.
*
* @param pattern the pattern.
*/
public static void removeDatePattern(String pattern) {
datePatterns.remove(pattern);
}
/*
* Try to parse `str` into a Date and return this Date as seconds
* since EPOCH, or null if it could not be parsed.
*/
private Long trySeconds(String str) {
for(String pattern : datePatterns) {
SimpleDateFormat parser = new SimpleDateFormat(pattern, locale);
try {
long milliseconds = parser.parse(str).getTime();
return milliseconds / 1000L;
}
catch(Exception e) {
// Just ignore and try the next pattern in `datePatterns`.
}
}
// Could not parse the string into a meaningful date, return null.
return null;
}
}

View File

@ -1,31 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Divided_By extends Filter {
/*
* divided_by(input, operand)
*
* division
*/
@Override
public Object apply(Object value, Object... params) {
if(value == null) {
value = 0L;
}
super.checkParams(params, 1);
Object rhsObj = params[0];
if(super.asNumber(rhsObj).doubleValue() == 0.0) {
throw new RuntimeException(Msg.code(724) + "Liquid error: divided by 0");
}
if (super.isInteger(value) && super.isInteger(rhsObj)) {
return super.asNumber(value).longValue() / super.asNumber(rhsObj).longValue();
}
return super.asNumber(value).doubleValue() / super.asNumber(rhsObj).doubleValue();
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Downcase extends Filter {
/*
* downcase(input)
*
* convert a input string to DOWNCASE
*/
@Override
public Object apply(Object value, Object... params) {
return super.asString(value).toLowerCase();
}
}

View File

@ -1,20 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Escape extends Filter {
/*
* escape(input)
*
* escape a string
*/
@Override
public Object apply(Object value, Object... params) {
String str = super.asString(value);
return str.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;");
}
}

View File

@ -1,21 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Escape_Once extends Filter {
/*
* escape_once(input)
*
* returns an escaped version of html without affecting
* existing escaped entities
*/
@Override
public Object apply(Object value, Object... params) {
String str = super.asString(value);
return str.replaceAll("&(?!([a-zA-Z]+|#[0-9]+|#x[0-9A-Fa-f]+);)", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;");
}
}

View File

@ -1,170 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Output markup takes filters. Filters are simple methods. The first
* parameter is always the output of the left side of the filter. The
* return value of the filter will be the new left value when the next
* filter is run. When there are no more filters, the template will
* receive the resulting string.
* <p/>
* -- https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
*/
public abstract class Filter extends LValue {
/**
* A map holding all filters.
*/
private static final Map<String, Filter> FILTERS = new HashMap<String, Filter>();
static {
// Initialize all standard filters.
registerFilter(new Append());
registerFilter(new Capitalize());
registerFilter(new Date());
registerFilter(new Divided_By());
registerFilter(new Downcase());
registerFilter(new Escape());
registerFilter(new Escape_Once());
registerFilter(new First());
registerFilter(new H());
registerFilter(new Join());
registerFilter(new Last());
registerFilter(new ca.uhn.fhir.narrative.template.filters.Map());
registerFilter(new Minus());
registerFilter(new Modulo());
registerFilter(new Newline_To_Br());
registerFilter(new Plus());
registerFilter(new Prepend());
registerFilter(new Remove());
registerFilter(new Remove_First());
registerFilter(new Replace());
registerFilter(new Replace_First());
registerFilter(new Size());
registerFilter(new Sort());
registerFilter(new Split());
registerFilter(new Strip_HTML());
registerFilter(new Strip_Newlines());
registerFilter(new Times());
registerFilter(new Truncate());
registerFilter(new Truncatewords());
registerFilter(new Upcase());
}
/**
* The name of the filter.
*/
public final String name;
/**
* Used for all package protected filters in the liqp.filters-package
* whose name is their class name lower cased.
*/
protected Filter() {
this.name = this.getClass().getSimpleName().toLowerCase();
}
/**
* Creates a new instance of a Filter.
*
* @param name
* the name of the filter.
*/
public Filter(String name) {
this.name = name;
}
/**
* Applies the filter on the 'value'.
*
* @param value
* the string value `AAA` in: `{{ 'AAA' | f:1,2,3 }}`
* @param params
* the values [1, 2, 3] in: `{{ 'AAA' | f:1,2,3 }}`
*
* @return the result of the filter.
*/
public abstract Object apply(Object value, Object... params);
/**
* Check the number of parameters and throws an exception if needed.
*
* @param params
* the parameters to check.
* @param expected
* the expected number of parameters.
*/
public final void checkParams(Object[] params, int expected) {
if(params == null || params.length != expected) {
throw new RuntimeException(Msg.code(726) + "Liquid error: wrong number of arguments (" +
(params == null ? 0 : params.length + 1) + " for " + (expected + 1) + ")");
}
}
/**
* Returns a value at a specific index from an array of parameters.
* If no such index exists, a RuntimeException is thrown.
*
* @param index
* the index of the value to be retrieved.
* @param params
* the values.
*
* @return a value at a specific index from an array of
* parameters.
*/
protected Object get(int index, Object... params) {
if (index >= params.length) {
throw new RuntimeException(Msg.code(727) + "error in filter '" + name +
"': cannot get param index: " + index +
" from: " + Arrays.toString(params));
}
return params[index];
}
/**
* Retrieves a filter with a specific name.
*
* @param name
* the name of the filter to retrieve.
*
* @return a filter with a specific name.
*/
public static Filter getFilter(String name) {
Filter filter = FILTERS.get(name);
if (filter == null) {
throw new RuntimeException(Msg.code(728) + "unknown filter: " + name);
}
return filter;
}
/**
* Returns all default filters.
*
* @return all default filters.
*/
public static Map<String, Filter> getFilters() {
return new HashMap<String, Filter>(FILTERS);
}
/**
* Registers a new filter.
*
* @param filter
* the filter to be registered.
*/
public static void registerFilter(Filter filter) {
FILTERS.put(filter.name, filter);
}
}

View File

@ -1,17 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class First extends Filter {
/*
* first(array)
*
* Get the first element of the passed in array
*/
@Override
public Object apply(Object value, Object... params) {
Object[] array = super.asArray(value);
return array.length == 0 ? null : super.asString(array[0]);
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class H extends Filter {
/*
* h(input)
*
* Alias for: escape
*/
@Override
public Object apply(Object value, Object... params) {
return Filter.getFilter("escape").apply(value, params);
}
}

View File

@ -1,35 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import java.util.Arrays;
class Join extends Filter {
/*
* join(input, glue = ' ')
*
* Join elements of the array with certain character between them
*/
@Override
public Object apply(Object value, Object... params) {
if (value == null) {
return "";
}
StringBuilder builder = new StringBuilder();
Object[] array = super.asArray(value);
String glue = params.length == 0 ? " " : super.asString(super.get(0, params));
for (int i = 0; i < array.length; i++) {
builder.append(super.asString(array[i]));
if (i < array.length - 1) {
builder.append(glue);
}
}
return builder.toString();
}
}

View File

@ -1,17 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Last extends Filter {
/*
* last(array)
*
* Get the last element of the passed in array
*/
@Override
public Object apply(Object value, Object... params) {
Object[] array = super.asArray(value);
return array.length == 0 ? null : super.asString(array[array.length - 1]);
}
}

View File

@ -1,39 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import java.util.ArrayList;
import java.util.List;
class Map extends Filter {
/*
* map(input, property)
*
* map/collect on a given property
*/
@Override
public Object apply(Object value, Object... params) {
if (value == null) {
return "";
}
List<Object> list = new ArrayList<Object>();
Object[] array = super.asArray(value);
String key = super.asString(super.get(0, params));
for (Object obj : array) {
java.util.Map map = (java.util.Map) obj;
Object val = map.get(key);
if (val != null) {
list.add(val);
}
}
return list.toArray(new Object[list.size()]);
}
}

View File

@ -1,27 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Minus extends Filter {
/*
* plus(input, operand)
*
* subtraction
*/
@Override
public Object apply(Object value, Object... params) {
if(value == null) {
value = 0L;
}
super.checkParams(params, 1);
Object rhsObj = params[0];
if (super.isInteger(value) && super.isInteger(rhsObj)) {
return super.asNumber(value).longValue() - super.asNumber(rhsObj).longValue();
}
return super.asNumber(value).doubleValue() - super.asNumber(rhsObj).doubleValue();
}
}

View File

@ -1,27 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Modulo extends Filter {
/*
* plus(input, operand)
*
* modulus
*/
@Override
public Object apply(Object value, Object... params) {
if(value == null) {
value = 0L;
}
super.checkParams(params, 1);
Object rhsObj = params[0];
if (super.isInteger(value) && super.isInteger(rhsObj)) {
return super.asNumber(value).longValue() % super.asNumber(rhsObj).longValue();
}
return super.asNumber(value).doubleValue() % super.asNumber(rhsObj).doubleValue();
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Newline_To_Br extends Filter {
/*
* newline_to_br(input)
*
* Add <br /> tags in front of all newlines in input string
*/
@Override
public Object apply(Object value, Object... params) {
return super.asString(value).replaceAll("[\n]", "<br />\n");
}
}

View File

@ -1,27 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Plus extends Filter {
/*
* plus(input, operand)
*
* addition
*/
@Override
public Object apply(Object value, Object... params) {
if(value == null) {
value = 0L;
}
super.checkParams(params, 1);
Object rhsObj = params[0];
if (super.isInteger(value) && super.isInteger(rhsObj)) {
return super.asNumber(value).longValue() + super.asNumber(rhsObj).longValue();
}
return super.asNumber(value).doubleValue() + super.asNumber(rhsObj).doubleValue();
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Prepend extends Filter {
/*
* (Object) append(input, string)
*
* add one string to another
*/
@Override
public Object apply(Object value, Object... params) {
return super.asString(super.get(0, params)) + super.asString(value);
}
}

View File

@ -1,23 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Remove extends Filter {
/*
* remove(input, string)
*
* remove a substring
*/
@Override
public Object apply(Object value, Object... params) {
String original = super.asString(value);
Object needle = super.get(0, params);
if (needle == null) {
throw new RuntimeException(Msg.code(718) + "invalid pattern: " + needle);
}
return original.replace(String.valueOf(needle), "");
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import ca.uhn.fhir.i18n.Msg;
import java.util.regex.Pattern;
class Remove_First extends Filter {
/*
* remove_first(input, string)
*
* remove the first occurrences of a substring
*/
@Override
public Object apply(Object value, Object... params) {
String original = super.asString(value);
Object needle = super.get(0, params);
if (needle == null) {
throw new RuntimeException(Msg.code(717) + "invalid pattern: " + needle);
}
return original.replaceFirst(Pattern.quote(String.valueOf(needle)), "");
}
}

View File

@ -1,35 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Replace extends Filter {
/*
* replace(input, string, replacement = '')
*
* Replace occurrences of a string with another
*/
@Override
public Object apply(Object value, Object... params) {
String original = super.asString(value);
Object needle = super.get(0, params);
String replacement = "";
if (needle == null) {
throw new RuntimeException(Msg.code(721) + "invalid pattern: " + needle);
}
if (params.length >= 2) {
Object obj = super.get(1, params);
if (obj == null) {
throw new RuntimeException(Msg.code(722) + "invalid replacement: " + needle);
}
replacement = super.asString(super.get(1, params));
}
return original.replace(String.valueOf(needle), String.valueOf(replacement));
}
}

View File

@ -1,40 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import ca.uhn.fhir.i18n.Msg;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Replace_First extends Filter {
/*
* replace_first(input, string, replacement = '')
*
* Replace the first occurrences of a string with another
*/
@Override
public Object apply(Object value, Object... params) {
String original = super.asString(value);
Object needle = super.get(0, params);
String replacement = "";
if (needle == null) {
throw new RuntimeException(Msg.code(719) + "invalid pattern: " + needle);
}
if (params.length >= 2) {
Object obj = super.get(1, params);
if (obj == null) {
throw new RuntimeException(Msg.code(720) + "invalid replacement: " + needle);
}
replacement = super.asString(super.get(1, params));
}
return original.replaceFirst(Pattern.quote(String.valueOf(needle)),
Matcher.quoteReplacement(replacement));
}
}

View File

@ -1,30 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Size extends Filter {
/*
* size(input)
*
* Return the size of an array or of an string
*/
@Override
public Object apply(Object value, Object... params) {
if (super.isArray(value)) {
return super.asArray(value).length;
}
if (super.isString(value)) {
return super.asString(value).length();
}
if (super.isNumber(value)) {
// we're only using 64 bit longs, no BigIntegers or the like.
// So just return 8 (the number of bytes in a long).
return 8;
}
// boolean or nil
return 0;
}
}

View File

@ -1,88 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import ca.uhn.fhir.i18n.Msg;
import java.util.*;
import java.util.Map;
class Sort extends Filter {
/*
* sort(input, property = nil)
*
* Sort elements of the array provide optional property with
* which to sort an array of hashes or drops
*/
@Override
public Object apply(Object value, Object... params) {
if (value == null) {
return "";
}
if(!super.isArray(value)) {
throw new RuntimeException(Msg.code(715) + "cannot sort: " + value);
}
Object[] array = super.asArray(value);
String property = params.length == 0 ? null : super.asString(params[0]);
List<Comparable> list = asComparableList(array, property);
Collections.sort(list);
return property == null ?
list.toArray(new Comparable[list.size()]) :
list.toArray(new SortableMap[list.size()]);
}
private List<Comparable> asComparableList(Object[] array, String property) {
List<Comparable> list = new ArrayList<Comparable>();
for (Object obj : array) {
if(obj instanceof java.util.Map && property != null) {
list.add(new SortableMap((java.util.Map<String, Comparable>)obj, property));
}
else {
list.add((Comparable) obj);
}
}
return list;
}
static class SortableMap extends HashMap<String, Comparable> implements Comparable<SortableMap> {
final String property;
SortableMap(java.util.Map<String, Comparable> map, String property) {
super.putAll(map);
this.property = property;
}
@Override
public int compareTo(SortableMap that) {
Comparable thisValue = this.get(property);
Comparable thatValue = that.get(property);
if(thisValue == null || thatValue == null) {
throw new RuntimeException(Msg.code(716) + "Liquid error: comparison of Hash with Hash failed");
}
return thisValue.compareTo(thatValue);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for(java.util.Map.Entry entry : super.entrySet()) {
builder.append(entry.getKey()).append(entry.getValue());
}
return builder.toString();
}
}
}

View File

@ -1,23 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
import java.util.regex.Pattern;
class Split extends Filter {
/*
* split(input, delimiter = ' ')
*
* Split a string on a matching pattern
*
* E.g. {{ "a~b" | split:'~' | first }} #=> 'a'
*/
@Override
public Object apply(Object value, Object... params) {
String original = super.asString(value);
String delimiter = super.asString(super.get(0, params));
return original.split("(?<!^)" + Pattern.quote(delimiter));
}
}

View File

@ -1,18 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Strip_HTML extends Filter {
/*
* strip_html(input)
*
* Remove all HTML tags from the string
*/
@Override
public Object apply(Object value, Object... params) {
throw new UnsupportedOperationException(Msg.code(723));
//
// String html = super.asString(value);
//
// return Jsoup.parse(html).text();
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Strip_Newlines extends Filter {
/*
* strip_newlines(input) click to toggle source
*
* Remove all newlines from the string
*/
@Override
public Object apply(Object value, Object... params) {
return super.asString(value).replaceAll("[\r\n]++", "");
}
}

View File

@ -1,27 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Times extends Filter {
/*
* times(input, operand)
*
* multiplication
*/
@Override
public Object apply(Object value, Object... params) {
if(value == null) {
value = 0L;
}
super.checkParams(params, 1);
Object rhsObj = params[0];
if (super.isInteger(value) && super.isInteger(rhsObj)) {
return super.asNumber(value).longValue() * super.asNumber(rhsObj).longValue();
}
return super.asNumber(value).doubleValue() * super.asNumber(rhsObj).doubleValue();
}
}

View File

@ -1,45 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Truncate extends Filter {
/*
* truncate(input, length = 50, truncate_string = "...")
*
* Truncate a string down to x characters
*/
@Override
public Object apply(Object value, Object... params) {
if (value == null) {
return "";
}
String text = super.asString(value);
int length = 50;
String truncateString = "...";
if (params.length >= 1) {
length = super.asNumber(super.get(0, params)).intValue();
}
if (params.length >= 2) {
truncateString = super.asString(super.get(1, params));
}
if (truncateString.length() >= length) {
return truncateString;
}
if (length == text.length()) {
return text;
}
if (length >= (text.length() + truncateString.length())) {
return text;
}
int remainingChars = length - truncateString.length();
return text.substring(0, remainingChars) + truncateString;
}
}

View File

@ -1,47 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Truncatewords extends Filter {
/*
* truncatewords(input, words = 15, truncate_string = "...")
*
* Truncate a string down to x words
*/
@Override
public Object apply(Object value, Object... params) {
if (value == null) {
return "";
}
String text = super.asString(value);
String[] words = text.split("\\s++");
int length = 15;
String truncateString = "...";
if (params.length >= 1) {
length = super.asNumber(super.get(0, params)).intValue();
}
if (params.length >= 2) {
truncateString = super.asString(super.get(1, params));
}
if (length >= words.length) {
return text;
}
return join(words, length) + truncateString;
}
private String join(String[] words, int length) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; i++) {
builder.append(words[i]).append(" ");
}
return builder.toString().trim();
}
}

View File

@ -1,15 +0,0 @@
package ca.uhn.fhir.narrative.template.filters;
class Upcase extends Filter {
/*
* upcase(input)
*
* convert a input string to UPCASE
*/
@Override
public Object apply(Object value, Object... params) {
return super.asString(value).toUpperCase();
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class AndNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public AndNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return super.asBoolean(a) && super.asBoolean(b);
}
}

View File

@ -1,24 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import java.util.Map;
public class AtomNode implements LNode {
public static final AtomNode EMPTY = new AtomNode(new Object());
private Object value;
public AtomNode(Object value) {
this.value = value;
}
public static boolean isEmpty(Object o) {
return o == EMPTY.value;
}
@Override
public Object render(Map<String, Object> context) {
return value;
}
}

View File

@ -1,23 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import java.util.Map;
class AttributeNode implements LNode {
private LNode key;
private LNode value;
public AttributeNode(LNode key, LNode value) {
this.key = key;
this.value = value;
}
@Override
public Object render(Map<String, Object> context) {
return new Object[]{
key.render(context),
value.render(context)
};
}
}

View File

@ -1,58 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import ca.uhn.fhir.narrative.template.tags.Tag;
public class BlockNode implements LNode {
private List<LNode> children;
public BlockNode() {
children = new ArrayList<LNode>();
}
public void add(LNode node) {
children.add(node);
}
public List<LNode> getChildren() {
return new ArrayList<LNode>(children);
}
@Override
public Object render(Map<String, Object> context) {
StringBuilder builder = new StringBuilder();
for (LNode node : children) {
Object value = node.render(context);
if(value == null) {
continue;
}
if(value == Tag.Statement.BREAK || value == Tag.Statement.CONTINUE) {
return value;
}
else if (value.getClass().isArray()) {
Object[] array = (Object[]) value;
for (Object obj : array) {
builder.append(String.valueOf(obj));
}
}
else {
builder.append(String.valueOf(value));
}
}
return builder.toString();
}
}

View File

@ -1,34 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import java.util.Arrays;
import java.util.Map;
import ca.uhn.fhir.narrative.template.LValue;
class ContainsNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public ContainsNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object collection = lhs.render(context);
Object needle = rhs.render(context);
if(super.isArray(collection)) {
Object[] array = super.asArray(collection);
return Arrays.asList(array).contains(needle);
}
if(super.isString(collection)) {
return super.asString(collection).contains(super.asString(needle));
}
return false;
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class EqNode implements LNode {
private LNode lhs;
private LNode rhs;
public EqNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return LValue.areEqual(a, b);
}
}

View File

@ -1,42 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.i18n.Msg;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import ca.uhn.fhir.narrative.template.filters.Filter;
public class FilterNode implements LNode {
private Filter filter;
private List<LNode> params;
public FilterNode(String filterName, Filter filter) {
if (filter == null) {
throw new IllegalArgumentException(Msg.code(731) + "no filter available named: " + filterName);
}
this.filter = filter;
this.params = new ArrayList<LNode>();
}
public void add(LNode param) {
params.add(param);
}
public Object apply(Object value, Map<String, Object> variables) {
List<Object> paramValues = new ArrayList<Object>();
for (LNode node : params) {
paramValues.add(node.render(variables));
}
return filter.apply(value, paramValues.toArray(new Object[paramValues.size()]));
}
@Override
public Object render(Map<String, Object> context) {
throw new RuntimeException(Msg.code(732) + "cannot render a filter");
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class GtEqNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public GtEqNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return (a instanceof Number) && (b instanceof Number) &&
super.asNumber(a).doubleValue() >= super.asNumber(b).doubleValue();
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class GtNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public GtNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return (a instanceof Number) && (b instanceof Number) &&
super.asNumber(a).doubleValue() > super.asNumber(b).doubleValue();
}
}

View File

@ -1,21 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import java.util.Map;
/**
* Denotes a node in the AST the parse creates from the
* input source.
*/
public interface LNode {
/**
* Renders this AST.
*
* @param context
* the context (variables) with which this
* node should be rendered.
*
* @return an Object denoting the rendered AST.
*/
Object render(Map<String, Object> context);
}

View File

@ -1,74 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.i18n.Msg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.dstu3.exceptions.FHIRException;
import org.hl7.fhir.dstu3.model.Base;
import org.hl7.fhir.dstu3.model.BooleanType;
import org.hl7.fhir.dstu3.utils.FluentPathEngine;
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.FhirTerser;
class LookupNode implements LNode {
private final String id;
public LookupNode(String id) {
this.id = id;
}
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LookupNode.class);
@Override
public Object render(Map<String, Object> context) {
ourLog.info("Processing path: {}", id);
FhirTerser terser = (FhirTerser) context.get("terser");
FluentPathEngine fpEngine = (FluentPathEngine) context.get("fpEngine");
IBaseResource resContext = (IBaseResource) context.get("context");
List<Base> retVal;
try {
retVal = fpEngine.evaluate((Base)resContext, id);
} catch (FHIRException e) {
throw new InternalErrorException(Msg.code(729) + e);
}
// terser.getValues(resContext, id);
ourLog.info("Evaluated to: {}", retVal);
if (retVal.size() == 1) {
if (IBaseBooleanDatatype.class.isAssignableFrom(retVal.get(0).getClass())) {
IBaseBooleanDatatype bool = (IBaseBooleanDatatype) retVal.get(0);
Boolean newRetVal = bool.getValue();
ourLog.info("Returning: {}", newRetVal);
return newRetVal;
}
}
return retVal;
}
interface Indexable {
Object get(Object value, Map<String, Object> context);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(id);
return builder.toString();
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class LtEqNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public LtEqNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return (a instanceof Number) && (b instanceof Number) &&
super.asNumber(a).doubleValue() <= super.asNumber(b).doubleValue();
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class LtNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public LtNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return (a instanceof Number) && (b instanceof Number) &&
super.asNumber(a).doubleValue() < super.asNumber(b).doubleValue();
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class NEqNode implements LNode {
private LNode lhs;
private LNode rhs;
public NEqNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return !LValue.areEqual(a, b);
}
}

View File

@ -1,26 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
class OrNode extends LValue implements LNode {
private LNode lhs;
private LNode rhs;
public OrNode(LNode lhs, LNode rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public Object render(Map<String, Object> context) {
Object a = lhs.render(context);
Object b = rhs.render(context);
return super.asBoolean(a) || super.asBoolean(b);
}
}

View File

@ -1,32 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
class OutputNode implements LNode {
private LNode expression;
private List<FilterNode> filters;
public OutputNode(LNode expression) {
this.expression = expression;
this.filters = new ArrayList<FilterNode>();
}
public void addFilter(FilterNode filter) {
filters.add(filter);
}
@Override
public Object render(Map<String, Object> context) {
Object value = expression.render(context);
for (FilterNode node : filters) {
value = node.apply(value, context);
}
return value;
}
}

View File

@ -1,41 +0,0 @@
package ca.uhn.fhir.narrative.template.nodes;
import ca.uhn.fhir.i18n.Msg;
import java.io.File;
import java.util.Map;
import ca.uhn.fhir.narrative.template.parser.Flavor;
import ca.uhn.fhir.narrative.template.tags.Include;
import ca.uhn.fhir.narrative.template.tags.Tag;
class TagNode implements LNode {
private Tag tag;
private LNode[] tokens;
private Flavor flavor;
public TagNode(String tagName, Tag tag, LNode... tokens) {
this(tagName, tag, Flavor.LIQUID, tokens);
}
public TagNode(String tagName, Tag tag, Flavor flavor, LNode... tokens) {
if (tag == null) {
throw new IllegalArgumentException(Msg.code(730) + "no tag available named: " + tagName);
}
this.tag = tag;
this.tokens = tokens;
this.flavor = flavor;
}
@Override
public Object render(Map<String, Object> context) {
// Check if the INCLUDES_DIRECTORY_KEY has already been set, and if not,
// set it based on the value in the flavor.
if (!context.containsKey(Include.INCLUDES_DIRECTORY_KEY)) {
context.put(Include.INCLUDES_DIRECTORY_KEY, new File(flavor.snippetsFolderName));
}
return tag.render(context, tokens);
}
}

View File

@ -1,13 +0,0 @@
package ca.uhn.fhir.narrative.template.parser;
public enum Flavor {
LIQUID("snippets"),
JEKYLL("_includes");
public final String snippetsFolderName;
Flavor(String snippetsFolderName) {
this.snippetsFolderName = snippetsFolderName;
}
}

View File

@ -1,39 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.FilterNode;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Assign extends Tag {
/*
* Assigns some value to a variable
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
String id = String.valueOf(nodes[0].render(context));
FilterNode filter = null;
LNode expression;
if(nodes.length >= 3) {
filter = (FilterNode)nodes[1];
expression = nodes[2];
}
else {
expression = nodes[1];
}
Object value = expression.render(context);
if(filter != null) {
value = filter.apply(value, context);
}
context.put(id, value);
return "";
}
}

View File

@ -1,23 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Capture extends Tag {
/*
* Block tag that captures text into a variable
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
String id = super.asString(nodes[0].render(context));
LNode block = nodes[1];
context.put(id, block.render(context));
return null;
}
}

View File

@ -1,60 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.BlockNode;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Case extends Tag {
/*
* Block tag, its the standard case...when block
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
// ^(CASE condition var
// ^(WHEN term+ block) 1,2,3 b1
// ^(ELSE block?)) b2
Object condition = nodes[0].render(context);
for (int i = 1; i < nodes.length; i++) {
LNode node = nodes[i];
if(i == nodes.length - 1 && node instanceof BlockNode) {
// this must be the trailing (optional) else-block
return node.render(context);
}
else {
boolean hit = false;
// Iterate through the list of terms (of which we do not know the size):
// - term (',' term)*
// - term ('or' term)*
// and stop when we encounter a BlockNode
while(!(node instanceof BlockNode)) {
Object whenExpressionValue = node.render(context);
if (LValue.areEqual(condition, whenExpressionValue)) {
hit = true;
}
i++;
node = nodes[i];
}
if(hit) {
return node.render(context);
}
}
}
return null;
}
}

View File

@ -1,16 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Comment extends Tag {
/*
* Block tag, comments out the text in the block
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
return "";
}
}

View File

@ -1,84 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Cycle extends Tag {
private static final String PREPEND = "\"'";
/*
* Cycle is usually used within a loop to alternate
* between values, like colors or DOM classes.
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
// The group-name is either the first token-expression, or if that is
// null (indicating there is no name), give it the name PREPEND followed
// by the number of expressions in the cycle-group.
String groupName = nodes[0] == null ?
PREPEND + (nodes.length - 1) :
super.asString(nodes[0].render(context));
// Prepend a groupName with a single- and double quote as to not
// let the groupName conflict with other variable assignments
groupName = PREPEND + groupName;
Object obj = context.remove(groupName);
List<Object> elements = new ArrayList<Object>();
for (int i = 1; i < nodes.length; i++) {
elements.add(nodes[i].render(context));
}
CycleGroup group;
if (obj == null) {
group = new CycleGroup(elements.size());
}
else {
group = (CycleGroup) obj;
}
context.put(groupName, group);
return group.next(elements);
}
private static class CycleGroup {
private final int sizeFirstCycle;
private int currentIndex;
CycleGroup(int sizeFirstCycle) {
this.sizeFirstCycle = sizeFirstCycle;
this.currentIndex = 0;
}
Object next(List<Object> elements) {
Object obj;
if (currentIndex >= elements.size()) {
obj = "";
}
else {
obj = elements.get(currentIndex);
}
currentIndex++;
if (currentIndex == sizeFirstCycle) {
currentIndex = 0;
}
return obj;
}
}
}

View File

@ -1,253 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.BlockNode;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class For extends Tag {
private static final String OFFSET = "offset";
private static final String LIMIT = "limit";
private static final String CONTINUE = "continue";
/*
* forloop.length # => length of the entire for loop
* forloop.index # => index of the current iteration
* forloop.index0 # => index of the current iteration (zero based)
* forloop.rindex # => how many items are still left?
* forloop.rindex0 # => how many items are still left? (zero based)
* forloop.first # => is this the first iteration?
* forloop.last # => is this the last iteration?
*/
private static final String FORLOOP = "forloop";
private static final String LENGTH = "length";
private static final String INDEX = "index";
private static final String INDEX0 = "index0";
private static final String RINDEX = "rindex";
private static final String RINDEX0 = "rindex0";
private static final String FIRST = "first";
private static final String LAST = "last";
private static final String NAME = "name";
/*
* For loop
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
// The first node in the array denotes whether this is a for-tag
// over an array, `for item in array ...`, or a for-tag over a
// range, `for i in (4..item.length)`.
boolean array = super.asBoolean(nodes[0].render(context));
String id = super.asString(nodes[1].render(context));
context.put(FORLOOP, new HashMap<String, Object>());
Object rendered = array ? renderArray(id, context, nodes) : renderRange(id, context, nodes);
context.remove(FORLOOP);
return rendered;
}
private Object renderArray(String id, Map<String, Object> context, LNode... tokens) {
StringBuilder builder = new StringBuilder();
// attributes start from index 5
Map<String, Integer> attributes = getAttributes(5, context, tokens);
int offset = attributes.get(OFFSET);
int limit = attributes.get(LIMIT);
Object[] array = super.asArray(tokens[2].render(context));
LNode block = tokens[3];
LNode blockIfEmptyOrNull = tokens[4];
if(array == null || array.length == 0) {
return blockIfEmptyOrNull == null ? null : blockIfEmptyOrNull.render(context);
}
int length = Math.min(limit, array.length);
Map<String, Object> forLoopMap = (Map<String, Object>)context.get(FORLOOP);
forLoopMap.put(NAME, id + "-" + tokens[2].toString());
int continueIndex = offset;
for (int i = offset, n = 0; n < limit && i < array.length; i++, n++) {
continueIndex = i;
boolean first = (i == offset);
boolean last = ((n == limit - 1) || (i == array.length - 1));
context.put(id, array[i]);
forLoopMap.put(LENGTH, length);
forLoopMap.put(INDEX, n + 1);
forLoopMap.put(INDEX0, n);
forLoopMap.put(RINDEX, length - n);
forLoopMap.put(RINDEX0, length - n - 1);
forLoopMap.put(FIRST, first);
forLoopMap.put(LAST, last);
List<LNode> children = ((BlockNode)block).getChildren();
boolean isBreak = false;
for (LNode node : children) {
Object value = node.render(context);
if(value == Tag.Statement.CONTINUE) {
// break from this inner loop: equals continue outer loop!
break;
}
if(value == Tag.Statement.BREAK) {
// break from inner loop
isBreak = true;
break;
}
if (value != null && value.getClass().isArray()) {
Object[] arr = (Object[]) value;
for (Object obj : arr) {
builder.append(String.valueOf(obj));
}
}
else {
builder.append(super.asString(value));
}
}
if(isBreak) {
// break from outer loop
break;
}
}
context.put(CONTINUE, continueIndex + 1);
return builder.toString();
}
private Object renderRange(String id, Map<String, Object> context, LNode... tokens) {
StringBuilder builder = new StringBuilder();
// attributes start from index 5
Map<String, Integer> attributes = getAttributes(5, context, tokens);
int offset = attributes.get(OFFSET);
int limit = attributes.get(LIMIT);
LNode block = tokens[4];
try {
int from = super.asNumber(tokens[2].render(context)).intValue();
int to = super.asNumber(tokens[3].render(context)).intValue();
int length = (to - from);
Map<String, Object> forLoopMap = (Map<String, Object>)context.get(FORLOOP);
int continueIndex = from + offset;
for (int i = from + offset, n = 0; i <= to && n < limit; i++, n++) {
continueIndex = i;
boolean first = (i == (from + offset));
boolean last = ((i == to) || (n == limit - 1));
context.put(id, i);
forLoopMap.put(LENGTH, length);
forLoopMap.put(INDEX, n + 1);
forLoopMap.put(INDEX0, n);
forLoopMap.put(RINDEX, length - n);
forLoopMap.put(RINDEX0, length - n - 1);
forLoopMap.put(FIRST, first);
forLoopMap.put(LAST, last);
List<LNode> children = ((BlockNode)block).getChildren();
boolean isBreak = false;
for (LNode node : children) {
Object value = node.render(context);
if(value == null) {
continue;
}
if(value == Tag.Statement.CONTINUE) {
// break from this inner loop: equals continue outer loop!
break;
}
if(value == Tag.Statement.BREAK) {
// break from inner loop
isBreak = true;
break;
}
if(super.isArray(value)) {
Object[] arr = super.asArray(value);
for (Object obj : arr) {
builder.append(String.valueOf(obj));
}
}
else {
builder.append(super.asString(value));
}
}
if(isBreak) {
// break from outer loop
break;
}
}
context.put(CONTINUE, continueIndex + 1);
}
catch (Exception e) {
/* just ignore incorrect expressions */
}
return builder.toString();
}
private Map<String, Integer> getAttributes(int fromIndex, Map<String, Object> context, LNode... tokens) {
Map<String, Integer> attributes = new HashMap<String, Integer>();
attributes.put(OFFSET, 0);
attributes.put(LIMIT, Integer.MAX_VALUE);
for (int i = fromIndex; i < tokens.length; i++) {
Object[] attribute = super.asArray(tokens[i].render(context));
try {
attributes.put(super.asString(attribute[0]), super.asNumber(attribute[1]).intValue());
}
catch (Exception e) {
/* just ignore incorrect attributes */
}
}
return attributes;
}
}

View File

@ -1,27 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class If extends Tag {
/*
* Standard if/else block
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
for (int i = 0; i < nodes.length - 1; i += 2) {
Object exprNodeValue = nodes[i].render(context);
LNode blockNode = nodes[i + 1];
if (super.asBoolean(exprNodeValue)) {
return blockNode.render(context);
}
}
return null;
}
}

View File

@ -1,43 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import ca.uhn.fhir.narrative.template.Template;
import java.io.File;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
public class Include extends Tag {
public static final String INCLUDES_DIRECTORY_KEY = "liqp@includes_directory";
public static String DEFAULT_EXTENSION = ".liquid";
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
// This value will always be defined: either a custom file set by the
// user, or else inside TagNode.
File includesDirectory = (File)context.get(INCLUDES_DIRECTORY_KEY);
try {
String includeResource = super.asString(nodes[0].render(context));
String extension = DEFAULT_EXTENSION;
if(includeResource.indexOf('.') > 0) {
extension = "";
}
File includeResourceFile = new File(includesDirectory, includeResource + extension);
Template include = Template.parse(includeResourceFile);
// check if there's a optional "with expression"
if(nodes.length > 1) {
Object value = nodes[1].render(context);
context.put(includeResource, value);
}
return include.render(context);
} catch(Exception e) {
return "";
}
}
}

View File

@ -1,16 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Raw extends Tag {
/*
* temporarily disable tag processing to avoid syntax conflicts.
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
return nodes[0].render(context);
}
}

View File

@ -1,126 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.HashMap;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Tablerow extends Tag {
private static final String COLS = "cols";
private static final String LIMIT = "limit";
/*
* tablerowloop.length # => length of the entire for loop
* tablerowloop.index # => index of the current iteration
* tablerowloop.index0 # => index of the current iteration (zero based)
* tablerowloop.rindex # => how many items are still left?
* tablerowloop.rindex0 # => how many items are still left? (zero based)
* tablerowloop.first # => is this the first iteration?
* tablerowloop.last # => is this the last iteration?
* tablerowloop.col # => index of column in the current row
* tablerowloop.col0 # => index of column in the current row (zero based)
* tablerowloop.col_first # => is this the first column in the row?
* tablerowloop.col_last # => is this the last column in the row?
*/
private static final String TABLEROWLOOP = "tablerowloop";
private static final String LENGTH = "length";
private static final String INDEX = "index";
private static final String INDEX0 = "index0";
private static final String RINDEX = "rindex";
private static final String RINDEX0 = "rindex0";
private static final String FIRST = "first";
private static final String LAST = "last";
private static final String COL = "col";
private static final String COL0 = "col0";
private static final String COL_FIRST = "col_first";
private static final String COL_LAST = "col_last";
/*
* Tables
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
String valueName = super.asString(nodes[0].render(context));
Object[] collection = super.asArray(nodes[1].render(context));
LNode block = nodes[2];
Map<String, Integer> attributes = getAttributes(collection, 3, context, nodes);
int cols = attributes.get(COLS);
int limit = attributes.get(LIMIT);
Map<String, Object> tablerowloopContext = new HashMap<String, Object>();
tablerowloopContext.put(LENGTH, collection.length);
context.put(TABLEROWLOOP, tablerowloopContext);
StringBuilder builder = new StringBuilder();
int total = Math.min(collection.length, limit);
if(total == 0) {
builder.append("<tr class=\"row1\">\n</tr>\n");
}
else {
for(int i = 0, c = 1, r = 0; i < total; i++, c++) {
context.put(valueName, collection[i]);
tablerowloopContext.put(INDEX0, i);
tablerowloopContext.put(INDEX, i + 1);
tablerowloopContext.put(RINDEX0, total - i - 1);
tablerowloopContext.put(RINDEX, total - i);
tablerowloopContext.put(FIRST, i == 0);
tablerowloopContext.put(LAST, i == total - 1);
tablerowloopContext.put(COL0, c - 1);
tablerowloopContext.put(COL, c);
tablerowloopContext.put(COL_FIRST, c == 1);
tablerowloopContext.put(COL_LAST, c == cols);
if(c == 1) {
r++;
builder.append("<tr class=\"row").append(r).append("\">").append(r == 1 ? "\n" : "");
}
builder.append("<td class=\"col").append(c).append("\">");
builder.append(super.asString(block.render(context)));
builder.append("</td>");
if(c == cols || i == total - 1) {
builder.append("</tr>\n");
c = 0;
}
}
}
context.remove(TABLEROWLOOP);
return builder.toString();
}
private Map<String, Integer> getAttributes(Object[] collection, int fromIndex, Map<String, Object> context, LNode... tokens) {
Map<String, Integer> attributes = new HashMap<String, Integer>();
attributes.put(COLS, collection.length);
attributes.put(LIMIT, Integer.MAX_VALUE);
for (int i = fromIndex; i < tokens.length; i++) {
Object[] attribute = super.asArray(tokens[i].render(context));
try {
attributes.put(super.asString(attribute[0]), super.asNumber(attribute[1]).intValue());
}
catch (Exception e) {
/* just ignore incorrect attributes */
}
}
return attributes;
}
}

View File

@ -1,121 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.narrative.template.LValue;
import java.util.HashMap;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
/**
* Tags are used for the logic in a template.
*/
public abstract class Tag extends LValue {
public enum Statement {
BREAK, CONTINUE;
@Override
public String toString() {
return "";
}
}
/**
* A map holding all tags.
*/
private static final Map<String, Tag> TAGS = new HashMap<String, Tag>();
static {
// Register all standard tags.
registerTag(new Assign());
registerTag(new Case());
registerTag(new Capture());
registerTag(new Comment());
registerTag(new Cycle());
registerTag(new For());
registerTag(new If());
registerTag(new Include());
registerTag(new Raw());
registerTag(new Tablerow());
registerTag(new Unless());
}
/**
* The name of this tag.
*/
public final String name;
/**
* Used for all package protected tags in the ca.uhn.fhir.narrative.template.tags-package
* whose name is their class name lower cased.
*/
protected Tag() {
this.name = this.getClass().getSimpleName().toLowerCase();
}
/**
* Creates a new instance of a Tag.
*
* @param name
* the name of the tag.
*/
public Tag(String name) {
this.name = name;
}
/**
* Retrieves a filter with a specific name.
*
* @param name
* the name of the filter to retrieve.
*
* @return a filter with a specific name.
*/
public static Tag getTag(String name) {
Tag tag = TAGS.get(name);
if (tag == null) {
throw new RuntimeException(Msg.code(733) + "unknown tag: " + name);
}
return tag;
}
/**
* Returns all default tags.
*
* @return all default tags.
*/
public static Map<String, Tag> getTags() {
return new HashMap<String, Tag>(TAGS);
}
/**
* Registers a new tag.
*
* @param tag
* the tag to be registered.
*/
public static void registerTag(Tag tag) {
TAGS.put(tag.name, tag);
}
/**
* Renders this tag.
*
* @param context
* the context (variables) with which this
* node should be rendered.
* @param nodes
* the nodes of this tag is created with. See
* the file `src/grammar/LiquidWalker.g` to see
* how each of the tags is created.
*
* @return an Object denoting the rendered AST.
*/
public abstract Object render(Map<String, Object> context, LNode... nodes);
}

View File

@ -1,27 +0,0 @@
package ca.uhn.fhir.narrative.template.tags;
import java.util.Map;
import ca.uhn.fhir.narrative.template.nodes.LNode;
class Unless extends Tag {
/*
* Mirror of if statement
*/
@Override
public Object render(Map<String, Object> context, LNode... nodes) {
for (int i = 0; i < nodes.length - 1; i += 2) {
Object exprNodeValue = nodes[i].render(context);
LNode blockNode = nodes[i + 1];
if (!super.asBoolean(exprNodeValue)) {
return blockNode.render(context);
}
}
return "";
}
}

View File

@ -1,32 +0,0 @@
package ca.uhn.fhir.narrative.template;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.model.Patient;
import org.junit.jupiter.api.Test;
import ca.uhn.fhir.context.FhirContext;
public class TemplateNarrativeGeneratorTest {
@Test
public void testTemplate() throws Exception {
String template = IOUtils.toString(getClass().getResourceAsStream("/patient.narrative"), StandardCharsets.UTF_8);
Patient input = new Patient();
input.addName().addFamily("LNAME1");
input.addName().addFamily("LNAME2");
input.addName().addGiven("FNAME1");
input.addName().addGiven("FNAME2");
TemplateNarrativeGenerator gen = new TemplateNarrativeGenerator();
String output = gen.processLiquid(FhirContext.forDstu3(), template, input);
ourLog.info(output);
}
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TemplateNarrativeGeneratorTest.class);
}

View File

@ -1,10 +0,0 @@
<div>
{{ Patient.name.given }}
{% if name.empty() == false %}
{{ name[0].family }}
{{ name[0].given }}
{% endif %}
</div>

View File

@ -1,126 +0,0 @@
/target/
/bin/
# Created by https://www.gitignore.io
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### Vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.loadpath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse

View File

@ -1,2 +0,0 @@
target/
bin/

View File

@ -1,159 +0,0 @@
<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>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>0.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-oauth2</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - OAUTH2 Support</name>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>0.8-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>0.8-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<!-- Only required for OpenID Connect Support -->
<dependency>
<groupId>org.mitre</groupId>
<artifactId>openid-connect-client</artifactId>
<version>${mitreid-connect-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.17.RELEASE</version>
</dependency>
<!-- Server -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet_api_version}</version>
<scope>provided</scope>
</dependency>
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty_version}</version>
<scope>test</scope>
</dependency>
<!-- UNIT TEST DEPENDENCIES -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest_version}</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring_security_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring_security_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
-->
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

View File

@ -1,199 +0,0 @@
package ca.uhn.fhir.rest.server.security;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 University Health Network
* %%
* 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 ca.uhn.fhir.i18n.Msg;
import java.text.ParseException;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.jwt.signer.service.impl.SymmetricCacheService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.ClientConfigurationService;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.rest.method.OtherOperationTypeEnum;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
public class OpenIdConnectBearerTokenServerInterceptor extends InterceptorAdapter {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OpenIdConnectBearerTokenServerInterceptor.class);
@Autowired
private ClientConfigurationService myClientConfigurationService;
@Autowired
private ServerConfigurationService myServerConfigurationService;
private int myTimeSkewAllowance = 300;
private SymmetricCacheService mySymmetricCacheService;
private JWKSetCacheService myValidationServices;
public OpenIdConnectBearerTokenServerInterceptor() {
mySymmetricCacheService = new SymmetricCacheService();
myValidationServices = new JWKSetCacheService();
}
@Override
public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
if (theRequestDetails.getOtherOperationType() == OtherOperationTypeEnum.METADATA) {
return true;
}
authenticate(theRequest);
return true;
}
public void authenticate(HttpServletRequest theRequest) throws AuthenticationException {
String token = theRequest.getHeader(Constants.HEADER_AUTHORIZATION);
if (token == null) {
throw new AuthenticationException(Msg.code(241) + "Not authorized (no authorization header found in request)");
}
if (!token.startsWith(Constants.HEADER_AUTHORIZATION_VALPREFIX_BEARER)) {
throw new AuthenticationException(Msg.code(242) + "Not authorized (authorization header does not contain a bearer token)");
}
token = token.substring(Constants.HEADER_AUTHORIZATION_VALPREFIX_BEARER.length());
SignedJWT idToken;
try {
idToken = SignedJWT.parse(token);
} catch (ParseException e) {
throw new AuthenticationException(Msg.code(243) + "Not authorized (bearer token could not be validated)", e);
}
// validate our ID Token over a number of tests
ReadOnlyJWTClaimsSet idClaims;
try {
idClaims = idToken.getJWTClaimsSet();
} catch (ParseException e) {
throw new AuthenticationException(Msg.code(244) + "Not authorized (bearer token could not be validated)", e);
}
String issuer = idClaims.getIssuer();
ServerConfiguration serverConfig = myServerConfigurationService.getServerConfiguration(issuer);
if (serverConfig == null) {
ourLog.error("No server configuration found for issuer: " + issuer);
throw new AuthenticationException(Msg.code(245) + "Not authorized (no server configuration found for issuer " + issuer + ")");
}
RegisteredClient clientConfig = myClientConfigurationService.getClientConfiguration(serverConfig);
if (clientConfig == null) {
ourLog.error("No client configuration found for issuer: " + issuer);
throw new AuthenticationException(Msg.code(246) + "Not authorized (no client configuration found for issuer " + issuer + ")");
}
// check the signature
JwtSigningAndValidationService jwtValidator = null;
JWSAlgorithm alg = idToken.getHeader().getAlgorithm();
if (alg.equals(JWSAlgorithm.HS256) || alg.equals(JWSAlgorithm.HS384) || alg.equals(JWSAlgorithm.HS512)) {
// generate one based on client secret
jwtValidator = mySymmetricCacheService.getSymmetricValidtor(clientConfig.getClient());
} else {
// otherwise load from the server's public key
jwtValidator = myValidationServices.getValidator(serverConfig.getJwksUri());
}
if (jwtValidator != null) {
if (!jwtValidator.validateSignature(idToken)) {
throw new AuthenticationException(Msg.code(247) + "Not authorized (signature validation failed)");
}
} else {
ourLog.error("No validation service found. Skipping signature validation");
throw new AuthenticationException(Msg.code(248) + "Not authorized (can't determine signature validator)");
}
// check expiration
if (idClaims.getExpirationTime() == null) {
throw new AuthenticationException(Msg.code(249) + "Id Token does not have required expiration claim");
} else {
// it's not null, see if it's expired
Date minAllowableExpirationTime = new Date(System.currentTimeMillis() - (myTimeSkewAllowance * 1000L));
Date expirationTime = idClaims.getExpirationTime();
if (!expirationTime.after(minAllowableExpirationTime)) {
throw new AuthenticationException(Msg.code(250) + "Id Token is expired: " + idClaims.getExpirationTime());
}
}
// check not before
if (idClaims.getNotBeforeTime() != null) {
Date now = new Date(System.currentTimeMillis() + (myTimeSkewAllowance * 1000));
if (now.before(idClaims.getNotBeforeTime())) {
throw new AuthenticationException(Msg.code(251) + "Id Token not valid untill: " + idClaims.getNotBeforeTime());
}
}
// check issued at
if (idClaims.getIssueTime() == null) {
throw new AuthenticationException(Msg.code(252) + "Id Token does not have required issued-at claim");
} else {
// since it's not null, see if it was issued in the future
Date now = new Date(System.currentTimeMillis() + (myTimeSkewAllowance * 1000));
if (now.before(idClaims.getIssueTime())) {
throw new AuthenticationException(Msg.code(253) + "Id Token was issued in the future: " + idClaims.getIssueTime());
}
}
}
public int getTimeSkewAllowance() {
return myTimeSkewAllowance;
}
public void setClientConfigurationService(ClientConfigurationService theClientConfigurationService) {
myClientConfigurationService = theClientConfigurationService;
}
public void setServerConfigurationService(ServerConfigurationService theServerConfigurationService) {
myServerConfigurationService = theServerConfigurationService;
}
public void setTimeSkewAllowance(int theTimeSkewAllowance) {
myTimeSkewAllowance = theTimeSkewAllowance;
}
public void setValidationServices(JWKSetCacheService theValidationServices) {
myValidationServices = theValidationServices;
}
}

View File

@ -1,34 +0,0 @@
package ca.uhn.fhir.rest.server.security;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
public class DummyOpenIdServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DummyOpenIdServlet.class);
@Override
protected void doGet(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
ourLog.info("Request: {}", theReq.getRequestURI());
if (theReq.getRequestURI().equals("/openid/jwk")) {
theResp.setStatus(200);
InputStream is = DummyOpenIdServlet.class.getResourceAsStream("/svr_keystore.jwks");
IOUtils.copy(is, theResp.getOutputStream());
IOUtils.closeQuietly(theResp.getOutputStream());
return;
}
super.doGet(theReq, theResp);
}
}

View File

@ -1,158 +0,0 @@
package ca.uhn.fhir.rest.server.security;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeEachClass;
import org.junit.jupiter.api.Test;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService;
import org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class OpenIdConnectBearerTokenServerInterceptorIntegrationTest {
private static CloseableHttpClient ourClient;
private static FhirContext ourCtx = new FhirContext();
private static int ourPort;
private static Server ourServer;
private static OpenIdConnectBearerTokenServerInterceptor myInterceptor;
@Test
public void testSearchWithoutToken() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(401, status.getStatusLine().getStatusCode());
}
@Test
public void testSearchWithExpiredToken() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?");
httpGet.addHeader(
"Authorization",
"Bearer "
+ "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MDY4NDE4NTgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0Ojg4ODhcL3Vobi1vcGVuaWQtY29ubmVjdFwvIiwianRpIjoiOTNiMzRjOTUtNTNiMC00YzZmLTkwYjEtYWVjODRjZTc3OGFhIiwiaWF0IjoxNDA2ODM4MjU4fQ.fYtwehPUulUYnDG_10bN6TNf7uw2FNUh_E40YagpITrVfXsV06pjU2YpNgy8nbSFmxY9IBH44UXTmMH9PLFiRn88WsPMSrUQbFCcvGIYwhqkRjGm_J1Y6oWIafUzCwZBCvk4Ne44p3DJRR6FSZRnnC850p55901DGQmNLe-rZJk3t0MHl6wySduqT3K1-Vbuq-7H6xLE10hKpLhSqBTghpQNKNjm48jm0sHcFa3ENWzyWPOmpNfzDKmJAYK2UnBtqNSJP6AJzVrJXqSu-uzasq0VOVcRU4n8b39vU1olbho1eKF0cfQlQwbrtvWipBJJSsRp_tmB9SV9BXhENxOFTw");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(401, status.getStatusLine().getStatusCode());
}
@Test
public void testSearchWithValidToken() throws Exception {
myInterceptor.setTimeSkewAllowance(10 * 365 * 24 * 60 * 60);
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?");
httpGet.addHeader(
"Authorization",
"Bearer "
+ "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MDY4NDE4NTgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0Ojg4ODhcL3Vobi1vcGVuaWQtY29ubmVjdFwvIiwianRpIjoiOTNiMzRjOTUtNTNiMC00YzZmLTkwYjEtYWVjODRjZTc3OGFhIiwiaWF0IjoxNDA2ODM4MjU4fQ.fYtwehPUulUYnDG_10bN6TNf7uw2FNUh_E40YagpITrVfXsV06pjU2YpNgy8nbSFmxY9IBH44UXTmMH9PLFiRn88WsPMSrUQbFCcvGIYwhqkRjGm_J1Y6oWIafUzCwZBCvk4Ne44p3DJRR6FSZRnnC850p55901DGQmNLe-rZJk3t0MHl6wySduqT3K1-Vbuq-7H6xLE10hKpLhSqBTghpQNKNjm48jm0sHcFa3ENWzyWPOmpNfzDKmJAYK2UnBtqNSJP6AJzVrJXqSu-uzasq0VOVcRU4n8b39vU1olbho1eKF0cfQlQwbrtvWipBJJSsRp_tmB9SV9BXhENxOFTw");
HttpResponse status = ourClient.execute(httpGet);
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
}
@BeforeEach
public void before() {
myInterceptor.setTimeSkewAllowance(10 * 60);
}
@AfterAll
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeAll
public static void beforeClass() throws Exception {
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);
ServletHandler proxyHandler = new ServletHandler();
DummyOpenIdServlet openIdServlet = new DummyOpenIdServlet();
ServletHolder proxyHolder = new ServletHolder(openIdServlet);
proxyHandler.addServletWithMapping(proxyHolder, "/openid/*");
RestfulServer servlet = new RestfulServer();
servlet.setResourceProviders(new DummyObservationResourceProvider());
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
// DynamicServerConfigurationService s = new DynamicServerConfigurationService();
// s.setWhitelist(new HashSet<String>());
// s.getWhitelist().add("http://localhost:8888/uhn-openid-connect/");
StaticServerConfigurationService srv = new StaticServerConfigurationService();
srv.setServers(new HashMap<String, ServerConfiguration>());
ServerConfiguration srvCfg = new ServerConfiguration();
srvCfg.setJwksUri("http://localhost:" + ourPort + "/openid/jwk");
srvCfg.setIssuer("http://localhost:8888/uhn-openid-connect/");
srv.getServers().put("http://localhost:8888/uhn-openid-connect/", srvCfg);
srv.afterPropertiesSet();
StaticClientConfigurationService cli = new StaticClientConfigurationService();
cli.setClients(new HashMap<String, RegisteredClient>());
cli.getClients().put("http://localhost:8888/uhn-openid-connect/", new RegisteredClient());
myInterceptor = new OpenIdConnectBearerTokenServerInterceptor();
myInterceptor.setClientConfigurationService(cli);
myInterceptor.setServerConfigurationService(srv);
servlet.registerInterceptor(myInterceptor);
ourServer.setHandler(proxyHandler);
JettyUtil.startServer(ourServer);
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
public static class DummyObservationResourceProvider implements IResourceProvider {
@Override
public Class<? extends IResource> getResourceType() {
return Observation.class;
}
@Search
public Observation search() {
Observation o = new Observation();
o.setId("1");
o.getName().setText("This is an observation");
return o;
}
}
}

View File

@ -1,83 +0,0 @@
package ca.uhn.fhir.rest.server.security;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import org.hamcrest.core.StringContains;
import org.junit.jupiter.api.Test;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService;
import org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.core.io.ClassPathResource;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
public class OpenIdConnectBearerTokenServerInterceptorTest {
@Test
public void testValidateToken() throws Exception {
StaticServerConfigurationService srv = new StaticServerConfigurationService();
srv.setServers(new HashMap<String, ServerConfiguration>());
ServerConfiguration srvCfg = new ServerConfiguration();
srvCfg.setJwksUri("AAAAAA");
srvCfg.setIssuer("http://localhost:8888/uhn-openid-connect/");
srv.getServers().put("http://localhost:8888/uhn-openid-connect/", srvCfg);
srv.afterPropertiesSet();
StaticClientConfigurationService cli = new StaticClientConfigurationService();
cli.setClients(new HashMap<String, RegisteredClient>());
cli.getClients().put("http://localhost:8888/uhn-openid-connect/", new RegisteredClient());
OpenIdConnectBearerTokenServerInterceptor mgr = new OpenIdConnectBearerTokenServerInterceptor();
mgr.setClientConfigurationService(cli);
mgr.setServerConfigurationService(srv);
HttpServletRequest req = mock(HttpServletRequest.class);
when(req.getHeader(Constants.HEADER_AUTHORIZATION))
.thenReturn(
"Bearer "
+ "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE0MDY4NDE4NTgsImF1ZCI6WyJjbGllbnQiXSwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0Ojg4ODhcL3Vobi1vcGVuaWQtY29ubmVjdFwvIiwianRpIjoiOTNiMzRjOTUtNTNiMC00YzZmLTkwYjEtYWVjODRjZTc3OGFhIiwiaWF0IjoxNDA2ODM4MjU4fQ.fYtwehPUulUYnDG_10bN6TNf7uw2FNUh_E40YagpITrVfXsV06pjU2YpNgy8nbSFmxY9IBH44UXTmMH9PLFiRn88WsPMSrUQbFCcvGIYwhqkRjGm_J1Y6oWIafUzCwZBCvk4Ne44p3DJRR6FSZRnnC850p55901DGQmNLe-rZJk3t0MHl6wySduqT3K1-Vbuq-7H6xLE10hKpLhSqBTghpQNKNjm48jm0sHcFa3ENWzyWPOmpNfzDKmJAYK2UnBtqNSJP6AJzVrJXqSu-uzasq0VOVcRU4n8b39vU1olbho1eKF0cfQlQwbrtvWipBJJSsRp_tmB9SV9BXhENxOFTw");
JWKSetCacheService val = mock(JWKSetCacheService.class);
JWKSetKeyStore keyStore = new JWKSetKeyStore();
keyStore.setLocation(new ClassPathResource("/svr_keystore.jwks"));
DefaultJwtSigningAndValidationService valSvc = new DefaultJwtSigningAndValidationService(keyStore);
when(val.getValidator("AAAAAA")).thenReturn(valSvc);
mgr.setValidationServices(val);
try {
mgr.authenticate(req);
fail();
} catch (AuthenticationException e) {
assertThat(e.getMessage(), StringContains.containsString("expired"));
}
mgr.setTimeSkewAllowance(10 * 365 * 24 * 60 * 60);
mgr.authenticate(req);
}
}

View File

@ -1,39 +0,0 @@
package ca.uhn.fhir.rest.server.security;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
/**
* Provides server ports
*/
public class PortUtil {
private static List<Integer> ourPorts = new ArrayList<Integer>();
/**
* This is really only used for unit tests but is included in the library so it can be reused across modules. Use with caution.
*/
public static int findFreePort() {
ServerSocket server;
try {
server = new ServerSocket(0);
int port = server.getLocalPort();
ourPorts.add(port);
server.close();
Thread.sleep(500);
return port;
} catch (IOException e) {
throw new Error(e);
} catch (InterruptedException e) {
throw new Error(e);
}
}
public static List<Integer> list() {
return ourPorts;
}
}

View File

@ -1,18 +0,0 @@
package ca.uhn.fhir.rest.server.security;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{
@Override
public void commence( HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException ) throws IOException{
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
}
}

View File

@ -1,24 +0,0 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.eclipse" additivity="false" level="info">
<appender-ref ref="STDOUT" />
</logger>
<!--
<logger name="ca.uhn.fhir.rest.client" additivity="false" level="trace">
<appender-ref ref="STDOUT" />
</logger>
-->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -1,11 +0,0 @@
{
"keys": [
{
"d": "S0pTrzR78vyso2ufMTAJMPNpqSgF0jggquQ2crgBw_il-QQ5zAHzlrreGWDcvr94i6PAy4xQYRAAaO_ZtjO4kMmEKdJ-bgsAJiIrUAlJdv0JCK-j3G64R0EiwrSzXqyt3E6kiA14o5wYgs86RO7TV6dpFyNuSIoZJeNG-NBviPIwY222PX07xjaMk7tSQdlTP6Vg1EZV-i0AqYGE-Ivn2eaI0KvjzPWVXVki1F6J4yQzErxcVILgicAp6Eeqy24E3enmrsQozj54Sswjy8r_MrGf2iSaf0GedLsCXWSQ-uojWF6llfjL9Q5be65ztPkvN4cPGn0o_sHzqewvFnZuAQ",
"e": "AQAB",
"n": "kmjocunUF1bw2rSnBtiA9P2LJcuUdTSpgS8e2MccFv0VLNFd50P7JMxmLt_ildr040371QPflz0wdE_O8gypJr17RyJCg7mthCRpNLxkVHS8Pd3p0fzn_xlmrm4gkR033k7aTH3bB-usjq5Z8A6GjxlUp2Of5TRJ1Tj9287m9X2w65DDCcOQYC8horObEEUkchfpyf5PGCdkq-1U46_P66RcFuLjxaO6R5OWrVK8Zd-tHOG-O3-nn0eAHxFvtGDiYOVImQ7rWEriTDQdefiIIOM_m73xbtdVM2jEgQfn76u0TvK7nLmz1w4XvddOv2TatXmAtNmTpP16629eqnKcMw",
"kty": "RSA",
"kid": "rsa1"
}
]
}

View File

@ -1,126 +0,0 @@
/bin
/target
*.log
*.log*
/target/
/target/
# Created by https://www.gitignore.io
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### Vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse

View File

@ -1,331 +0,0 @@
<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>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>3.0.0</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR Structures - DSTU1 (FHIR v0.80)</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<optional>true</optional>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>
<!-- UNIT TEST DEPENDENCIES -->
<dependency>
<!-- This is used for cors -->
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<classifier>jdk15</classifier>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang</artifactId>
<groupId>commons-lang</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<classifier>jdk15-sources</classifier>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang</artifactId>
<groupId>commons-lang</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<artifactId>commons-lang</artifactId>
<groupId>commons-lang</groupId>
<scope>test</scope>
<version>2.5</version>
</dependency>
<dependency>
<groupId>directory-naming</groupId>
<artifactId>naming-java</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>test</scope>
</dependency>
<!--
The JPA project uses a newer API but we'll try to hold to this version
as much as possible. See #283.
This dependency comes last so that the newer version brought in by
Jetty for unit tests comes first on the classpath (since jetty
needs that newer version. The unit tests are slooooow otherwise.
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<dumpOnExit>true</dumpOnExit>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
</configuration>
</plugin>
<plugin>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals>
<goal>generate-structures</goal>
</goals>
</execution>
</executions>
<configuration>
<package>ca.uhn.fhir.model.dstu</package>
<baseResourceNames>
<baseResourceName>adversereaction</baseResourceName>
<baseResourceName>alert</baseResourceName>
<baseResourceName>allergyintolerance</baseResourceName>
<baseResourceName>appointmentresponse</baseResourceName>
<baseResourceName>appointment</baseResourceName>
<baseResourceName>availability</baseResourceName>
<baseResourceName>careplan</baseResourceName>
<baseResourceName>claim</baseResourceName>
<baseResourceName>composition</baseResourceName>
<baseResourceName>conceptmap</baseResourceName>
<baseResourceName>condition</baseResourceName>
<baseResourceName>conformance</baseResourceName>
<baseResourceName>coverage</baseResourceName>
<baseResourceName>deviceobservationreport</baseResourceName>
<baseResourceName>device</baseResourceName>
<baseResourceName>diagnosticorder</baseResourceName>
<baseResourceName>diagnosticreport</baseResourceName>
<baseResourceName>documentmanifest</baseResourceName>
<baseResourceName>documentreference</baseResourceName>
<baseResourceName>encounter</baseResourceName>
<baseResourceName>familyhistory</baseResourceName>
<baseResourceName>geneexpression</baseResourceName>
<baseResourceName>geneticanalysis</baseResourceName>
<baseResourceName>group</baseResourceName>
<baseResourceName>gvfmeta</baseResourceName>
<baseResourceName>gvfvariant</baseResourceName>
<baseResourceName>imagingstudy</baseResourceName>
<baseResourceName>immunizationrecommendation</baseResourceName>
<baseResourceName>immunization</baseResourceName>
<baseResourceName>list</baseResourceName>
<baseResourceName>location</baseResourceName>
<baseResourceName>media</baseResourceName>
<baseResourceName>medicationadministration</baseResourceName>
<baseResourceName>medicationdispense</baseResourceName>
<baseResourceName>medicationprescription</baseResourceName>
<baseResourceName>medication</baseResourceName>
<baseResourceName>medicationstatement</baseResourceName>
<baseResourceName>messageheader</baseResourceName>
<baseResourceName>microarray</baseResourceName>
<baseResourceName>observation</baseResourceName>
<baseResourceName>operationoutcome</baseResourceName>
<baseResourceName>orderresponse</baseResourceName>
<baseResourceName>order</baseResourceName>
<baseResourceName>organization</baseResourceName>
<baseResourceName>other</baseResourceName>
<baseResourceName>patient</baseResourceName>
<baseResourceName>practitioner</baseResourceName>
<baseResourceName>procedure</baseResourceName>
<baseResourceName>profile</baseResourceName>
<baseResourceName>provenance</baseResourceName>
<baseResourceName>query</baseResourceName>
<baseResourceName>questionnaire</baseResourceName>
<baseResourceName>relatedperson</baseResourceName>
<baseResourceName>remittance</baseResourceName>
<baseResourceName>securityevent</baseResourceName>
<baseResourceName>sequencinganalysis</baseResourceName>
<baseResourceName>sequencinglab</baseResourceName>
<baseResourceName>slot</baseResourceName>
<baseResourceName>specimen</baseResourceName>
<baseResourceName>substance</baseResourceName>
<baseResourceName>supply</baseResourceName>
<baseResourceName>user</baseResourceName>
<baseResourceName>valueset</baseResourceName>
</baseResourceNames>
<buildDatatypes>true</buildDatatypes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-sources/tinder</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-plugin</artifactId>
<versionRange>[0.4-SNAPSHOT,)</versionRange>
<goals>
<goal>generate-structures</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${basedir}/target/generated-resources/tinder</directory>
</resource>
</resources>
</build>
</project>

View File

@ -1,411 +0,0 @@
package ca.uhn.fhir.model.dstu;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 ca.uhn.fhir.i18n.Msg;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.join;
import java.io.InputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
import ca.uhn.fhir.context.RuntimeChildCompositeDatatypeDefinition;
import ca.uhn.fhir.context.RuntimeChildContainedResources;
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimeChildExtension;
import ca.uhn.fhir.context.RuntimeChildPrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimeChildResourceBlockDefinition;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
import ca.uhn.fhir.context.RuntimeCompositeDatatypeDefinition;
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
import ca.uhn.fhir.context.RuntimeResourceBlockDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.fhirpath.IFluentPath;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IFhirVersion;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.Profile;
import ca.uhn.fhir.model.dstu.resource.Profile.ExtensionDefn;
import ca.uhn.fhir.model.dstu.resource.Profile.Structure;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureElement;
import ca.uhn.fhir.model.dstu.resource.Profile.StructureElementDefinitionType;
import ca.uhn.fhir.model.dstu.valueset.DataTypeEnum;
import ca.uhn.fhir.model.dstu.valueset.SlicingRulesEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.Dstu1BundleFactory;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
import ca.uhn.fhir.rest.server.provider.ServerProfileProvider;
public class FhirDstu1 implements IFhirVersion {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirDstu1.class);
// private Map<RuntimeChildDeclaredExtensionDefinition, String> myExtensionDefToCode = new
// HashMap<RuntimeChildDeclaredExtensionDefinition, String>();
private String myId;
@Override
public ServerConformanceProvider createServerConformanceProvider(RestfulServer theServer) {
return new ServerConformanceProvider(theServer);
}
@Override
public IResourceProvider createServerProfilesProvider(RestfulServer theRestfulServer) {
return new ServerProfileProvider(theRestfulServer);
}
private void fillBasics(StructureElement theElement, BaseRuntimeElementDefinition<?> def, LinkedList<String> path, BaseRuntimeDeclaredChildDefinition theChild) {
if (path.isEmpty()) {
path.add(def.getName());
theElement.setName(def.getName());
} else {
path.add(WordUtils.uncapitalize(theChild.getElementName()));
theElement.setName(theChild.getElementName());
}
theElement.setPath(StringUtils.join(path, '.'));
}
private void fillExtensions(Structure theStruct, LinkedList<String> path, List<RuntimeChildDeclaredExtensionDefinition> extList, String elementName, boolean theIsModifier) {
if (extList.size() > 0) {
StructureElement extSlice = theStruct.addElement();
extSlice.setName(elementName);
extSlice.setPath(join(path, '.') + '.' + elementName);
extSlice.getSlicing().getDiscriminator().setValue("url");
extSlice.getSlicing().setOrdered(false);
extSlice.getSlicing().setRules(SlicingRulesEnum.OPEN);
extSlice.getDefinition().addType().setCode(DataTypeEnum.EXTENSION);
for (RuntimeChildDeclaredExtensionDefinition nextExt : extList) {
StructureElement nextProfileExt = theStruct.addElement();
nextProfileExt.getDefinition().setIsModifier(theIsModifier);
nextProfileExt.setName(extSlice.getName());
nextProfileExt.setPath(extSlice.getPath());
fillMinAndMaxAndDefinitions(nextExt, nextProfileExt);
StructureElementDefinitionType type = nextProfileExt.getDefinition().addType();
type.setCode(DataTypeEnum.EXTENSION);
if (nextExt.isDefinedLocally()) {
type.setProfile(nextExt.getExtensionUrl().substring(nextExt.getExtensionUrl().indexOf('#')));
} else {
type.setProfile(nextExt.getExtensionUrl());
}
}
} else {
StructureElement extSlice = theStruct.addElement();
extSlice.setName(elementName);
extSlice.setPath(join(path, '.') + '.' + elementName);
extSlice.getDefinition().setIsModifier(theIsModifier);
extSlice.getDefinition().addType().setCode(DataTypeEnum.EXTENSION);
extSlice.getDefinition().setMin(0);
extSlice.getDefinition().setMax("*");
}
}
private void fillMinAndMaxAndDefinitions(BaseRuntimeDeclaredChildDefinition child, StructureElement elem) {
elem.getDefinition().setMin(child.getMin());
if (child.getMax() == Child.MAX_UNLIMITED) {
elem.getDefinition().setMax("*");
} else {
elem.getDefinition().setMax(Integer.toString(child.getMax()));
}
if (isNotBlank(child.getShortDefinition())) {
elem.getDefinition().getShort().setValue(child.getShortDefinition());
}
if (isNotBlank(child.getFormalDefinition())) {
elem.getDefinition().getFormal().setValue(child.getFormalDefinition());
}
}
private void fillName(StructureElement elem, BaseRuntimeElementDefinition<?> nextDef, String theServerBase) {
assert nextDef != null;
StructureElementDefinitionType type = elem.getDefinition().addType();
String name = nextDef.getName();
DataTypeEnum fromCodeString = DataTypeEnum.VALUESET_BINDER.fromCodeString(name);
if (fromCodeString == null) {
throw new ConfigurationException(Msg.code(767) + "Unknown type: " + name);
}
type.setCode(fromCodeString);
}
private void fillProfile(Structure theStruct, StructureElement theElement, BaseRuntimeElementDefinition<?> def, LinkedList<String> path, BaseRuntimeDeclaredChildDefinition theChild, String theServerBase) {
fillBasics(theElement, def, path, theChild);
String expectedPath = StringUtils.join(path, '.');
ourLog.debug("Filling profile for: {} - Path: {}", expectedPath);
String name = def.getName();
if (!expectedPath.equals(name)) {
path.pollLast();
theElement.getDefinition().getNameReference().setValue(def.getName());
return;
}
fillExtensions(theStruct, path, def.getExtensionsNonModifier(), "extension", false);
fillExtensions(theStruct, path, def.getExtensionsModifier(), "modifierExtension", true);
if (def.getChildType() == ChildTypeEnum.RESOURCE) {
StructureElement narrative = theStruct.addElement();
narrative.setName("text");
narrative.setPath(join(path, '.') + ".text");
narrative.getDefinition().addType().setCode(DataTypeEnum.NARRATIVE);
narrative.getDefinition().setIsModifier(false);
narrative.getDefinition().setMin(0);
narrative.getDefinition().setMax("1");
StructureElement contained = theStruct.addElement();
contained.setName("contained");
contained.setPath(join(path, '.') + ".contained");
contained.getDefinition().addType().getCode().setValue("Resource");
contained.getDefinition().setIsModifier(false);
contained.getDefinition().setMin(0);
contained.getDefinition().setMax("1");
}
if (def instanceof BaseRuntimeElementCompositeDefinition) {
BaseRuntimeElementCompositeDefinition<?> cdef = ((BaseRuntimeElementCompositeDefinition<?>) def);
for (BaseRuntimeChildDefinition nextChild : cdef.getChildren()) {
if (nextChild instanceof RuntimeChildUndeclaredExtensionDefinition) {
continue;
}
if (nextChild instanceof RuntimeChildExtension) {
continue;
}
BaseRuntimeDeclaredChildDefinition child = (BaseRuntimeDeclaredChildDefinition) nextChild;
StructureElement elem = theStruct.addElement();
fillMinAndMaxAndDefinitions(child, elem);
if (child instanceof RuntimeChildResourceBlockDefinition) {
RuntimeResourceBlockDefinition nextDef = (RuntimeResourceBlockDefinition) child.getSingleChildOrThrow();
fillProfile(theStruct, elem, nextDef, path, child, theServerBase);
} else if (child instanceof RuntimeChildContainedResources) {
// ignore
} else if (child instanceof RuntimeChildDeclaredExtensionDefinition) {
throw new IllegalStateException(Msg.code(768) + "Unexpected child type: " + child.getClass().getCanonicalName());
} else if (child instanceof RuntimeChildCompositeDatatypeDefinition || child instanceof RuntimeChildPrimitiveDatatypeDefinition || child instanceof RuntimeChildChoiceDefinition || child instanceof RuntimeChildResourceDefinition) {
Iterator<String> childNamesIter = child.getValidChildNames().iterator();
String nextName = childNamesIter.next();
BaseRuntimeElementDefinition<?> nextDef = child.getChildByName(nextName);
fillBasics(elem, nextDef, path, child);
fillName(elem, nextDef, theServerBase);
while (childNamesIter.hasNext()) {
nextDef = child.getChildByName(childNamesIter.next());
fillName(elem, nextDef, theServerBase);
}
path.pollLast();
} else {
throw new IllegalStateException(Msg.code(769) + "Unexpected child type: " + child.getClass().getCanonicalName());
}
}
} else {
throw new IllegalStateException(Msg.code(770) + "Unexpected child type: " + def.getClass().getCanonicalName());
}
path.pollLast();
}
@Override
public IResource generateProfile(RuntimeResourceDefinition theRuntimeResourceDefinition, String theServerBase) {
Profile retVal = new Profile();
RuntimeResourceDefinition def = theRuntimeResourceDefinition;
myId = def.getId();
if (StringUtils.isBlank(myId)) {
myId = theRuntimeResourceDefinition.getName().toLowerCase();
}
retVal.setId(new IdDt(myId));
// Scan for extensions
scanForExtensions(retVal, def, new HashMap<RuntimeChildDeclaredExtensionDefinition, String>());
Collections.sort(retVal.getExtensionDefn(), new Comparator<ExtensionDefn>() {
@Override
public int compare(ExtensionDefn theO1, ExtensionDefn theO2) {
return theO1.getCode().compareTo(theO2.getCode());
}
});
// Scan for children
retVal.setName(def.getName());
Structure struct = retVal.addStructure();
LinkedList<String> path = new LinkedList<String>();
StructureElement element = struct.addElement();
element.getDefinition().setMin(1);
element.getDefinition().setMax("1");
fillProfile(struct, element, def, path, null, theServerBase);
retVal.getStructure().get(0).getElement().get(0).getDefinition().addType().getCode().setValue("Resource");
return retVal;
}
@Override
public Class<? extends BaseContainedDt> getContainedType() {
return ContainedDt.class;
}
@Override
public InputStream getFhirVersionPropertiesFile() {
InputStream str = FhirDstu1.class.getResourceAsStream("/ca/uhn/fhir/model/dstu/fhirversion.properties");
if (str == null) {
str = FhirDstu1.class.getResourceAsStream("ca/uhn/fhir/model/dstu/fhirversion.properties");
}
if (str == null) {
throw new ConfigurationException(Msg.code(771) + "Can not find model property file on classpath: " + "/ca/uhn/fhir/model/dstu/model.properties");
}
return str;
}
@Override
public IPrimitiveType<Date> getLastUpdated(IBaseResource theResource) {
return ResourceMetadataKeyEnum.UPDATED.get((IResource) theResource);
}
@Override
public String getPathToSchemaDefinitions() {
return "/ca/uhn/fhir/model/dstu/schema";
}
@Override
public Class<? extends BaseResourceReferenceDt> getResourceReferenceType() {
return ResourceReferenceDt.class;
}
@Override
public FhirVersionEnum getVersion() {
return FhirVersionEnum.DSTU1;
}
@Override
public IVersionSpecificBundleFactory newBundleFactory(FhirContext theContext) {
return new Dstu1BundleFactory(theContext);
}
@Override
public BaseCodingDt newCodingDt() {
return new CodingDt();
}
private Map<RuntimeChildDeclaredExtensionDefinition, String> scanForExtensions(Profile theProfile, BaseRuntimeElementDefinition<?> def, Map<RuntimeChildDeclaredExtensionDefinition, String> theExtensionDefToCode) {
BaseRuntimeElementCompositeDefinition<?> cdef = ((BaseRuntimeElementCompositeDefinition<?>) def);
for (RuntimeChildDeclaredExtensionDefinition nextChild : cdef.getExtensions()) {
if (theExtensionDefToCode.containsKey(nextChild)) {
continue;
}
if (nextChild.isDefinedLocally() == false) {
continue;
}
ExtensionDefn defn = theProfile.addExtensionDefn();
String code = null;
if (nextChild.getExtensionUrl().contains("#") && !nextChild.getExtensionUrl().endsWith("#")) {
code = nextChild.getExtensionUrl().substring(nextChild.getExtensionUrl().indexOf('#') + 1);
} else {
throw new ConfigurationException(Msg.code(772) + "Locally defined extension has no '#[code]' part in extension URL: " + nextChild.getExtensionUrl());
}
defn.setCode(code);
if (theExtensionDefToCode.values().contains(code)) {
throw new IllegalStateException(Msg.code(773) + "Duplicate extension code: " + code);
}
theExtensionDefToCode.put(nextChild, code);
if (nextChild.getChildType() != null && IPrimitiveDatatype.class.isAssignableFrom(nextChild.getChildType())) {
RuntimePrimitiveDatatypeDefinition pdef = (RuntimePrimitiveDatatypeDefinition) nextChild.getSingleChildOrThrow();
defn.getDefinition().addType().setCode(DataTypeEnum.VALUESET_BINDER.fromCodeString(pdef.getName()));
} else if (nextChild.getChildType() != null && ICompositeDatatype.class.isAssignableFrom(nextChild.getChildType())) {
RuntimeCompositeDatatypeDefinition pdef = (RuntimeCompositeDatatypeDefinition) nextChild.getSingleChildOrThrow();
defn.getDefinition().addType().setCode(DataTypeEnum.VALUESET_BINDER.fromCodeString(pdef.getName()));
} else {
BaseRuntimeElementDefinition<?> singleChildOrThrow = nextChild.getSingleChildOrThrow();
if (singleChildOrThrow instanceof RuntimeResourceBlockDefinition) {
RuntimeResourceBlockDefinition pdef = (RuntimeResourceBlockDefinition) singleChildOrThrow;
scanForExtensions(theProfile, pdef, theExtensionDefToCode);
for (RuntimeChildDeclaredExtensionDefinition nextChildExt : pdef.getExtensions()) {
StructureElementDefinitionType type = defn.getDefinition().addType();
type.setCode(DataTypeEnum.EXTENSION);
type.setProfile("#" + theExtensionDefToCode.get(nextChildExt));
}
}
}
}
return theExtensionDefToCode;
}
@Override
public IIdType newIdType() {
return new IdDt();
}
@Override
public IContextValidationSupport<?, ?, ?, ?, ?, ?> createValidationSupport() {
throw new UnsupportedOperationException(Msg.code(774) + "Validation support is not supported in DSTU1 contexts");
}
@Override
public IFluentPath createFluentPathExecutor(FhirContext theFhirContext) {
throw new UnsupportedOperationException(Msg.code(775) + "FluentPath is not supported in DSTU1 contexts");
}
}

View File

@ -1,28 +0,0 @@
package ca.uhn.fhir.model.dstu.api;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 ca.uhn.fhir.model.dstu.resource.BaseResource;
public abstract class BaseResourceDstu extends BaseResource {
}

View File

@ -1,30 +0,0 @@
package ca.uhn.fhir.model.dstu.composite;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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%
*/
@DatatypeDef(name="AgeDt")
public class AgeDt extends QuantityDt {
// TODO: implement restricions
}

View File

@ -1,53 +0,0 @@
package ca.uhn.fhir.model.dstu.composite;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.ArrayList;
import java.util.List;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
@DatatypeDef(name = "contained")
public class ContainedDt extends BaseContainedDt {
@Child(name = "resource", type = IResource.class, order = 0, min = 0, max = Child.MAX_UNLIMITED)
private List<IResource> myContainedResources;
public List<IResource> getContainedResources() {
if (myContainedResources == null) {
myContainedResources = new ArrayList<IResource>();
}
return myContainedResources;
}
public void setContainedResources(List<IResource> theContainedResources) {
myContainedResources = theContainedResources;
}
@Override
public boolean isEmpty() {
return myContainedResources == null || myContainedResources.size() == 0;
}
}

View File

@ -1,33 +0,0 @@
package ca.uhn.fhir.model.dstu.composite;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 ca.uhn.fhir.model.api.annotation.DatatypeDef;
@DatatypeDef(name = "Duration")
public class DurationDt extends QuantityDt {
// TODO: implement restricions
// There SHALL be a code if there is a value and it SHALL be an expression of length. If system is present, it SHALL be UCUM.
// (f:code or not(f:value)) and (not(exists(f:system)) or f:system/@value='http://unitsofmeasure.org')
}

View File

@ -1,176 +0,0 @@
package ca.uhn.fhir.model.dstu.composite;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.List;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.XhtmlDt;
/**
* HAPI/FHIR <b>Narrative</b> Datatype
* (A human-readable formatted text, including images)
*
* <p>
* <b>Definition:</b>
* A human-readable formatted text, including images
* </p>
*
* <p>
* <b>Requirements:</b>
*
* </p>
*/
@DatatypeDef(name="Narrative")
public class NarrativeDt extends BaseNarrativeDt<NarrativeStatusEnum> {
@Child(name="status", type=CodeDt.class, order=0, min=1, max=1)
private BoundCodeDt<NarrativeStatusEnum> myStatus;
@Child(name="div", type=XhtmlDt.class, order=1, min=1, max=1)
private XhtmlDt myDiv;
public NarrativeDt() {
// nothing
}
public NarrativeDt(XhtmlDt theDiv, NarrativeStatusEnum theStatus) {
setDiv(theDiv);
setStatus(theStatus);
}
@Override
public boolean isEmpty() {
return ca.uhn.fhir.util.ElementUtil.isEmpty( myStatus, myDiv );
}
@Override
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(Class<T> theType) {
return ca.uhn.fhir.util.ElementUtil.allPopulatedChildElements( theType, myStatus, myDiv );
}
/**
* Gets the value(s) for <b>status</b> (generated | extensions | additional).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data
* </p>
*/
public BoundCodeDt<NarrativeStatusEnum> getStatus() {
if (myStatus == null) {
myStatus = new BoundCodeDt<NarrativeStatusEnum>(NarrativeStatusEnum.VALUESET_BINDER);
}
return myStatus;
}
/**
* Sets the value(s) for <b>status</b> (generated | extensions | additional)
*
* <p>
* <b>Definition:</b>
* The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data
* </p>
*/
public void setStatus(BoundCodeDt<NarrativeStatusEnum> theValue) {
myStatus = theValue;
}
/**
* Sets the value(s) for <b>status</b> (generated | extensions | additional)
*
* <p>
* <b>Definition:</b>
* The status of the narrative - whether it's entirely generated (from just the defined data or the extensions too), or whether a human authored it and it may contain additional data
* </p>
*/
public void setStatus(NarrativeStatusEnum theValue) {
getStatus().setValueAsEnum(theValue);
}
/**
* Gets the value(s) for <b>div</b> (Limited xhtml content).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* The actual narrative content, a stripped down version of XHTML
* </p>
*/
public XhtmlDt getDiv() {
if (myDiv == null) {
myDiv = new XhtmlDt();
}
return myDiv;
}
/**
* Sets the value(s) for <b>div</b> (Limited xhtml content)
*
* <p>
* <b>Definition:</b>
* The actual narrative content, a stripped down version of XHTML
* </p>
*/
public void setDiv(XhtmlDt theValue) {
myDiv = theValue;
}
/**
* Sets the value using a textual DIV (or simple text block which will be
* converted to XHTML)
*/
public void setDiv(String theTextDiv) {
myDiv = new XhtmlDt(theTextDiv);
}
}

View File

@ -1,242 +0,0 @@
package ca.uhn.fhir.model.dstu.composite;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.List;
import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
/**
* HAPI/FHIR <b>ResourceReferenceDt</b> Datatype
* (A reference from one resource to another)
*
* <p>
* <b>Definition:</b>
* A reference from one resource to another
* </p>
*
* <p>
* <b>Requirements:</b>
*
* </p>
*/
@DatatypeDef(name="ResourceReferenceDt")
public class ResourceReferenceDt
extends BaseResourceReferenceDt implements ICompositeDatatype
{
/**
* Constructor
*/
public ResourceReferenceDt() {
// nothing
}
/**
* Constructor which creates a resource reference containing the actual resource in question.
* <p>
* <b> When using this in a server:</b> Generally if this is serialized, it will be serialized as a contained
* resource, so this should not be used if the intent is not to actually supply the referenced resource. This is not
* a hard-and-fast rule however, as the server can be configured to not serialized this resource, or to load an ID
* and contain even if this constructor is not used.
* </p>
*
* @param theResource
* The resource instance
*/
@SimpleSetter()
public ResourceReferenceDt(IResource theResource) {
super(theResource);
}
/**
* Constructor which accepts a reference directly (this can be an ID, a partial/relative URL or a complete/absolute
* URL)
*
* @param theId
* The reference itself
*/
public ResourceReferenceDt(String theId) {
setReference(new IdDt(theId));
}
/**
* Constructor which accepts a reference directly (this can be an ID, a partial/relative URL or a complete/absolute
* URL)
*
* @param theResourceId
* The reference itself
*/
public ResourceReferenceDt(IIdType theResourceId) {
setReference(theResourceId);
}
@Child(name="reference", type=IdDt.class, order=0, min=0, max=1)
@Description(
shortDefinition="Relative, internal or absolute URL reference",
formalDefinition="A reference to a location at which the other resource is found. The reference may a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources"
)
private IdDt myReference;
@Child(name="display", type=StringDt.class, order=1, min=0, max=1)
@Description(
shortDefinition="Text alternative for the resource",
formalDefinition="Plain text narrative that identifies the resource in addition to the resource reference"
)
private StringDt myDisplay;
@Override
public boolean isEmpty() {
return super.isBaseEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty( myReference, myDisplay);
}
@Override
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(Class<T> theType) {
return ca.uhn.fhir.util.ElementUtil.allPopulatedChildElements(theType, myReference, myDisplay);
}
/**
* Gets the value(s) for <b>reference</b> (Relative, internal or absolute URL reference).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* A reference to a location at which the other resource is found. The reference may a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources
* </p>
*/
public IdDt getReference() {
if (myReference == null) {
myReference = new IdDt();
}
return myReference;
}
@Override
public IdDt getReferenceElement() {
return getReference();
}
/**
* Sets the value(s) for <b>reference</b> (Relative, internal or absolute URL reference)
*
* <p>
* <b>Definition:</b>
* A reference to a location at which the other resource is found. The reference may a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources
* </p>
*/
public ResourceReferenceDt setReference(IdDt theValue) {
myReference = theValue;
return this;
}
/**
* Sets the value for <b>reference</b> (Relative, internal or absolute URL reference)
*
* <p>
* <b>Definition:</b>
* A reference to a location at which the other resource is found. The reference may a relative reference, in which case it is relative to the service base URL, or an absolute URL that resolves to the location where the resource is found. The reference may be version specific or not. If the reference is not to a FHIR RESTful server, then it should be assumed to be version specific. Internal fragment references (start with '#') refer to contained resources
* </p>
*/
public ResourceReferenceDt setReference( String theId) {
myReference = new IdDt(theId);
return this;
}
/**
* Gets the value(s) for <b>display</b> (Text alternative for the resource).
* creating it if it does
* not exist. Will not return <code>null</code>.
*
* <p>
* <b>Definition:</b>
* Plain text narrative that identifies the resource in addition to the resource reference
* </p>
*/
public StringDt getDisplay() {
if (myDisplay == null) {
myDisplay = new StringDt();
}
return myDisplay;
}
/**
* Sets the value(s) for <b>display</b> (Text alternative for the resource)
*
* <p>
* <b>Definition:</b>
* Plain text narrative that identifies the resource in addition to the resource reference
* </p>
*/
public ResourceReferenceDt setDisplay(StringDt theValue) {
myDisplay = theValue;
return this;
}
/**
* Sets the value for <b>display</b> (Text alternative for the resource)
*
* <p>
* <b>Definition:</b>
* Plain text narrative that identifies the resource in addition to the resource reference
* </p>
*/
public ResourceReferenceDt setDisplay( String theString) {
myDisplay = new StringDt(theString);
return this;
}
@Override
public StringDt getDisplayElement() {
return getDisplay();
}
}

View File

@ -1,410 +0,0 @@
package ca.uhn.fhir.model.dstu.resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseMetaType;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.model.api.BaseElement;
import ca.uhn.fhir.model.api.ICompositeElement;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.resource.ResourceMetadataMap;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import ca.uhn.fhir.util.ElementUtil;
public abstract class BaseResource extends BaseElement implements IResource {
/**
* <b>Fluent Client</b> search parameter constant for <b>_id</b>
* <p>
* Description: <b>the _id of a resource</b><br>
* Type: <b>string</b><br>
* Path: <b>Resource._id</b><br>
* </p>
*/
public static final StringClientParam RES_ID = new StringClientParam(BaseResource.SP_RES_ID);
/**
* Search parameter constant for <b>_id</b>
*/
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="string" )
public static final String SP_RES_ID = "_id";
@Child(name = "contained", order = 2, min = 0, max = 1)
private ContainedDt myContained;
private IdDt myId;
@Child(name = "language", order = 0, min = 0, max = 1)
private CodeDt myLanguage;
private ResourceMetadataMap myResourceMetadata;
@Child(name = "text", order = 1, min = 0, max = 1)
private NarrativeDt myText;
/**
* NOP implementation of this method.
*
* @see ICompositeElement#getAllPopulatedChildElementsOfType(Class) for an explanation of why you
* don't need to override this method
*/
@Override
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(Class<T> theType) {
return Collections.emptyList();
}
@Override
public ContainedDt getContained() {
if (myContained == null) {
myContained = new ContainedDt();
}
return myContained;
}
public IdDt getId() {
if (myId == null) {
myId = new IdDt();
}
return myId;
}
@Override
public IIdType getIdElement() {
return getId();
}
@Override
public CodeDt getLanguage() {
if (myLanguage == null) {
myLanguage = new CodeDt();
}
return myLanguage;
}
@Override
public IBaseMetaType getMeta() {
return new IBaseMetaType() {
private static final long serialVersionUID = 1L;
@Override
public IBaseMetaType addProfile(String theProfile) {
ArrayList<IdDt> newTagList = new ArrayList<IdDt>();
List<IdDt> existingTagList = ResourceMetadataKeyEnum.PROFILES.get(BaseResource.this);
if (existingTagList != null) {
newTagList.addAll(existingTagList);
}
ResourceMetadataKeyEnum.PROFILES.put(BaseResource.this, newTagList);
IdDt tag = new IdDt(theProfile);
newTagList.add(tag);
return this;
}
@Override
public IBaseCoding addSecurity() {
List<BaseCodingDt> tagList = ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this);
if (tagList == null) {
tagList = new ArrayList<BaseCodingDt>();
ResourceMetadataKeyEnum.SECURITY_LABELS.put(BaseResource.this, tagList);
}
CodingDt tag = new CodingDt();
tagList.add(tag);
return asBaseCoding(tag);
}
@Override
public IBaseCoding addTag() {
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this);
if (tagList == null) {
tagList = new TagList();
ResourceMetadataKeyEnum.TAG_LIST.put(BaseResource.this, tagList);
}
Tag tag = new Tag();
tagList.add(tag);
return tag;
}
/**
* This view is used because the old DSTU1 BaseCodingDt can't implements IBaseCoding
*/
private IBaseCoding asBaseCoding(final BaseCodingDt theCoding) {
return new IBaseCoding() {
private static final long serialVersionUID = 1L;
@Override
public String getCode() {
return theCoding.getCodeElement().getValue();
}
@Override
public String getDisplay() {
return theCoding.getDisplayElement().getValue();
}
@Override
public List<String> getFormatCommentsPost() {
return Collections.emptyList();
}
@Override
public List<String> getFormatCommentsPre() {
return Collections.emptyList();
}
@Override
public String getSystem() {
return theCoding.getSystemElement().getValue();
}
@Override
public boolean hasFormatComment() {
return false;
}
@Override
public boolean isEmpty() {
return ElementUtil.isEmpty(getSystem(), getCode(), getDisplay());
}
@Override
public IBaseCoding setCode(String theTerm) {
theCoding.setCode(theTerm);
return this;
}
@Override
public IBaseCoding setDisplay(String theLabel) {
theCoding.setDisplay(theLabel);
return this;
}
@Override
public IBaseCoding setSystem(String theScheme) {
theCoding.setSystem(theScheme);
return this;
}
};
}
@Override
public List<String> getFormatCommentsPost() {
return Collections.emptyList();
}
@Override
public List<String> getFormatCommentsPre() {
return Collections.emptyList();
}
@Override
public Date getLastUpdated() {
InstantDt lu = ResourceMetadataKeyEnum.UPDATED.get(BaseResource.this);
if (lu != null) {
return lu.getValue();
}
return null;
}
@Override
public List<? extends IPrimitiveType<String>> getProfile() {
ArrayList<IPrimitiveType<String>> retVal = new ArrayList<IPrimitiveType<String>>();
List<IdDt> profilesList = ResourceMetadataKeyEnum.PROFILES.get(BaseResource.this);
if (profilesList == null) {
return Collections.emptyList();
}
for (IdDt next : profilesList) {
retVal.add(next);
}
return Collections.unmodifiableList(retVal);
}
@Override
public List<? extends IBaseCoding> getSecurity() {
ArrayList<IBaseCoding> retVal = new ArrayList<IBaseCoding>();
List<BaseCodingDt> labelsList = ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this);
if (labelsList == null) {
return Collections.emptyList();
}
for (BaseCodingDt next : labelsList) {
retVal.add(asBaseCoding(next));
}
return Collections.unmodifiableList(retVal);
}
@Override
public IBaseCoding getSecurity(String theSystem, String theCode) {
for (BaseCodingDt next : ResourceMetadataKeyEnum.SECURITY_LABELS.get(BaseResource.this)) {
if (theSystem.equals(next.getSystemElement().getValue()) && theCode.equals(next.getCodeElement().getValue())) {
return asBaseCoding(next);
}
}
return null;
}
@Override
public List<? extends IBaseCoding> getTag() {
ArrayList<IBaseCoding> retVal = new ArrayList<IBaseCoding>();
for (Tag next : ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this)) {
retVal.add(next);
}
return Collections.unmodifiableList(retVal);
}
@Override
public IBaseCoding getTag(String theSystem, final String theCode) {
for (final Tag next : ResourceMetadataKeyEnum.TAG_LIST.get(BaseResource.this)) {
if (next.getScheme().equals(theSystem) && next.getTerm().equals(theCode)) {
return next;
}
}
return null;
}
@Override
public String getVersionId() {
return getId().getVersionIdPart();
}
@Override
public boolean hasFormatComment() {
return false;
}
@Override
public boolean isEmpty() {
return getResourceMetadata().isEmpty();
}
@Override
public IBaseMetaType setLastUpdated(Date theHeaderDateValue) {
ResourceMetadataKeyEnum.UPDATED.put(BaseResource.this, new InstantDt(theHeaderDateValue));
return this;
}
@Override
public IBaseMetaType setVersionId(String theVersionId) {
setId(getId().withVersion(theVersionId));
return this;
}
};
}
@Override
public ResourceMetadataMap getResourceMetadata() {
if (myResourceMetadata == null) {
myResourceMetadata = new ResourceMetadataMap();
}
return myResourceMetadata;
}
@Override
public NarrativeDt getText() {
if (myText == null) {
myText = new NarrativeDt();
}
return myText;
}
/**
* Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
* content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
*/
@Override
protected boolean isBaseEmpty() {
return super.isBaseEmpty() && ElementUtil.isEmpty(myLanguage, myText, myId);
}
public void setContained(ContainedDt theContained) {
myContained = theContained;
}
public void setId(IdDt theId) {
myId = theId;
}
public BaseResource setId(IIdType theId) {
if (theId instanceof IdDt) {
myId = (IdDt) theId;
} else if (theId != null) {
myId = new IdDt(theId.getValue());
}
return this;
}
public BaseResource setId(String theId) {
if (theId == null) {
myId = null;
} else {
myId = new IdDt(theId);
}
return this;
}
@Override
public void setLanguage(CodeDt theLanguage) {
myLanguage = theLanguage;
}
@Override
public void setResourceMetadata(ResourceMetadataMap theMap) {
Validate.notNull(theMap, "The Map must not be null");
myResourceMetadata = theMap;
}
public void setText(NarrativeDt theText) {
myText = theText;
}
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
b.append("id", getId().toUnqualified());
return b.toString();
}
}

View File

@ -1,115 +0,0 @@
package ca.uhn.fhir.model.dstu.resource;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.Collections;
import java.util.List;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.IElement;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.model.primitive.Base64BinaryDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.util.ElementUtil;
@ResourceDef(name = "Binary", profile = "http://hl7.org/fhir/profiles/Binary", id = "binary")
public class Binary extends BaseResource implements IBaseBinary {
@Child(name = "content", order = 1)
private Base64BinaryDt myContent = new Base64BinaryDt();
@Child(name = "contentType", order = 0)
private StringDt myContentType;
/**
* Constructor
*/
public Binary() {
// nothing
}
/**
* Constructor
*
* @param theContentType
* The content type
* @param theContent
* The binary contents
*/
public Binary(String theContentType, byte[] theContent) {
setContentType(theContentType);
setContent(theContent);
}
@Override
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(Class<T> theType) {
return Collections.emptyList();
}
public byte[] getContent() {
return myContent.getValue();
}
public String getContentAsBase64() {
return myContent.getValueAsString();
}
public String getContentType() {
if (myContentType == null) {
return null;
}
return myContentType.getValue();
}
@Override
public boolean isEmpty() {
return (myContent.isEmpty()) && ElementUtil.isEmpty(myContentType);
}
public Binary setContent(byte[] theContent) {
myContent.setValue(theContent);
return this;
}
public Binary setContentAsBase64(String theContent) {
myContent.setValueAsString(theContent);
return this;
}
public Binary setContentType(String theContentType) {
myContentType = new StringDt(theContentType);
return this;
}
@Override
public String getResourceName() {
return Binary.class.getName();
}
@Override
public FhirVersionEnum getStructureFhirVersionEnum() {
return FhirVersionEnum.DSTU1;
}
}

View File

@ -1,125 +0,0 @@
package ca.uhn.fhir.model.primitive;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 static org.apache.commons.lang3.StringUtils.defaultString;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import ca.uhn.fhir.model.api.IBoundCodeableConcept;
import ca.uhn.fhir.model.api.IValueSetEnumBinder;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
@DatatypeDef(name = "CodeableConcept", isSpecialization = true)
public class BoundCodeableConceptDt<T extends Enum<?>> extends CodeableConceptDt implements IBoundCodeableConcept {
private IValueSetEnumBinder<T> myBinder;
/**
* Constructor
*/
public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder) {
myBinder = theBinder;
}
/**
* Constructor
*/
public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder, T theValue) {
myBinder = theBinder;
setValueAsEnum(theValue);
}
/**
* Constructor
*/
public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder, Collection<T> theValues) {
myBinder = theBinder;
setValueAsEnum(theValues);
}
/**
* Sets the {@link #getCoding()} to contain a coding with the code and
* system defined by the given enumerated types, AND clearing any existing
* codings first. If theValue is null, existing codings are cleared and no
* codings are added.
*
* @param theValues
* The values to add, or <code>null</code>
*/
public void setValueAsEnum(Collection<T> theValues) {
getCoding().clear();
if (theValues != null) {
for (T next : theValues) {
getCoding().add(new CodingDt(myBinder.toSystemString(next), myBinder.toCodeString(next)));
}
}
}
/**
* Sets the {@link #getCoding()} to contain a coding with the code and
* system defined by the given enumerated type, AND clearing any existing
* codings first. If theValue is null, existing codings are cleared and no
* codings are added.
*
* @param theValue
* The value to add, or <code>null</code>
*/
public void setValueAsEnum(T theValue) {
getCoding().clear();
if (theValue == null) {
return;
}
getCoding().add(new CodingDt(myBinder.toSystemString(theValue), myBinder.toCodeString(theValue)));
}
/**
* Loops through the {@link #getCoding() codings} in this codeable concept
* and returns the first bound enumerated type that matches. <b>Use
* caution</b> using this method, see the return description for more
* information.
*
* @return Returns the bound enumerated type, or <code>null</code> if none
* are found. Note that a null return value doesn't neccesarily
* imply that this Codeable Concept has no codes, only that it has
* no codes that match the enum.
*/
public Set<T> getValueAsEnum() {
Set<T> retVal = new HashSet<T>();
for (CodingDt next : getCoding()) {
if (next == null) {
continue;
}
T nextT = myBinder.fromCodeString(defaultString(next.getCode().getValue()), defaultString(next.getSystem().getValueAsString()));
if (nextT != null) {
retVal.add(nextT);
} else {
// TODO: throw special exception type?
}
}
return retVal;
}
}

View File

@ -1,373 +0,0 @@
package ca.uhn.fhir.rest.server;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 ca.uhn.fhir.i18n.Msg;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ResourceReferenceInfo;
public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
private Bundle myBundle;
private FhirContext myContext;
public Dstu1BundleFactory(FhirContext theContext) {
myContext = theContext;
}
private void addProfileIfNeeded(IRestfulServer<?> theServer, String theServerBase, IBaseResource nextRes) {
RuntimeResourceDefinition def = theServer.getFhirContext().getResourceDefinition(nextRes);
if (theServer.getAddProfileTag() == AddProfileTagEnum.ALWAYS || !def.isStandardType()) {
TagList tl = ResourceMetadataKeyEnum.TAG_LIST.get((IResource) nextRes);
if (tl == null) {
tl = new TagList();
ResourceMetadataKeyEnum.TAG_LIST.put((IResource) nextRes, tl);
}
RuntimeResourceDefinition nextDef = myContext.getResourceDefinition(nextRes);
String profile = nextDef.getResourceProfile(theServerBase);
if (isNotBlank(profile)) {
tl.add(new Tag(Tag.HL7_ORG_PROFILE_TAG, profile, null));
}
}
}
@Override
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
if (myBundle == null) {
myBundle = new Bundle();
}
List<IResource> includedResources = new ArrayList<IResource>();
Set<IdDt> addedResourceIds = new HashSet<IdDt>();
for (IBaseResource next : theResult) {
if (next.getIdElement().isEmpty() == false) {
addedResourceIds.add((IdDt) next.getIdElement());
}
}
for (IBaseResource nextBaseRes : theResult) {
IResource next = (IResource) nextBaseRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
do {
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
for (ResourceReferenceInfo nextRefInfo : references) {
if (!theBundleInclusionRule.shouldIncludeReferencedResource(nextRefInfo, theIncludes))
continue;
IResource nextRes = (IResource) nextRefInfo.getResourceReference().getResource();
if (nextRes != null) {
if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IdDt id = nextRes.getId();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceName(nextRes);
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRes);
}
}
}
}
includedResources.addAll(addedResourcesThisPass);
// Linked resources may themselves have linked resources
references = new ArrayList<ResourceReferenceInfo>();
for (IResource iResource : addedResourcesThisPass) {
List<ResourceReferenceInfo> newReferences = myContext.newTerser().getAllResourceReferences(iResource);
references.addAll(newReferences);
}
} while (references.isEmpty() == false);
myBundle.addResource(next, myContext, theServerBase);
}
/*
* Actually add the resources to the bundle
*/
for (IResource next : includedResources) {
BundleEntry entry = myBundle.addResource(next, myContext, theServerBase);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
if (entry.getSearchMode().isEmpty()) {
entry.getSearchMode().setValueAsEnum(BundleEntrySearchModeEnum.INCLUDE);
}
}
}
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theCompleteUrl, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated) {
if (myBundle.getAuthorName().isEmpty()) {
myBundle.getAuthorName().setValue(theAuthor);
}
if (theLastUpdated != null && myBundle.getUpdated().isEmpty() && isNotBlank(theLastUpdated.getValueAsString())) {
myBundle.getUpdated().setValueAsString(theLastUpdated.getValueAsString());
}
if (myBundle.getBundleId().isEmpty()) {
myBundle.getBundleId().setValue(UUID.randomUUID().toString());
}
if (myBundle.getLinkBase().isEmpty()) {
myBundle.getLinkBase().setValue(theServerBase);
}
if (myBundle.getLinkSelf().isEmpty()) {
myBundle.getLinkSelf().setValue(theCompleteUrl);
}
if (theBundleType != null && myBundle.getType().isEmpty()) {
myBundle.getType().setValueAsString(theBundleType.getCode());
}
if (myBundle.getTotalResults().isEmpty() && theTotalResults != null) {
myBundle.getTotalResults().setValue(theTotalResults);
}
}
@Override
public Bundle getDstu1Bundle() {
return myBundle;
}
@Override
public IResource getResourceBundle() {
return null;
}
@Override
public void initializeBundleFromBundleProvider(IRestfulServer<?> theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
int numToReturn;
String searchId = null;
List<IBaseResource> resourceList;
Integer numTotalResults = theResult.size();
if (theServer.getPagingProvider() == null) {
numToReturn = numTotalResults;
resourceList = theResult.getResources(0, numToReturn);
RestfulServerUtils.validateResourceListNotNull(resourceList);
} else {
IPagingProvider pagingProvider = theServer.getPagingProvider();
if (theLimit == null || theLimit.equals(Integer.valueOf(0))) {
numToReturn = pagingProvider.getDefaultPageSize();
} else {
numToReturn = Math.min(pagingProvider.getMaximumPageSize(), theLimit);
}
if (numTotalResults != null) {
numToReturn = Math.min(numToReturn, numTotalResults - theOffset);
}
resourceList = theResult.getResources(theOffset, numToReturn + theOffset);
RestfulServerUtils.validateResourceListNotNull(resourceList);
if (theSearchId != null) {
searchId = theSearchId;
} else {
if (numTotalResults == null || numTotalResults > numToReturn) {
searchId = pagingProvider.storeResultList(theResult);
Validate.notNull(searchId, "Paging provider returned null searchId");
}
}
}
for (IBaseResource next : resourceList) {
if (next.getIdElement() == null || next.getIdElement().isEmpty()) {
if (!(next instanceof BaseOperationOutcome)) {
throw new InternalErrorException(Msg.code(776) + "Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
}
}
if (theServer.getAddProfileTag() != AddProfileTagEnum.NEVER) {
addProfileIfNeeded(theServer, theServerBase, next);
}
}
addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, theServerBase, theServer.getBundleInclusionRule(), theIncludes);
addRootPropertiesToBundle(null, theServerBase, theCompleteUrl, numTotalResults, theBundleType, theResult.getPublished());
if (theServer.getPagingProvider() != null) {
int limit;
limit = theLimit != null ? theLimit : theServer.getPagingProvider().getDefaultPageSize();
limit = Math.min(limit, theServer.getPagingProvider().getMaximumPageSize());
if (searchId != null) {
if (numTotalResults == null || theOffset + numToReturn < numTotalResults) {
myBundle.getLinkNext()
.setValue(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint, theBundleType));
}
if (theOffset > 0) {
int start = Math.max(0, theOffset - limit);
myBundle.getLinkPrevious().setValue(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, start, limit, theResponseEncoding, thePrettyPrint, theBundleType));
}
}
}
}
@Override
public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults,
BundleTypeEnum theBundleType) {
myBundle = new Bundle();
myBundle.getAuthorName().setValue(theAuthor);
myBundle.getBundleId().setValue(UUID.randomUUID().toString());
myBundle.getLinkBase().setValue(theServerBase);
myBundle.getLinkSelf().setValue(theCompleteUrl);
myBundle.getType().setValueAsEnum(theBundleType);
List<IBaseResource> includedResources = new ArrayList<IBaseResource>();
Set<IIdType> addedResourceIds = new HashSet<IIdType>();
for (IBaseResource next : theResult) {
if (next.getIdElement().isEmpty() == false) {
addedResourceIds.add(next.getIdElement());
}
}
for (IBaseResource nextRes : theResult) {
IResource next = (IResource) nextRes;
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty() == false) {
containedIds.add(nextContained.getId().getValue());
}
}
List<BaseResourceReferenceDt> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
do {
List<IBaseResource> addedResourcesThisPass = new ArrayList<IBaseResource>();
for (BaseResourceReferenceDt nextRef : references) {
IBaseResource nextRefRes = nextRef.getResource();
if (nextRefRes != null) {
if (nextRefRes.getIdElement().hasIdPart()) {
if (containedIds.contains(nextRefRes.getIdElement().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IIdType id = nextRefRes.getIdElement();
if (id.hasResourceType() == false) {
String resName = myContext.getResourceName(nextRefRes);
id = id.withResourceType(resName);
}
if (!addedResourceIds.contains(id)) {
addedResourceIds.add(id);
addedResourcesThisPass.add(nextRefRes);
}
}
}
}
// Linked resources may themselves have linked resources
references = new ArrayList<BaseResourceReferenceDt>();
for (IBaseResource iResource : addedResourcesThisPass) {
List<BaseResourceReferenceDt> newReferences = myContext.newTerser().getAllPopulatedChildElementsOfType(iResource, BaseResourceReferenceDt.class);
references.addAll(newReferences);
}
includedResources.addAll(addedResourcesThisPass);
} while (references.isEmpty() == false);
myBundle.addResource(next, myContext, theServerBase);
}
/*
* Actually add the resources to the bundle
*/
for (IBaseResource next : includedResources) {
BundleEntry entry = myBundle.addResource((IResource) next, myContext, theServerBase);
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) {
if (entry.getSearchMode().isEmpty()) {
entry.getSearchMode().setValueAsEnum(BundleEntrySearchModeEnum.INCLUDE);
}
}
}
myBundle.getTotalResults().setValue(theTotalResults);
}
@Override
public void initializeWithBundleResource(IBaseResource theResource) {
throw new UnsupportedOperationException(Msg.code(777) + "DSTU1 server doesn't support resource style bundles");
}
@Override
public List<IBaseResource> toListOfResources() {
return new ArrayList<IBaseResource>(myBundle.toListOfResources());
}
}

View File

@ -1,85 +0,0 @@
package ca.uhn.fhir.rest.server.audit;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.HashMap;
import java.util.Map;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.model.dstu.resource.AdverseReaction;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
public class AdverseReactionAuditor implements IResourceAuditor<AdverseReaction> {
private AdverseReaction myResource = null;
@Override
public AdverseReaction getResource() {
return myResource;
}
@Override
public void setResource(AdverseReaction resource) {
myResource = resource;
}
@Override
public boolean isAuditable() {
return myResource != null;
}
@Override
public String getName() {
if(myResource == null) return null;
return "AdverseReaction:" + myResource.getIdentifierFirstRep().getValue();
}
@Override
public BaseIdentifierDt getIdentifier() {
if(myResource == null) return null;
return myResource.getIdentifierFirstRep();
}
@Override
public SecurityEventObjectTypeEnum getType() {
return SecurityEventObjectTypeEnum.OTHER;
}
@Override
public String getDescription() {
return null;
}
@Override
public Map<String, String> getDetail() {
Map<String, String> details = new HashMap<String, String>();
details.put("subject", myResource.getSubject().getReference().getValue());
details.put("version", myResource.getId().getVersionIdPart());
return details;
}
@Override
public BaseCodingDt getSensitivity() {
return null;
}
}

View File

@ -1,89 +0,0 @@
package ca.uhn.fhir.rest.server.audit;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.HashMap;
import java.util.Map;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
public class DiagnosticReportAuditor implements IResourceAuditor<DiagnosticReport> {
DiagnosticReport myDiagnosticReport;
@Override
public boolean isAuditable() {
return myDiagnosticReport != null;
}
@Override
public String getName() {
if(myDiagnosticReport != null){
return "Diagnostic Report: " + myDiagnosticReport.getName().getText().getValue();
}
return null;
}
@Override
public IdentifierDt getIdentifier() {
if(myDiagnosticReport != null){
return myDiagnosticReport.getIdentifier();
}
return null;
}
@Override
public SecurityEventObjectTypeEnum getType() {
return SecurityEventObjectTypeEnum.OTHER;
}
@Override
public DiagnosticReport getResource() {
return myDiagnosticReport;
}
@Override
public void setResource(DiagnosticReport theDiagnosticReport) {
myDiagnosticReport = theDiagnosticReport;
}
@Override
public String getDescription() {
return null; //name and ID should suffice for audit purposes
}
@Override
public Map<String, String> getDetail() {
Map<String, String> details = new HashMap<String, String>();
details.put("dateIssued", myDiagnosticReport.getIssued().getValueAsString());
details.put("version", myDiagnosticReport.getId().getVersionIdPart());
details.put("subject", myDiagnosticReport.getSubject().getReference().getValue());
return details;
}
@Override
public BaseCodingDt getSensitivity() {
return null; //no sensitivity indicated
}
}

View File

@ -1,104 +0,0 @@
package ca.uhn.fhir.rest.server.audit;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.HashMap;
import java.util.Map;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Encounter;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
public class EncounterAuditor implements IResourceAuditor<Encounter> {
private Encounter myEncounter;
@Override
public Encounter getResource() {
return myEncounter;
}
@Override
public void setResource(Encounter theEncounter) {
myEncounter = theEncounter;
}
@Override
public boolean isAuditable() {
return myEncounter != null;
}
@Override
public String getName() {
if(myEncounter != null){
String id = myEncounter.getIdentifierFirstRep().getValue().getValue();
String system = myEncounter.getIdentifierFirstRep().getSystem().getValueAsString();
String service = myEncounter.getServiceProvider().getDisplay().getValue();
return "Encounter: " + id + "/" + system + ": " + service;
}
return null;
}
@Override
public IdentifierDt getIdentifier() {
if(myEncounter != null){
return myEncounter.getIdentifierFirstRep();
}
return null;
}
@Override
public SecurityEventObjectTypeEnum getType() {
return SecurityEventObjectTypeEnum.OTHER;
}
@Override
public String getDescription() {
if(myEncounter != null){
String type = myEncounter.getTypeFirstRep().getText().getValue();
String status = myEncounter.getStatus().getValueAsString();
String startDate = myEncounter.getPeriod().getStart().getValueAsString();
String endDate = myEncounter.getPeriod().getEnd().getValueAsString();
return "Encounter: " + type + ": " + status +", "+ startDate + " - " + endDate;
}
return null;
}
@Override
public Map<String, String> getDetail() {
Map<String, String> details = new HashMap<String, String>();
details.put("startDate", myEncounter.getPeriod().getStart().getValueAsString());
details.put("endDate", myEncounter.getPeriod().getEnd().getValueAsString());
details.put("service", myEncounter.getServiceProvider().getDisplay().getValue());
details.put("type", myEncounter.getTypeFirstRep().getText().getValue());
details.put("status", myEncounter.getStatus().getValueAsString());
details.put("subject", myEncounter.getSubject().getReference().getValue());
return details;
}
@Override
public BaseCodingDt getSensitivity() {
//override this method to provide sensitivity information about the visit
return null;
}
}

View File

@ -1,81 +0,0 @@
package ca.uhn.fhir.rest.server.audit;
/*
* #%L
* HAPI FHIR Structures - DSTU1 (FHIR v0.80)
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* 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 java.util.Map;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.model.dstu.valueset.SecurityEventObjectTypeEnum;
public interface IResourceAuditor<T extends IResource> {
/**
* @return the resource to be audited
*/
public T getResource();
/**
* @param resource the resource to be audited by this auditor
*/
public void setResource(T resource);
/**
* @return true if this resource is to be audited, false otherwise
*/
public boolean isAuditable();
/**
* An instance-specific descriptor of the Participant Object ID audited, such as a person's name
* @return the descriptive name of the resource object
*/
public String getName();
/**
* @return the identifier of the resource to be audited
*/
public BaseIdentifierDt getIdentifier();
/**
* @return the SecurityEventObjectTypeEnum of this resource
*/
public SecurityEventObjectTypeEnum getType();
/**
* @return a text description of the resource
*/
public String getDescription();
/**
* @return a map of additional details to be audited
*/
public Map<String, String> getDetail();
/**
* Denotes policy-defined sensitivity for the Participant Object ID such as VIP, HIV status, mental health status or similar topics
* @return the sensitivity of this resource
*/
public BaseCodingDt getSensitivity();
}

Some files were not shown because too many files have changed in this diff Show More