Udate to latest DSTU2 definitions

This commit is contained in:
jamesagnew 2015-08-31 08:20:24 -04:00
commit a9f978a8a2
1290 changed files with 650928 additions and 1076339 deletions

View File

@ -19,6 +19,6 @@ before_script:
- export MAVEN_SKIP_RC=true
script:
- mvn -B clean install && cd hapi-fhir-cobertura && mvn -B -DTRAVIS_JOB_ID=$TRAVIS_JOB_ID -P COBERTURA clean cobertura:cobertura coveralls:report
- mvn -B clean install && cd hapi-fhir-cobertura && mvn -B -DTRAVIS_JOB_ID=$TRAVIS_JOB_ID -P COBERTURA clean test jacoco:report coveralls:report

View File

@ -6,6 +6,8 @@ HAPI FHIR - Java API for HL7 FHIR Clients and Servers
[![Build Status](https://travis-ci.org/jamesagnew/hapi-fhir.svg?branch=master)](https://travis-ci.org/jamesagnew/hapi-fhir)
[![Coverage Status](https://coveralls.io/repos/jamesagnew/hapi-fhir/badge.svg?branch=master&service=github)](https://coveralls.io/github/jamesagnew/hapi-fhir?branch=master)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/ca.uhn.hapi.fhir/hapi-fhir-base/badge.svg)](http://search.maven.org/#search|ga|1|ca.uhn.hapi.fhir)
[![Dependency Status](https://www.versioneye.com/user/projects/55e1d0d9c6d8f2001c00043e/badge.svg?style=flat)](https://www.versioneye.com/user/projects/55e1d0d9c6d8f2001c00043e)
[![License](https://img.shields.io/badge/license-apache%202.0-ff69b4.svg)](https://github.com/jamesagnew/hapi-fhir/blob/master/LICENSE.txt)
Complete project documentation is available here:
http://jamesagnew.github.io/hapi-fhir/

View File

@ -10,6 +10,7 @@ import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
import ca.uhn.fhir.model.dstu2.composite.SimpleQuantityDt;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
@ -167,8 +168,8 @@ public class FhirDataModel {
observation.setValue(q);
// Set the reference range
observation.getReferenceRangeFirstRep().setLow(new QuantityDt(100));
observation.getReferenceRangeFirstRep().setHigh(new QuantityDt(200));
observation.getReferenceRangeFirstRep().setLow(new SimpleQuantityDt(100));
observation.getReferenceRangeFirstRep().setHigh(new SimpleQuantityDt(200));
// END SNIPPET: observation

View File

@ -49,33 +49,27 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-android</artifactId>
<version>4.3.5.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-android</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons_io_version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons_codec_version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons_lang_version}</version>
</dependency>
<!-- Android does not come with the Servlet API bundled, and MethodUtil

View File

@ -22,33 +22,22 @@
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
<!-- XML -->
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>${woodstox_version}</version>
</dependency>
<!-- Only required for OpenID Connect Support -->
<!-- <dependency> <groupId>org.mitre</groupId> <artifactId>openid-connect-client</artifactId>
<version>${mitreid-connect-version}</version> <optional>true</optional> </dependency>
<dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId>
<version>2.0.2.RELEASE</version> <optional>true</optional> </dependency> -->
<!-- -->
<!-- Only required for narrative generator support -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
<optional>true</optional>
</dependency>
@ -56,7 +45,6 @@
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
<optional>true</optional>
<!-- <exclusions> <exclusion> <artifactId>servlet-api</artifactId> <groupId>javax.servlet</groupId>
</exclusion> </exclusions> -->
@ -66,13 +54,11 @@
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
<optional>true</optional>
</dependency>
@ -83,29 +69,24 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons_lang_version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons_codec_version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons_io_version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>

View File

@ -52,7 +52,6 @@ import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseDatatypeElement;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import org.hl7.fhir.instance.model.api.IBaseEnumeration;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseReference;
@ -626,12 +625,6 @@ class ModelScanner {
} else if (IBaseEnumeration.class.isAssignableFrom(nextElementType)) {
Class<?> binderType = ReflectionUtil.getGenericCollectionTypeOfFieldWithSecondOrderForList(next);
def = new RuntimeChildPrimitiveEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, binderType);
} else if (childAnnotation.enumFactory().getSimpleName().equals("NoEnumFactory") == false) {
Class<? extends IBaseEnumFactory<?>> enumFactory = childAnnotation.enumFactory();
def = new RuntimeChildEnumerationDatatypeDefinition(next, elementName, childAnnotation, descriptionAnnotation, nextDatatype, enumFactory);
// } else if ("id".equals(elementName) && IIdType.class.isAssignableFrom(nextDatatype)) {
// def = new RuntimeChildIdDatatypeDefinition(next, elementName, descriptionAnnotation,
// childAnnotation, nextDatatype);
} else {
def = new RuntimeChildPrimitiveDatatypeDefinition(next, elementName, descriptionAnnotation, childAnnotation, nextDatatype);
}

View File

@ -1,59 +0,0 @@
package ca.uhn.fhir.context;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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.lang.reflect.Field;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
public class RuntimeChildEnumerationDatatypeDefinition extends RuntimeChildPrimitiveDatatypeDefinition {
private Class<? extends IBaseEnumFactory<?>> myBinderType;
private volatile IBaseEnumFactory<?> myBinder;
public RuntimeChildEnumerationDatatypeDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, Class<? extends IBase> theDatatype,
Class<? extends IBaseEnumFactory<?>> theBinderType) {
super(theField, theElementName, theDescriptionAnnotation, theChildAnnotation, theDatatype);
myBinderType = theBinderType;
}
@Override
public IBaseEnumFactory<?> getInstanceConstructorArguments() {
IBaseEnumFactory<?> retVal = myBinder;
if (retVal == null) {
try {
retVal = myBinderType.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("Failed to instantiate " + myBinderType, e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Failed to instantiate " + myBinderType, e);
}
myBinder = retVal;
}
return retVal;
}
}

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.model.api;
*/
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -32,66 +33,56 @@ import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.IdDt;
/**
* This interface is the parent interface for all FHIR Resource definition
* classes. Classes implementing this interface should be annotated
* with the {@link ResourceDef @ResourceDef} annotation.
* This interface is the parent interface for all FHIR Resource definition classes. Classes implementing this interface should be annotated with the {@link ResourceDef @ResourceDef} annotation.
*
* <p>
* Note that this class is a part of HAPI's model API, used to define
* structure classes. Users will often interact with this interface, but
* should not need to implement it directly.
* Note that this class is a part of HAPI's model API, used to define structure classes. Users will often interact with this interface, but should not need to implement it directly.
* </p>
*/
public interface IResource extends ICompositeElement, org.hl7.fhir.instance.model.api.IBaseResource {
public static final Include INCLUDE_ALL = new Include("*");
public static final Set<Include> WILDCARD_ALL_SET = new HashSet<Include>(Arrays.asList(INCLUDE_ALL));
/**
* Include constant for <code>*</code> (return all includes)
*/
public static final Include INCLUDE_ALL = new Include("*", false).toLocked();
/**
/**
* Include set containing only {@link #INCLUDE_ALL}
*/
public static final Set<Include> WILDCARD_ALL_SET = Collections.unmodifiableSet(new HashSet<Include>(Arrays.asList(INCLUDE_ALL)));
/**
* Returns the contained resource list for this resource.
* <p>
* Usage note: HAPI will generally populate and use the resources from this
* list automatically (placing inline resources in the contained list when
* encoding, and copying contained resources from this list to their
* appropriate references when parsing) so it is generally not neccesary to
* interact with this list directly. Instead, in a server you can place
* resource instances in reference fields (such as <code>Patient#setManagingOrganization(ResourceReferenceDt)</code> )
* and the resource will be automatically contained. In a client, contained resources will
* be automatically populated into their appropriate fields by the HAPI parser.
* Usage note: HAPI will generally populate and use the resources from this list automatically (placing inline resources in the contained list when encoding, and copying contained resources from
* this list to their appropriate references when parsing) so it is generally not neccesary to interact with this list directly. Instead, in a server you can place resource instances in reference
* fields (such as <code>Patient#setManagingOrganization(ResourceReferenceDt)</code> ) and the resource will be automatically contained. In a client, contained resources will be automatically
* populated into their appropriate fields by the HAPI parser.
* </p>
* TODO: document contained resources and link there
*/
BaseContainedDt getContained();
/**
* Returns the ID of this resource. Note that this identifier is the URL (or a portion
* of the URL) used to access this resource, and is not the same thing as any business
* identifiers stored within the resource. For example, a Patient resource might
* have any number of medical record numbers but these are not stored here.
* Returns the ID of this resource. Note that this identifier is the URL (or a portion of the URL) used to access this resource, and is not the same thing as any business identifiers stored within
* the resource. For example, a Patient resource might have any number of medical record numbers but these are not stored here.
* <p>
* This ID is specified as the "Logical ID" and "Version ID" in the FHIR specification, see
* <a href="http://www.hl7.org/implement/standards/fhir/resources.html#metadata">here</a>
* This ID is specified as the "Logical ID" and "Version ID" in the FHIR specification, see <a href="http://www.hl7.org/implement/standards/fhir/resources.html#metadata">here</a>
* </p>
*/
IdDt getId();
/**
* Gets the language of the resource itself - <b>NOTE that this language attribute
* applies to the resource itself, it is not (for example) the language spoken by
* a practitioner or patient</b>
* Gets the language of the resource itself - <b>NOTE that this language attribute applies to the resource itself, it is not (for example) the language spoken by a practitioner or patient</b>
*/
CodeDt getLanguage();
/**
* Returns the metadata map for this object, creating it if neccesary.
* Metadata entries are used to get/set feed bundle entries, such as the
* resource version, or the last updated timestamp.
* Returns the metadata map for this object, creating it if neccesary. Metadata entries are used to get/set feed bundle entries, such as the resource version, or the last updated timestamp.
* <p>
* Keys in this map are enumerated in the {@link ResourceMetadataKeyEnum},
* and each key has a specific value type that it must use.
* Keys in this map are enumerated in the {@link ResourceMetadataKeyEnum}, and each key has a specific value type that it must use.
* </p>
*
* @see ResourceMetadataKeyEnum for a list of allowable keys and the object
* types that values of a given key must use.
* @see ResourceMetadataKeyEnum for a list of allowable keys and the object types that values of a given key must use.
*/
ResourceMetadataMap getResourceMetadata();
@ -99,40 +90,31 @@ public interface IResource extends ICompositeElement, org.hl7.fhir.instance.mode
* Returns the narrative block for this resource
*/
BaseNarrativeDt getText();
/**
* Sets the ID of this resource. Note that this identifier is the URL (or a portion
* of the URL) used to access this resource, and is not the same thing as any business
* identifiers stored within the resource. For example, a Patient resource might
* have any number of medical record numbers but these are not stored here.
* Sets the ID of this resource. Note that this identifier is the URL (or a portion of the URL) used to access this resource, and is not the same thing as any business identifiers stored within the
* resource. For example, a Patient resource might have any number of medical record numbers but these are not stored here.
* <p>
* This ID is specified as the "Logical ID" and "Version ID" in the FHIR specification, see
* <a href="http://www.hl7.org/implement/standards/fhir/resources.html#metadata">here</a>
* This ID is specified as the "Logical ID" and "Version ID" in the FHIR specification, see <a href="http://www.hl7.org/implement/standards/fhir/resources.html#metadata">here</a>
* </p>
*/
void setId(IdDt theId);
/**
* Sets the language of the resource itself - <b>NOTE that this language attribute
* applies to the resource itself, it is not (for example) the language spoken by
* a practitioner or patient</b>
* Sets the language of the resource itself - <b>NOTE that this language attribute applies to the resource itself, it is not (for example) the language spoken by a practitioner or patient</b>
*/
void setLanguage(CodeDt theLanguage);
/**
* Sets the metadata map for this object. Metadata entries are used to
* get/set feed bundle entries, such as the resource version, or the last
* updated timestamp.
* Sets the metadata map for this object. Metadata entries are used to get/set feed bundle entries, such as the resource version, or the last updated timestamp.
*
* @throws NullPointerException
* The map must not be null
* The map must not be null
*/
void setResourceMetadata(ResourceMetadataMap theMap);
/**
* Returns a String representing the name of this Resource. This return
* value is not used for anything by HAPI itself, but is provided as a
* convenience to developers using the API.
* Returns a String representing the name of this Resource. This return value is not used for anything by HAPI itself, but is provided as a convenience to developers using the API.
*
* @return the name of this resource, e.g. "Patient", or "Observation"
*/
@ -141,7 +123,6 @@ public interface IResource extends ICompositeElement, org.hl7.fhir.instance.mode
/**
* Returns the FHIR version represented by this structure
*/
public ca.uhn.fhir.context.FhirVersionEnum getStructureFhirVersionEnum();
public ca.uhn.fhir.context.FhirVersionEnum getStructureFhirVersionEnum();
}

View File

@ -34,6 +34,7 @@ public class Include {
private boolean myRecurse;
private String myValue;
private boolean myImmutable;
/**
* Constructor for <b>non-recursive</b> include
@ -125,9 +126,18 @@ public class Include {
}
public void setValue(String theValue) {
if (myImmutable) {
throw new IllegalStateException("Can not change the value of this include");
}
myValue = theValue;
}
public Include toLocked() {
Include retVal = new Include(myValue, myRecurse);
retVal.myImmutable = true;
return retVal;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);

View File

@ -24,11 +24,6 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Enumeration;
import net.sourceforge.cobertura.CoverageIgnore;
import org.hl7.fhir.instance.model.api.IBaseEnumFactory;
import ca.uhn.fhir.model.api.IElement;
@ -112,32 +107,4 @@ public @interface Child {
*/
boolean summary() default false;
/**
* For children which accept an {@link Enumeration} as the type, this
* field indicates the type to use for the enum factory
*/
Class<? extends IBaseEnumFactory<?>> enumFactory() default NoEnumFactory.class;
@CoverageIgnore
public static class NoEnumFactory implements IBaseEnumFactory<Enum<?>> {
@CoverageIgnore
private NoEnumFactory() {
// non instantiable
}
@CoverageIgnore
@Override
public Enum<?> fromCode(String theCodeString) throws IllegalArgumentException {
return null;
}
@CoverageIgnore
@Override
public String toCode(Enum<?> theCode) {
return null;
}
}
}

View File

@ -199,6 +199,34 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return getIdPartAsBigDecimal();
}
private String determineLocalPrefix(String theValue) {
if (theValue == null || theValue.isEmpty()) {
return null;
}
if (theValue.startsWith("#")) {
return "#";
}
int lastPrefix = -1;
for (int i = 0; i < theValue.length(); i++) {
char nextChar = theValue.charAt(i);
if (nextChar == ':') {
lastPrefix = i;
} else if (!Character.isLetter(nextChar) || !Character.isLowerCase(nextChar)) {
break;
}
}
if (lastPrefix != -1) {
String candidate = theValue.substring(0, lastPrefix + 1);
if (candidate.startsWith("cid:") || candidate.startsWith("urn:")) {
return candidate;
} else {
return null;
}
} else {
return null;
}
}
@Override
public boolean equals(Object theArg0) {
if (!(theArg0 instanceof IdDt)) {
@ -383,6 +411,34 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return isBlank(getValue());
}
@Override
public boolean isIdPartValid() {
String id = getIdPart();
if (StringUtils.isBlank(id)) {
return false;
}
if (id.length() > 64) {
return false;
}
for (int i = 0; i < id.length(); i++) {
char nextChar = id.charAt(i);
if (nextChar >= 'a' && nextChar <= 'z') {
continue;
}
if (nextChar >= 'A' && nextChar <= 'Z') {
continue;
}
if (nextChar >= '0' && nextChar <= '9') {
continue;
}
if (nextChar == '-' || nextChar == '.') {
continue;
}
return false;
}
return true;
}
/**
* Returns <code>true</code> if the unqualified ID is a valid {@link Long} value (in other words, it consists only of digits)
*/
@ -407,7 +463,7 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
public boolean isLocal() {
return "#".equals(myBaseUrl);
}
/**
* Copies the value from the given IdDt to <code>this</code> IdDt. It is generally not neccesary to use this method but it is provided for consistency with the rest of the API.
*/
@ -416,34 +472,6 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
setValue(theId.getValue());
}
private String determineLocalPrefix(String theValue) {
if (theValue == null || theValue.isEmpty()) {
return null;
}
if (theValue.startsWith("#")) {
return "#";
}
int lastPrefix = -1;
for (int i = 0; i < theValue.length(); i++) {
char nextChar = theValue.charAt(i);
if (nextChar == ':') {
lastPrefix = i;
} else if (!Character.isLetter(nextChar) || !Character.isLowerCase(nextChar)) {
break;
}
}
if (lastPrefix != -1) {
String candidate = theValue.substring(0, lastPrefix + 1);
if (candidate.startsWith("cid:") || candidate.startsWith("urn:")) {
return candidate;
} else {
return null;
}
} else {
return null;
}
}
/**
* Set the value
*
@ -602,6 +630,14 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return new IdDt(value + '/' + Constants.PARAM_HISTORY + '/' + theVersion);
}
/**
* Construct a new ID with with form "urn:uuid:[UUID]" where [UUID] is a new, randomly
* created UUID generated by {@link UUID#randomUUID()}
*/
public static IdDt newRandomUuid() {
return new IdDt("urn:uuid:" + UUID.randomUUID().toString());
}
/**
* Retrieves the ID from the given resource instance
*/
@ -634,12 +670,4 @@ public class IdDt extends UriDt implements IPrimitiveDatatype<String>, IIdType {
return theIdPart.toString();
}
/**
* Construct a new ID with with form "urn:uuid:[UUID]" where [UUID] is a new, randomly
* created UUID generated by {@link UUID#randomUUID()}
*/
public static IdDt newRandomUuid() {
return new IdDt("urn:uuid:" + UUID.randomUUID().toString());
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link CompositeClientParam} instead. That class is identical to this one but was renamed to reduce
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class CompositeParam<A extends IParam, B extends IParam> extends CompositeClientParam<A,B> {
public CompositeParam(String theParamName) {
super(theParamName);
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link DateClientParam} instead. That class is identical to this one but was renamed to reduct
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class DateParam extends DateClientParam {
public DateParam(String theParamName) {
super(theParamName);
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link NumberClientParam} instead. That class is identical to this one but was renamed to reduct
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class NumberParam extends NumberClientParam {
public NumberParam(String theParamName) {
super(theParamName);
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link QuantityClientParam} instead. That class is identical to this one but was renamed to reduct
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class QuantityParam extends QuantityClientParam {
public QuantityParam(String theParamName) {
super(theParamName);
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link ReferenceClientParam} instead. That class is identical to this one but was renamed to reduct
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class ReferenceParam extends ReferenceClientParam {
public ReferenceParam(String theParamName) {
super(theParamName);
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link StringClientParam} instead. That class is identical to this one but was renamed to reduct
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class StringParam extends StringClientParam {
public StringParam(String theParamName) {
super(theParamName);
}
}

View File

@ -1,36 +0,0 @@
package ca.uhn.fhir.rest.gclient;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2015 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%
*/
/**
* @deprecated Use {@link TokenClientParam} instead. That class is identical to this one but was renamed to reduct
* confusing duplicate names in the API. This class will be removed in a future release.
*/
@Deprecated
public class TokenParam extends TokenClientParam {
public TokenParam(String theParamName) {
super(theParamName);
}
}

View File

@ -42,20 +42,22 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
}
/**
* Constructor which copies the {@link InternalCodingDt#getSystemElement() system} and {@link InternalCodingDt#getCodeElement() code} from a {@link InternalCodingDt} instance and adds it as a parameter
* Constructor which copies the {@link InternalCodingDt#getSystemElement() system} and {@link InternalCodingDt#getCodeElement() code} from a {@link InternalCodingDt} instance and adds it as a
* parameter
*
* @param theCodingDt
* The coding
* The coding
*/
public TokenParam(BaseCodingDt theCodingDt) {
this(toSystemValue(theCodingDt.getSystemElement()), theCodingDt.getCodeElement().getValue());
}
/**
* Constructor which copies the {@link BaseIdentifierDt#getSystemElement() system} and {@link BaseIdentifierDt#getValueElement() value} from a {@link BaseIdentifierDt} instance and adds it as a parameter
* Constructor which copies the {@link BaseIdentifierDt#getSystemElement() system} and {@link BaseIdentifierDt#getValueElement() value} from a {@link BaseIdentifierDt} instance and adds it as a
* parameter
*
* @param theIdentifierDt
* The identifier
* The identifier
*/
public TokenParam(BaseIdentifierDt theIdentifierDt) {
this(toSystemValue(theIdentifierDt.getSystemElement()), theIdentifierDt.getValueElement().getValue());
@ -102,12 +104,18 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
*/
@Override
void doSetValueAsQueryToken(String theQualifier, String theParameter) {
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
if (barIndex != -1) {
setSystem(theParameter.substring(0, barIndex));
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
setText(Constants.PARAMQUALIFIER_TOKEN_TEXT.equals(theQualifier));
setSystem(null);
if (theParameter == null) {
setValue(null);
} else {
setValue(ParameterUtil.unescape(theParameter));
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
if (barIndex != -1) {
setSystem(theParameter.substring(0, barIndex));
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
} else {
setValue(ParameterUtil.unescape(theParameter));
}
}
}

View File

@ -288,7 +288,7 @@ public class RestfulServer extends HttpServlet {
/**
* Returns the default encoding to return (XML/JSON) if an incoming request does not specify a preference (either with the <code>_format</code> URL parameter, or with an <code>Accept</code> header
* in the request. The default is {@link EncodingEnum#XML}.
* in the request. The default is {@link EncodingEnum#XML}. Will not return null.
*/
public EncodingEnum getDefaultResponseEncoding() {
return myDefaultResponseEncoding;

View File

@ -19,8 +19,8 @@ package ca.uhn.fhir.rest.server;
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.io.OutputStreamWriter;
@ -92,6 +92,46 @@ public class RestfulServerUtils {
}
}
public static void configureResponseParser(RequestDetails theRequestDetails, IParser parser) {
// Pretty print
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
parser.setPrettyPrint(prettyPrint);
parser.setServerBaseUrl(theRequestDetails.getFhirServerBase());
// Summary mode
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequestDetails);
// _elements
Set<String> elements = ElementsParameter.getElementsValueOrNull(theRequestDetails);
if (elements != null && summaryMode != null && !summaryMode.equals(Collections.singleton(SummaryEnum.FALSE))) {
throw new InvalidRequestException("Cannot combine the " + Constants.PARAM_SUMMARY + " and " + Constants.PARAM_ELEMENTS + " parameters");
}
Set<String> elementsAppliesTo = null;
if (elements != null && isNotBlank(theRequestDetails.getResourceName())) {
elementsAppliesTo = Collections.singleton(theRequestDetails.getResourceName());
}
if (summaryMode != null) {
if (summaryMode.contains(SummaryEnum.COUNT)) {
parser.setEncodeElements(Collections.singleton("Bundle.total"));
} else if (summaryMode.contains(SummaryEnum.TEXT)) {
parser.setEncodeElements(TEXT_ENCODE_ELEMENTS);
} else {
parser.setSuppressNarratives(summaryMode.contains(SummaryEnum.DATA));
parser.setSummaryMode(summaryMode.contains(SummaryEnum.TRUE));
}
}
if (elements != null && elements.size() > 0) {
Set<String> newElements = new HashSet<String>();
for (String next : elements) {
newElements.add("*." + next);
}
parser.setEncodeElements(newElements);
parser.setEncodeElementsAppliesToResourceTypes(elementsAppliesTo);
}
}
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, EncodingEnum theResponseEncoding, boolean thePrettyPrint) {
try {
StringBuilder b = new StringBuilder();
@ -235,8 +275,7 @@ public class RestfulServerUtils {
}
/**
* Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's
* <code>"_format"</code> parameter and <code>"Accept:"</code> HTTP header.
* Determine whether a response should be given in JSON or XML format based on the incoming HttpServletRequest's <code>"_format"</code> parameter and <code>"Accept:"</code> HTTP header.
*/
public static EncodingEnum determineResponseEncodingWithDefault(RestfulServer theServer, HttpServletRequest theReq) {
EncodingEnum retVal = determineResponseEncodingNoDefault(theReq);
@ -253,8 +292,7 @@ public class RestfulServerUtils {
if (retVal == null) {
/*
* HAPI originally supported a custom parameter called _narrative, but this has been superceded by an official
* parameter called _summary
* HAPI originally supported a custom parameter called _narrative, but this has been superceded by an official parameter called _summary
*/
String[] narrative = requestParams.get(Constants.PARAM_NARRATIVE);
if (narrative != null && narrative.length > 0) {
@ -288,16 +326,12 @@ public class RestfulServerUtils {
}
public static IParser getNewParser(FhirContext theContext, RequestDetails theRequestDetails) {
// Pretty print
boolean prettyPrint = RestfulServerUtils.prettyPrintResponse(theRequestDetails.getServer(), theRequestDetails);
// Determine response encoding
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequestDetails.getServletRequest());
if (responseEncoding == null) {
responseEncoding = theRequestDetails.getServer().getDefaultResponseEncoding();
}
IParser parser;
switch (responseEncoding) {
case JSON:
@ -308,41 +342,9 @@ public class RestfulServerUtils {
parser = theContext.newXmlParser();
break;
}
parser.setPrettyPrint(prettyPrint);
parser.setServerBaseUrl(theRequestDetails.getFhirServerBase());
// Summary mode
Set<SummaryEnum> summaryMode = RestfulServerUtils.determineSummaryMode(theRequestDetails);
// _elements
Set<String> elements = ElementsParameter.getElementsValueOrNull(theRequestDetails);
if (elements != null && summaryMode != null && !summaryMode.equals(Collections.singleton(SummaryEnum.FALSE))) {
throw new InvalidRequestException("Cannot combine the " + Constants.PARAM_SUMMARY + " and " + Constants.PARAM_ELEMENTS + " parameters");
}
Set<String> elementsAppliesTo = null;
if (elements != null && isNotBlank(theRequestDetails.getResourceName())) {
elementsAppliesTo = Collections.singleton(theRequestDetails.getResourceName());
}
if (summaryMode != null) {
if (summaryMode.contains(SummaryEnum.COUNT)) {
parser.setEncodeElements(Collections.singleton("Bundle.total"));
} else if (summaryMode.contains(SummaryEnum.TEXT)) {
parser.setEncodeElements(TEXT_ENCODE_ELEMENTS);
} else {
parser.setSuppressNarratives(summaryMode.contains(SummaryEnum.DATA));
parser.setSummaryMode(summaryMode.contains(SummaryEnum.TRUE));
}
}
if (elements != null && elements.size() > 0) {
Set<String> newElements = new HashSet<String>();
for (String next : elements) {
newElements.add("*." + next);
}
parser.setEncodeElements(newElements);
parser.setEncodeElementsAppliesToResourceTypes(elementsAppliesTo);
}
configureResponseParser(theRequestDetails, parser);
return parser;
}
@ -357,6 +359,55 @@ public class RestfulServerUtils {
return writer;
}
public static Set<String> parseAcceptHeaderAndReturnHighestRankedOptions(HttpServletRequest theRequest) {
Set<String> retVal = new HashSet<String>();
Enumeration<String> acceptValues = theRequest.getHeaders(Constants.HEADER_ACCEPT);
if (acceptValues != null) {
float bestQ = -1f;
while (acceptValues.hasMoreElements()) {
String nextAcceptHeaderValue = acceptValues.nextElement();
Matcher m = ACCEPT_HEADER_PATTERN.matcher(nextAcceptHeaderValue);
float q = 1.0f;
while (m.find()) {
String contentTypeGroup = m.group(1);
if (isNotBlank(contentTypeGroup)) {
String name = m.group(3);
String value = m.group(4);
if (name != null && value != null) {
if ("q".equals(name)) {
try {
q = Float.parseFloat(value);
q = Math.max(q, 0.0f);
} catch (NumberFormatException e) {
ourLog.debug("Invalid Accept header q value: {}", value);
}
}
}
if (q > bestQ) {
retVal.clear();
bestQ = q;
}
if (q == bestQ) {
retVal.add(contentTypeGroup.trim());
}
}
if (!",".equals(m.group(5))) {
break;
}
}
}
}
return retVal;
}
public static PreferReturnEnum parsePreferHeader(String theValue) {
if (isBlank(theValue)) {
return null;
@ -414,8 +465,8 @@ public class RestfulServerUtils {
return prettyPrint;
}
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, String theServerBase, Set<SummaryEnum> theSummaryMode, boolean theRespondGzip, boolean theRequestIsBrowser, RequestDetails theRequestDetails)
throws IOException {
public static void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, Bundle bundle, String theServerBase, Set<SummaryEnum> theSummaryMode, boolean theRespondGzip,
boolean theRequestIsBrowser, RequestDetails theRequestDetails) throws IOException {
assert!theServerBase.endsWith("/");
theHttpResponse.setStatus(200);
@ -446,8 +497,8 @@ public class RestfulServerUtils {
}
}
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IBaseResource theResource, boolean theRequestIsBrowser, Set<SummaryEnum> theSummaryMode, int stausCode, boolean theRespondGzip,
boolean theAddContentLocationHeader, RequestDetails theRequestDetails) throws IOException {
public static void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IBaseResource theResource, boolean theRequestIsBrowser, Set<SummaryEnum> theSummaryMode,
int stausCode, boolean theRespondGzip, boolean theAddContentLocationHeader, RequestDetails theRequestDetails) throws IOException {
theHttpResponse.setStatus(stausCode);
// Determine response encoding
@ -497,12 +548,12 @@ public class RestfulServerUtils {
// Ok, we're not serving a binary resource, so apply default encoding
responseEncoding = responseEncoding != null ? responseEncoding : theServer.getDefaultResponseEncoding();
boolean encodingDomainResourceAsText = theSummaryMode.contains(SummaryEnum.TEXT);
if (encodingDomainResourceAsText) {
/*
* If the user requests "text" for a bundle, only suppress the non text elements in the Element.entry.resource
* parts, we're not streaming just the narrative as HTML (since bundles don't even have one)
* If the user requests "text" for a bundle, only suppress the non text elements in the Element.entry.resource parts, we're not streaming just the narrative as HTML (since bundles don't even
* have one)
*/
if ("Bundle".equals(theServer.getFhirContext().getResourceDefinition(theResource).getName())) {
encodingDomainResourceAsText = false;

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.rest.server.interceptor;
*/
import java.io.IOException;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -166,8 +167,8 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
/*
* It's not a browser...
*/
String accept = theServletRequest.getHeader(Constants.HEADER_ACCEPT);
if (accept == null || !accept.toLowerCase().contains("html")) {
Set<String> highestRankedAcceptValues = RestfulServerUtils.parseAcceptHeaderAndReturnHighestRankedOptions(theRequestDetails.getServletRequest());
if (highestRankedAcceptValues.contains(Constants.CT_HTML) == false) {
return super.outgoingResponse(theRequestDetails, theResponseObject, theServletRequest, theServletResponse);
}
@ -192,11 +193,16 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
}
private void streamResponse(RequestDetails theRequestDetails, HttpServletResponse theServletResponse, IBaseResource resource) {
IParser p = RestfulServerUtils.getNewParser(theRequestDetails.getServer().getFhirContext(), theRequestDetails);
IParser p;
if (theRequestDetails.getParameters().containsKey(Constants.PARAM_FORMAT)) {
p = RestfulServerUtils.getNewParser(theRequestDetails.getServer().getFhirContext(), theRequestDetails);
} else {
EncodingEnum defaultResponseEncoding = theRequestDetails.getServer().getDefaultResponseEncoding();
p = defaultResponseEncoding.newParser(theRequestDetails.getServer().getFhirContext());
RestfulServerUtils.configureResponseParser(theRequestDetails, p);
}
EncodingEnum encoding = p.getEncoding();
String encoded = p.encodeResourceToString(resource);
theServletResponse.setContentType(Constants.CT_HTML_WITH_UTF8);
@ -245,8 +251,8 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
/*
* It's not a browser...
*/
String accept = theServletRequest.getHeader(Constants.HEADER_ACCEPT);
if (accept == null || !accept.toLowerCase().contains("html")) {
Set<String> accept = RestfulServerUtils.parseAcceptHeaderAndReturnHighestRankedOptions(theRequestDetails.getServletRequest());
if (!accept.contains(Constants.CT_HTML)) {
return super.handleException(theRequestDetails, theException, theServletRequest, theServletResponse);
}

View File

@ -21,6 +21,14 @@ package ca.uhn.fhir.util;
*/
public class ExtensionConstants {
/**
* Non instantiable
*/
private ExtensionConstants() {
// nothing
}
public static final String PARAM_IS_REQUIRED = "http://hl7api.sourceforge.net/hapi-fhir/extensions.xml#paramIsRequired";
public static final String QUERY_RETURN_TYPE = "http://hl7api.sourceforge.net/hapi-fhir/extensions.xml#queryReturnType";

View File

@ -92,6 +92,19 @@ public interface IIdType {
*/
boolean isAbsolute();
/**
* Returns <code>true</code> if the {@link #getIdPart() ID part of this object} is valid according to the FHIR rules for valid IDs.
* <p>
* The FHIR specification states:
* <code>Any combination of upper or lower case ASCII letters ('A'..'Z', and 'a'..'z', numerals ('0'..'9'), '-' and '.', with a length limit of 64 characters. (This might be an integer, an un-prefixed OID, UUID or any other identifier pattern that meets these constraints.) regex: [A-Za-z0-9\-\.]{1,64}</code>
* </p>
*/
boolean isIdPartValid();
/**
* Returns <code>true</code> if the {@link #getIdPart() ID part of this object} contains
* only numbers
*/
boolean isIdPartValidLong();
Long getIdPartAsLong();

View File

@ -52,7 +52,8 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionMissingUrl=Unable to perfor
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithInvalidId=Can not process entity with ID[{0}], this is not a valid FHIR ID
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which contain at least one non-numeric character
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.invalidParameterChain=Invalid parameter chain: {0}
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.multipleParamsWithSameNameOneIsMissingTrue=This server does not know how to handle multiple "{0}" parameters where one has a value of :missing=true

2
hapi-fhir-cli/.gitignore vendored Normal file
View File

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

View File

@ -1,27 +1,20 @@
<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>
<!--
Note: HAPI projects use the "hapi-fhir" POM as their base to provide
easy management.
You do not need to use this in your own projects, so the
"parent" tag and it's contents below may be removed if you
are using this file as a basis for your own project.
-->
<!-- Note: HAPI projects use the "hapi-fhir" POM as their base to provide easy management. You do not need to use this in your own projects, so the "parent" tag
and it's contents below may be removed if you are using this file as a basis for your own project. -->
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>1.1-SNAPSHOT</version>
<version>1.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>ca.uhn.hapi.example</groupId>
<artifactId>hapi-fhir-examples-uploader</artifactId>
<version>1.1-SNAPSHOT</version>
<artifactId>hapi-fhir-cli</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - Examples Uploader</name>
<name>HAPI FHIR - Command Line Client</name>
<dependencies>
@ -29,42 +22,52 @@
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>1.1-SNAPSHOT</version>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>1.1-SNAPSHOT</version>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<!--
Tells Maven to name the generated WAR file as
hapi-fhir-jpaserver-example.war
-->
<!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver-example.war -->
<finalName>hapi-fhir-jpaserver-example</finalName>
<!--
The following is not required for the application to build, but
allows you to test it by issuing "mvn jetty:run" from the command
line.
-->
<!-- The following is not required for the application to build, but allows you to test it by issuing "mvn jetty:run" from the command line. -->
<pluginManagement>
<plugins>
<plugin>
@ -79,11 +82,9 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!--
Tell Maven which Java source version you want to use
-->
<!-- Tell Maven which Java source version you want to use -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@ -92,11 +93,8 @@
<target>1.6</target>
</configuration>
</plugin>
<!--
The configuration here tells the WAR plugin to include the FHIR Tester
overlay. You can omit it if you are not using that feature.
-->
<!-- The configuration here tells the WAR plugin to include the FHIR Tester overlay. You can omit it if you are not using that feature. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
@ -109,11 +107,8 @@
</overlays>
</configuration>
</plugin>
<!--
This plugin is just a part of the HAPI internal build process, you do not
need to incude it in your own projects
-->
<!-- This plugin is just a part of the HAPI internal build process, you do not need to incude it in your own projects -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
@ -121,7 +116,7 @@
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -0,0 +1,17 @@
package ca.uhn.fhir.cli;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.IGenericClient;
public class BaseCommand {
public BaseCommand() {
super();
}
protected IGenericClient newClient(FhirContext ctx) {
IGenericClient fhirClient = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu2");
return fhirClient;
}
}

View File

@ -1,8 +1,9 @@
package ca.uhn.fhir.exampleuploader;
package ca.uhn.fhir.cli;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -21,18 +22,22 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryTransaction;
import ca.uhn.fhir.model.dstu2.resource.Bundle.EntryRequest;
import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.util.ResourceReferenceInfo;
public class Uploader {
public class ExampleDataUploader extends BaseCommand {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Uploader.class);
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleDataUploader.class);
public static void main(String[] args) throws Exception {
new ExampleDataUploader().execute();
}
private void execute() throws IOException, ClientProtocolException, UnsupportedEncodingException {
ourLog.info("Starting...");
FhirContext ctx = FhirContext.forDstu2();
@ -85,13 +90,13 @@ public class Uploader {
if (nextEntry1.getResource() instanceof SearchParameter) {
continue;
}
bundle.addEntry().setTransaction(new EntryTransaction().setMethod(HTTPVerbEnum.POST)).setResource(nextEntry1.getResource());
bundle.addEntry().setRequest(new EntryRequest().setMethod(HTTPVerbEnum.POST)).setResource(nextEntry1.getResource());
}
} else {
if (parsed instanceof SearchParameter) {
continue;
}
bundle.addEntry().setTransaction(new EntryTransaction().setMethod(HTTPVerbEnum.POST)).setResource((IResource) parsed);
bundle.addEntry().setRequest(new EntryRequest().setMethod(HTTPVerbEnum.POST)).setResource((IResource) parsed);
}
}
@ -113,10 +118,10 @@ public class Uploader {
for (Entry next : bundle.getEntry()) {
List<ResourceReferenceInfo> refs = ctx.newTerser().getAllResourceReferences(next.getResource());
for (ResourceReferenceInfo nextRef : refs) {
// if (nextRef.getResourceReference().getReferenceElement().isAbsolute()) {
// ourLog.info("Discarding absolute reference: {}", nextRef.getResourceReference().getReferenceElement().getValue());
// nextRef.getResourceReference().getReferenceElement().setValue(null);
// }
// if (nextRef.getResourceReference().getReferenceElement().isAbsolute()) {
// ourLog.info("Discarding absolute reference: {}", nextRef.getResourceReference().getReferenceElement().getValue());
// nextRef.getResourceReference().getReferenceElement().setValue(null);
// }
nextRef.getResourceReference().getReferenceElement().setValue(nextRef.getResourceReference().getReferenceElement().toUnqualifiedVersionless().getValue());
String value = nextRef.getResourceReference().getReferenceElement().toUnqualifiedVersionless().getValue();
if (!ids.contains(value) && !nextRef.getResourceReference().getReferenceElement().isLocal()) {
@ -127,13 +132,13 @@ public class Uploader {
}
}
}
// for (Entry next : bundle.getEntry()) {
// if (next.getResource().getId().hasIdPart() && Character.isLetter(next.getResource().getId().getIdPart().charAt(0))) {
// next.getTransaction().setUrl(next.getResource().getResourceName() + '/' + next.getResource().getId().getIdPart());
// next.getTransaction().setMethod(HTTPVerbEnum.PUT);
// }
// }
// for (Entry next : bundle.getEntry()) {
// if (next.getResource().getId().hasIdPart() && Character.isLetter(next.getResource().getId().getIdPart().charAt(0))) {
// next.getTransaction().setUrl(next.getResource().getResourceName() + '/' + next.getResource().getId().getIdPart());
// next.getTransaction().setMethod(HTTPVerbEnum.PUT);
// }
// }
ourLog.info("{} good references", goodRefs);
@ -141,9 +146,8 @@ public class Uploader {
ourLog.info("Final bundle: {} entries", bundle.getEntry().size());
ourLog.info("Final bundle: {} chars", encoded.length());
IGenericClient fhirClient = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu2");
IGenericClient fhirClient = newClient(ctx);
fhirClient.transaction().withBundle(bundle).execute();
}
}

View File

@ -0,0 +1,91 @@
package ca.uhn.fhir.cli;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.ClientProtocolException;
import org.hl7.fhir.instance.model.Bundle;
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.instance.model.StructureDefinition;
import org.hl7.fhir.instance.model.ValueSet;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.IGenericClient;
public class ValidationDataUploader extends BaseCommand {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationDataUploader.class);
public static void main(String[] args) throws Exception {
new ValidationDataUploader().execute();
}
private void execute() throws IOException, ClientProtocolException, UnsupportedEncodingException {
ourLog.info("Starting...");
FhirContext ctx = FhirContext.forDstu2Hl7Org();
IGenericClient client = newClient(ctx);
// String vsContents =
// IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/valuesets.xml"),
// "UTF-8");
// Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
//
// int total = bundle.getEntry().size();
// int count = 1;
// for (BundleEntryComponent i : bundle.getEntry()) {
// ValueSet next = (ValueSet) i.getResource();
// next.setId(next.getIdElement().toUnqualifiedVersionless());
//
// ourLog.info("Uploading ValueSet {}/{} : {}", new Object[] {count,total,next.getIdElement().getValue()});
// client.update().resource(next).execute();
//
// count++;
// }
//
// ourLog.info("Finished uploading ValueSets");
String vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"), "UTF-8");
Bundle bundle = ctx.newXmlParser().parseResource(Bundle.class, vsContents);
int total;
int count;
// total = bundle.getEntry().size();
// count = 1;
// for (BundleEntryComponent i : bundle.getEntry()) {
// ValueSet next = (ValueSet) i.getResource();
// next.setId(next.getIdElement().toUnqualifiedVersionless());
//
// ourLog.info("Uploading v3-codesystems ValueSet {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
// client.update().resource(next).execute();
//
// count++;
// }
ourLog.info("Finished uploading ValueSets");
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
Resource[] mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/*.profile.xml");
total = mappingLocations.length;
count = 1;
for (Resource i : mappingLocations) {
StructureDefinition next = ctx.newXmlParser().parseResource(StructureDefinition.class, IOUtils.toString(i.getInputStream(), "UTF-8"));
next.setId(next.getIdElement().toUnqualifiedVersionless());
ourLog.info("Uploading StructureDefinition {}/{} : {}", new Object[] { count, total, next.getIdElement().getValue() });
client.update().resource(next).execute();
count++;
}
ourLog.info("Finished uploading ValueSets");
}
}

View File

@ -36,6 +36,11 @@
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId>
@ -45,24 +50,17 @@
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<!--
Use an older version of SLF4j just to make sure we compile correctly
against old SLF4j - Some people can't upgrade and we have no real
need for recent features.
-->
<!-- Use an older version of SLF4j just to make sure we compile correctly against old SLF4j - Some people can't upgrade and we have no real need for recent features. -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@ -146,18 +144,15 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava_version}</version>
</dependency>
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>${xmlunit_version}</version>
<scope>test</scope>
</dependency>
@ -176,36 +171,10 @@
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<maxmem>256m</maxmem>
<instrumentation>
<ignores>
<ignore>ca.uhn.fhir.model.dstu.valueset.*</ignore>
</ignores>
<excludes>
<ignore>**/valueset/*.class</ignore>
<ignore>**/exceptions/*.class</ignore>
</excludes>
<!-- <ignoreMethodAnnotations> <ignoreMethodAnnotation>net.sourceforge.cobertura.CoverageIgnore</ignoreMethodAnnotation> </ignoreMethodAnnotations> -->
</instrumentation>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <configuration> <skip>false</skip> <formats> <format>html</format> <format>xml</format> </formats>
<maxmem>256m</maxmem> <instrumentation> <ignores> <ignore>ca.uhn.fhir.model.dstu.valueset.*</ignore> </ignores> <excludes> <ignore>**/valueset/*.class</ignore> <ignore>**/exceptions/*.class</ignore> </excludes>
</instrumentation> </configuration> <executions> <execution> <phase>verify</phase> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin> -->
</plugins>
</pluginManagement>
<plugins>
@ -214,11 +183,6 @@
<artifactId>coveralls-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<coberturaReports>
<coberturaReport>
${basedir}/target/coverage.xml
</coberturaReport>
</coberturaReports>
<sourceEncoding>UTF-8</sourceEncoding>
<serviceName>travis-ci</serviceName>
<serviceJobId>${env.TRAVIS_JOB_ID}</serviceJobId>
@ -272,7 +236,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<runOrder>alphabetical</runOrder>
<argLine>-Xms512m -Xmx1024m</argLine>
<argLine>-Xms512m -Xmx1024m ${argLine}</argLine>
</configuration>
</plugin>
<plugin>
@ -291,26 +255,25 @@
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<phase>verify</phase>
<id>prepare-agent</id>
<goals>
<goal>check</goal>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>${maven_cobertura_plugin_version}</version> <configuration> <check> <branchRate>85</branchRate>
<lineRate>85</lineRate> <haltOnFailure>true</haltOnFailure> <totalBranchRate>85</totalBranchRate> <totalLineRate>85</totalLineRate> <packageLineRate>85</packageLineRate> <packageBranchRate>85</packageBranchRate>
<regexes> <regex> <pattern>com.example.reallyimportant.*</pattern> <branchRate>90</branchRate> <lineRate>80</lineRate> </regex> <regex> <pattern>com.example.boringcode.*</pattern> <branchRate>40</branchRate>
<lineRate>30</lineRate> </regex> </regexes> </check> </configuration> <executions> <execution> <goals> <goal>clean</goal> <goal>check</goal> </goals> </execution> </executions> </plugin> -->
</plugins>
<resources>
</resources>
@ -331,22 +294,6 @@
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<report>cobertura</report>
</reports>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>

View File

@ -0,0 +1,378 @@
<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>
<!-- The parent of this project is the deployable POM. This project isn't deployable, but this keeps it before the root pom in the reactor order when building the site. I don't know why this works...
Need to investigate this. -->
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>1.2-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-cobertura</artifactId>
<packaging>jar</packaging>
<name>HAPI FHIR - Cobertura Test Coverage</name>
<dependencies>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<!--
Use an older version of SLF4j just to make sure we compile correctly
against old SLF4j - Some people can't upgrade and we have no real
need for recent features.
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Test Database -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</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>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15-sources</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>directory-naming</groupId>
<artifactId>naming-java</artifactId>
<version>0.8</version>
<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>
<version>${guava_version}</version>
</dependency>
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>${xmlunit_version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skipDeploy>true</skipDeploy>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<maxmem>256m</maxmem>
<instrumentation>
<ignores>
<ignore>ca.uhn.fhir.model.dstu.valueset.*</ignore>
</ignores>
<excludes>
<ignore>**/valueset/*.class</ignore>
<ignore>**/exceptions/*.class</ignore>
</excludes>
<!-- <ignoreMethodAnnotations> <ignoreMethodAnnotation>net.sourceforge.cobertura.CoverageIgnore</ignoreMethodAnnotation> </ignoreMethodAnnotations> -->
</instrumentation>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<coberturaReports>
<coberturaReport>
${basedir}/target/coverage.xml
</coberturaReport>
</coberturaReports>
<sourceEncoding>UTF-8</sourceEncoding>
<serviceName>travis-ci</serviceName>
<serviceJobId>${env.TRAVIS_JOB_ID}</serviceJobId>
<sourceDirectories>
<sourceDirectory>../hapi-fhir-structures-dstu/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-hl7org-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/main/java</sourceDirectory>
</sourceDirectories>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${maven_build_helper_plugin_version}</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../hapi-fhir-base/src/main/java</source>
<source>../hapi-fhir-jpaserver-base/src/main/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>../hapi-fhir-structures-dstu/src/test/java</source>
<source>../hapi-fhir-structures-dstu2/src/test/java</source>
<source>../hapi-fhir-structures-hl7org-dstu2/src/test/java</source>
<source>../hapi-fhir-jpaserver-base/src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<runOrder>alphabetical</runOrder>
<argLine>-Xms512m -Xmx1024m</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> <version>${maven_cobertura_plugin_version}</version> <configuration> <check> <branchRate>85</branchRate>
<lineRate>85</lineRate> <haltOnFailure>true</haltOnFailure> <totalBranchRate>85</totalBranchRate> <totalLineRate>85</totalLineRate> <packageLineRate>85</packageLineRate> <packageBranchRate>85</packageBranchRate>
<regexes> <regex> <pattern>com.example.reallyimportant.*</pattern> <branchRate>90</branchRate> <lineRate>80</lineRate> </regex> <regex> <pattern>com.example.boringcode.*</pattern> <branchRate>40</branchRate>
<lineRate>30</lineRate> </regex> </regexes> </check> </configuration> <executions> <execution> <goals> <goal>clean</goal> <goal>check</goal> </goals> </execution> </executions> </plugin> -->
</plugins>
<resources>
</resources>
<testResources>
<testResource>
<directory>../hapi-fhir-jpaserver-base/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-dstu2/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-structures-hl7org-dstu2/src/test/resources</directory>
</testResource>
</testResources>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<report>cobertura</report>
</reports>
<configuration>
<check>
<haltOnFailure>true</haltOnFailure>
</check>
</configuration>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${maven_project_info_plugin_version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</reporting>
<profiles>
<profile>
<id>TRAVIS</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Travis build seems to run out of memory unless we don't reuse JVMs -->
<reuseForks>false</reuseForks>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -33,27 +33,22 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback_version}</version>
</dependency>
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
</dependency>
</dependencies>
@ -76,7 +71,6 @@
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven_assembly_plugin_version}</version>
<executions>
<execution>
<phase>package</phase>

View File

@ -0,0 +1,13 @@
update hfj_resource set forced_id_pid = null where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_history_tag where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_res_ver where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_forced_id where resource_pid in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_spidx_date where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_spidx_number where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_spidx_quantity where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_spidx_string where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_spidx_token where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_res_link where src_resource_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_res_tag where res_id in (select res_id from hfj_resource where sp_index_status = 2);
delete from hfj_resource where res_id in (select res_id from hfj_resource where sp_index_status = 2);

View File

@ -43,25 +43,26 @@
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu</artifactId>
<version>1.2-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-hl7org-dstu2</artifactId>
<version>1.2-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation-resources</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
@ -242,7 +243,6 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava_version}</version>
</dependency>
<dependency>
@ -265,6 +265,11 @@
<artifactId>jetty-util</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>

View File

@ -117,6 +117,8 @@ import ca.uhn.fhir.util.FhirTerser;
public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
public static final long INDEX_STATUS_INDEXED = Long.valueOf(1L);
public static final long INDEX_STATUS_INDEXING_FAILED = Long.valueOf(2L);
public static final String NS_JPA_PROFILE = "https://github.com/jamesagnew/hapi-fhir/ns/jpa/profile";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirDao.class);
@ -1127,12 +1129,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
entity.setParamsDatePopulated(dateParams.isEmpty() == false);
entity.setResourceLinks(links);
entity.setHasLinks(links.isEmpty() == false);
entity.setIndexStatus(INDEX_STATUS_INDEXED);
} else {
populateResourceIntoEntity(theResource, entity);
entity.setUpdated(new Date());
entity.setLanguage(theResource.getLanguage().getValue());
entity.setIndexStatus(null);
}

View File

@ -1697,13 +1697,17 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
}
/**
* May be implemented by subclasses to validate resources prior to storage
* May be overridden by subclasses to validate resources prior to storage
*
* @param theResource
* The resource that is about to be stored
*/
protected void preProcessResourceForStorage(T theResource) {
// nothing by default
if (theResource.getId().hasIdPart()) {
if (!theResource.getId().isIdPartValid()) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithInvalidId", theResource.getId().getIdPart()));
}
}
}
@Override
@ -2303,7 +2307,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IResource> extends BaseH
try {
entity = readEntityLatestVersion(resourceId);
} catch (ResourceNotFoundException e) {
if (Character.isDigit(theResource.getId().getIdPart().charAt(0))) {
if (resourceId.isIdPartValidLong()) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getId().getIdPart()));
}
return doCreate(theResource, null, thePerformIndexing);

View File

@ -22,34 +22,50 @@ package ca.uhn.fhir.jpa.dao;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public abstract class BaseHapiFhirSystemDao<T> extends BaseHapiFhirDao implements IFhirSystemDao<T> {
public abstract class BaseHapiFhirSystemDao<T> extends BaseHapiFhirDao<IBaseResource>implements IFhirSystemDao<T> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirSystemDao.class);
@Transactional(propagation=Propagation.REQUIRED)
@PersistenceContext()
protected EntityManager myEntityManager;
@Autowired
private PlatformTransactionManager myTxManager;
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void deleteAllTagsOnServer() {
// Notify interceptors
@ -59,40 +75,6 @@ public abstract class BaseHapiFhirSystemDao<T> extends BaseHapiFhirDao implement
myEntityManager.createQuery("DELETE from ResourceTag t").executeUpdate();
}
@PersistenceContext()
protected EntityManager myEntityManager;
protected boolean hasValue(InstantDt theInstantDt) {
return theInstantDt != null && theInstantDt.isEmpty() == false;
}
protected ResourceTable tryToLoadEntity(IdDt nextId) {
ResourceTable entity;
try {
Long pid = translateForcedIdToPid(nextId);
entity = myEntityManager.find(ResourceTable.class, pid);
} catch (ResourceNotFoundException e) {
entity = null;
}
return entity;
}
protected ResourceTable loadFirstEntityFromCandidateMatches(Set<Long> candidateMatches) {
return myEntityManager.find(ResourceTable.class, candidateMatches.iterator().next());
}
@Override
public IBundleProvider history(Date theSince) {
// Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
StopWatch w = new StopWatch();
IBundleProvider retVal = super.history(null, null, theSince);
ourLog.info("Processed global history in {}ms", w.getMillisAndRestart());
return retVal;
}
@Override
public TagList getAllTags() {
// Notify interceptors
@ -124,4 +106,122 @@ public abstract class BaseHapiFhirSystemDao<T> extends BaseHapiFhirDao implement
return retVal;
}
protected boolean hasValue(InstantDt theInstantDt) {
return theInstantDt != null && theInstantDt.isEmpty() == false;
}
@Override
public IBundleProvider history(Date theSince) {
// Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
StopWatch w = new StopWatch();
IBundleProvider retVal = super.history(null, null, theSince);
ourLog.info("Processed global history in {}ms", w.getMillisAndRestart());
return retVal;
}
protected ResourceTable loadFirstEntityFromCandidateMatches(Set<Long> candidateMatches) {
return myEntityManager.find(ResourceTable.class, candidateMatches.iterator().next());
}
@Transactional()
@Override
public int markAllResourcesForReindexing() {
return myEntityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " t SET t.myIndexStatus = null").executeUpdate();
}
private void markResourceAsIndexingFailed(final ResourceTable theResourceTable) {
ourLog.info("Marking resource with PID {} and ID {} as indexing_failed", new Object[] { theResourceTable.getId(), theResourceTable.getIdDt().getValue() });
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
Query q = myEntityManager.createQuery("UPDATE ResourceTable t SET t.myIndexStatus = :status WHERE t.myId = :id");
q.setParameter("status", INDEX_STATUS_INDEXING_FAILED);
q.setParameter("id", theResourceTable.getId());
q.executeUpdate();
return null;
}
});
}
@SuppressWarnings("unchecked")
@Override
@Transactional()
public int performReindexingPass(Integer theCount) {
TypedQuery<ResourceTable> q = myEntityManager.createQuery("SELECT t FROM " + ResourceTable.class.getSimpleName() + " t WHERE t.myIndexStatus IS null", ResourceTable.class);
int maxResult = 500;
if (theCount != null) {
maxResult = Math.min(theCount, 2000);
}
q.setMaxResults(maxResult);
List<ResourceTable> resources = q.getResultList();
ourLog.info("Indexing {} resources", resources.size());
int count = 0;
long start = System.currentTimeMillis();
for (ResourceTable resourceTable : resources) {
final IBaseResource resource;
try {
resource = toResource(resourceTable);
} catch (DataFormatException e) {
ourLog.warn("Failure parsing resource: {}", e.toString());
markResourceAsIndexingFailed(resourceTable);
continue;
}
@SuppressWarnings("rawtypes")
final IFhirResourceDao dao = getDao(resource.getClass());
if (dao == null) {
ourLog.warn("No DAO for type: {}", resource.getClass());
markResourceAsIndexingFailed(resourceTable);
continue;
}
if (resource.getIdElement().isIdPartValid() == false) {
ourLog.warn("Not going to try and index an invalid ID: {}", resource.getIdElement());
markResourceAsIndexingFailed(resourceTable);
continue;
}
try {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
dao.update(resource, null, true);
return null;
}
});
} catch (Exception e) {
ourLog.error("Failed to index resource {}: {}", new Object[] { resource.getIdElement(), e.toString() });
markResourceAsIndexingFailed(resourceTable);
}
count++;
}
long delay = System.currentTimeMillis() - start;
ourLog.info("Indexed {} / {} resources in {}ms", new Object[] { count, resources.size(), delay });
return resources.size();
}
protected ResourceTable tryToLoadEntity(IdDt nextId) {
ResourceTable entity;
try {
Long pid = translateForcedIdToPid(nextId);
entity = myEntityManager.find(ResourceTable.class, pid);
} catch (ResourceNotFoundException e) {
entity = null;
}
return entity;
}
}

View File

@ -28,26 +28,36 @@ import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.rest.server.IBundleProvider;
/**
* @param <T> The bundle type
* @param <T>
* The bundle type
*/
public interface IFhirSystemDao<T> extends IDao {
T transaction(T theResources);
IBundleProvider history(Date theDate);
TagList getAllTags();
Map<String, Long> getResourceCounts();
/**
* Not supported for DSTU1
*/
MetaDt metaGetOperation();
/**
* Use with caution! This deletes everything!!
*/
void deleteAllTagsOnServer();
TagList getAllTags();
Map<String, Long> getResourceCounts();
IBundleProvider history(Date theDate);
int performReindexingPass(Integer theCount);
/**
* Marks all indexes as needing fresh indexing
*
* @return Returns the number of affected rows
*/
int markAllResourcesForReindexing();
/**
* Not supported for DSTU1
*/
MetaDt metaGetOperation();
T transaction(T theResources);
}

View File

@ -32,6 +32,7 @@ import javax.measure.quantity.Quantity;
import javax.measure.unit.NonSI;
import javax.measure.unit.Unit;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import ca.uhn.fhir.context.ConfigurationException;
@ -60,6 +61,7 @@ import ca.uhn.fhir.model.dstu2.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
import ca.uhn.fhir.model.dstu2.resource.Conformance.RestSecurity;
import ca.uhn.fhir.model.dstu2.resource.Location;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Patient.Communication;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
@ -73,6 +75,8 @@ import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISearchParamExtractor {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorDstu2.class);
public SearchParamExtractorDstu2(FhirContext theContext) {
super(theContext);
}
@ -80,8 +84,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamDates(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamDates(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
*/
@Override
public List<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) {
@ -143,8 +146,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamNumber(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamNumber(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
*/
@Override
public ArrayList<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) {
@ -191,18 +193,12 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
nextValue = newValue;
/*
* @SuppressWarnings("unchecked") PhysicsUnit<? extends
* org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends
* org.unitsofmeasurement.quantity.Quantity<?>>)
* UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if
* (unit.isCompatible(UCUM.DAY)) {
* @SuppressWarnings("unchecked") PhysicsUnit<? extends org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends org.unitsofmeasurement.quantity.Quantity<?>>)
* UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if (unit.isCompatible(UCUM.DAY)) {
*
* @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit
* = (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY);
* double dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt
* newValue = new DurationDt(); newValue.setSystem(UCUM_NS);
* newValue.setCode(UCUM.DAY.getSymbol()); newValue.setValue(dayValue); nextValue=newValue;
* }
* @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit = (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY);
* double dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt newValue = new DurationDt(); newValue.setSystem(UCUM_NS);
* newValue.setCode(UCUM.DAY.getSymbol()); newValue.setValue(dayValue); nextValue=newValue; }
*/
}
}
@ -246,8 +242,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamQuantity(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamQuantity(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
*/
@Override
public List<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IResource theResource) {
@ -281,7 +276,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
continue;
}
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValue.getValueElement().getValue(), nextValue.getSystemElement().getValueAsString(), nextValue.getCode());
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(resourceName, nextValue.getValueElement().getValue(),
nextValue.getSystemElement().getValueAsString(), nextValue.getCode());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
} else {
@ -302,8 +298,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamStrings(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamStrings(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
*/
@Override
public List<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IResource theResource) {
@ -317,11 +312,11 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
String nextPath = nextSpDef.getPath();
String resourceName = nextSpDef.getName();
if (isBlank(nextPath)) {
// TODO: implement phonetic, and any others that have no path
if ("Questionnaire".equals(def.getName()) && nextSpDef.getName().equals("title")) {
Questionnaire q = (Questionnaire) theResource;
String title = q.getGroup().getTitle();
@ -399,8 +394,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
/*
* (non-Javadoc)
*
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamTokens(ca.uhn.fhir.jpa.entity.ResourceTable,
* ca.uhn.fhir.model.api.IResource)
* @see ca.uhn.fhir.jpa.dao.ISearchParamExtractor#extractSearchParamTokens(ca.uhn.fhir.jpa.entity.ResourceTable, ca.uhn.fhir.model.api.IResource)
*/
@Override
public List<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IResource theResource) {
@ -411,7 +405,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
ValueSet vs = (ValueSet) theResource;
useSystem = vs.getCodeSystem().getSystem();
}
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
@ -442,32 +436,41 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
}
for (Object nextObject : extractValues(nextPath, theResource)) {
// Patient:language
// Patient:language
if (nextObject instanceof Patient.Communication) {
Communication nextValue = (Patient.Communication) nextObject;
nextObject= nextValue.getLanguage();
nextObject = nextValue.getLanguage();
}
if (nextObject instanceof IdentifierDt) {
IdentifierDt nextValue = (IdentifierDt) nextObject;
if (nextValue.isEmpty()) {
continue;
}
systems.add(nextValue.getSystemElement().getValueAsString());
codes.add(nextValue.getValueElement().getValue());
String system = StringUtils.defaultIfBlank(nextValue.getSystemElement().getValueAsString(), null);
String value = nextValue.getValueElement().getValue();
if (isNotBlank(value)) {
systems.add(system);
codes.add(value);
}
if (isNotBlank(nextValue.getType().getText())) {
addStringParam(theEntity, retVal, nextSpDef, nextValue.getType().getText());
}
} else if (nextObject instanceof ContactPointDt) {
ContactPointDt nextValue = (ContactPointDt) nextObject;
if (nextValue.isEmpty()) {
ContactPointDt nextValue = (ContactPointDt) nextObject;
if (nextValue.isEmpty()) {
continue;
}
if (isNotBlank(needContactPointSystem)) {
if (!needContactPointSystem.equals(nextValue.getSystemElement().getValueAsString())) {
continue;
}
if (isNotBlank(needContactPointSystem)) {
if (!needContactPointSystem.equals(nextValue.getSystemElement().getValueAsString())) {
continue;
}
}
systems.add(nextValue.getSystemElement().getValueAsString());
codes.add(nextValue.getValueElement().getValue());
}
systems.add(nextValue.getSystemElement().getValueAsString());
codes.add(nextValue.getValueElement().getValue());
} else if (nextObject instanceof IPrimitiveDatatype<?>) {
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
if (nextValue.isEmpty()) {
@ -481,39 +484,23 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
codes.add(nextValue.getValueAsString());
} else if (nextObject instanceof CodingDt) {
CodingDt nextValue = (CodingDt) nextObject;
if (nextValue.isEmpty()) {
continue;
}
String nextSystem = nextValue.getSystemElement().getValueAsString();
String nextCode = nextValue.getCodeElement().getValue();
if (isNotBlank(nextSystem) || isNotBlank(nextCode)) {
systems.add(nextSystem);
codes.add(nextCode);
}
if (!nextValue.getDisplayElement().isEmpty()) {
systems.add(null);
codes.add(nextValue.getDisplayElement().getValue());
}
extractTokensFromCoding(systems, codes, theEntity, retVal, nextSpDef, nextValue);
} else if (nextObject instanceof CodeableConceptDt) {
CodeableConceptDt nextCC = (CodeableConceptDt) nextObject;
if (!nextCC.getTextElement().isEmpty()) {
String value = nextCC.getTextElement().getValue();
if (value.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
value = value.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
}
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(nextSpDef.getName(), BaseHapiFhirDao.normalizeString(value), value);
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
addStringParam(theEntity, retVal, nextSpDef, nextCC.getTextElement().getValue());
}
extractTokensFromCodeableConcept(systems, codes, nextCC);
extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef);
} else if (nextObject instanceof RestSecurity) {
// Conformance.security search param points to something kind of useless right now - This should probably be fixed.
RestSecurity sec = (RestSecurity)nextObject;
RestSecurity sec = (RestSecurity) nextObject;
for (BoundCodeableConceptDt<RestfulSecurityServiceEnum> nextCC : sec.getService()) {
extractTokensFromCodeableConcept(systems, codes, nextCC);
extractTokensFromCodeableConcept(systems, codes, nextCC, theEntity, retVal, nextSpDef);
}
} else if (nextObject instanceof Location.Position) {
ourLog.warn("Position search not currently supported, not indexing location");
continue;
} else {
if (!multiType) {
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
@ -560,22 +547,35 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
return retVal;
}
private void extractTokensFromCodeableConcept(List<String> systems, List<String> codes, CodeableConceptDt nextCC) {
for (CodingDt nextCoding : nextCC.getCoding()) {
if (nextCoding.isEmpty()) {
continue;
}
private void addStringParam(ResourceTable theEntity, ArrayList<BaseResourceIndexedSearchParam> retVal, RuntimeSearchParam nextSpDef, String value) {
if (value.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
value = value.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
}
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(nextSpDef.getName(), BaseHapiFhirDao.normalizeString(value), value);
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
}
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity,
ArrayList<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
for (CodingDt nextCoding : theCodeableConcept.getCoding()) {
extractTokensFromCoding(theSystems, theCodes, theEntity, theListToPopulate, theParameterDef, nextCoding);
}
}
private void extractTokensFromCoding(List<String> theSystems, List<String> theCodes, ResourceTable theEntity, ArrayList<BaseResourceIndexedSearchParam> theListToPopulate,
RuntimeSearchParam theParameterDef, CodingDt nextCoding) {
if (nextCoding != null && !nextCoding.isEmpty()) {
String nextSystem = nextCoding.getSystemElement().getValueAsString();
String nextCode = nextCoding.getCodeElement().getValue();
if (isNotBlank(nextSystem) || isNotBlank(nextCode)) {
systems.add(nextSystem);
codes.add(nextCode);
theSystems.add(nextSystem);
theCodes.add(nextCode);
}
if (!nextCoding.getDisplayElement().isEmpty()) {
systems.add(null);
codes.add(nextCoding.getDisplayElement().getValue());
addStringParam(theEntity, theListToPopulate, theParameterDef, nextCoding.getDisplayElement().getValue());
}
}

View File

@ -53,17 +53,18 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
indexes = {
@Index(name = "IDX_RES_DATE", columnNames = { "RES_UPDATED" }),
@Index(name = "IDX_RES_LANG", columnNames = { "RES_TYPE", "RES_LANGUAGE" }),
@Index(name = "IDX_RES_PROFILE", columnNames = { "RES_PROFILE" })
@Index(name = "IDX_RES_PROFILE", columnNames = { "RES_PROFILE" }),
@Index(name = "IDX_INDEXSTATUS", columnNames = { "SP_INDEX_STATUS" })
})
//@formatter:on
public class ResourceTable extends BaseHasResource implements Serializable {
private static final int MAX_LANGUAGE_LENGTH = 20;
private static final int MAX_PROFILE_LENGTH = 200;
private static final long serialVersionUID = 1L;
static final int RESTYPE_LEN = 30;
private static final long serialVersionUID = 1L;
@Column(name = "SP_HAS_LINKS")
private boolean myHasLinks;
@ -74,6 +75,12 @@ public class ResourceTable extends BaseHasResource implements Serializable {
@OneToMany(mappedBy = "myTargetResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection<ResourceLink> myIncomingResourceLinks;
@Column(name = "SP_INDEX_STATUS", nullable=true)
private Long myIndexStatus;
@Column(name = "RES_LANGUAGE", length=MAX_LANGUAGE_LENGTH, nullable=true)
private String myLanguage;
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection<ResourceIndexedSearchParamDate> myParamsDate;
@ -105,6 +112,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
@Column(name = "SP_TOKEN_PRESENT")
private boolean myParamsTokenPopulated;
@Column(name = "RES_PROFILE", length=MAX_PROFILE_LENGTH,nullable=true)
private String myProfile;
@OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection<ResourceLink> myResourceLinks;
@ -117,34 +127,6 @@ public class ResourceTable extends BaseHasResource implements Serializable {
@Column(name = "RES_VER")
private long myVersion;
@Column(name = "RES_LANGUAGE", length=MAX_LANGUAGE_LENGTH, nullable=true)
private String myLanguage;
@Column(name = "RES_PROFILE", length=MAX_PROFILE_LENGTH,nullable=true)
private String myProfile;
public String getLanguage() {
return myLanguage;
}
public void setLanguage(String theLanguage) {
if (defaultString(theLanguage).length()> MAX_LANGUAGE_LENGTH) {
throw new UnprocessableEntityException("Language exceeds maximum length of " + MAX_LANGUAGE_LENGTH + " chars: " + theLanguage);
}
myLanguage = theLanguage;
}
public String getProfile() {
return myProfile;
}
public void setProfile(String theProfile) {
if (defaultString(theProfile).length()> MAX_PROFILE_LENGTH) {
throw new UnprocessableEntityException("Profile name exceeds maximum length of " + MAX_PROFILE_LENGTH + " chars: " + theProfile);
}
myProfile = theProfile;
}
public ResourceTag addTag(TagDefinition theTag) {
ResourceTag tag = new ResourceTag(this, theTag);
tag.setResourceType(getResourceType());
@ -155,12 +137,20 @@ public class ResourceTable extends BaseHasResource implements Serializable {
public Long getId() {
return myId;
}
public IdDt getIdDt() {
Object id = getForcedId() == null ? myId : getForcedId().getForcedId();
return new IdDt(myResourceType + '/' + id + '/' + Constants.PARAM_HISTORY + '/' + myVersion);
}
public Long getIndexStatus() {
return myIndexStatus;
}
public String getLanguage() {
return myLanguage;
}
public Collection<ResourceIndexedSearchParamDate> getParamsDate() {
if (myParamsDate == null) {
myParamsDate = new ArrayList<ResourceIndexedSearchParamDate>();
@ -175,7 +165,6 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return myParamsNumber;
}
public Collection<ResourceIndexedSearchParamQuantity> getParamsQuantity() {
if(myParamsQuantity==null) {
myParamsQuantity=new ArrayList<ResourceIndexedSearchParamQuantity>();
@ -197,6 +186,11 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return myParamsToken;
}
public String getProfile() {
return myProfile;
}
public Collection<ResourceLink> getResourceLinks() {
if (myResourceLinks == null) {
myResourceLinks = new ArrayList<ResourceLink>();
@ -260,6 +254,17 @@ public class ResourceTable extends BaseHasResource implements Serializable {
myId = theId;
}
public void setIndexStatus(Long theIndexStatus) {
myIndexStatus = theIndexStatus;
}
public void setLanguage(String theLanguage) {
if (defaultString(theLanguage).length()> MAX_LANGUAGE_LENGTH) {
throw new UnprocessableEntityException("Language exceeds maximum length of " + MAX_LANGUAGE_LENGTH + " chars: " + theLanguage);
}
myLanguage = theLanguage;
}
public void setParamsDate(Collection<ResourceIndexedSearchParamDate> theParamsDate) {
if (!isParamsDatePopulated() && theParamsDate.isEmpty()) {
return;
@ -320,6 +325,13 @@ public class ResourceTable extends BaseHasResource implements Serializable {
myParamsTokenPopulated = theParamsTokenPopulated;
}
public void setProfile(String theProfile) {
if (defaultString(theProfile).length()> MAX_PROFILE_LENGTH) {
throw new UnprocessableEntityException("Profile name exceeds maximum length of " + MAX_PROFILE_LENGTH + " chars: " + theProfile);
}
myProfile = theProfile;
}
public void setResourceLinks(List<ResourceLink> theLinks) {
if (!isHasLinks() && theLinks.isEmpty()) {
return;

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.provider;
import java.util.Collections;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.rest.annotation.IdParam;
@ -50,8 +50,8 @@ public class BaseJpaResourceProviderEncounterDstu2 extends JpaResourceProviderDs
paramMap.setCount(theCount.getValue());
}
paramMap.setRevIncludes(Collections.singleton(new Include("*")));
paramMap.setIncludes(Collections.singleton(new Include("*")));
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.add("_id", new StringParam(theId.getIdPart()));
ca.uhn.fhir.rest.server.IBundleProvider retVal = getDao().search(paramMap);
return retVal;

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.provider;
import java.util.Collections;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.rest.annotation.IdParam;
@ -48,8 +48,8 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
paramMap.setCount(theCount.getValue());
}
paramMap.setRevIncludes(Collections.singleton(new Include("*")));
paramMap.setIncludes(Collections.singleton(new Include("*")));
paramMap.setRevIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.add("_id", new StringParam(theId.getIdPart()));
ca.uhn.fhir.rest.server.IBundleProvider retVal = getDao().search(paramMap);
return retVal;

View File

@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.provider;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
@ -40,8 +42,6 @@ import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
import ca.uhn.fhir.util.ExtensionConstants;
import javax.servlet.http.HttpServletRequest;
public class JpaConformanceProviderDstu1 extends ServerConformanceProvider {
private String myImplementationDescription;

View File

@ -40,6 +40,7 @@ import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Transaction;
import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.param.NumberParam;
public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle> {
@ -49,7 +50,7 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle> {
//@formatter:off
// This is generated by hand:
// gls hapi-fhir-structures-dstu2/target/generated-sources/tinder/ca/uhn/fhir/model/dstu2/resource/ | sort | sed "s/.java//" | sed "s/^/@OperationParam(name=\"/" | sed "s/$/\", type=IntegerDt.class, min=0, max=1),/"
// ls hapi-fhir-structures-dstu2/target/generated-sources/tinder/ca/uhn/fhir/model/dstu2/resource/ | sort | sed "s/.java//" | sed "s/^/@OperationParam(name=\"/" | sed "s/$/\", type=IntegerDt.class, min=0, max=1),/"
@Operation(name="$get-resource-counts", idempotent=true, returnParameters= {
@OperationParam(name="AllergyIntolerance", type=IntegerDt.class, min=0, max=1),
@OperationParam(name="Appointment", type=IntegerDt.class, min=0, max=1),
@ -157,6 +158,33 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider<Bundle> {
return retVal;
}
//@formatter:off
@Operation(name="$mark-all-resources-for-reindexing", idempotent=true, returnParameters= {
@OperationParam(name="count", type=IntegerDt.class)
})
//@formatter:on
public Parameters markAllResourcesForReindexing() {
int count = mySystemDao.markAllResourcesForReindexing();
Parameters retVal = new Parameters();
retVal.addParameter().setName("count").setValue(new IntegerDt(count));
return retVal;
}
//@formatter:off
@Operation(name="$perform-reindexing-pass", idempotent=true, returnParameters= {
@OperationParam(name="count", type=IntegerDt.class)
})
//@formatter:on
public Parameters performReindexingPass(@OperationParam(min=0, max=1, name="count") IntegerDt theCount) {
Integer countIn = theCount != null && theCount.getValue()!= null ? theCount.getValue().intValue() : null;
int count = mySystemDao.performReindexingPass(countIn);
Parameters retVal = new Parameters();
retVal.addParameter().setName("count").setValue(new IntegerDt(count));
return retVal;
}
//@formatter:off
@Operation(name="$meta", idempotent=true, returnParameters= {
@OperationParam(name="return", type=MetaDt.class)

View File

@ -0,0 +1,154 @@
package ca.uhn.fhir.jpa.dao;
import static org.mockito.Mockito.mock;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.ForcedId;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTag;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.entity.ResourceLink;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.ResourceTag;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Device;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.dstu2.resource.Location;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
//@formatter:off
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
"classpath:hapi-fhir-server-resourceproviders-dstu2.xml",
"classpath:fhir-jpabase-spring-test-config.xml"})
@TransactionConfiguration(defaultRollback=false)
//@formatter:on
public class BaseJpaDstu2Test extends BaseJpaTest {
@Autowired
@Qualifier("myDeviceDaoDstu2")
protected IFhirResourceDao<Device> myDeviceDao;
@Autowired
@Qualifier("myDiagnosticReportDaoDstu2")
protected IFhirResourceDao<DiagnosticReport> myDiagnosticReportDao;
@Autowired
@Qualifier("myEncounterDaoDstu2")
protected IFhirResourceDao<Encounter> myEncounterDao;
@Autowired
protected FhirContext myFhirCtx;
protected IServerInterceptor myInterceptor;
@Autowired
@Qualifier("myLocationDaoDstu2")
protected IFhirResourceDao<Location> myLocationDao;
@Autowired
@Qualifier("myObservationDaoDstu2")
protected IFhirResourceDao<Observation> myObservationDao;
@Autowired
@Qualifier("myOrganizationDaoDstu2")
protected IFhirResourceDao<Organization> myOrganizationDao;
@Autowired
@Qualifier("myPatientDaoDstu2")
protected IFhirResourceDao<Patient> myPatientDao;
@Autowired
@Qualifier("myPractitionerDaoDstu2")
protected IFhirResourceDao<Practitioner> myPractitionerDao;
@Autowired
@Qualifier("myQuestionnaireDaoDstu2")
protected IFhirResourceDao<Questionnaire> myQuestionnaireDao;
@Autowired
@Qualifier("myQuestionnaireResponseDaoDstu2")
protected IFhirResourceDao<QuestionnaireResponse> myQuestionnaireResponseDao;
@Autowired
@Qualifier("mySystemDaoDstu2")
protected IFhirSystemDao<Bundle> mySystemDao;
@Autowired
protected DaoConfig myDaoConfig;
@Autowired
protected PlatformTransactionManager myTxManager;
@PersistenceContext()
protected EntityManager myEntityManager;
/**
* Just so that JUnit doesn't complain about no test methods in this class
*/
@Test
public void doNothing() {
// nothing
}
@Before
@Transactional()
public void beforePurgeDatabase() {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
myEntityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate();
return null;
}
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + ForcedId.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d").executeUpdate();
return null;
}
});
txTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus theStatus) {
myEntityManager.createQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d").executeUpdate();
myEntityManager.createQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d").executeUpdate();
return null;
}
});
}
@Before
public void beforeCreateInterceptor() {
myInterceptor = mock(IServerInterceptor.class);
myDaoConfig.setInterceptors(myInterceptor);
}
}

View File

@ -1,9 +1,15 @@
package ca.uhn.fhir.jpa.dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import ca.uhn.fhir.rest.server.IBundleProvider;
public class BaseJpaTest {
@AfterClass
@ -15,4 +21,18 @@ public class BaseJpaTest {
// }
}
@SuppressWarnings({ "rawtypes" })
protected List toList(IBundleProvider theSearch) {
return theSearch.getResources(0, theSearch.size());
}
protected List<IIdType> toUnqualifiedVersionlessIds(IBundleProvider theFound) {
List<IIdType> retVal = new ArrayList<IIdType>();
for (IBaseResource next : theFound.getResources(0, theFound.size())) {
retVal.add((IIdType) next.getIdElement().toUnqualifiedVersionless());
}
return retVal;
}
}

View File

@ -72,7 +72,7 @@ public class FhirResourceDaoDstu1Test extends BaseJpaTest {
ourPatientDao.create(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("clients may only assign IDs which begin with a non-numeric"));
assertThat(e.getMessage(), containsString("clients may only assign IDs which contain at least one non-numeric"));
}
}
@ -117,7 +117,7 @@ public class FhirResourceDaoDstu1Test extends BaseJpaTest {
ourPatientDao.update(p1);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("clients may only assign IDs which begin with a non-numeric"));
assertThat(e.getMessage(), containsString("clients may only assign IDs which contain at least one non-numeric"));
}
}

View File

@ -0,0 +1,285 @@
package ca.uhn.fhir.jpa.dao;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public class FhirResourceDaoDstu2UpdateTest extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2UpdateTest.class);
@Test
public void testUpdateAndGetHistoryResource() throws InterruptedException {
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().addFamily("Tester").addGiven("Joe");
MethodOutcome outcome = myPatientDao.create(patient);
assertNotNull(outcome.getId());
assertFalse(outcome.getId().isEmpty());
assertEquals("1", outcome.getId().getVersionIdPart());
Date now = new Date();
Patient retrieved = myPatientDao.read(outcome.getId());
InstantDt published = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
InstantDt updated = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
assertTrue(published.before(now));
assertTrue(updated.before(now));
Thread.sleep(1000);
reset(myInterceptor);
retrieved.getIdentifierFirstRep().setValue("002");
MethodOutcome outcome2 = myPatientDao.update(retrieved);
assertEquals(outcome.getId().getIdPart(), outcome2.getId().getIdPart());
assertNotEquals(outcome.getId().getVersionIdPart(), outcome2.getId().getVersionIdPart());
assertEquals("2", outcome2.getId().getVersionIdPart());
// Verify interceptor
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.UPDATE), detailsCapt.capture());
ActionRequestDetails details = detailsCapt.getValue();
assertNotNull(details.getId());
assertEquals("Patient", details.getResourceType());
assertEquals(Patient.class, details.getResource().getClass());
Date now2 = new Date();
Patient retrieved2 = myPatientDao.read(outcome.getId().toVersionless());
assertEquals("2", retrieved2.getId().getVersionIdPart());
assertEquals("002", retrieved2.getIdentifierFirstRep().getValue());
InstantDt published2 = (InstantDt) retrieved2.getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
InstantDt updated2 = (InstantDt) retrieved2.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
assertTrue(published2.before(now));
assertTrue(updated2.after(now));
assertTrue(updated2.before(now2));
Thread.sleep(2000);
/*
* Get history
*/
IBundleProvider historyBundle = myPatientDao.history(outcome.getId(), null);
assertEquals(2, historyBundle.size());
List<IBaseResource> history = historyBundle.getResources(0, 2);
assertEquals("1", history.get(1).getIdElement().getVersionIdPart());
assertEquals("2", history.get(0).getIdElement().getVersionIdPart());
assertEquals(published, ResourceMetadataKeyEnum.PUBLISHED.get((IResource) history.get(1)));
assertEquals(published, ResourceMetadataKeyEnum.PUBLISHED.get((IResource) history.get(1)));
assertEquals(updated, ResourceMetadataKeyEnum.UPDATED.get((IResource) history.get(1)));
assertEquals("001", ((Patient) history.get(1)).getIdentifierFirstRep().getValue());
assertEquals(published2, ResourceMetadataKeyEnum.PUBLISHED.get((IResource) history.get(0)));
assertEquals(updated2, ResourceMetadataKeyEnum.UPDATED.get((IResource) history.get(0)));
assertEquals("002", ((Patient) history.get(0)).getIdentifierFirstRep().getValue());
}
@Test
public void testUpdateByUrl() {
String methodName = "testUpdateByUrl";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
myPatientDao.update(p, "Patient?identifier=urn%3Asystem%7C" + methodName);
p = myPatientDao.read(id.toVersionless());
assertThat(p.getId().toVersionless().toString(), not(containsString("test")));
assertEquals(id.toVersionless(), p.getId().toVersionless());
assertNotEquals(id, p.getId());
assertThat(p.getId().toString(), endsWith("/_history/2"));
}
@Test
public void testUpdateCreatesTextualIdIfItDoesntAlreadyExist() {
Patient p = new Patient();
String methodName = "testUpdateCreatesTextualIdIfItDoesntAlreadyExist";
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Hello");
p.setId("Patient/" + methodName);
IIdType id = myPatientDao.update(p).getId();
assertEquals("Patient/" + methodName, id.toUnqualifiedVersionless().getValue());
p = myPatientDao.read(id);
assertEquals(methodName, p.getIdentifierFirstRep().getValue());
}
@Test
public void testUpdateDoesntFailForUnknownIdWithNumberThenText() {
String methodName = "testUpdateFailsForUnknownIdWithNumberThenText";
Patient p = new Patient();
p.setId("0" + methodName);
p.addName().addFamily(methodName);
myPatientDao.update(p);
}
@Test
public void testUpdateMaintainsSearchParams() throws InterruptedException {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsDstu2AAA");
p1.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2AAA");
IIdType p1id = myPatientDao.create(p1).getId();
Patient p2 = new Patient();
p2.addIdentifier().setSystem("urn:system").setValue("testUpdateMaintainsSearchParamsDstu2BBB");
p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB");
myPatientDao.create(p2).getId();
Set<Long> ids = myPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2AAA"));
assertEquals(1, ids.size());
assertThat(ids, contains(p1id.getIdPartAsLong()));
// Update the name
p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsDstu2BBB");
MethodOutcome update2 = myPatientDao.update(p1);
IIdType p1id2 = update2.getId();
ids = myPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2AAA"));
assertEquals(0, ids.size());
ids = myPatientDao.searchForIds(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2BBB"));
assertEquals(2, ids.size());
// Make sure vreads work
p1 = myPatientDao.read(p1id);
assertEquals("testUpdateMaintainsSearchParamsDstu2AAA", p1.getNameFirstRep().getGivenAsSingleString());
p1 = myPatientDao.read(p1id2);
assertEquals("testUpdateMaintainsSearchParamsDstu2BBB", p1.getNameFirstRep().getGivenAsSingleString());
}
@Test
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
p1.addName().addFamily("Tester").addGiven("testUpdateRejectsInvalidTypes");
IIdType p1id = myPatientDao.create(p1).getId();
Organization p2 = new Organization();
p2.getNameElement().setValue("testUpdateRejectsInvalidTypes");
try {
p2.setId(new IdDt("Organization/" + p1id.getIdPart()));
myOrganizationDao.update(p2);
fail();
} catch (UnprocessableEntityException e) {
// good
}
try {
p2.setId(new IdDt("Patient/" + p1id.getIdPart()));
myOrganizationDao.update(p2);
fail();
} catch (UnprocessableEntityException e) {
ourLog.error("Good", e);
}
}
@Test
public void testUpdateUnknownNumericIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/9999999999999999");
try {
myPatientDao.update(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Can not create resource with ID[9999999999999999], no resource with this ID exists and clients may only"));
}
}
@Test
public void testUpdateWithInvalidIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/123:456");
try {
myPatientDao.update(p);
fail();
} catch (InvalidRequestException e) {
assertEquals("Can not process entity with ID[123:456], this is not a valid FHIR ID", e.getMessage());
}
}
@Test
public void testUpdateWithNumericIdFails() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/123");
try {
myPatientDao.update(p);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("clients may only assign IDs which contain at least one non-numeric"));
}
}
@Test
public void testUpdateWithNumericThenTextIdSucceeds() {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue("testCreateNumericIdFails");
p.addName().addFamily("Hello");
p.setId("Patient/123abc");
IIdType id = myPatientDao.update(p).getId();
assertEquals("123abc", id.getIdPart());
assertEquals("1", id.getVersionIdPart());
p = myPatientDao.read(id.toUnqualifiedVersionless());
assertEquals("Patient/123abc", p.getId().toUnqualifiedVersionless().getValue());
assertEquals("Hello", p.getName().get(0).getFamily().get(0).getValue());
}
}

View File

@ -14,28 +14,25 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.InputStream;
import java.sql.SQLException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.model.api.IResource;
@ -63,28 +60,82 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public class FhirSystemDaoDstu2Test extends BaseJpaTest {
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
private static ClassPathXmlApplicationContext ourCtx;
private static FhirContext ourFhirContext;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
private static IFhirResourceDao<Observation> ourObservationDao;
private static IFhirResourceDao<Patient> ourPatientDao;
private static IFhirSystemDao<Bundle> ourSystemDao;
private static IServerInterceptor ourInterceptor;
private void deleteEverything() {
FhirSystemDaoDstu2Test.doDeleteEverything(ourSystemDao);
}
@Test
public void testSystemMetaOperation() {
deleteEverything();
public void testRendexing() {
Patient p = new Patient();
p.addName().addFamily("family");
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
ResourceTable entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
assertEquals(Long.valueOf(1), entity.getIndexStatus());
mySystemDao.markAllResourcesForReindexing();
MetaDt meta = ourSystemDao.metaGetOperation();
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
assertEquals(null, entity.getIndexStatus());
mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
assertEquals(Long.valueOf(1), entity.getIndexStatus());
// Just make sure this doesn't cause a choke
mySystemDao.performReindexingPass(100000);
// Try making the resource unparseable
TransactionTemplate template = new TransactionTemplate(myTxManager);
template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
template.execute(new TransactionCallback<ResourceTable>() {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
ResourceTable table = myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
table.setEncoding(ResourceEncodingEnum.JSON);
table.setIndexStatus(null);
try {
table.setResource("{\"resourceType\":\"FOO\"}".getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
myEntityManager.merge(table);
return null;
}});
mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
assertEquals(Long.valueOf(2), entity.getIndexStatus());
}
@Test
public void testSystemMetaOperation() {
MetaDt meta = mySystemDao.metaGetOperation();
List<CodingDt> published = meta.getTag();
assertEquals(0, published.size());
@ -106,7 +157,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
profiles.add(new IdDt("http://profile/1"));
ResourceMetadataKeyEnum.PROFILES.put(patient, profiles);
id1 = ourPatientDao.create(patient).getId();
id1 = myPatientDao.create(patient).getId();
}
{
Patient patient = new Patient();
@ -124,10 +175,10 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
profiles.add(new IdDt("http://profile/2"));
ResourceMetadataKeyEnum.PROFILES.put(patient, profiles);
ourPatientDao.create(patient);
myPatientDao.create(patient);
}
meta = ourSystemDao.metaGetOperation();
meta = mySystemDao.metaGetOperation();
published = meta.getTag();
assertEquals(2, published.size());
assertEquals(null, published.get(0).getSystem());
@ -149,11 +200,11 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertEquals("http://profile/1", profiles.get(0).getValue());
assertEquals("http://profile/2", profiles.get(1).getValue());
ourPatientDao.removeTag(id1, TagTypeEnum.TAG, null, "Dog");
ourPatientDao.removeTag(id1, TagTypeEnum.SECURITY_LABEL, "seclabel:sys:1", "seclabel:code:1");
ourPatientDao.removeTag(id1, TagTypeEnum.PROFILE, BaseHapiFhirDao.NS_JPA_PROFILE, "http://profile/1");
myPatientDao.removeTag(id1, TagTypeEnum.TAG, null, "Dog");
myPatientDao.removeTag(id1, TagTypeEnum.SECURITY_LABEL, "seclabel:sys:1", "seclabel:code:1");
myPatientDao.removeTag(id1, TagTypeEnum.PROFILE, BaseHapiFhirDao.NS_JPA_PROFILE, "http://profile/1");
meta = ourSystemDao.metaGetOperation();
meta = mySystemDao.metaGetOperation();
published = meta.getTag();
assertEquals(1, published.size());
assertEquals("http://foo", published.get(0).getSystem());
@ -178,7 +229,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType id = ourPatientDao.update(p).getId();
IIdType id = myPatientDao.update(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
@ -192,7 +243,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o.getSubject().setReference("Patient/" + methodName);
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(2, resp.getEntry().size());
Entry respEntry = resp.getEntry().get(0);
@ -206,7 +257,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertThat(respEntry.getResponse().getLocation(), endsWith("/_history/1"));
assertEquals("1", respEntry.getResponse().getEtag());
o = (Observation) ourObservationDao.read(new IdDt(respEntry.getResponse().getLocationElement()));
o = (Observation) myObservationDao.read(new IdDt(respEntry.getResponse().getLocationElement()));
assertEquals(id.toVersionless(), o.getSubject().getReference());
assertEquals("1", o.getId().getVersionIdPart());
@ -220,7 +271,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
@ -240,11 +291,11 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient/THIS_ID_DOESNT_EXIST");
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(3, resp.getEntry().size());
assertEquals(BundleTypeEnum.BATCH_RESPONSE, resp.getTypeElement().getValueAsEnum());
ourLog.info(ourFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
EntryResponse respEntry;
// Bundle.entry[0] is operation outcome
@ -267,7 +318,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertEquals("201 Created", respEntry.getStatus());
IdDt createdId = new IdDt(respEntry.getLocation());
assertEquals("Patient", createdId.getResourceType());
ourPatientDao.read(createdId); // shouldn't fail
myPatientDao.read(createdId); // shouldn't fail
// Check GET
respEntry = resp.getEntry().get(2).getResponse();
@ -290,7 +341,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(),
@ -312,7 +363,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(),
@ -326,12 +377,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id = ourPatientDao.create(p).getId();
IIdType id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
id = ourPatientDao.create(p).getId();
id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
Bundle request = new Bundle();
@ -347,7 +398,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (PreconditionFailedException e) {
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
@ -370,7 +421,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o.getSubject().setReference("Patient/" + methodName);
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
assertEquals(2, resp.getEntry().size());
@ -388,7 +439,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertThat(respEntry.getResponse().getLocation(), endsWith("/_history/1"));
assertEquals("1", respEntry.getResponse().getEtag());
o = (Observation) ourObservationDao.read(new IdDt(respEntry.getResponse().getLocationElement()));
o = (Observation) myObservationDao.read(new IdDt(respEntry.getResponse().getLocationElement()));
assertEquals(new IdDt(patientId).toUnqualifiedVersionless(), o.getSubject().getReference());
}
@ -402,7 +453,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
p.setId("Patient/" + methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(1, resp.getEntry().size());
Entry respEntry = resp.getEntry().get(0);
@ -415,13 +466,13 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
* embedded operation
*/
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
ActionRequestDetails details = detailsCapt.getValue();
assertEquals("Bundle", details.getResourceType());
assertEquals(Bundle.class, details.getResource().getClass());
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(ourInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.CREATE), detailsCapt.capture());
details = detailsCapt.getValue();
assertNotNull(details.getId());
assertEquals("Patient", details.getResourceType());
@ -441,7 +492,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Resource Organization/9999999999999999 not found, specified in path: Patient.managingOrganization"));
@ -460,7 +511,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Resource Organization/" + methodName + " not found, specified in path: Patient.managingOrganization"));
@ -473,13 +524,13 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id1 = ourPatientDao.create(p1).getId();
IIdType id1 = myPatientDao.create(p1).getId();
ourLog.info("Created patient, got it: {}", id1);
Patient p2 = new Patient();
p2.addIdentifier().setSystem("urn:system").setValue(methodName);
p2.setId("Patient/" + methodName);
IIdType id2 = ourPatientDao.update(p2).getId();
IIdType id2 = myPatientDao.update(p2).getId();
ourLog.info("Created patient, got it: {}", id2);
Bundle request = new Bundle();
@ -487,24 +538,24 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient/" + id1.getIdPart());
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient/" + id2.getIdPart());
ourPatientDao.read(id1.toVersionless());
ourPatientDao.read(id2.toVersionless());
myPatientDao.read(id1.toVersionless());
myPatientDao.read(id2.toVersionless());
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(2, resp.getEntry().size());
assertEquals("204 No Content", resp.getEntry().get(0).getResponse().getStatus());
assertEquals("204 No Content", resp.getEntry().get(1).getResponse().getStatus());
try {
ourPatientDao.read(id1.toVersionless());
myPatientDao.read(id1.toVersionless());
fail();
} catch (ResourceGoneException e) {
// good
}
try {
ourPatientDao.read(id2.toVersionless());
myPatientDao.read(id2.toVersionless());
fail();
} catch (ResourceGoneException e) {
// good
@ -518,33 +569,33 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id = ourPatientDao.create(p).getId();
IIdType id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(1, resp.getEntry().size());
Entry nextEntry = resp.getEntry().get(0);
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + " No Content", nextEntry.getResponse().getStatus());
try {
ourPatientDao.read(id.toVersionless());
myPatientDao.read(id.toVersionless());
fail();
} catch (ResourceGoneException e) {
// ok
}
try {
ourPatientDao.read(new IdDt("Patient/" + methodName));
myPatientDao.read(new IdDt("Patient/" + methodName));
fail();
} catch (ResourceNotFoundException e) {
// ok
}
IBundleProvider history = ourPatientDao.history(id, null);
IBundleProvider history = myPatientDao.history(id, null);
assertEquals(2, history.size());
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get((IResource) history.getResources(0, 0).get(0)));
@ -559,12 +610,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id = ourPatientDao.create(p).getId();
IIdType id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
id = ourPatientDao.create(p).getId();
id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
@ -576,7 +627,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (ResourceNotFoundException e) {
assertThat(e.getMessage(), containsString("resource with match URL \"Patient?"));
@ -591,7 +642,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (ResourceNotFoundException e) {
assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
@ -605,19 +656,19 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType id = ourPatientDao.update(p).getId();
IIdType id = myPatientDao.update(p).getId();
ourLog.info("Created patient, got it: {}", id);
Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
Bundle res = ourSystemDao.transaction(request);
Bundle res = mySystemDao.transaction(request);
assertEquals(1, res.getEntry().size());
assertEquals(Constants.STATUS_HTTP_204_NO_CONTENT + " No Content", res.getEntry().get(0).getResponse().getStatus());
try {
ourPatientDao.read(id.toVersionless());
myPatientDao.read(id.toVersionless());
fail();
} catch (ResourceGoneException e) {
// ok
@ -638,7 +689,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
patient2.addIdentifier().setSystem("urn:system").setValue("testPersistWithSimpleLinkP02");
request.addEntry().setResource(patient2).getRequest().setMethod(HTTPVerbEnum.POST);
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
}
@Test
@ -646,17 +697,17 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/transaction_link_patient_eve.xml");
String bundleStr = IOUtils.toString(bundleRes);
Bundle bundle = ourFhirContext.newXmlParser().parseResource(Bundle.class, bundleStr);
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, bundleStr);
Bundle resp = ourSystemDao.transaction(bundle);
Bundle resp = mySystemDao.transaction(bundle);
ourLog.info(ourFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
assertThat(resp.getEntry().get(0).getResponse().getLocation(), startsWith("Patient/a555-44-4444/_history/"));
assertThat(resp.getEntry().get(1).getResponse().getLocation(), startsWith("Patient/temp6789/_history/"));
assertThat(resp.getEntry().get(2).getResponse().getLocation(), startsWith("Organization/GHH/_history/"));
Patient p = ourPatientDao.read(new IdDt("Patient/a555-44-4444/_history/1"));
Patient p = myPatientDao.read(new IdDt("Patient/a555-44-4444/_history/1"));
assertEquals("Patient/temp6789", p.getLink().get(0).getOther().getReference().getValue());
}
@ -665,11 +716,11 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/josh-bundle.json");
String bundleStr = IOUtils.toString(bundleRes);
Bundle bundle = ourFhirContext.newJsonParser().parseResource(Bundle.class, bundleStr);
Bundle bundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, bundleStr);
Bundle resp = ourSystemDao.transaction(bundle);
Bundle resp = mySystemDao.transaction(bundle);
ourLog.info(ourFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp));
assertEquals("201 Created", resp.getEntry().get(0).getResponse().getStatus());
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus());
@ -682,14 +733,14 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType idv1 = ourPatientDao.update(p).getId();
IIdType idv1 = myPatientDao.update(p).getId();
ourLog.info("Created patient, got id: {}", idv1);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Family Name");
p.setId("Patient/" + methodName);
IIdType idv2 = ourPatientDao.update(p).getId();
IIdType idv2 = myPatientDao.update(p).getId();
ourLog.info("Updated patient, got id: {}", idv2);
Bundle request = new Bundle();
@ -697,7 +748,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualified().getValue());
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(3, resp.getEntry().size());
@ -721,25 +772,25 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
* embedded operation
*/
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(ourInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
ActionRequestDetails details = detailsCapt.getValue();
assertEquals("Bundle", details.getResourceType());
assertEquals(Bundle.class, details.getResource().getClass());
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(ourInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.READ), detailsCapt.capture());
verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.READ), detailsCapt.capture());
details = detailsCapt.getValue();
assertEquals(idv1.toUnqualifiedVersionless(), details.getId());
assertEquals("Patient", details.getResourceType());
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(ourInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.VREAD), detailsCapt.capture());
verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.VREAD), detailsCapt.capture());
details = detailsCapt.getValue();
assertEquals(idv1.toUnqualified(), details.getId());
assertEquals("Patient", details.getResourceType());
detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(ourInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.SEARCH_TYPE), detailsCapt.capture());
verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.SEARCH_TYPE), detailsCapt.capture());
details = detailsCapt.getValue();
assertEquals("Patient", details.getResourceType());
@ -753,19 +804,19 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType idv1 = ourPatientDao.update(p).getId();
IIdType idv1 = myPatientDao.update(p).getId();
ourLog.info("Created patient, got id: {}", idv1);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Family Name");
p.setId("Patient/" + methodName);
IIdType idv2 = ourPatientDao.update(p).getId();
IIdType idv2 = myPatientDao.update(p).getId();
ourLog.info("Updated patient, got id: {}", idv2);
Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?" + Constants.PARAM_COUNT + "=1");
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(1, resp.getEntry().size());
@ -779,7 +830,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?" + Constants.PARAM_COUNT + "=GKJGKJG");
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(), ("Invalid _count value: GKJGKJG"));
}
@ -788,7 +839,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient?" + Constants.PARAM_COUNT + "=");
respBundle = ourSystemDao.transaction(request);
respBundle = mySystemDao.transaction(request);
assertThat(respBundle.getEntry().size(), greaterThan(0));
}
@ -799,14 +850,14 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType idv1 = ourPatientDao.update(p).getId();
IIdType idv1 = myPatientDao.update(p).getId();
ourLog.info("Created patient, got id: {}", idv1);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Family Name");
p.setId("Patient/" + methodName);
IIdType idv2 = ourPatientDao.update(p).getId();
IIdType idv2 = myPatientDao.update(p).getId();
ourLog.info("Updated patient, got id: {}", idv2);
Bundle request = new Bundle();
@ -814,7 +865,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv1.getVersionIdPart() + "\"");
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv2.getVersionIdPart() + "\"");
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(3, resp.getEntry().size());
@ -844,7 +895,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id = ourPatientDao.create(p).getId();
IIdType id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
@ -858,7 +909,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o.getSubject().setReference("Patient/" + methodName);
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(2, resp.getEntry().size());
Entry nextEntry = resp.getEntry().get(0);
@ -873,7 +924,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertThat(nextEntry.getResponse().getLocation(), not(emptyString()));
nextEntry = resp.getEntry().get(1);
o = ourObservationDao.read(new IdDt(nextEntry.getResponse().getLocation()));
o = myObservationDao.read(new IdDt(nextEntry.getResponse().getLocation()));
assertEquals(id.toVersionless(), o.getSubject().getReference());
}
@ -885,12 +936,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
IIdType id = ourPatientDao.create(p).getId();
IIdType id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
id = ourPatientDao.create(p).getId();
id = myPatientDao.create(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
@ -905,7 +956,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
try {
ourSystemDao.transaction(request);
mySystemDao.transaction(request);
fail();
} catch (PreconditionFailedException e) {
assertThat(e.getMessage(), containsString("with match URL \"Patient"));
@ -919,7 +970,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addName().addFamily("Hello");
IIdType id = ourPatientDao.create(p).getId();
IIdType id = myPatientDao.create(p).getId();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
@ -932,7 +983,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o.getSubject().setReference("Patient/" + methodName);
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(2, resp.getEntry().size());
Entry nextEntry = resp.getEntry().get(0);
@ -945,7 +996,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertThat(patientId.getValue(), endsWith("/_history/1"));
nextEntry = resp.getEntry().get(1);
o = ourObservationDao.read(new IdDt(nextEntry.getResponse().getLocation()));
o = myObservationDao.read(new IdDt(nextEntry.getResponse().getLocation()));
assertEquals(patientId.toVersionless(), o.getSubject().getReference());
}
@ -958,7 +1009,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType id = ourPatientDao.update(p).getId();
IIdType id = myPatientDao.update(p).getId();
ourLog.info("Created patient, got it: {}", id);
p = new Patient();
@ -972,7 +1023,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o.getSubject().setReference("Patient/" + methodName);
request.addEntry().setResource(o).getRequest().setMethod(HTTPVerbEnum.POST);
Bundle resp = ourSystemDao.transaction(request);
Bundle resp = mySystemDao.transaction(request);
assertEquals(2, resp.getEntry().size());
Entry nextEntry = resp.getEntry().get(0);
@ -986,7 +1037,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
nextEntry = resp.getEntry().get(1);
assertEquals(Constants.STATUS_HTTP_201_CREATED + " Created", nextEntry.getResponse().getStatus());
o = ourObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()));
o = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()));
assertEquals(id.toVersionless(), o.getSubject().getReference());
}
@ -1115,9 +1166,9 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o2.setSubject(new ResourceReferenceDt("urn:oid:0.1.2.3"));
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
Bundle resp = ourSystemDao.transaction(res);
Bundle resp = mySystemDao.transaction(res);
ourLog.info(ourFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
assertEquals(3, resp.getEntry().size());
@ -1126,8 +1177,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdDt(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdDt(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
o1 = ourObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()));
o2 = ourObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()));
o1 = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()));
o2 = myObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()));
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
@ -1158,9 +1209,9 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
o2.setSubject(new ResourceReferenceDt("Patient/urn:oid:0.1.2.3"));
res.addEntry().setResource(o2).getRequest().setMethod(HTTPVerbEnum.POST).setUrl("Observation");
Bundle resp = ourSystemDao.transaction(res);
Bundle resp = mySystemDao.transaction(res);
ourLog.info(ourFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
assertEquals(BundleTypeEnum.TRANSACTION_RESPONSE, resp.getTypeElement().getValueAsEnum());
assertEquals(3, resp.getEntry().size());
@ -1169,38 +1220,13 @@ public class FhirSystemDaoDstu2Test extends BaseJpaTest {
assertTrue(resp.getEntry().get(1).getResponse().getLocation(), new IdDt(resp.getEntry().get(1).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
assertTrue(resp.getEntry().get(2).getResponse().getLocation(), new IdDt(resp.getEntry().get(2).getResponse().getLocation()).getIdPart().matches("^[0-9]+$"));
o1 = ourObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()));
o2 = ourObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()));
o1 = myObservationDao.read(new IdDt(resp.getEntry().get(1).getResponse().getLocation()));
o2 = myObservationDao.read(new IdDt(resp.getEntry().get(2).getResponse().getLocation()));
assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart()));
}
@AfterClass
public static void afterClass() throws SQLException {
ourCtx.close();
}
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() {
ourCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu2.xml", "fhir-jpabase-spring-test-config.xml");
ourFhirContext = ourCtx.getBean(FhirContext.class);
assertEquals(FhirVersionEnum.DSTU2, ourFhirContext.getVersion().getVersion());
ourPatientDao = ourCtx.getBean("myPatientDaoDstu2", IFhirResourceDao.class);
ourObservationDao = ourCtx.getBean("myObservationDaoDstu2", IFhirResourceDao.class);
ourSystemDao = ourCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
ourInterceptor = mock(IServerInterceptor.class);
DaoConfig daoConfig = ourCtx.getBean(DaoConfig.class);
daoConfig.setInterceptors(ourInterceptor);
}
@Before
public void before() {
reset(ourInterceptor);
}
static void doDeleteEverything(IFhirSystemDao<Bundle> systemDao) {
IBundleProvider all = systemDao.history(null);

View File

@ -6,8 +6,14 @@ import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
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.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
@ -21,6 +27,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
@ -63,6 +70,8 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
// private static IFhirResourceDao<Patient> ourPatientDao;
// private static IFhirResourceDao<Questionnaire> ourQuestionnaireDao;
private static Server ourServer;
private static String ourServerBase;
private static CloseableHttpClient ourHttpClient;
// private static JpaConformanceProvider ourConfProvider;
@ -165,7 +174,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
.forResource(Encounter.class)
.where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
.include(Encounter.INCLUDE_LOCATION_LOCATION)
.include(Location.INCLUDE_PARTOF)
.include(Location.INCLUDE_PARTOF.asRecursive())
.execute();
//@formatter:on
@ -482,6 +491,22 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getId().getIdPart());
}
@Test
public void testMetadata() throws Exception {
HttpGet get = new HttpGet(ourServerBase + "/metadata");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
String resp = IOUtils.toString(response.getEntity().getContent());
ourLog.info(resp);
assertEquals(200, response.getStatusLine().getStatusCode());
assertThat(resp, stringContainsInOrder("THIS IS THE DESC"));
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
response.close();
}
}
@AfterClass
public static void afterClass() throws Exception {
@ -496,7 +521,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
RestfulServer restServer = new RestfulServer(ourCtx);
String serverBase = "http://localhost:" + port + "/fhir/context";
ourServerBase = "http://localhost:" + port + "/fhir/context";
ourAppCtx = new ClassPathXmlApplicationContext("hapi-fhir-server-resourceproviders-dstu1.xml", "fhir-jpabase-spring-test-config.xml");
@ -514,6 +539,11 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
restServer.setPagingProvider(new FifoMemoryPagingProvider(10));
IFhirSystemDao<List<IResource>> systemDao = ourAppCtx.getBean(IFhirSystemDao.class);
JpaConformanceProviderDstu1 confProvider = new JpaConformanceProviderDstu1(restServer, systemDao);
confProvider.setImplementationDescription("THIS IS THE DESC");
restServer.setServerConformanceProvider(confProvider);
ourServer = new Server(port);
ServletContextHandler proxyHandler = new ServletContextHandler();
@ -526,9 +556,14 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
ourServer.setHandler(proxyHandler);
ourServer.start();
ourClient = ourCtx.newRestfulGenericClient(serverBase);
ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
ourClient.registerInterceptor(new LoggingInterceptor(true));
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourHttpClient = builder.build();
}
}

View File

@ -33,6 +33,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
@ -57,6 +58,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
@ -122,14 +124,18 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
private static IFhirResourceDao<Organization> ourOrganizationDao;
private static int ourPort;
// private static IFhirResourceDao<Observation> ourObservationDao;
// private static IFhirResourceDao<Patient> ourPatientDao;
// private static IFhirResourceDao<Questionnaire> ourQuestionnaireDao;
private static Server ourServer;
private static String ourServerBase;
// private static JpaConformanceProvider ourConfProvider;
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);
IOUtils.closeQuietly(resp.getEntity().getContent());
assertEquals(200, resp.getStatusLine().getStatusCode());
}
private void delete(String theResourceType, String theParamName, String theParamValue) {
Bundle resources;
do {
@ -145,148 +151,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
} while (resources.size() > 0);
}
/**
* See #198
*/
@Test
public void testSortFromResourceProvider() {
Patient p;
String methodName = "testSortFromResourceProvider";
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Daniel").addFamily("Adams");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Aaron").addFamily("Alexis");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Carol").addFamily("Allen");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Ruth").addFamily("Black");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Brian").addFamily("Brooks");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Susan").addFamily("Clark");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Amy").addFamily("Clark");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Anthony").addFamily("Coleman");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Steven").addFamily("Coleman");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Lisa").addFamily("Coleman");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Ruth").addFamily("Cook");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Betty").addFamily("Davis");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Joshua").addFamily("Diaz");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Brian").addFamily("Gracia");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Stephan").addFamily("Graham");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Sarah").addFamily("Graham");
ourClient.create().resource(p).execute();
//@formatter:off
Bundle resp = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", methodName))
.sort().ascending(Patient.FAMILY)
.sort().ascending(Patient.GIVEN)
.limitTo(100)
.execute();
//@formatter:on
List<String> names = toNameList(resp);
ourLog.info(StringUtils.join(names, '\n'));
//@formatter:off
assertThat(names, contains( // this matches in order only
"Daniel Adams",
"Aaron Alexis",
"Carol Allen",
"Ruth Black",
"Brian Brooks",
"Amy Clark",
"Susan Clark",
"Anthony Coleman",
"Lisa Coleman",
"Steven Coleman",
"Ruth Cook",
"Betty Davis",
"Joshua Diaz",
"Brian Gracia",
"Sarah Graham",
"Stephan Graham"));
//@formatter:om
}
private List<String> toNameList(Bundle resp) {
List<String> names = new ArrayList<String>();
for (BundleEntry next : resp.getEntries()) {
Patient nextPt= (Patient) next.getResource();
String nextStr = nextPt.getNameFirstRep().getGivenAsSingleString()+ " " + nextPt.getNameFirstRep().getFamilyAsSingleString();
if (isNotBlank(nextStr)) {
names.add(nextStr);
}
}
return names;
}
private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue) {
Bundle resources = ourClient.search().forResource(theResourceType).where(new TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
for (IResource next : resources.toListOfResources()) {
@ -347,46 +211,34 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
@Test
public void testMetaOperations() throws Exception {
String methodName = "testMetaOperations";
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
ValueSet options = new ValueSet();
options.getCodeSystem().setSystem("urn:system").addConcept().setCode("code0");
IIdType optId = ourClient.create().resource(options).execute().getId();
Patient pt = new Patient();
pt.addName().addFamily(methodName);
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
Questionnaire q = new Questionnaire();
q.getGroup().addQuestion().setLinkId("link0").setRequired(false).setType(AnswerFormatEnum.CHOICE).setOptions(new ResourceReferenceDt(optId));
IIdType qId = ourClient.create().resource(q).execute().getId();
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
assertEquals(0, meta.getTag().size());
QuestionnaireResponse qa;
MetaDt inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
assertEquals(1, meta.getTag().size());
// Good code
inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
assertEquals(0, meta.getTag().size());
qa = new QuestionnaireResponse();
qa.getQuestionnaire().setReference(qId.toUnqualifiedVersionless().getValue());
qa.getGroup().addQuestion().setLinkId("link0").addAnswer().setValue(new CodingDt().setSystem("urn:system").setCode("code0"));
ourClient.create().resource(qa).execute();
}
// Bad code
@Test
public void testGetResourceCountsOperation() throws Exception {
String methodName = "testMetaOperations";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts");
CloseableHttpResponse response = ourHttpClient.execute(get);
qa = new QuestionnaireResponse();
qa.getQuestionnaire().setReference(qId.toUnqualifiedVersionless().getValue());
qa.getGroup().addQuestion().setLinkId("link0").addAnswer().setValue(new CodingDt().setSystem("urn:system").setCode("code1"));
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent());
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
assertThat(output, containsString("<parameter><name value=\"Patient\"/><valueInteger value=\""));
} finally {
response.close();
ourClient.create().resource(qa).execute();
fail();
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Question with linkId[link0]"));
}
}
@ -427,34 +279,22 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
@Test
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
ValueSet options = new ValueSet();
options.getCodeSystem().setSystem("urn:system").addConcept().setCode("code0");
IIdType optId = ourClient.create().resource(options).execute().getId();
Questionnaire q = new Questionnaire();
q.getGroup().addQuestion().setLinkId("link0").setRequired(false).setType(AnswerFormatEnum.CHOICE).setOptions(new ResourceReferenceDt(optId));
IIdType qId = ourClient.create().resource(q).execute().getId();
public void testCreateResourceReturnsOperationOutcomeByDefault() throws IOException {
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
QuestionnaireResponse qa;
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
// Good code
qa = new QuestionnaireResponse();
qa.getQuestionnaire().setReference(qId.toUnqualifiedVersionless().getValue());
qa.getGroup().addQuestion().setLinkId("link0").addAnswer().setValue(new CodingDt().setSystem("urn:system").setCode("code0"));
ourClient.create().resource(qa).execute();
// Bad code
qa = new QuestionnaireResponse();
qa.getQuestionnaire().setReference(qId.toUnqualifiedVersionless().getValue());
qa.getGroup().addQuestion().setLinkId("link0").addAnswer().setValue(new CodingDt().setSystem("urn:system").setCode("code1"));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
ourClient.create().resource(qa).execute();
fail();
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Question with linkId[link0]"));
assertEquals(201, response.getStatusLine().getStatusCode());
String respString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(response.toString());
ourLog.info(respString);
assertThat(respString, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\">"));
} finally {
response.getEntity().getContent().close();
response.close();
}
}
@ -478,27 +318,6 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
}
@Test
public void testCreateResourceReturnsOperationOutcomeByDefault() throws IOException {
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
HttpPost post = new HttpPost(ourServerBase + "/Patient");
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
CloseableHttpResponse response = ourHttpClient.execute(post);
try {
assertEquals(201, response.getStatusLine().getStatusCode());
String respString = IOUtils.toString(response.getEntity().getContent());
ourLog.info(response.toString());
ourLog.info(respString);
assertThat(respString, containsString("<OperationOutcome xmlns=\"http://hl7.org/fhir\">"));
} finally {
response.getEntity().getContent().close();
response.close();
}
}
@Test
public void testDeepChaining() {
delete("Location", Location.SP_NAME, "testDeepChainingL1");
@ -527,8 +346,8 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
Bundle res = ourClient.search()
.forResource(Encounter.class)
.where(Encounter.IDENTIFIER.exactly().systemAndCode("urn:foo", "testDeepChainingE1"))
.include(Encounter.INCLUDE_LOCATION)
.include(Location.INCLUDE_PARTOF)
.include(Encounter.INCLUDE_LOCATION.asRecursive())
.include(Location.INCLUDE_PARTOF.asRecursive())
.execute();
//@formatter:on
@ -604,8 +423,7 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
/*
* Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to
* make sure that works too..
* Try it with a raw socket call. The Apache client won't let us use the unescaped "|" in the URL but we want to make sure that works too..
*/
Socket sock = new Socket();
sock.setSoTimeout(3000);
@ -845,6 +663,27 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
ourLog.info(ids.toString());
}
@Test
public void testGetResourceCountsOperation() throws Exception {
String methodName = "testMetaOperations";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent());
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
assertThat(output, containsString("<parameter><name value=\"Patient\"/><valueInteger value=\""));
} finally {
response.close();
}
}
/**
* See issue #52
*/
@ -863,6 +702,29 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
}
@Test
public void testMetaOperations() throws Exception {
String methodName = "testMetaOperations";
Patient pt = new Patient();
pt.addName().addFamily(methodName);
IIdType id = ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless();
MetaDt meta = ourClient.meta().get(MetaDt.class).fromResource(id).execute();
assertEquals(0, meta.getTag().size());
MetaDt inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().add().onResource(id).meta(inMeta).execute();
assertEquals(1, meta.getTag().size());
inMeta = new MetaDt();
inMeta.addTag().setSystem("urn:system1").setCode("urn:code1");
meta = ourClient.meta().delete().onResource(id).meta(inMeta).execute();
assertEquals(0, meta.getTag().size());
}
/**
* Test for issue #60
*/
@ -979,7 +841,8 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId();
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint().execute();
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint()
.execute();
assertEquals(1, actual.size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
@ -1172,6 +1035,33 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
}
@Test
public void testSearchWithTextInexactMatch() throws Exception {
Observation obs = new Observation();
obs.getCode().setText("THIS_IS_THE_TEXT");
obs.getCode().addCoding().setSystem("SYSTEM").setCode("CODE").setDisplay("THIS_IS_THE_DISPLAY");
ourClient.create().resource(obs).execute();
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_TEXT");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_");
testSearchReturnsResults("/Observation?code%3Atext=this_is_the_");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_DISPLAY");
testSearchReturnsResults("/Observation?code%3Atext=THIS_IS_THE_disp");
}
private void testSearchReturnsResults(String search) throws IOException, ClientProtocolException {
int matches;
HttpGet get = new HttpGet(ourServerBase + search);
CloseableHttpResponse response = ourHttpClient.execute(get);
String resp = IOUtils.toString(response.getEntity().getContent());
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(resp);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp);
matches = bundle.getTotal();
assertThat(matches, greaterThan(0));
}
@Test
public void testSearchWithMissing() throws Exception {
ourLog.info("Starting testSearchWithMissing");
@ -1242,6 +1132,144 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
assertThat("Wanted " + orgMissing + " but found: " + list, list, containsInRelativeOrder(orgMissing));
}
@Test
public void testSearchWithMissing2() throws Exception {
checkParamMissing(Observation.SP_CODE);
checkParamMissing(Observation.SP_CATEGORY);
checkParamMissing(Observation.SP_VALUE_STRING);
checkParamMissing(Observation.SP_ENCOUNTER);
checkParamMissing(Observation.SP_DATE);
}
/**
* See #198
*/
@Test
public void testSortFromResourceProvider() {
Patient p;
String methodName = "testSortFromResourceProvider";
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Daniel").addFamily("Adams");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Aaron").addFamily("Alexis");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Carol").addFamily("Allen");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Ruth").addFamily("Black");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Brian").addFamily("Brooks");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Susan").addFamily("Clark");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Amy").addFamily("Clark");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Anthony").addFamily("Coleman");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Steven").addFamily("Coleman");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Lisa").addFamily("Coleman");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Ruth").addFamily("Cook");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Betty").addFamily("Davis");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Joshua").addFamily("Diaz");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Brian").addFamily("Gracia");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Stephan").addFamily("Graham");
ourClient.create().resource(p).execute();
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addGiven("Sarah").addFamily("Graham");
ourClient.create().resource(p).execute();
//@formatter:off
Bundle resp = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", methodName))
.sort().ascending(Patient.FAMILY)
.sort().ascending(Patient.GIVEN)
.limitTo(100)
.execute();
//@formatter:on
List<String> names = toNameList(resp);
ourLog.info(StringUtils.join(names, '\n'));
//@formatter:off
assertThat(names, contains( // this matches in order only
"Daniel Adams",
"Aaron Alexis",
"Carol Allen",
"Ruth Black",
"Brian Brooks",
"Amy Clark",
"Susan Clark",
"Anthony Coleman",
"Lisa Coleman",
"Steven Coleman",
"Ruth Cook",
"Betty Davis",
"Joshua Diaz",
"Brian Gracia",
"Sarah Graham",
"Stephan Graham"));
//@formatter:om
}
/**
* Test for issue #60
*/
@ -1578,6 +1606,18 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
return list;
}
private List<String> toNameList(Bundle resp) {
List<String> names = new ArrayList<String>();
for (BundleEntry next : resp.getEntries()) {
Patient nextPt = (Patient) next.getResource();
String nextStr = nextPt.getNameFirstRep().getGivenAsSingleString() + " " + nextPt.getNameFirstRep().getFamilyAsSingleString();
if (isNotBlank(nextStr)) {
names.add(nextStr);
}
}
return names;
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
@ -1585,6 +1625,21 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
ourHttpClient.close();
}
@Test
public void testMetadata() throws Exception {
HttpGet get = new HttpGet(ourServerBase + "/metadata");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
String resp = IOUtils.toString(response.getEntity().getContent());
ourLog.info(resp);
assertEquals(200, response.getStatusLine().getStatusCode());
assertThat(resp, stringContainsInOrder("THIS IS THE DESC"));
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
response.close();
}
}
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() throws Exception {
@ -1609,6 +1664,11 @@ public class ResourceProviderDstu2Test extends BaseJpaTest {
JpaSystemProviderDstu2 systemProv = ourAppCtx.getBean(JpaSystemProviderDstu2.class, "mySystemProviderDstu2");
restServer.setPlainProviders(systemProv);
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle> systemDao = ourAppCtx.getBean(IFhirSystemDao.class);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(restServer, systemDao);
confProvider.setImplementationDescription("THIS IS THE DESC");
restServer.setServerConformanceProvider(confProvider);
restServer.setPagingProvider(new FifoMemoryPagingProvider(10));
ourServer = new Server(ourPort);

View File

@ -314,7 +314,7 @@
],
"deleted": true,
"item": {
"reference": "MedicationPrescription/1",
"reference": "MedicationOrder/1",
"display": "use of Ventolin Inhaler was discontinued"
}
}
@ -324,7 +324,7 @@
{
"base": "urn:uuid:",
"resource": {
"resourceType": "MedicationPrescription",
"resourceType": "MedicationOrder",
"id": "124a6916-5d84-4b8c-b250-10cefb8e6e86",
"meta": {
"lastUpdated": "2013-05-05T16:13:03Z"

View File

@ -18,7 +18,8 @@
<appender-ref ref="STDOUT" />
</logger>
<logger name="org.hibernate.SQL" additivity="false" level="trace">
<!-- Set to 'trace' to enable SQL logging -->
<logger name="org.hibernate.SQL" additivity="false" level="info">
<appender-ref ref="STDOUT" />
</logger>

View File

@ -81,14 +81,12 @@
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<!-- Used for CORS support -->
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>1.0.1</version>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
@ -101,7 +99,6 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.3.RELEASE</version>
<scope>provided</scope>
</dependency>
@ -214,6 +211,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
<executions>
<execution>

View File

@ -46,12 +46,10 @@
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
</dependency>
<!--dependency>
@ -64,63 +62,46 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring_version}</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>${derby_version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<version>${derby_version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby_version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback_version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j_version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava_version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
@ -128,31 +109,26 @@
<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-webapp</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>

View File

@ -1,73 +0,0 @@
package ca.uhn.fhirtest;
import java.io.IOException;
import java.util.Properties;
import org.hsqldb.Server;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.server.ServerAcl.AclFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;
public class HsqldbServer implements SmartLifecycle {
private final Logger logger = LoggerFactory.getLogger(HsqldbServer.class);
private HsqlProperties properties;
private Server server;
private boolean running = false;
public HsqldbServer(Properties props) {
properties = new HsqlProperties(props);
}
@Override
public boolean isRunning() {
if (server != null)
server.checkRunning(running);
return running;
}
@Override
public void start() {
if (server == null) {
logger.info("Starting HSQL server...");
server = new Server();
try {
server.setProperties(properties);
server.start();
running = true;
} catch (AclFormatException afe) {
logger.error("Error starting HSQL server.", afe);
throw new Error(afe);
} catch (IOException e) {
logger.error("Error starting HSQL server.", e);
throw new Error(e);
}
}
}
@Override
public void stop() {
logger.info("Stopping HSQL server...");
if (server != null) {
server.stop();
running = false;
}
}
@Override
public int getPhase() {
return 0;
}
@Override
public boolean isAutoStartup() {
return true;
}
@Override
public void stop(Runnable runnable) {
stop();
runnable.run();
}
}

View File

@ -24,8 +24,8 @@
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyTenSevenDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.jdbc.batch_size" value="0" />
<property name="hibernate.cache.use_minimal_puts" value="false" />
<property name="hibernate.jdbc.batch_size" value="20" />
<property name="hibernate.cache.use_minimal_puts" value="true" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.use_second_level_cache" value="false" />

View File

@ -1,7 +1,5 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
@ -13,33 +11,19 @@
<context:annotation-config />
<context:mbean-server />
<bean depends-on="dbServer" id="myPersistenceDataSource"
class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<!-- ;create=true /opt/glassfish/glassfish4/glassfish/nodes/localhost-domain1/fhirtest/fhirdb -->
<!-- <property name="url" value="jdbc:hsqldb:hsql://localhost/uhnfhirdb"/> -->
<!-- <property name="url" value="jdbc:derby:directory:#{systemproperties['fhir.db.location']};create=true"
/> -->
<bean depends-on="dbServer" id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"></property>
<property name="url"
value="jdbc:derby://localhost:1527/#{systemProperties['fhir.db.location.dstu2']};create=true" />
<!-- <property name="url" value="jdbc:derby://localhost:1527//opt/glassfish/fhirtest/fhirtest;create=true"
/> -->
<!--<property name="url" value="jdbc:derby://localhost:1527#{systemProperties['fhir.db.location']};create=true"
/> -->
<property name="url" value="jdbc:derby://localhost:1527/#{systemProperties['fhir.db.location.dstu2']};create=true" />
<property name="username" value="SA" />
<property name="password" value="SA" />
</bean>
<!--for mysql -->
<!-- <bean depends-on="dbServer" id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://fhirdb.url/fhirdbname" /> <property
name="username" value="sa"/> <property name="password" value="sa"/> <property
name="testOnBorrow" value="true"/> <property name="validationQuery" value="select
1;"/> </bean> -->
<!-- <bean depends-on="dbServer" id="myPersistenceDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> <property name="driverClassName"
value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://fhirdb.url/fhirdbname" /> <property name="username" value="sa"/> <property name="password"
value="sa"/> <property name="testOnBorrow" value="true"/> <property name="validationQuery" value="select 1;"/> </bean> -->
<bean depends-on="dbServer" id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<bean depends-on="dbServer" id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myPersistenceDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/fhirtest_persistence.xml" />
<property name="persistenceUnitName" value="FHIR_UT" />
@ -48,10 +32,8 @@
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.DerbyTenSevenDialect" />
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect"
/> -->
<!-- <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"
/> -->
<!-- <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" /> -->
<!-- <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" /> -->
</bean>
</property>
</bean>

View File

@ -72,25 +72,21 @@
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
<scope>test</scope>
</dependency>
@ -131,13 +127,8 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava_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>

View File

@ -4,6 +4,7 @@ import static org.junit.Assert.*;
import java.math.BigDecimal;
import org.apache.commons.lang3.StringUtils;
import org.junit.BeforeClass;
import org.junit.Test;
@ -17,6 +18,19 @@ public class IdDtTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdDtTest.class);
@Test
public void testDetectIsIdPartValid() {
assertTrue(new IdDt("0").isIdPartValid());
assertTrue(new IdDt("0a").isIdPartValid());
assertTrue(new IdDt("0abgZZ").isIdPartValid());
assertTrue(new IdDt("---").isIdPartValid());
assertTrue(new IdDt("1.2.3.4").isIdPartValid());
assertFalse(new IdDt(" 1").isIdPartValid());
assertFalse(new IdDt("1:1").isIdPartValid());
assertFalse(new IdDt(StringUtils.leftPad("", 65, '0')).isIdPartValid());
}
@Test
public void testDetectLocal() {
IdDt id;

View File

@ -1,9 +1,12 @@
package ca.uhn.fhir.rest.client;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.*;
import java.net.URL;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
@ -25,9 +28,13 @@ import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.PortUtil;
import ch.qos.logback.classic.BasicConfigurator;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.util.LogbackMDCAdapter;
import ch.qos.logback.core.Appender;
/**
@ -44,6 +51,7 @@ public class LoggingInterceptorTest {
@SuppressWarnings("unchecked")
@Before
public void before() {
/*
* This is a bit funky, but it's useful for verifying that the headers actually get logged
*/
@ -51,7 +59,7 @@ public class LoggingInterceptorTest {
when(myMockAppender.getName()).thenReturn("MOCK");
org.slf4j.Logger logger = LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
myLoggerRoot = (ch.qos.logback.classic.Logger) logger;
myLoggerRoot.addAppender(myMockAppender);
}
@ -86,6 +94,15 @@ public class LoggingInterceptorTest {
@BeforeClass
public static void beforeClass() throws Exception {
URL conf = LoggingInterceptor.class.getResource("/logback-test-dstuforce.xml");
assertNotNull(conf);
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
context.reset();
configurator.doConfigure(conf);
ourPort = PortUtil.findFreePort();
ourServer = new Server(ourPort);

View File

@ -13,6 +13,7 @@ import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
@ -25,16 +26,72 @@ public class ResourceMethodTest {
private SearchMethodBinding rm;
@Search
public Bundle foo() {
return null;
}
@Before
public void before() throws NoSuchMethodException, SecurityException {
rm = new SearchMethodBinding(Patient.class, ResourceMethodTest.class.getMethod("foo"), FhirContext.forDstu1(), null);
}
@Search
public Bundle foo() {
return null;
}
@Test
public void testAllParams() {
List<IParameter> methodParams = new ArrayList<IParameter>();
methodParams.add(new SearchParameter("firstName", false));
methodParams.add(new SearchParameter("lastName", false));
methodParams.add(new SearchParameter("mrn", true));
rm.setParameters(methodParams);
Set<String> inputParams = new HashSet<String>();
inputParams.add("firstName");
inputParams.add("lastName");
inputParams.add("mrn");
RequestDetails params = RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams);
boolean actual = rm.incomingServerRequestMatchesMethod(params);
assertTrue( actual); // True
}
@Test
public void testAllParamsWithExtra() {
List<IParameter> methodParams = new ArrayList<IParameter>();
methodParams.add(new SearchParameter("firstName", false));
methodParams.add(new SearchParameter("lastName", false));
methodParams.add(new SearchParameter("mrn", true));
rm.setParameters(methodParams);
Set<String> inputParams = new HashSet<String>();
inputParams.add("firstName");
inputParams.add("lastName");
inputParams.add("mrn");
inputParams.add("foo");
assertEquals(false, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
}
@Test
public void testMixedParams() {
List<IParameter> methodParams = new ArrayList<IParameter>();
methodParams.add(new SearchParameter("firstName", false));
methodParams.add(new SearchParameter("lastName", false));
methodParams.add(new SearchParameter("mrn", true));
rm.setParameters(methodParams);
Set<String> inputParams = new HashSet<String>();
inputParams.add("firstName");
inputParams.add("mrn");
assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
}
@Test
public void testRequiredParamsMissing() {
List<IParameter> methodParams = new ArrayList<IParameter>();
@ -67,59 +124,13 @@ public class ResourceMethodTest {
assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
}
@Test
public void testMixedParams() {
List<IParameter> methodParams = new ArrayList<IParameter>();
methodParams.add(new SearchParameter("firstName", false));
methodParams.add(new SearchParameter("lastName", false));
methodParams.add(new SearchParameter("mrn", true));
rm.setParameters(methodParams);
Set<String> inputParams = new HashSet<String>();
inputParams.add("firstName");
inputParams.add("mrn");
assertEquals(true, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // True
@Test(expected=IllegalStateException.class)
public void testWildcardImmutable() {
IResource.INCLUDE_ALL.setValue("AAA");
}
@Test
public void testAllParams() {
List<IParameter> methodParams = new ArrayList<IParameter>();
methodParams.add(new SearchParameter("firstName", false));
methodParams.add(new SearchParameter("lastName", false));
methodParams.add(new SearchParameter("mrn", true));
rm.setParameters(methodParams);
Set<String> inputParams = new HashSet<String>();
inputParams.add("firstName");
inputParams.add("lastName");
inputParams.add("mrn");
RequestDetails params = RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams);
boolean actual = rm.incomingServerRequestMatchesMethod(params);
assertTrue( actual); // True
}
@Test
public void testAllParamsWithExtra() {
List<IParameter> methodParams = new ArrayList<IParameter>();
methodParams.add(new SearchParameter("firstName", false));
methodParams.add(new SearchParameter("lastName", false));
methodParams.add(new SearchParameter("mrn", true));
rm.setParameters(methodParams);
Set<String> inputParams = new HashSet<String>();
inputParams.add("firstName");
inputParams.add("lastName");
inputParams.add("mrn");
inputParams.add("foo");
assertEquals(false, rm.incomingServerRequestMatchesMethod(RequestDetails.withResourceAndParams("Patient", RequestTypeEnum.GET, inputParams))); // False
public void testWildcardSet() {
assertTrue(IResource.WILDCARD_ALL_SET.contains(IResource.INCLUDE_ALL));
}
}

View File

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

View File

@ -1,5 +1,4 @@
<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">
<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>
@ -28,8 +27,7 @@
</dependency>
<!-- Testing -->
<!-- <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu</artifactId>
<version>0.8</version> <scope>test</scope> </dependency> -->
<!-- <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu</artifactId> <version>0.8</version> <scope>test</scope> </dependency> -->
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
@ -69,32 +67,27 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback_version}</version>
<optional>true</optional>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ebaysf.web</groupId>
<artifactId>cors-filter</artifactId>
<version>${ebay_cors_filter_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
<scope>test</scope>
</dependency>
@ -135,15 +128,8 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava_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>
@ -161,122 +147,124 @@
</goals>
<configuration>
<baseResourceNames>
<baseResourceName>supplyrequest</baseResourceName>
<baseResourceName>supplydelivery</baseResourceName>
<baseResourceName>account</baseResourceName>
<baseResourceName>allergyintolerance</baseResourceName>
<baseResourceName>appointment</baseResourceName>
<baseResourceName>appointmentresponse</baseResourceName>
<baseResourceName>auditevent</baseResourceName>
<baseResourceName>basic</baseResourceName>
<baseResourceName>binary</baseResourceName>
<baseResourceName>bodysite</baseResourceName>
<baseResourceName>bundle</baseResourceName>
<baseResourceName>careplan</baseResourceName>
<baseResourceName>claim</baseResourceName>
<baseResourceName>claimresponse</baseResourceName>
<baseResourceName>clinicalimpression</baseResourceName>
<baseResourceName>communication</baseResourceName>
<baseResourceName>communicationrequest</baseResourceName>
<baseResourceName>composition</baseResourceName>
<baseResourceName>conceptmap</baseResourceName>
<baseResourceName>condition</baseResourceName>
<baseResourceName>conformance</baseResourceName>
<baseResourceName>contract</baseResourceName>
<baseResourceName>contraindication</baseResourceName>
<baseResourceName>coverage</baseResourceName>
<baseResourceName>dataelement</baseResourceName>
<baseResourceName>device</baseResourceName>
<baseResourceName>devicecomponent</baseResourceName>
<baseResourceName>devicemetric</baseResourceName>
<baseResourceName>deviceuserequest</baseResourceName>
<baseResourceName>deviceusestatement</baseResourceName>
<baseResourceName>diagnosticorder</baseResourceName>
<baseResourceName>diagnosticreport</baseResourceName>
<baseResourceName>documentation</baseResourceName>
<baseResourceName>documentmanifest</baseResourceName>
<baseResourceName>documentreference</baseResourceName>
<!--<baseResourceName>domainresource</baseResourceName>-->
<baseResourceName>eligibilityrequest</baseResourceName>
<baseResourceName>eligibilityresponse</baseResourceName>
<baseResourceName>encounter</baseResourceName>
<baseResourceName>enrollmentrequest</baseResourceName>
<baseResourceName>enrollmentresponse</baseResourceName>
<baseResourceName>episodeofcare</baseResourceName>
<baseResourceName>explanationofbenefit</baseResourceName>
<baseResourceName>familymemberhistory</baseResourceName>
<baseResourceName>flag</baseResourceName>
<baseResourceName>goal</baseResourceName>
<baseResourceName>group</baseResourceName>
<baseResourceName>healthcareservice</baseResourceName>
<baseResourceName>imagingobjectselection</baseResourceName>
<baseResourceName>imagingstudy</baseResourceName>
<baseResourceName>immunization</baseResourceName>
<baseResourceName>immunizationrecommendation</baseResourceName>
<baseResourceName>implementationguide</baseResourceName>
<baseResourceName>list</baseResourceName>
<baseResourceName>location</baseResourceName>
<baseResourceName>media</baseResourceName>
<baseResourceName>medication</baseResourceName>
<baseResourceName>medicationadministration</baseResourceName>
<baseResourceName>medicationdispense</baseResourceName>
<baseResourceName>medicationorder</baseResourceName>
<baseResourceName>medicationstatement</baseResourceName>
<baseResourceName>messageheader</baseResourceName>
<baseResourceName>namingsystem</baseResourceName>
<baseResourceName>nutritionorder</baseResourceName>
<baseResourceName>observation</baseResourceName>
<baseResourceName>operationdefinition</baseResourceName>
<baseResourceName>operationoutcome</baseResourceName>
<baseResourceName>order</baseResourceName>
<baseResourceName>orderresponse</baseResourceName>
<baseResourceName>organization</baseResourceName>
<baseResourceName>parameters</baseResourceName>
<baseResourceName>patient</baseResourceName>
<baseResourceName>paymentnotice</baseResourceName>
<baseResourceName>paymentreconciliation</baseResourceName>
<baseResourceName>person</baseResourceName>
<baseResourceName>practitioner</baseResourceName>
<baseResourceName>procedure</baseResourceName>
<baseResourceName>procedurerequest</baseResourceName>
<baseResourceName>processrequest</baseResourceName>
<baseResourceName>processresponse</baseResourceName>
<baseResourceName>Condition</baseResourceName>
<baseResourceName>DeviceComponent</baseResourceName>
<baseResourceName>Communication</baseResourceName>
<baseResourceName>Group</baseResourceName>
<baseResourceName>ValueSet</baseResourceName>
<baseResourceName>Coverage</baseResourceName>
<baseResourceName>Appointment</baseResourceName>
<baseResourceName>Slot</baseResourceName>
<baseResourceName>Contraindication</baseResourceName>
<baseResourceName>Composition</baseResourceName>
<baseResourceName>EpisodeOfCare</baseResourceName>
<baseResourceName>Conformance</baseResourceName>
<baseResourceName>NamingSystem</baseResourceName>
<baseResourceName>HealthcareService</baseResourceName>
<baseResourceName>OrderResponse</baseResourceName>
<baseResourceName>ConceptMap</baseResourceName>
<baseResourceName>Practitioner</baseResourceName>
<baseResourceName>CarePlan</baseResourceName>
<baseResourceName>Substance</baseResourceName>
<baseResourceName>DeviceUseRequest</baseResourceName>
<baseResourceName>Schedule</baseResourceName>
<baseResourceName>EligibilityRequest</baseResourceName>
<baseResourceName>QuestionnaireResponse</baseResourceName>
<baseResourceName>PaymentReconciliation</baseResourceName>
<baseResourceName>ImagingObjectSelection</baseResourceName>
<baseResourceName>OperationDefinition</baseResourceName>
<baseResourceName>ClaimResponse</baseResourceName>
<baseResourceName>BodySite</baseResourceName>
<baseResourceName>CommunicationRequest</baseResourceName>
<baseResourceName>RiskAssessment</baseResourceName>
<baseResourceName>Observation</baseResourceName>
<baseResourceName>AllergyIntolerance</baseResourceName>
<baseResourceName>ExplanationOfBenefit</baseResourceName>
<baseResourceName>RelatedPerson</baseResourceName>
<baseResourceName>AuditEvent</baseResourceName>
<baseResourceName>EligibilityResponse</baseResourceName>
<baseResourceName>Person</baseResourceName>
<baseResourceName>ProcedureRequest</baseResourceName>
<baseResourceName>ProcessRequest</baseResourceName>
<baseResourceName>Claim</baseResourceName>
<baseResourceName>DeviceMetric</baseResourceName>
<baseResourceName>Organization</baseResourceName>
<baseResourceName>ImmunizationRecommendation</baseResourceName>
<baseResourceName>MedicationDispense</baseResourceName>
<baseResourceName>MedicationPrescription</baseResourceName>
<baseResourceName>PaymentNotice</baseResourceName>
<baseResourceName>MedicationStatement</baseResourceName>
<baseResourceName>AppointmentResponse</baseResourceName>
<baseResourceName>Questionnaire</baseResourceName>
<baseResourceName>OperationOutcome</baseResourceName>
<baseResourceName>Media</baseResourceName>
<baseResourceName>Binary</baseResourceName>
<baseResourceName>VisionPrescription</baseResourceName>
<baseResourceName>DocumentReference</baseResourceName>
<baseResourceName>Immunization</baseResourceName>
<baseResourceName>Bundle</baseResourceName>
<baseResourceName>Subscription</baseResourceName>
<baseResourceName>ImagingStudy</baseResourceName>
<baseResourceName>Provenance</baseResourceName>
<baseResourceName>Device</baseResourceName>
<baseResourceName>StructureDefinition</baseResourceName>
<baseResourceName>Order</baseResourceName>
<baseResourceName>Procedure</baseResourceName>
<baseResourceName>DiagnosticReport</baseResourceName>
<baseResourceName>Medication</baseResourceName>
<baseResourceName>MessageHeader</baseResourceName>
<baseResourceName>DataElement</baseResourceName>
<baseResourceName>DocumentManifest</baseResourceName>
<baseResourceName>MedicationAdministration</baseResourceName>
<baseResourceName>Encounter</baseResourceName>
<baseResourceName>List</baseResourceName>
<baseResourceName>DeviceUseStatement</baseResourceName>
<baseResourceName>Goal</baseResourceName>
<baseResourceName>NutritionOrder</baseResourceName>
<baseResourceName>SearchParameter</baseResourceName>
<baseResourceName>ReferralRequest</baseResourceName>
<baseResourceName>EnrollmentRequest</baseResourceName>
<baseResourceName>Location</baseResourceName>
<baseResourceName>Contract</baseResourceName>
<baseResourceName>Basic</baseResourceName>
<baseResourceName>Specimen</baseResourceName>
<baseResourceName>EnrollmentResponse</baseResourceName>
<baseResourceName>Patient</baseResourceName>
<baseResourceName>DiagnosticOrder</baseResourceName>
<baseResourceName>Parameters</baseResourceName>
<!--<baseResourceName>protocol</baseResourceName>-->
<baseResourceName>provenance</baseResourceName>
<baseResourceName>questionnaire</baseResourceName>
<baseResourceName>questionnaireresponse</baseResourceName>
<baseResourceName>referralrequest</baseResourceName>
<baseResourceName>relatedperson</baseResourceName>
<baseResourceName>remittance</baseResourceName>
<!--<baseResourceName>resource</baseResourceName>-->
<baseResourceName>riskassessment</baseResourceName>
<baseResourceName>schedule</baseResourceName>
<baseResourceName>searchparameter</baseResourceName>
<baseResourceName>slot</baseResourceName>
<baseResourceName>specimen</baseResourceName>
<baseResourceName>structuredefinition</baseResourceName>
<baseResourceName>subscription</baseResourceName>
<baseResourceName>substance</baseResourceName>
<baseResourceName>supplydelivery</baseResourceName>
<baseResourceName>supplyrequest</baseResourceName>
<baseResourceName>supportingdocumentation</baseResourceName>
<!--<baseResourceName>template</baseResourceName>-->
<baseResourceName>test</baseResourceName>
<baseResourceName>testscript</baseResourceName>
<baseResourceName>user</baseResourceName>
<baseResourceName>valueset</baseResourceName>
<baseResourceName>visionprescription</baseResourceName>
</baseResourceNames>
<package>ca.uhn.fhir.model.dstu2</package>
<version>dstu2</version>
<buildDatatypes>true</buildDatatypes>
</configuration>
</execution>
<!--
<execution>
<id>clean_source</id>
<goals>
<goal>minimize-resources</goal>
</goals>
<configuration>
<fhirVersion>DSTU2</fhirVersion>
<targetDirectory>${project.baseDir}/../hapi-tinder-plugin/</targetDirectory>
</configuration>
</execution>
-->
<!-- <execution> <id>clean_source</id> <goals> <goal>minimize-resources</goal> </goals> <configuration> <fhirVersion>DSTU2</fhirVersion> <targetDirectory>${project.baseDir}/../hapi-tinder-plugin/</targetDirectory>
</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. -->
<!--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>

View File

@ -23,7 +23,7 @@ import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
* #L%
*/
@DatatypeDef(name="MoneyDt")
@DatatypeDef(name="Money")
public class MoneyDt extends QuantityDt {
}

View File

@ -0,0 +1,99 @@
package ca.uhn.fhir.model.dstu2.composite;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
/*
* #%L
* HAPI FHIR Structures - DSTU2 (FHIR v0.5.0)
* %%
* Copyright (C) 2014 - 2015 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="SimpleQuantity")
public class SimpleQuantityDt extends QuantityDt {
private static final long serialVersionUID = 1L;
/**
* Constructor
*/
public SimpleQuantityDt() {
// nothing
}
/**
* Constructor
*/
@SimpleSetter
public SimpleQuantityDt(@SimpleSetter.Parameter(name="theValue") double theValue) {
setValue(theValue);
}
/**
* Constructor
*/
@SimpleSetter
public SimpleQuantityDt(@SimpleSetter.Parameter(name="theValue") long theValue) {
setValue(theValue);
}
/**
* Constructor
*/
@SimpleSetter
public SimpleQuantityDt(@SimpleSetter.Parameter(name = "theComparator") QuantityComparatorEnum theComparator, @SimpleSetter.Parameter(name = "theValue") double theValue,
@SimpleSetter.Parameter(name = "theUnits") String theUnits) {
setValue(theValue);
setComparator(theComparator);
setUnit(theUnits);
}
/**
* Constructor
*/
@SimpleSetter
public SimpleQuantityDt(@SimpleSetter.Parameter(name = "theComparator") QuantityComparatorEnum theComparator, @SimpleSetter.Parameter(name = "theValue") long theValue,
@SimpleSetter.Parameter(name = "theUnits") String theUnits) {
setValue(theValue);
setComparator(theComparator);
setUnit(theUnits);
}
/**
* Constructor
*/
@SimpleSetter
public SimpleQuantityDt(@SimpleSetter.Parameter(name="theValue") double theValue, @SimpleSetter.Parameter(name="theSystem") String theSystem, @SimpleSetter.Parameter(name="theUnits") String theUnits) {
setValue(theValue);
setSystem(theSystem);
setUnit(theUnits);
}
/**
* Constructor
*/
@SimpleSetter
public SimpleQuantityDt(@SimpleSetter.Parameter(name="theValue") long theValue, @SimpleSetter.Parameter(name="theSystem") String theSystem, @SimpleSetter.Parameter(name="theUnits") String theUnits) {
setValue(theValue);
setSystem(theSystem);
setUnit(theUnits);
}
}

View File

@ -10,45 +10,45 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Account</sch:title>
<sch:rule context="f:Account">
<sch:rule context="//f:Account">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:text/f:div">
<sch:rule context="//f:Account/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:identifier/f:period">
<sch:rule context="//f:Account/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:identifier/f:assigner">
<sch:rule context="//f:Account/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:activePeriod">
<sch:rule context="//f:Account/f:activePeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:balance">
<sch:rule context="//f:Account/f:balance">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:coveragePeriod">
<sch:rule context="//f:Account/f:coveragePeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:subject">
<sch:rule context="//f:Account/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Account/f:owner">
<sch:rule context="//f:Account/f:owner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,42 +10,45 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>AllergyIntolerance</sch:title>
<sch:rule context="f:AllergyIntolerance">
<sch:rule context="//f:AllergyIntolerance">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:text/f:div">
<sch:rule context="//f:AllergyIntolerance/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:identifier/f:period">
<sch:rule context="//f:AllergyIntolerance/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:identifier/f:assigner">
<sch:rule context="//f:AllergyIntolerance/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:recorder">
<sch:rule context="//f:AllergyIntolerance/f:recorder">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:patient">
<sch:rule context="//f:AllergyIntolerance/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:reporter">
<sch:rule context="//f:AllergyIntolerance/f:reporter">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AllergyIntolerance/f:event/f:duration">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
<sch:rule context="//f:AllergyIntolerance/f:notes/f:authorReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
<sch:rule context="//f:AllergyIntolerance/f:reaction/f:notes/f:authorReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:schema>

View File

@ -10,39 +10,44 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Appointment</sch:title>
<sch:rule context="f:Appointment">
<sch:rule context="//f:Appointment">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
<sch:assert test="(not((f:status/@value='proposed') or (f:status/@value='cancelled')) and exists(f:start) and exists(f:end))">app-3: Only proposed or cancelled appointments can be missing start/end dates</sch:assert>
<sch:assert test="((exists(f:start) and exists(f:end)) or (not(exists(f:start)) and not(exists(f:end))))">app-2: Either start and end are specified, or neither</sch:assert>
</sch:rule>
<sch:rule context="f:Appointment/f:text/f:div">
<sch:rule context="//f:Appointment/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Appointment/f:identifier/f:period">
<sch:rule context="//f:Appointment/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Appointment/f:identifier/f:assigner">
<sch:rule context="//f:Appointment/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Appointment/f:slot">
<sch:rule context="//f:Appointment/f:slot">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Appointment/f:order">
<sch:rule context="//f:Appointment/f:order">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Appointment/f:participant/f:actor">
<sch:rule context="//f:Appointment/f:participant">
<sch:assert test="(exists(f:type) or exists(f:actor))">app-1: Either the type or actor on the participant MUST be specified</sch:assert>
</sch:rule>
<sch:rule context="//f:Appointment/f:participant/f:actor">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,36 +10,37 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>AppointmentResponse</sch:title>
<sch:rule context="f:AppointmentResponse">
<sch:rule context="//f:AppointmentResponse">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
<sch:assert test="(exists(f:type) or exists(f:actor))">apr-1: Either the type or actor on the participant should be specified</sch:assert>
</sch:rule>
<sch:rule context="f:AppointmentResponse/f:text/f:div">
<sch:rule context="//f:AppointmentResponse/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:AppointmentResponse/f:identifier/f:period">
<sch:rule context="//f:AppointmentResponse/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:AppointmentResponse/f:identifier/f:assigner">
<sch:rule context="//f:AppointmentResponse/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AppointmentResponse/f:appointment">
<sch:rule context="//f:AppointmentResponse/f:appointment">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AppointmentResponse/f:actor">
<sch:rule context="//f:AppointmentResponse/f:actor">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,46 +10,54 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>AuditEvent</sch:title>
<sch:rule context="f:AuditEvent">
<sch:rule context="//f:AuditEvent">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:text/f:div">
<sch:rule context="//f:AuditEvent/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:participant">
<sch:assert test="exists(f:userId) != exists(f:reference)">sev-3: Either a userId or a reference, but not both</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:participant/f:reference">
<sch:rule context="//f:AuditEvent/f:participant/f:reference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:participant/f:location">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:object">
<sch:assert test="not(exists(f:name)) or not(exists(f:query))">sev-1: Either a name or a query (or both)</sch:assert>
<sch:assert test="exists(f:identifier) != exists(f:reference)">sev-2: Either an identifier or a reference, but not both</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:object/f:identifier/f:period">
<sch:rule context="//f:AuditEvent/f:participant/f:userId/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:object/f:identifier/f:assigner">
<sch:rule context="//f:AuditEvent/f:participant/f:userId/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:AuditEvent/f:object/f:reference">
<sch:rule context="//f:AuditEvent/f:participant/f:location">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
<sch:rule context="//f:AuditEvent/f:source/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="//f:AuditEvent/f:source/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="//f:AuditEvent/f:object">
<sch:assert test="not(exists(f:name)) or not(exists(f:query))">sev-1: Either a name or a query (NOT both)</sch:assert>
</sch:rule>
<sch:rule context="//f:AuditEvent/f:object/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="//f:AuditEvent/f:object/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="//f:AuditEvent/f:object/f:reference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:schema>

View File

@ -10,36 +10,36 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Basic</sch:title>
<sch:rule context="f:Basic">
<sch:rule context="//f:Basic">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Basic/f:text/f:div">
<sch:rule context="//f:Basic/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Basic/f:identifier/f:period">
<sch:rule context="//f:Basic/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Basic/f:identifier/f:assigner">
<sch:rule context="//f:Basic/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Basic/f:subject">
<sch:rule context="//f:Basic/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Basic/f:author">
<sch:rule context="//f:Basic/f:author">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,13 +10,13 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Binary</sch:title>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,36 +10,36 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>BodySite</sch:title>
<sch:rule context="f:BodySite">
<sch:rule context="//f:BodySite">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:BodySite/f:text/f:div">
<sch:rule context="//f:BodySite/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:BodySite/f:patient">
<sch:rule context="//f:BodySite/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:BodySite/f:identifier/f:period">
<sch:rule context="//f:BodySite/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:BodySite/f:identifier/f:assigner">
<sch:rule context="//f:BodySite/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:BodySite/f:image">
<sch:rule context="//f:BodySite/f:image">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,27 +10,27 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Bundle</sch:title>
<sch:rule context="f:Bundle">
<sch:rule context="//f:Bundle">
<sch:assert test="count(for $entry in entry[resource] return $entry[count(parent::Bundle/entry[fullUrl/@value=$entry/fullUrl/@value and resource/*/meta/versionId/@value=$entry/resource/*/meta/versionId/@value])!=1])=0">bdl-7: FullUrl must be unique in a bundle, or else entries with the same fullUrl must have different meta.versionId</sch:assert>
<sch:assert test="not(f:entry/f:request) or (f:type/@value = 'batch') or (f:type/@value = 'transaction') or (f:type/@value = 'history')">bdl-3: entry.transaction when (and only when) a transaction</sch:assert>
<sch:assert test="not(f:entry/f:response) or (f:type/@value = 'batch-response') or (f:type/@value = 'transaction-response')">bdl-4: entry.transactionResponse when (and only when) a transaction-response</sch:assert>
<sch:assert test="not(f:total) or (f:type/@value = 'searchset') or (f:type/@value = 'history')">bdl-1: total only when a search or history</sch:assert>
<sch:assert test="not(f:entry/f:search) or (f:type/@value = 'searchset')">bdl-2: entry.search only when a search</sch:assert>
</sch:rule>
<sch:rule context="f:Bundle/f:entry">
<sch:rule context="//f:Bundle/f:entry">
<sch:assert test="f:resource or f:request or f:response">bdl-5: must be a resource unless there's a transaction or transaction response</sch:assert>
<sch:assert test="(not(exists(f:fullUrl)) and not(exists(f:resource))) or (exists(f:fullUrl) and exists(f:resource))">bdl-6: The fullUrl element must be present when a resource is present, and not present otherwise</sch:assert>
</sch:rule>
<sch:rule context="f:Bundle/f:signature/f:whoReference">
<sch:rule context="//f:Bundle/f:signature/f:whoReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,115 +10,114 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>CarePlan</sch:title>
<sch:rule context="f:CarePlan">
<sch:rule context="//f:CarePlan">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:text/f:div">
<sch:rule context="//f:CarePlan/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:identifier/f:period">
<sch:rule context="//f:CarePlan/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:identifier/f:assigner">
<sch:rule context="//f:CarePlan/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:patient">
<sch:rule context="//f:CarePlan/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:period">
<sch:rule context="//f:CarePlan/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:author">
<sch:rule context="//f:CarePlan/f:author">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:concern">
<sch:rule context="//f:CarePlan/f:concern">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:support">
<sch:rule context="//f:CarePlan/f:support">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:participant/f:member">
<sch:rule context="//f:CarePlan/f:participant/f:member">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:goal">
<sch:rule context="//f:CarePlan/f:goal">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:actionResulting">
<sch:rule context="//f:CarePlan/f:activity/f:actionResulting">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:reference">
<sch:rule context="//f:CarePlan/f:activity/f:reference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail">
<sch:rule context="//f:CarePlan/f:activity/f:detail">
<sch:assert test="not(exists(f:detail)) or not(exists(f:simple))">cpl-3: Only provide a detail reference, or a simple detail summary</sch:assert>
<sch:assert test="(f:category/@value=('supply')) = exists(f:quantity)">cpl-2: Quantity can only be specified if activity category is supply</sch:assert>
<sch:assert test="(f:category/@value=('drug','diet')) = exists(f:dailyAmount)">cpl-1: DailyDose can only be specified if activity category is drug or food</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:reasonReference">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:reasonReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:goal">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:goal">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat">
<sch:assert test="not(exists(f:periodMax)) or exists(period)">tim-6: If there's a periodMax, there must be a period</sch:assert>
<sch:assert test="not(exists(f:durationMax)) or exists(duration)">tim-7: If there's a durationMax, there must be a duration</sch:assert>
<sch:assert test="not(exists(f:duration)) or exists(f:durationUnits)">tim-1: if there's a duration, there needs to be duration units</sch:assert>
<sch:assert test="not(exists(f:period)) or exists(f:periodUnits)">tim-2: if there's a period, there needs to be duration units</sch:assert>
<sch:assert test="not(exists(f:frequency)) or not(exists(f:when))">tim-3: Either frequency or when can exist, not both</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsDuration">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsDuration">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsRange">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsRange">
<sch:assert test="not(exists(f:low/f:value/@value)) or not(exists(f:high/f:value/@value)) or (number(f:low/f:value/@value) &lt;= number(f:high/f:value/@value))">rng-2: If present, low SHALL have a lower value than high</sch:assert>
<sch:assert test="not(exists(f:low/f:comparator) or exists(f:high/f:comparator))">rng-3: Quantity values cannot have a comparator when used in a Range</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsRange/f:low">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsRange/f:low">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsRange/f:high">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsRange/f:high">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsPeriod">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:boundsPeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:duration">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:duration">
<sch:assert test="@value &gt;= 0 or not(@value)">tim-4: duration SHALL be a non-negative value</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:period">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledTiming/f:repeat/f:period">
<sch:assert test="@value &gt;= 0 or not(@value)">tim-5: period SHALL be a non-negative value</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:scheduledPeriod">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:scheduledPeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:location">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:location">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:performer">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:performer">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:product">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:product">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:dailyAmount">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:dailyAmount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:CarePlan/f:activity/f:detail/f:quantity">
<sch:rule context="//f:CarePlan/f:activity/f:detail/f:quantity">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<sch:ns prefix="f" uri="http://hl7.org/fhir"/>
<sch:ns prefix="h" uri="http://www.w3.org/1999/xhtml"/>
<sch:pattern>
<sch:title>Observation</sch:title>
<sch:rule context="f:Cholesterol">
<sch:assert test="count(f:referenceRange) &gt;= 1">referenceRange: minimum cardinality is 1</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol">
<sch:assert test="count(f:referenceRange) &lt;= 1">referenceRange: maximum cardinality is 1</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol">
<sch:assert test="count(f:related) &lt;= 0">related: maximum cardinality is 0</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Observation.valueQuantity</sch:title>
<sch:rule context="f:Cholesterol/f:valueQuantity">
<sch:assert test="count(f:comparator) &lt;= 0">comparator: maximum cardinality is 0</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol/f:valueQuantity">
<sch:assert test="count(f:unit) &gt;= 1">unit: minimum cardinality is 1</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol/f:valueQuantity">
<sch:assert test="count(f:system) &gt;= 1">system: minimum cardinality is 1</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol/f:valueQuantity">
<sch:assert test="count(f:code) &gt;= 1">code: minimum cardinality is 1</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Observation.referenceRange</sch:title>
<sch:rule context="f:Cholesterol/f:referenceRange">
<sch:assert test="count(f:low) &lt;= 0">low: maximum cardinality is 0</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol/f:referenceRange">
<sch:assert test="count(f:high) &gt;= 1">high: minimum cardinality is 1</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol/f:referenceRange">
<sch:assert test="count(f:meaning) &lt;= 0">meaning: maximum cardinality is 0</sch:assert>
</sch:rule>
<sch:rule context="f:Cholesterol/f:referenceRange">
<sch:assert test="count(f:age) &lt;= 0">age: maximum cardinality is 0</sch:assert>
</sch:rule>
</sch:pattern>
</sch:schema>

View File

@ -10,102 +10,102 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Claim</sch:title>
<sch:rule context="f:Claim">
<sch:rule context="//f:Claim">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:text/f:div">
<sch:rule context="//f:Claim/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:identifier/f:period">
<sch:rule context="//f:Claim/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:identifier/f:assigner">
<sch:rule context="//f:Claim/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:target">
<sch:rule context="//f:Claim/f:target">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:provider">
<sch:rule context="//f:Claim/f:provider">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:organization">
<sch:rule context="//f:Claim/f:organization">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:enterer">
<sch:rule context="//f:Claim/f:enterer">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:facility">
<sch:rule context="//f:Claim/f:facility">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:prescription">
<sch:rule context="//f:Claim/f:prescription">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:originalPrescription">
<sch:rule context="//f:Claim/f:originalPrescription">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:payee/f:provider">
<sch:rule context="//f:Claim/f:payee/f:provider">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:payee/f:organization">
<sch:rule context="//f:Claim/f:payee/f:organization">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:payee/f:person">
<sch:rule context="//f:Claim/f:payee/f:person">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:referral">
<sch:rule context="//f:Claim/f:referral">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:patient">
<sch:rule context="//f:Claim/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:coverage/f:coverage">
<sch:rule context="//f:Claim/f:coverage/f:coverage">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:coverage/f:claimResponse">
<sch:rule context="//f:Claim/f:coverage/f:claimResponse">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:provider">
<sch:rule context="//f:Claim/f:item/f:provider">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:quantity">
<sch:rule context="//f:Claim/f:item/f:quantity">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:unitPrice">
<sch:rule context="//f:Claim/f:item/f:unitPrice">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:net">
<sch:rule context="//f:Claim/f:item/f:net">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:detail/f:quantity">
<sch:rule context="//f:Claim/f:item/f:detail/f:quantity">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:detail/f:unitPrice">
<sch:rule context="//f:Claim/f:item/f:detail/f:unitPrice">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:detail/f:net">
<sch:rule context="//f:Claim/f:item/f:detail/f:net">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:detail/f:subDetail/f:quantity">
<sch:rule context="//f:Claim/f:item/f:detail/f:subDetail/f:quantity">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:detail/f:subDetail/f:unitPrice">
<sch:rule context="//f:Claim/f:item/f:detail/f:subDetail/f:unitPrice">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Claim/f:item/f:detail/f:subDetail/f:net">
<sch:rule context="//f:Claim/f:item/f:detail/f:subDetail/f:net">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,90 +10,90 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>ClaimResponse</sch:title>
<sch:rule context="f:ClaimResponse">
<sch:rule context="//f:ClaimResponse">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:text/f:div">
<sch:rule context="//f:ClaimResponse/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:identifier/f:period">
<sch:rule context="//f:ClaimResponse/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:identifier/f:assigner">
<sch:rule context="//f:ClaimResponse/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:request">
<sch:rule context="//f:ClaimResponse/f:request">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:organization">
<sch:rule context="//f:ClaimResponse/f:organization">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:requestProvider">
<sch:rule context="//f:ClaimResponse/f:requestProvider">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:requestOrganization">
<sch:rule context="//f:ClaimResponse/f:requestOrganization">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:item/f:adjudication/f:amount">
<sch:rule context="//f:ClaimResponse/f:item/f:adjudication/f:amount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:item/f:detail/f:adjudication/f:amount">
<sch:rule context="//f:ClaimResponse/f:item/f:detail/f:adjudication/f:amount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:item/f:detail/f:subDetail/f:adjudication/f:amount">
<sch:rule context="//f:ClaimResponse/f:item/f:detail/f:subDetail/f:adjudication/f:amount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:addItem/f:fee">
<sch:rule context="//f:ClaimResponse/f:addItem/f:fee">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:addItem/f:adjudication/f:amount">
<sch:rule context="//f:ClaimResponse/f:addItem/f:adjudication/f:amount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:addItem/f:detail/f:fee">
<sch:rule context="//f:ClaimResponse/f:addItem/f:detail/f:fee">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:addItem/f:detail/f:adjudication/f:amount">
<sch:rule context="//f:ClaimResponse/f:addItem/f:detail/f:adjudication/f:amount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:totalCost">
<sch:rule context="//f:ClaimResponse/f:totalCost">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:unallocDeductable">
<sch:rule context="//f:ClaimResponse/f:unallocDeductable">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:totalBenefit">
<sch:rule context="//f:ClaimResponse/f:totalBenefit">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:paymentAdjustment">
<sch:rule context="//f:ClaimResponse/f:paymentAdjustment">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:paymentAmount">
<sch:rule context="//f:ClaimResponse/f:paymentAmount">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:paymentRef/f:period">
<sch:rule context="//f:ClaimResponse/f:paymentRef/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:paymentRef/f:assigner">
<sch:rule context="//f:ClaimResponse/f:paymentRef/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:coverage/f:coverage">
<sch:rule context="//f:ClaimResponse/f:coverage/f:coverage">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClaimResponse/f:coverage/f:claimResponse">
<sch:rule context="//f:ClaimResponse/f:coverage/f:claimResponse">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<sch:ns prefix="f" uri="http://hl7.org/fhir"/>
<sch:ns prefix="h" uri="http://www.w3.org/1999/xhtml"/>
</sch:schema>

View File

@ -10,48 +10,48 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>ClinicalImpression</sch:title>
<sch:rule context="f:ClinicalImpression">
<sch:rule context="//f:ClinicalImpression">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:text/f:div">
<sch:rule context="//f:ClinicalImpression/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:patient">
<sch:rule context="//f:ClinicalImpression/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:assessor">
<sch:rule context="//f:ClinicalImpression/f:assessor">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:previous">
<sch:rule context="//f:ClinicalImpression/f:previous">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:problem">
<sch:rule context="//f:ClinicalImpression/f:problem">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:triggerReference">
<sch:rule context="//f:ClinicalImpression/f:triggerReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:investigations/f:item">
<sch:rule context="//f:ClinicalImpression/f:investigations/f:item">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:plan">
<sch:rule context="//f:ClinicalImpression/f:plan">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ClinicalImpression/f:action">
<sch:rule context="//f:ClinicalImpression/f:action">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,48 +10,48 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Communication</sch:title>
<sch:rule context="f:Communication">
<sch:rule context="//f:Communication">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:text/f:div">
<sch:rule context="//f:Communication/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:identifier/f:period">
<sch:rule context="//f:Communication/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:identifier/f:assigner">
<sch:rule context="//f:Communication/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:sender">
<sch:rule context="//f:Communication/f:sender">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:recipient">
<sch:rule context="//f:Communication/f:recipient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:payload/f:contentAttachment">
<sch:rule context="//f:Communication/f:payload/f:contentAttachment">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:payload/f:contentReference">
<sch:rule context="//f:Communication/f:payload/f:contentReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:encounter">
<sch:rule context="//f:Communication/f:encounter">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Communication/f:subject">
<sch:rule context="//f:Communication/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,51 +10,51 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>CommunicationRequest</sch:title>
<sch:rule context="f:CommunicationRequest">
<sch:rule context="//f:CommunicationRequest">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:text/f:div">
<sch:rule context="//f:CommunicationRequest/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:identifier/f:period">
<sch:rule context="//f:CommunicationRequest/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:identifier/f:assigner">
<sch:rule context="//f:CommunicationRequest/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:sender">
<sch:rule context="//f:CommunicationRequest/f:sender">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:recipient">
<sch:rule context="//f:CommunicationRequest/f:recipient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:payload/f:contentAttachment">
<sch:rule context="//f:CommunicationRequest/f:payload/f:contentAttachment">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:payload/f:contentReference">
<sch:rule context="//f:CommunicationRequest/f:payload/f:contentReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:requester">
<sch:rule context="//f:CommunicationRequest/f:requester">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:encounter">
<sch:rule context="//f:CommunicationRequest/f:encounter">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:CommunicationRequest/f:subject">
<sch:rule context="//f:CommunicationRequest/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,63 +10,63 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Composition</sch:title>
<sch:rule context="f:Composition">
<sch:rule context="//f:Composition">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:text/f:div">
<sch:rule context="//f:Composition/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:identifier/f:period">
<sch:rule context="//f:Composition/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:identifier/f:assigner">
<sch:rule context="//f:Composition/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:subject">
<sch:rule context="//f:Composition/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:author">
<sch:rule context="//f:Composition/f:author">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:attester/f:party">
<sch:rule context="//f:Composition/f:attester/f:party">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:custodian">
<sch:rule context="//f:Composition/f:custodian">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:event/f:period">
<sch:rule context="//f:Composition/f:event/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:event/f:detail">
<sch:rule context="//f:Composition/f:event/f:detail">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:encounter">
<sch:rule context="//f:Composition/f:encounter">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:section">
<sch:rule context="//f:Composition/f:section">
<sch:assert test="exists(f:text) or exists(f:entry) or exists(f:section)">cmp-1: A section must at least one of text, entries, or sub-sections</sch:assert>
<sch:assert test="not(exists(f:emptyReason) and exists(f:entry))">cmp-2: A section can only have an emptyReason if it is empty</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:section/f:text/f:div">
<sch:rule context="//f:Composition/f:section/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Composition/f:section/f:entry">
<sch:rule context="//f:Composition/f:section/f:entry">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,45 +10,45 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>ConceptMap</sch:title>
<sch:rule context="f:ConceptMap">
<sch:rule context="//f:ConceptMap">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:text/f:div">
<sch:rule context="//f:ConceptMap/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:identifier/f:period">
<sch:rule context="//f:ConceptMap/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:identifier/f:assigner">
<sch:rule context="//f:ConceptMap/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:contact/f:telecom">
<sch:rule context="//f:ConceptMap/f:contact/f:telecom">
<sch:assert test="not(exists(f:value)) or exists(f:system)">cpt-2: A system is required if a value is provided.</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:contact/f:telecom/f:period">
<sch:rule context="//f:ConceptMap/f:contact/f:telecom/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:sourceReference">
<sch:rule context="//f:ConceptMap/f:sourceReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:targetReference">
<sch:rule context="//f:ConceptMap/f:targetReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:ConceptMap/f:element/f:target">
<sch:rule context="//f:ConceptMap/f:element/f:target">
<sch:assert test="exists(f:comments) or ((f:equivalence/@value != 'narrower') and (f:equivalence/@value != 'inexact'))">cmd-1: If the map is narrower or inexact, there SHALL be some comments</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,83 +10,81 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Condition</sch:title>
<sch:rule context="f:Condition">
<sch:rule context="//f:Condition">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:text/f:div">
<sch:rule context="//f:Condition/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:identifier/f:period">
<sch:rule context="//f:Condition/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:identifier/f:assigner">
<sch:rule context="//f:Condition/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:patient">
<sch:rule context="//f:Condition/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:encounter">
<sch:rule context="//f:Condition/f:encounter">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:asserter">
<sch:rule context="//f:Condition/f:asserter">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:onsetAge">
<sch:rule context="//f:Condition/f:onsetAge">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:onsetPeriod">
<sch:rule context="//f:Condition/f:onsetPeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:onsetRange">
<sch:rule context="//f:Condition/f:onsetRange">
<sch:assert test="not(exists(f:low/f:value/@value)) or not(exists(f:high/f:value/@value)) or (number(f:low/f:value/@value) &lt;= number(f:high/f:value/@value))">rng-2: If present, low SHALL have a lower value than high</sch:assert>
<sch:assert test="not(exists(f:low/f:comparator) or exists(f:high/f:comparator))">rng-3: Quantity values cannot have a comparator when used in a Range</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:onsetRange/f:low">
<sch:rule context="//f:Condition/f:onsetRange/f:low">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:onsetRange/f:high">
<sch:rule context="//f:Condition/f:onsetRange/f:high">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:abatementAge">
<sch:rule context="//f:Condition/f:abatementAge">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:abatementPeriod">
<sch:rule context="//f:Condition/f:abatementPeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:abatementRange">
<sch:rule context="//f:Condition/f:abatementRange">
<sch:assert test="not(exists(f:low/f:value/@value)) or not(exists(f:high/f:value/@value)) or (number(f:low/f:value/@value) &lt;= number(f:high/f:value/@value))">rng-2: If present, low SHALL have a lower value than high</sch:assert>
<sch:assert test="not(exists(f:low/f:comparator) or exists(f:high/f:comparator))">rng-3: Quantity values cannot have a comparator when used in a Range</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:abatementRange/f:low">
<sch:rule context="//f:Condition/f:abatementRange/f:low">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:abatementRange/f:high">
<sch:rule context="//f:Condition/f:abatementRange/f:high">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:stage">
<sch:rule context="//f:Condition/f:stage">
<sch:assert test="exists(f:summary) or exists(f:assessment)">con-1: Stage SHALL have summary or assessment</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:stage/f:assessment">
<sch:rule context="//f:Condition/f:stage/f:assessment">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:evidence">
<sch:rule context="//f:Condition/f:evidence">
<sch:assert test="exists(f:code) or exists(f:detail)">con-2: evidence SHALL have code or details</sch:assert>
</sch:rule>
<sch:rule context="f:Condition/f:evidence/f:detail">
<sch:rule context="//f:Condition/f:evidence/f:detail">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,26 +10,19 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Conformance</sch:title>
<sch:rule context="f:Conformance">
<sch:rule context="//f:Conformance">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance">
<sch:assert test="count(f:rest)=count(distinct-values(f:rest/f:mode/@value))">cnf-8: There can only be one REST declaration per mode</sch:assert>
<sch:assert test="count(f:document[f:mode='producer'])=count(distinct-values(f:document[f:mode='producer']/f:profile/@value)) and count(f:document[f:mode='consumer'])=count(distinct-values(f:document[f:mode='consumer']/f:profile/@value))">cnf-7: The set of documents must be unique by the combination of profile &amp; mode</sch:assert>
<sch:assert test="count(f:software | f:implementation | f:description) &gt; 0">cnf-2: A Conformance statement SHALL have at least one of description, software, or implementation</sch:assert>
@ -37,43 +30,48 @@
<sch:assert test="not(exists(f:software) or exists(f:implementation)) or (f:kind/@value != 'requirements')">cnf-14: Conformance statements of kind 'requirements' do not have software or implementation elements</sch:assert>
<sch:assert test="not(exists(f:implementation)) or (f:kind/@value != 'capability')">cnf-15: Conformance statements of kind 'software' do not have implementation elements</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:contact/f:telecom">
<sch:rule context="//f:Conformance/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="//f:Conformance/f:contact/f:telecom">
<sch:assert test="not(exists(f:value)) or exists(f:system)">cpt-2: A system is required if a value is provided.</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:contact/f:telecom/f:period">
<sch:rule context="//f:Conformance/f:contact/f:telecom/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:profile">
<sch:rule context="//f:Conformance/f:profile">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:rest">
<sch:rule context="//f:Conformance/f:rest">
<sch:assert test="count(f:resource)=count(distinct-values(f:resource/f:type/@value))">cnf-9: A given resource can only be described once per RESTful mode</sch:assert>
<sch:assert test="count(f:query)=count(distinct-values(f:query/f:name/@value))">cnf-10: A given query can only be described once per RESTful mode</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:rest/f:resource">
<sch:rule context="//f:Conformance/f:rest/f:resource">
<sch:assert test="count(f:operation)=count(distinct-values(f:operation/f:code/@value))">cnf-11: Operation codes must be unique in the context of a resource</sch:assert>
<sch:assert test="count(f:searchParam)=count(distinct-values(f:searchParam/f:name/@value))">cnf-12: Search parameter names must be unique in the context of a resource</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:rest/f:resource/f:profile">
<sch:rule context="//f:Conformance/f:rest/f:resource/f:profile">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:rest/f:resource/f:searchParam">
<sch:rule context="//f:Conformance/f:rest/f:resource/f:searchParam">
<sch:assert test="not(exists(f:chain)) or (f:type/@value = 'reference')">cnf-13: Search parameters can only have chain names when the search parameter type is 'reference'</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:rest/f:operation/f:definition">
<sch:rule context="//f:Conformance/f:rest/f:operation/f:definition">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:messaging">
<sch:rule context="//f:Conformance/f:messaging">
<sch:assert test="exists(f:endpoint) = (f:kind/@value = 'implementation')">cnf-3: Messaging end point is required (and is only permitted) when statement is for an implementation</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:messaging/f:event/f:request">
<sch:rule context="//f:Conformance/f:messaging/f:event/f:request">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:messaging/f:event/f:response">
<sch:rule context="//f:Conformance/f:messaging/f:event/f:response">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Conformance/f:document/f:profile">
<sch:rule context="//f:Conformance/f:document/f:profile">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
<sch:ns prefix="f" uri="http://hl7.org/fhir"/>
<sch:ns prefix="h" uri="http://www.w3.org/1999/xhtml"/>
<sch:pattern>
<sch:title>Contract</sch:title>
<sch:rule context="f:ConsentDirective">
<sch:assert test="count(f:valuedItem) &lt;= 0">valuedItem: maximum cardinality is 0</sch:assert>
</sch:rule>
<sch:rule context="f:ConsentDirective">
<sch:assert test="count(f:binding[x]) &gt;= 1">binding[x]: minimum cardinality is 1</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Contract.term</sch:title>
<sch:rule context="f:ConsentDirective/f:term">
<sch:assert test="count(f:valuedItem) &lt;= 0">valuedItem: maximum cardinality is 0</sch:assert>
</sch:rule>
</sch:pattern>
</sch:schema>

View File

@ -10,123 +10,123 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Contract</sch:title>
<sch:rule context="f:Contract">
<sch:rule context="//f:Contract">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:text/f:div">
<sch:rule context="//f:Contract/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:identifier/f:period">
<sch:rule context="//f:Contract/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:identifier/f:assigner">
<sch:rule context="//f:Contract/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:applies">
<sch:rule context="//f:Contract/f:applies">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:subject">
<sch:rule context="//f:Contract/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:authority">
<sch:rule context="//f:Contract/f:authority">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:domain">
<sch:rule context="//f:Contract/f:domain">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:actor/f:entity">
<sch:rule context="//f:Contract/f:actor/f:entity">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:valuedItem/f:entityReference">
<sch:rule context="//f:Contract/f:valuedItem/f:entityReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:valuedItem/f:identifier/f:period">
<sch:rule context="//f:Contract/f:valuedItem/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:valuedItem/f:identifier/f:assigner">
<sch:rule context="//f:Contract/f:valuedItem/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:valuedItem/f:quantity">
<sch:rule context="//f:Contract/f:valuedItem/f:quantity">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:valuedItem/f:unitPrice">
<sch:rule context="//f:Contract/f:valuedItem/f:unitPrice">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:valuedItem/f:net">
<sch:rule context="//f:Contract/f:valuedItem/f:net">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:signer/f:party">
<sch:rule context="//f:Contract/f:signer/f:party">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:identifier/f:period">
<sch:rule context="//f:Contract/f:term/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:identifier/f:assigner">
<sch:rule context="//f:Contract/f:term/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:applies">
<sch:rule context="//f:Contract/f:term/f:applies">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:subject">
<sch:rule context="//f:Contract/f:term/f:subject">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:actor/f:entity">
<sch:rule context="//f:Contract/f:term/f:actor/f:entity">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:valuedItem/f:entityReference">
<sch:rule context="//f:Contract/f:term/f:valuedItem/f:entityReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:valuedItem/f:identifier/f:period">
<sch:rule context="//f:Contract/f:term/f:valuedItem/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:valuedItem/f:identifier/f:assigner">
<sch:rule context="//f:Contract/f:term/f:valuedItem/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:valuedItem/f:quantity">
<sch:rule context="//f:Contract/f:term/f:valuedItem/f:quantity">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:valuedItem/f:unitPrice">
<sch:rule context="//f:Contract/f:term/f:valuedItem/f:unitPrice">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:term/f:valuedItem/f:net">
<sch:rule context="//f:Contract/f:term/f:valuedItem/f:net">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:bindingAttachment">
<sch:rule context="//f:Contract/f:bindingAttachment">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:bindingReference">
<sch:rule context="//f:Contract/f:bindingReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:friendly/f:contentAttachment">
<sch:rule context="//f:Contract/f:friendly/f:contentAttachment">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:friendly/f:contentReference">
<sch:rule context="//f:Contract/f:friendly/f:contentReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:legal/f:contentAttachment">
<sch:rule context="//f:Contract/f:legal/f:contentAttachment">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:legal/f:contentReference">
<sch:rule context="//f:Contract/f:legal/f:contentReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:rule/f:contentAttachment">
<sch:rule context="//f:Contract/f:rule/f:contentAttachment">
<sch:assert test="not(exists(f:data)) or exists(f:contentType)">att-1: It the Attachment has data, it SHALL have a contentType</sch:assert>
</sch:rule>
<sch:rule context="f:Contract/f:rule/f:contentReference">
<sch:rule context="//f:Contract/f:rule/f:contentReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,42 +10,42 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Contraindication</sch:title>
<sch:rule context="f:Contraindication">
<sch:rule context="//f:Contraindication">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:text/f:div">
<sch:rule context="//f:Contraindication/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:patient">
<sch:rule context="//f:Contraindication/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:implicated">
<sch:rule context="//f:Contraindication/f:implicated">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:author">
<sch:rule context="//f:Contraindication/f:author">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:identifier/f:period">
<sch:rule context="//f:Contraindication/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:identifier/f:assigner">
<sch:rule context="//f:Contraindication/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Contraindication/f:mitigation/f:author">
<sch:rule context="//f:Contraindication/f:mitigation/f:author">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,60 +10,60 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Coverage</sch:title>
<sch:rule context="f:Coverage">
<sch:rule context="//f:Coverage">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:text/f:div">
<sch:rule context="//f:Coverage/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:issuer">
<sch:rule context="//f:Coverage/f:issuer">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:bin/f:period">
<sch:rule context="//f:Coverage/f:bin/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:bin/f:assigner">
<sch:rule context="//f:Coverage/f:bin/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:period">
<sch:rule context="//f:Coverage/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:subscriberId/f:period">
<sch:rule context="//f:Coverage/f:subscriberId/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:subscriberId/f:assigner">
<sch:rule context="//f:Coverage/f:subscriberId/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:identifier/f:period">
<sch:rule context="//f:Coverage/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:identifier/f:assigner">
<sch:rule context="//f:Coverage/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:subscriber">
<sch:rule context="//f:Coverage/f:subscriber">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:network/f:period">
<sch:rule context="//f:Coverage/f:network/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:network/f:assigner">
<sch:rule context="//f:Coverage/f:network/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Coverage/f:contract">
<sch:rule context="//f:Coverage/f:contract">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,43 +10,41 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>DataElement</sch:title>
<sch:rule context="f:DataElement">
<sch:rule context="//f:DataElement">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:text/f:div">
<sch:rule context="//f:DataElement/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:identifier/f:period">
<sch:rule context="//f:DataElement/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:identifier/f:assigner">
<sch:rule context="//f:DataElement/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:contact/f:telecom">
<sch:rule context="//f:DataElement/f:contact/f:telecom">
<sch:assert test="not(exists(f:value)) or exists(f:system)">cpt-2: A system is required if a value is provided.</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:contact/f:telecom/f:period">
<sch:rule context="//f:DataElement/f:contact/f:telecom/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element">
<sch:rule context="//f:DataElement/f:element">
<sch:assert test="not(exists(f:base))">dae-1: No base allowed</sch:assert>
<sch:assert test="not(exists(f:slicing))">dae-2: No slicing allowed</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element">
<sch:assert test="(not(f:max/@value) and not(f:min/@value)) or (f:max/@value = '*') or (f:max/@value &gt;= f:min/@value)">eld-2: Min &lt;= Max</sch:assert>
<sch:assert test="not(exists(f:min)) or not(exists(f:max)) or (not(f:max/@value) and not(f:min/@value)) or (f:max/@value = '*') or (f:max/@value &gt;= f:min/@value)">eld-2: Min &lt;= Max</sch:assert>
<sch:assert test="not(exists(f:nameReference) and exists(f:*[starts-with(local-name(.), 'value')]))">eld-5: Either a namereference or a fixed value (but not both) is permitted</sch:assert>
<sch:assert test="not(exists(f:*[starts-with(local-name(.), 'pattern')])) or (count(f:type)=1 )">eld-7: Pattern may only be specified if there is one type</sch:assert>
<sch:assert test="not(exists(f:*[starts-with(local-name(.), 'fixed')])) or (count(f:type)=1 )">eld-6: Fixed value may only be specified if there is one type</sch:assert>
@ -56,24 +54,24 @@
<sch:assert test="not(exists(for $type in f:type return $type/preceding-sibling::f:type[f:code/@value=$type/f:code/@value and f:profile/@value = $type/f:profile/@value]))">eld-13: Types must be unique by the combination of code and profile</sch:assert>
<sch:assert test="not(exists(f:*[starts-with(local-name(.), 'fixed')])) or not(exists(f:meaningWhenMissing))">eld-15: default value and meaningWhenMissing are mutually exclusive</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element/f:slicing">
<sch:rule context="//f:DataElement/f:element/f:slicing">
<sch:assert test="(f:discriminator) or (f:definition)">eld-1: If there are no discriminators, there must be a definition</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element/f:max">
<sch:rule context="//f:DataElement/f:element/f:max">
<sch:assert test="@value='*' or (normalize-space(@value)!='' and normalize-space(translate(@value, '0123456789',''))='')">eld-3: Max SHALL be a number or &quot;*&quot;</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element/f:type">
<sch:rule context="//f:DataElement/f:element/f:type">
<sch:assert test="not(exists(f:aggregation)) or exists(f:code[@value = 'Reference'])">eld-4: Aggregation may only be specified if one of the allowed types for the element is a resource</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element/f:binding">
<sch:rule context="//f:DataElement/f:element/f:binding">
<sch:assert test="(exists(f:valueSetUri) or exists(f:valueSetReference)) or exists(f:description)">eld-10: provide either a reference or a description (or both)</sch:assert>
<sch:assert test="not(f:conformance/@value='example' and f:isExtensible/@value='false')">eld-9: Example value sets are always extensible</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element/f:binding/f:valueSetUri">
<sch:rule context="//f:DataElement/f:element/f:binding/f:valueSetUri">
<sch:assert test="starts-with(@value, 'http:') or starts-with(@value, 'https:')">eld-12: uri SHALL start with http:// or https://</sch:assert>
</sch:rule>
<sch:rule context="f:DataElement/f:element/f:binding/f:valueSetReference">
<sch:rule context="//f:DataElement/f:element/f:binding/f:valueSetReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,48 +10,48 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Device</sch:title>
<sch:rule context="f:Device">
<sch:rule context="//f:Device">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:text/f:div">
<sch:rule context="//f:Device/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:identifier/f:period">
<sch:rule context="//f:Device/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:identifier/f:assigner">
<sch:rule context="//f:Device/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:note/f:authorReference">
<sch:rule context="//f:Device/f:note/f:authorReference">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:owner">
<sch:rule context="//f:Device/f:owner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:location">
<sch:rule context="//f:Device/f:location">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:patient">
<sch:rule context="//f:Device/f:patient">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:contact">
<sch:rule context="//f:Device/f:contact">
<sch:assert test="not(exists(f:value)) or exists(f:system)">cpt-2: A system is required if a value is provided.</sch:assert>
</sch:rule>
<sch:rule context="f:Device/f:contact/f:period">
<sch:rule context="//f:Device/f:contact/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,42 +10,42 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>DeviceComponent</sch:title>
<sch:rule context="f:DeviceComponent">
<sch:rule context="//f:DeviceComponent">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:text/f:div">
<sch:rule context="//f:DeviceComponent/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:identifier/f:period">
<sch:rule context="//f:DeviceComponent/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:identifier/f:assigner">
<sch:rule context="//f:DeviceComponent/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:source">
<sch:rule context="//f:DeviceComponent/f:source">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:parent">
<sch:rule context="//f:DeviceComponent/f:parent">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:productionSpecification/f:componentId/f:period">
<sch:rule context="//f:DeviceComponent/f:productionSpecification/f:componentId/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceComponent/f:productionSpecification/f:componentId/f:assigner">
<sch:rule context="//f:DeviceComponent/f:productionSpecification/f:componentId/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

View File

@ -10,65 +10,64 @@
fhir-invariants.sch (the contents are identical; only include those
resources relevant to your implementation).
-->
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>Global</sch:title>
<sch:rule context="//f:*">
<sch:assert test="@value|f:*|h:div">global-1: All FHIR elements must have a @value or children</sch:assert>
</sch:rule>
</sch:pattern>
<sch:pattern>
<sch:title>DeviceMetric</sch:title>
<sch:rule context="f:DeviceMetric">
<sch:rule context="//f:DeviceMetric">
<sch:assert test="not(parent::f:contained and f:contained)">dom-2: If the resource is contained in another resource, it SHALL NOT contain nested Resources</sch:assert>
<sch:assert test="not(parent::f:contained and f:text)">dom-1: If the resource is contained in another resource, it SHALL NOT contain any narrative</sch:assert>
<sch:assert test="not(exists(f:contained/f:meta/f:versionId)) and not(exists(f:contained/f:meta/f:lastUpdated))">dom-4: If a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated</sch:assert>
<sch:assert test="not(exists(for $id in f:contained/*/@id return $id[not(ancestor::f:contained/parent::*/descendant::f:reference/@value=concat('#', $id))]))">dom-3: If the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:text/f:div">
<sch:rule context="//f:DeviceMetric/f:text/f:div">
<sch:assert test="not(descendant-or-self::*/@*[not(name(.)=('abbr', 'accesskey', 'align', 'alt', 'axis', 'bgcolor', 'border', 'cellhalign', 'cellpadding', 'cellspacing', 'cellvalign', 'char', 'charoff', 'charset', 'cite', 'class', 'colspan', 'compact', 'coords', 'dir', 'frame', 'headers', 'height', 'href', 'hreflang', 'hspace', 'id', 'lang', 'longdesc', 'name', 'nowrap', 'rel', 'rev', 'rowspan', 'rules', 'scope', 'shape', 'span', 'src', 'start', 'style', 'summary', 'tabindex', 'title', 'type', 'valign', 'value', 'vspace', 'width'))])">txt-3: The narrative SHALL contain only the basic html formatting attributes described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="not(descendant-or-self::*[not(local-name(.)=('a', 'abbr', 'acronym', 'b', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'colgroup', 'dd', 'dfn', 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var'))])">txt-1: The narrative SHALL contain only the basic html formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, &lt;a&gt; elements (either name or href), images and internally contained style attributes</sch:assert>
<sch:assert test="descendant::text()[normalize-space(.)!=''] or descendant::h:img[@src]">txt-2: The narrative SHALL have some non-whitespace content</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:identifier/f:period">
<sch:rule context="//f:DeviceMetric/f:identifier/f:period">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:identifier/f:assigner">
<sch:rule context="//f:DeviceMetric/f:identifier/f:assigner">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:source">
<sch:rule context="//f:DeviceMetric/f:source">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:parent">
<sch:rule context="//f:DeviceMetric/f:parent">
<sch:assert test="not(starts-with(f:reference/@value, '#')) or exists(ancestor::*[self::f:entry or self::f:parameter]/f:resource/f:*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')]|/*/f:contained/f:*[f:id/@value=substring-after(current()/f:reference/@value, '#')])">ref-1: SHALL have a local reference if the resource is provided inline</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat">
<sch:assert test="not(exists(f:periodMax)) or exists(period)">tim-6: If there's a periodMax, there must be a period</sch:assert>
<sch:assert test="not(exists(f:durationMax)) or exists(duration)">tim-7: If there's a durationMax, there must be a duration</sch:assert>
<sch:assert test="not(exists(f:duration)) or exists(f:durationUnits)">tim-1: if there's a duration, there needs to be duration units</sch:assert>
<sch:assert test="not(exists(f:period)) or exists(f:periodUnits)">tim-2: if there's a period, there needs to be duration units</sch:assert>
<sch:assert test="not(exists(f:frequency)) or not(exists(f:when))">tim-3: Either frequency or when can exist, not both</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsDuration">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsDuration">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsRange">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsRange">
<sch:assert test="not(exists(f:low/f:value/@value)) or not(exists(f:high/f:value/@value)) or (number(f:low/f:value/@value) &lt;= number(f:high/f:value/@value))">rng-2: If present, low SHALL have a lower value than high</sch:assert>
<sch:assert test="not(exists(f:low/f:comparator) or exists(f:high/f:comparator))">rng-3: Quantity values cannot have a comparator when used in a Range</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsRange/f:low">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsRange/f:low">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsRange/f:high">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsRange/f:high">
<sch:assert test="not(exists(f:code)) or exists(f:system)">qty-3: If a code for the units is present, the system SHALL also be present</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsPeriod">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:boundsPeriod">
<sch:assert test="not(exists(f:start)) or not(exists(f:end)) or (f:start/@value &lt;= f:end/@value)">per-1: If present, start SHALL have a lower value than end</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:duration">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:duration">
<sch:assert test="@value &gt;= 0 or not(@value)">tim-4: duration SHALL be a non-negative value</sch:assert>
</sch:rule>
<sch:rule context="f:DeviceMetric/f:measurementPeriod/f:repeat/f:period">
<sch:rule context="//f:DeviceMetric/f:measurementPeriod/f:repeat/f:period">
<sch:assert test="@value &gt;= 0 or not(@value)">tim-5: period SHALL be a non-negative value</sch:assert>
</sch:rule>
</sch:pattern>
</sch:pattern>
</sch:schema>

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