From a8e248036e73e54d0a88f4e18948403bb7cd35b2 Mon Sep 17 00:00:00 2001 From: Sebastien Riviere Date: Mon, 10 Jul 2017 12:38:33 +0200 Subject: [PATCH 1/2] Fix STU3 validation: find correct extension profile, use custom datatype profile, allow to disable terminology checks --- .../hl7/fhir/dstu3/elementmodel/Property.java | 24 +++++- .../fhir/dstu3/elementmodel/XmlParser.java | 77 ++++++++++++++++++- .../validation/FhirInstanceValidator.java | 17 ++++ .../FhirInstanceValidatorDstu3Test.java | 8 ++ 4 files changed, 120 insertions(+), 6 deletions(-) diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/Property.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/Property.java index 1ee43f96585..f64f2542344 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/Property.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/Property.java @@ -2,6 +2,7 @@ package org.hl7.fhir.dstu3.elementmodel; import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.dstu3.conformance.ProfileUtilities; import org.hl7.fhir.dstu3.context.IWorkerContext; @@ -203,7 +204,7 @@ public class Property { ElementDefinition ed = definition; StructureDefinition sd = structure; List children = ProfileUtilities.getChildMap(sd, ed); - if (children.isEmpty()) { + if (children.isEmpty() || isElementWithOnlyExtension(ed, children)) { // ok, find the right definitions String t = null; if (ed.getType().size() == 1) @@ -240,7 +241,13 @@ public class Property { } } if (!"xhtml".equals(t)) { - sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+t); + final String url; + if (StringUtils.isNotBlank(ed.getType().get(0).getProfile())) { + url = ed.getType().get(0).getProfile(); + } else { + url = "http://hl7.org/fhir/StructureDefinition/" + t; + } + sd = context.fetchResource(StructureDefinition.class, url); if (sd == null) throw new DefinitionException("Unable to find type '"+t+"' for name '"+elementName+"' on property "+definition.getPath()); children = ProfileUtilities.getChildMap(sd, sd.getSnapshot().getElement().get(0)); @@ -340,5 +347,18 @@ public class Property { return context; } + private boolean isElementWithOnlyExtension(final ElementDefinition ed, final List children) { + boolean result = false; + if (!ed.getType().isEmpty()) { + result = true; + for (final ElementDefinition ele : children) { + if (!ele.getPath().contains("extension")) { + result = false; + break; + } + } + } + return result; + } } diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java index b1490fb9abb..179613b5d4a 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java @@ -23,6 +23,7 @@ import org.hl7.fhir.dstu3.elementmodel.Element.SpecialElement; import org.hl7.fhir.dstu3.formats.FormatUtilities; import org.hl7.fhir.dstu3.formats.IParser.OutputStyle; import org.hl7.fhir.dstu3.model.DateTimeType; +import org.hl7.fhir.dstu3.model.ElementDefinition; import org.hl7.fhir.dstu3.model.ElementDefinition.PropertyRepresentation; import org.hl7.fhir.dstu3.model.Enumeration; import org.hl7.fhir.dstu3.model.StructureDefinition; @@ -45,6 +46,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; +import org.apache.commons.lang3.StringUtils; public class XmlParser extends ParserBase { private boolean allowXsiLocation; @@ -250,7 +252,13 @@ public class XmlParser extends ParserBase { Node child = node.getFirstChild(); while (child != null) { if (child.getNodeType() == Node.ELEMENT_NODE) { - Property property = getElementProp(properties, child.getLocalName()); + final Property property; + if (StringUtils.contains(child.getLocalName(), "extension")) { + property = getExtensionProp(properties, child); + } else { + property = getElementProp(properties, child.getLocalName()); + } + if (property != null) { if (!property.isChoice() && "xhtml".equals(property.getType())) { XhtmlNode xhtml = new XhtmlParser().setValidatorMode(true).parseHtmlNode((org.w3c.dom.Element) child); @@ -293,6 +301,48 @@ public class XmlParser extends ParserBase { } } + private Property getExtensionProp(final List properties, final Node child) { + // get the correct property corresponding to the extension + Property property = null; + final Node extensionNode = child.getAttributes().getNamedItem("url"); + if (extensionNode != null) { + for (final Property prop : properties) { + if (prop.getName().contains("extension")) { + if (findExtension(prop.getDefinition(), extensionNode.getNodeValue())) { + property = prop; + break; + } + } + } + } + if (property == null) { + property = getElementProp(properties, child.getLocalName()); + } + + return isDefaultExtensionElement(property) ? null : property; + } + + private boolean isDefaultExtensionElement(final Property property) { + if (property == null) { + return false; + } + final ElementDefinition ed = property.getDefinition(); + return StringUtils.contains(ed.getPath(), "extension") && ed.getType().isEmpty() && !ed.getSlicing().isEmpty(); + } + + private boolean findExtension(final ElementDefinition definition, final String localName) { + boolean result = false; + if(StringUtils.isNotBlank(localName)) { + for (ElementDefinition.TypeRefComponent type:definition.getType()) { + if(localName.equals(type.getProfile())) { + result = true; + break; + } + } + } + return result; + } + private Property getElementProp(List properties, String nodeName) { List propsSortedByLongestFirst = new ArrayList(properties); // sort properties according to their name longest first, so .requestOrganizationReference comes first before .request[x] @@ -337,15 +387,34 @@ public class XmlParser extends ParserBase { private void parseResource(String string, org.w3c.dom.Element container, Element parent, Property elementProperty) throws FHIRFormatError, DefinitionException, FHIRException, IOException { org.w3c.dom.Element res = XMLUtil.getFirstChild(container); - String name = res.getLocalName(); - StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+name); + final String profile = findProfile(res); + final StructureDefinition sd = context.fetchResource(StructureDefinition.class, profile); if (sd == null) throw new FHIRFormatError("Contained resource does not appear to be a FHIR resource (unknown name '"+res.getLocalName()+"')"); parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(parent.getProperty()), elementProperty); - parent.setType(name); + parent.setType(res.getLocalName()); parseChildren(res.getLocalName(), res, parent); } + private String findProfile(final org.w3c.dom.Element res) { + String url = null; + for (int i = 0; i < res.getChildNodes().getLength(); i++) { + final Node child = res.getChildNodes().item(i); + if ("meta".equals(child.getLocalName())) { + for (int j = 0; j < child.getChildNodes().getLength(); j++) { + final Node subChild = child.getChildNodes().item(j); + if ("profile".equals(subChild.getLocalName())) { + final Node profileNode = subChild.getAttributes().getNamedItem("value"); + url = profileNode.getNodeValue(); + break; + } + } + break; + } + } + return StringUtils.isNotBlank(url) ? url : "http://hl7.org/fhir/StructureDefinition/" + res.getLocalName(); + } + private void reapComments(org.w3c.dom.Element element, Element context) { Node node = element.getPreviousSibling(); while (node != null && node.getNodeType() != Node.ELEMENT_NODE) { diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java index 91154b6773f..41868853974 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.java @@ -44,6 +44,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid private DocumentBuilderFactory myDocBuilderFactory; private StructureDefinition myStructureDefintion; private IValidationSupport myValidationSupport; + private boolean noTerminologyChecks = false; /** * Constructor @@ -127,6 +128,21 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid myAnyExtensionsAllowed = theAnyExtensionsAllowed; } + /** + * If set to {@literal true} (default is false) the valueSet will not be validate + */ + public boolean isNoTerminologyChecks() { + return noTerminologyChecks; + } + + /** + * If set to {@literal true} (default is false) the valueSet will not be validate + */ + public void setNoTerminologyChecks(final boolean theNoTerminologyChecks) { + noTerminologyChecks = theNoTerminologyChecks; + } + + /** * Sets the "best practice warning level". When validating, any deviations from best practices will be reported at * this level. @@ -171,6 +187,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid v.setBestPracticeWarningLevel(getBestPracticeWarningLevel()); v.setAnyExtensionsAllowed(isAnyExtensionsAllowed()); v.setResourceIdRule(IdStatus.OPTIONAL); + v.setNoTerminologyChecks(isNoTerminologyChecks()); List messages = new ArrayList(); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/FhirInstanceValidatorDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/FhirInstanceValidatorDstu3Test.java index 0f745eb9648..73f0de6468e 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/FhirInstanceValidatorDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/validation/FhirInstanceValidatorDstu3Test.java @@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -838,6 +839,13 @@ public class FhirInstanceValidatorDstu3Test { assertEquals(0, all.size()); } + @Test + public void testIsNoTerminologyChecks() { + assertFalse(myInstanceVal.isNoTerminologyChecks()); + myInstanceVal.setNoTerminologyChecks(true); + assertTrue(myInstanceVal.isNoTerminologyChecks()); + } + @Test @Ignore public void testValidateStructureDefinition() throws IOException { From ecac0ffb5fff8ce8b138306ad6444aefb7a96a94 Mon Sep 17 00:00:00 2001 From: Sebastien Riviere Date: Fri, 14 Jul 2017 12:51:19 +0200 Subject: [PATCH 2/2] Add junit test --- .../fhir/dstu3/elementmodel/PropertyTest.java | 65 +++ .../src/test/resources/customPatientSd.xml | 447 ++++++++++++++++++ 2 files changed, 512 insertions(+) create mode 100644 hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/elementmodel/PropertyTest.java create mode 100644 hapi-fhir-structures-dstu3/src/test/resources/customPatientSd.xml diff --git a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/elementmodel/PropertyTest.java b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/elementmodel/PropertyTest.java new file mode 100644 index 00000000000..63323ab1911 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/elementmodel/PropertyTest.java @@ -0,0 +1,65 @@ +package org.hl7.fhir.dstu3.elementmodel; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import org.apache.commons.io.IOUtils; +import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport; +import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext; +import org.hl7.fhir.dstu3.model.ElementDefinition; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.hl7.fhir.exceptions.DefinitionException; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Created by axemj on 14/07/2017. + */ +public class PropertyTest { + + private static final FhirContext ourCtx = FhirContext.forDstu3(); + private Property property; + private StructureDefinition sd; + private HapiWorkerContext workerContext; + + @Before + public void setUp() throws IOException { + final String sdString = IOUtils.toString(getClass().getResourceAsStream("/customPatientSd.xml"), StandardCharsets.UTF_8); + final IParser parser = ourCtx.newXmlParser(); + sd = parser.parseResource(StructureDefinition.class, sdString); + workerContext = new HapiWorkerContext(ourCtx, new DefaultProfileValidationSupport()); + } + + @Test + public void getChildPropertiesPrimitiveTest() throws DefinitionException { + final ElementDefinition ed = sd.getSnapshot().getElement().get(1); + property = new Property(workerContext, ed, sd); + final List result = property.getChildProperties("id", null); + assertFalse(result.isEmpty()); + assertEquals(3, result.size()); + assertEquals("id.id", result.get(0).getDefinition().getPath()); + } + + @Test + public void getChildPropertiesOnlyExtensionElementTest() throws DefinitionException { + final ElementDefinition ed = sd.getSnapshot().getElement().get(23); + property = new Property(workerContext, ed, sd); + final List result = property.getChildProperties("birthdate", null); + assertFalse(result.isEmpty()); + assertEquals(3, result.size()); + assertEquals("date.id", result.get(0).getDefinition().getPath()); + } + + @Test(expected = Error.class) + public void getChildPropertiesErrorTest() throws DefinitionException { + final ElementDefinition ed = sd.getSnapshot().getElement().get(7); + property = new Property(workerContext, ed, sd); + property.getChildProperties("birthdate", null); + } +} diff --git a/hapi-fhir-structures-dstu3/src/test/resources/customPatientSd.xml b/hapi-fhir-structures-dstu3/src/test/resources/customPatientSd.xml new file mode 100644 index 00000000000..592badb62ab --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/resources/customPatientSd.xml @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <status value="draft"/> + <experimental value="false"/> + <date value="2017-07-14T08:37:31+02:00"/> + <publisher value="Me"/> + <contact> + <name value="test"/> + <telecom> + <system value="email"/> + <value value="test@test.com"/> + <use value="work"/> + </telecom> + </contact> + <description value="Information about an individual receiving health care services"/> + <useContext> + <code> + <system value="urn:iso:std:iso:3166"/> + <code value="FR"/> + <display value="France"/> + </code> + </useContext> + <fhirVersion value="3.0.1"/> + <kind value="resource"/> + <abstract value="false"/> + <type value="Patient"/> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/patient"/> + <derivation value="constraint"/> + <snapshot> + <element> + <path value="Patient"/> + </element> + <element> + <path value="Patient.id"/> + <short value="Logical id of this artifact"/> + <definition value="The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="id"/> + </type> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.meta"/> + <short value="Metadata about the resource"/> + <definition value="The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content may not always be associated with version changes to the resource."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Meta"/> + </type> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.text"/> + <max value="0"/> + </element> + <element> + <path value="Patient.contained"/> + <max value="0"/> + </element> + <element> + <path value="Patient.implicitRules"/> + <max value="0"/> + </element> + <element> + <path value="Patient.language"/> + <short value="Language of the resource content"/> + <definition value="The base language in which the resource is written."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="code"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + </element> + <element> + <path value="Patient.extension"/> + <slicing> + <discriminator> + <type value="value"/> + <path value="url"/> + </discriminator> + <rules value="open"/> + </slicing> + <definition value="May be used to represent additional information that is not part of the basic definition of the element."/> + </element> + <element> + <path value="Patient.extension"/> + <short value="identityReliabilityCode"/> + <definition value="The patient identity reliability code"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/identityReliabilityCode"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + <binding> + <strength value="required"/> + <valueSetReference> + <reference value="ValueSet/IDENTITYSTATUS"/> + </valueSetReference> + </binding> + </element> + <element> + <path value="Patient.extension"/> + <short value="lunarBirthDate"/> + <definition value="The patient lunar's birth date"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/lunarBirthDate"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + </element> + <element> + <path value="Patient.extension"/> + <short value="legalStatus"/> + <definition value="The patient legal status"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/legalStatus"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + <binding> + <strength value="required"/> + <valueSetReference> + <reference value="ValueSet/ADT_LEGALSTATUS"/> + </valueSetReference> + </binding> + </element> + <element> + <path value="Patient.extension"/> + <short value="familyStatus"/> + <definition value="The patient family status"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/familyStatus"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + <binding> + <strength value="required"/> + <valueSetReference> + <reference value="ValueSet/FAMILYSTATUS"/> + </valueSetReference> + </binding> + </element> + <element> + <path value="Patient.extension"/> + <short value="birthPlace"/> + <definition value="The patient birth place"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://hl7.org/fhir/StructureDefinition/birthPlace"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + </element> + <element> + <path value="Patient.extension"/> + <short value="homeless"/> + <definition value="The patient being homeless, true if homeless"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/homeless"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + </element> + <element> + <path value="Patient.extension"/> + <short value="phoneConsent"/> + <definition value="The patient consent on phone level"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/phoneConsent"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + <binding> + <strength value="required"/> + <valueSetReference> + <reference value="ValueSet/ADT_CONTACT_CONSENT_MOBILE"/> + </valueSetReference> + </binding> + </element> + <element> + <path value="Patient.extension"/> + <short value="emailConsent"/> + <definition value="The patient consent on email level"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/emailConsent"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + <binding> + <strength value="required"/> + <valueSetReference> + <reference value="ValueSet/ADT_CONTACT_CONSENT_EMAIL"/> + </valueSetReference> + </binding> + </element> + <element> + <path value="Patient.extension"/> + <short value="comments"/> + <definition value="The patient comments"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/comments"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + </element> + <element> + <path value="Patient.extension"/> + <short value="nationality"/> + <definition value="The patient nationality"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://hl7.org/fhir/StructureDefinition/patient-nationality"/> + </type> + <isModifier value="false"/> + </element> + <element> + <path value="Patient.identifier"/> + <short value="An identifier for this patient"/> + <definition value="An identifier for this patient."/> + <min value="0"/> + <max value="*"/> + <type> + <code value="Identifier"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/Identifier"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.active"/> + <max value="0"/> + </element> + <element> + <path value="Patient.name"/> + <short value="A name associated with the patient"/> + <definition value="A name associated with the individual."/> + <min value="0"/> + <max value="*"/> + <type> + <code value="HumanName"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/HumanName"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.telecom"/> + <short value="A contact detail for the individual"/> + <definition value="A contact detail (e.g. a telephone number or an email address) by which the individual may be contacted."/> + <min value="0"/> + <max value="*"/> + <type> + <code value="ContactPoint"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/ContactPoint"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.gender"/> + <short value="male | female | other | unknown"/> + <definition value="Administrative Gender - the gender that the patient is considered to have for administration and record keeping purposes."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="code"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.birthDate"/> + <short value="The date of birth for the individual"/> + <definition value="The date of birth for the individual."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="date"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.birthDate.extension"/> + <slicing> + <discriminator> + <type value="value"/> + <path value="url"/> + </discriminator> + <rules value="open"/> + </slicing> + </element> + <element> + <path value="Patient.birthDate.extension"/> + <short value="approximateBirthDate"/> + <definition value="Flag to indicate if the birthdate is approximative or not"/> + <min value="0"/> + <max value="1"/> + <type> + <code value="Extension"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/birthdate-approximative"/> + </type> + <isModifier value="false"/> + </element> + <element> + <path value="Patient.deceased[x]"/> + <short value="Indicates if the individual is deceased or not"/> + <definition value="Indicates if the individual is deceased or not."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="boolean"/> + </type> + <type> + <code value="dateTime"/> + </type> + <isModifier value="true"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.address"/> + <short value="Addresses for the individual"/> + <definition value="Addresses for the individual."/> + <min value="0"/> + <max value="*"/> + <type> + <code value="Address"/> + <profile value="http://www.myServer.com/fhir/StructureDefinition/Address"/> + </type> + <isModifier value="false"/> + <isSummary value="true"/> + </element> + <element> + <path value="Patient.maritalStatus"/> + <max value="0"/> + </element> + <element> + <path value="Patient.multipleBirth[x]"/> + <short value="Whether patient is part of a multiple birth"/> + <definition value="Indicates whether the patient is part of a multiple (bool) or indicates the actual birth order (integer)."/> + <min value="0"/> + <max value="1"/> + <type> + <code value="boolean"/> + </type> + <type> + <code value="integer"/> + </type> + <isModifier value="false"/> + <isSummary value="false"/> + </element> + <element> + <path value="Patient.photo"/> + <max value="0"/> + </element> + <element> + <path value="Patient.contact"/> + <max value="0"/> + </element> + <element> + <path value="Patient.animal"/> + <max value="0"/> + </element> + <element> + <path value="Patient.communication"/> + <max value="0"/> + </element> + <element> + <path value="Patient.generalPractitioner"/> + <max value="0"/> + </element> + <element> + <path value="Patient.managingOrganization"/> + <max value="0"/> + </element> + <element> + <path value="Patient.link"/> + <max value="0"/> + </element> + </snapshot> +</StructureDefinition> +