From 3317d8bd86d26107c5c4cd24c80a3387c4667fc0 Mon Sep 17 00:00:00 2001 From: "dotasek.dev" Date: Mon, 6 May 2024 17:03:08 -0400 Subject: [PATCH 1/7] Add shim interfaces and classes for CR project compatibility --- .../fhir/r5/context/BaseWorkerContext.java | 6 +- .../hl7/fhir/r5/context/IWorkerContext.java | 16 +- .../fhir/r5/context/SimpleWorkerContext.java | 2 +- .../org/hl7/fhir/r5/model/ExpressionNode.java | 228 ++++++++++++++++++ .../org/hl7/fhir/r5/utils/FHIRPathEngine.java | 30 +++ .../utilities/TerminologyServiceOptions.java | 44 ++-- .../validation/ValidationOptions.java | 2 + 7 files changed, 301 insertions(+), 27 deletions(-) create mode 100644 org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java create mode 100644 org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index e408f6b35..49521c97d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -277,7 +277,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte protected boolean canRunWithoutTerminology; protected boolean noTerminologyServer; private int expandCodesLimit = 1000; - protected ILoggingService logger = new SystemOutLoggingService(); + protected org.hl7.fhir.r5.context.ILoggingService logger = new SystemOutLoggingService(); protected Parameters expParameters; private Map packages = new HashMap<>(); @@ -1985,7 +1985,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte this.canRunWithoutTerminology = canRunWithoutTerminology; } - public void setLogger(@Nonnull ILoggingService logger) { + public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger) { this.logger = logger; } @@ -2810,7 +2810,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } @Override - public ILoggingService getLogger() { + public org.hl7.fhir.r5.context.ILoggingService getLogger() { return logger; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java index 3a58fd8ba..256868682 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java @@ -109,6 +109,18 @@ import javax.annotation.Nonnull; public interface IWorkerContext { + /** + @deprecated This interface only exists to provide backward compatibility for the following two projects: + clinical-reasoning + clinical_quality-language + + Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards + compatibility with core version 6.1.2.2 + **/ + @Deprecated(forRemoval = true) + public interface ILoggingService extends org.hl7.fhir.r5.context.ILoggingService{ + + } public class OIDDefinitionComparer implements Comparator { @Override @@ -630,8 +642,8 @@ public interface IWorkerContext { // todo: figure these out public Map getNSUrlMap(); - public void setLogger(@Nonnull ILoggingService logger); - public ILoggingService getLogger(); + public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger); + public org.hl7.fhir.r5.context.ILoggingService getLogger(); public boolean isNoTerminologyServer(); public Set getCodeSystemsUsed(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index 66581d063..0b09ee369 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -214,7 +214,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon private final boolean allowLoadingDuplicates; @With - private final ILoggingService loggingService; + private final org.hl7.fhir.r5.context.ILoggingService loggingService; public SimpleWorkerContextBuilder() { cacheTerminologyClientErrors = false; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java new file mode 100644 index 000000000..b37397775 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/ExpressionNode.java @@ -0,0 +1,228 @@ +package org.hl7.fhir.r5.model; + +import org.hl7.fhir.r5.fhirpath.TypeDetails; +import org.hl7.fhir.utilities.SourceLocation; + +import java.util.List; + +/** + @deprecated This interface only exists to provide backward compatibility for the following two projects: + clinical-reasoning + clinical_quality-language + + Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards + compatibility with core version 6.1.2.2 + **/ +public class ExpressionNode extends org.hl7.fhir.r5.fhirpath.ExpressionNode{ + + private final org.hl7.fhir.r5.fhirpath.ExpressionNode wrappedExpressionNode; + public ExpressionNode(int uniqueId) { + super(0); + wrappedExpressionNode = new org.hl7.fhir.r5.fhirpath.ExpressionNode(uniqueId); + } + + public ExpressionNode(org.hl7.fhir.r5.fhirpath.ExpressionNode wrappedExpressionNode) { + super(0); + this.wrappedExpressionNode = wrappedExpressionNode; + } + + @Override + public String toString() { + return wrappedExpressionNode.toString(); + } + + @Override + public String getName() { + return wrappedExpressionNode.getName(); + } + + @Override + public void setName(String name) { + wrappedExpressionNode.setName(name); + } + + @Override + public Base getConstant() { + return wrappedExpressionNode.getConstant(); + } + + @Override + public void setConstant(Base constant) { + wrappedExpressionNode.setConstant(constant); + } + + @Override + public Function getFunction() { + return wrappedExpressionNode.getFunction(); + } + + @Override + public void setFunction(Function function) { + wrappedExpressionNode.setFunction(function); + } + + @Override + public boolean isProximal() { + return wrappedExpressionNode.isProximal(); + } + + @Override + public void setProximal(boolean proximal) { + wrappedExpressionNode.setProximal(proximal); + } + + @Override + public Operation getOperation() { + return wrappedExpressionNode.getOperation(); + } + + @Override + public void setOperation(Operation operation) { + wrappedExpressionNode.setOperation(operation); + } + + @Override + public org.hl7.fhir.r5.fhirpath.ExpressionNode getInner() { + return wrappedExpressionNode.getInner(); + } + + @Override + public void setInner(org.hl7.fhir.r5.fhirpath.ExpressionNode value) { + wrappedExpressionNode.setInner(value); + } + + @Override + public org.hl7.fhir.r5.fhirpath.ExpressionNode getOpNext() { + return wrappedExpressionNode.getOpNext(); + } + + @Override + public void setOpNext(org.hl7.fhir.r5.fhirpath.ExpressionNode value) { + wrappedExpressionNode.setOpNext(value); + } + + @Override + public List getParameters() { + return wrappedExpressionNode.getParameters(); + } + + @Override + public boolean checkName() { + return wrappedExpressionNode.checkName(); + } + + @Override + public Kind getKind() { + return wrappedExpressionNode.getKind(); + } + + @Override + public void setKind(Kind kind) { + wrappedExpressionNode.setKind(kind); + } + + @Override + public org.hl7.fhir.r5.fhirpath.ExpressionNode getGroup() { + return wrappedExpressionNode.getGroup(); + } + + @Override + public void setGroup(org.hl7.fhir.r5.fhirpath.ExpressionNode group) { + wrappedExpressionNode.setGroup(group); + } + + @Override + public SourceLocation getStart() { + return wrappedExpressionNode.getStart(); + } + + @Override + public void setStart(SourceLocation start) { + wrappedExpressionNode.setStart(start); + } + + @Override + public SourceLocation getEnd() { + return wrappedExpressionNode.getEnd(); + } + + @Override + public void setEnd(SourceLocation end) { + wrappedExpressionNode.setEnd(end); + } + + @Override + public SourceLocation getOpStart() { + return wrappedExpressionNode.getOpStart(); + } + + @Override + public void setOpStart(SourceLocation opStart) { + wrappedExpressionNode.setOpStart(opStart); + } + + @Override + public SourceLocation getOpEnd() { + return wrappedExpressionNode.getOpEnd(); + } + + @Override + public void setOpEnd(SourceLocation opEnd) { + wrappedExpressionNode.setOpEnd(opEnd); + } + + @Override + public String getUniqueId() { + return wrappedExpressionNode.getUniqueId(); + } + + @Override + public int parameterCount() { + return wrappedExpressionNode.parameterCount(); + } + + @Override + public String Canonical() { + return wrappedExpressionNode.Canonical(); + } + + @Override + public String summary() { + return wrappedExpressionNode.summary(); + } + + @Override + public String check() { + return wrappedExpressionNode.check(); + } + + @Override + public TypeDetails getTypes() { + return wrappedExpressionNode.getTypes(); + } + + @Override + public void setTypes(TypeDetails types) { + wrappedExpressionNode.setTypes(types); + } + + @Override + public TypeDetails getOpTypes() { + return wrappedExpressionNode.getOpTypes(); + } + + @Override + public void setOpTypes(TypeDetails opTypes) { + wrappedExpressionNode.setOpTypes(opTypes); + } + + @Override + public List getDistalNames() { + return wrappedExpressionNode.getDistalNames(); + } + + @Override + public boolean isNullSet() { + return wrappedExpressionNode.isNullSet(); + } +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java new file mode 100644 index 000000000..3d6633604 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/FHIRPathEngine.java @@ -0,0 +1,30 @@ +package org.hl7.fhir.r5.utils; + +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.model.Base; + +import java.util.List; + +/** + @deprecated This interface only exists to provide backward compatibility for the following two projects: + clinical-reasoning + clinical_quality-language + + Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards + compatibility with core version 6.1.2.2 + **/ +public class FHIRPathEngine extends org.hl7.fhir.r5.fhirpath.FHIRPathEngine { + + public interface IEvaluationContext extends org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext{ } + public FHIRPathEngine(IWorkerContext worker) { + super(worker); + } + + public org.hl7.fhir.r5.model.ExpressionNode parse(String string) { + return new org.hl7.fhir.r5.model.ExpressionNode(super.parse(string)); + } + + public List evaluate(Base base, org.hl7.fhir.r5.model.ExpressionNode expressionNode) { + return super.evaluate(base, expressionNode); + } +} \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/TerminologyServiceOptions.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/TerminologyServiceOptions.java index 2dd989c9a..7666bbed5 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/TerminologyServiceOptions.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/TerminologyServiceOptions.java @@ -1,7 +1,7 @@ -package org.hl7.fhir.utilities; - -import org.hl7.fhir.utilities.validation.ValidationOptions; - +package org.hl7.fhir.utilities; + +import org.hl7.fhir.utilities.validation.ValidationOptions; + /* Copyright (c) 2011+, HL7, Inc. All rights reserved. @@ -30,21 +30,23 @@ import org.hl7.fhir.utilities.validation.ValidationOptions; POSSIBILITY OF SUCH DAMAGE. */ - - -/** - * This class is superceded by TerminologyValidationOptions but retained here for backwards compatibility - * @author graha - * - */ -public class TerminologyServiceOptions extends ValidationOptions { - - public TerminologyServiceOptions(FhirPublication fhirVersion) { - super(fhirVersion); - } - - public TerminologyServiceOptions(FhirPublication fhirVersion, String lang) { - super(fhirVersion, lang); - } - + + +/** + * This class is superceded by TerminologyValidationOptions but retained here for backwards compatibility + * @author graha + * + */ +public class TerminologyServiceOptions extends ValidationOptions { + + public TerminologyServiceOptions() { this(FhirPublication.R5); } + + public TerminologyServiceOptions(FhirPublication fhirVersion) { + super(fhirVersion); + } + + public TerminologyServiceOptions(FhirPublication fhirVersion, String lang) { + super(fhirVersion, lang); + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java index 47a32d217..3657e9e8d 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/validation/ValidationOptions.java @@ -25,6 +25,8 @@ public class ValidationOptions { private boolean exampleOK = false; private FhirPublication fhirVersion; + public ValidationOptions() { this(FhirPublication.R5); } + public ValidationOptions(FhirPublication fhirVersion) { super(); this.fhirVersion = fhirVersion; From 81f02da5c2c0b18fcf7cb06652fe111640012873 Mon Sep 17 00:00:00 2001 From: Max Bureck Date: Tue, 7 May 2024 15:24:14 +0200 Subject: [PATCH 2/7] Fix split logic of canonical into url and version in several places Removed - org.hl7.fhir.r4b.renderers.DataRenderer#versionFromCanonical - org.hl7.fhir.r4b.renderers.DataRenderer#systemFromCanonical - org.hl7.fhir.r5.renderers.DataRenderer#versionFromCanonical - org.hl7.fhir.r5.renderers.DataRenderer#systemFromCanonical - org.hl7.fhir.validation.BaseValidator#versionFromCanonical - org.hl7.fhir.validation.BaseValidator#systemFromCanonical Replaced all usages of aforementioned methods by the use of org.hl7.fhir.utilities.CanonicalPair. Improved CanonicalPair to avoid multiple lookup of the | character. And added a few convenience methods to the class. This fixes the issues of #1611 (not replacing all canonical splits in other places of the code). --- .../org/hl7/fhir/utilities/CanonicalPair.java | 66 ++++++++++++-- .../hl7/fhir/utilities/CanonicalPairTest.java | 90 +++++++++++++++++++ .../hl7/fhir/validation/BaseValidator.java | 18 ---- .../instance/type/CodeSystemValidator.java | 4 +- 4 files changed, 154 insertions(+), 24 deletions(-) create mode 100644 org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/CanonicalPairTest.java diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/CanonicalPair.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/CanonicalPair.java index 6fe972e01..221b90e55 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/CanonicalPair.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/CanonicalPair.java @@ -1,26 +1,82 @@ package org.hl7.fhir.utilities; +import org.apache.commons.lang3.StringUtils; + +/** + * Abstraction that splits a canonical in form of {@code |} into a URL and a version part. + */ public class CanonicalPair { - private String url; - private String version; + private final String url; + private final String version; + /** + * Static factory method, that invokes the {@link CanonicalPair#CanonicalPair(String) CanonicalPair constructor} + * with the given argument. + * @param target the canonical to be split. May be {@code null}. + * @return new instance of CanonicalPair + */ + public static CanonicalPair of(String target) { + return new CanonicalPair(target); + } + + /** + * Wraps the given canonical and if needed splits off the version part.

+ * The given parameter {@code target} is expected to be a canonical. + * @param target canonical to create a url, version pair from. May be {@code null}. + */ public CanonicalPair(String target) { - if (target != null && target.contains("|")) { - this.url = target.substring(0, target.indexOf("|")); - this.version = target.substring(target.indexOf("|")+1); + int pipeIndex = target != null ? target.indexOf('|') : -1; + if (pipeIndex >= 0) { + this.url = target.substring(0, pipeIndex); + this.version = target.substring(pipeIndex+1); } else { this.url = target; this.version = null; } } + /** + * Returns the URL part of the canonical (everything before the {@code "|"} character, or the complete + * canonical if the character is not present). If the source + * @return URL part of the source canonical. May be {@code null}, if source canonical was {@code null} + */ public String getUrl() { return url; } + /** + * Returns the version part of the source canonical (everything after the {@code "|"} character. + * @return version part of the canonical, may be {@code null}, if canonical was {@code null}, or canonical contains no + * {@code "|"} character. + */ public String getVersion() { return version; } + /** + * Determines if the version part of the canonical is not {@code null} + * @return {@code true} if version is not {@code null}, otherwise {@code false} + */ + public boolean hasVersion() { + return version != null; + } + + /** + * Returns the version of this pair, or the parameter {@code alternative}, + * if the version of this pair is {@code null}. + * @param alternative to be returned from this method if the encapsulated version is {@code null}. + * @return either the held version, or {@code alternative}, if version is {@code null} + */ + public String getVersionOr(String alternative) { + return hasVersion() ? version : alternative; + } + + /** + * Determines if the encapsulated version of this pair is not {@code null} and not an empty string. + * @return {@code true} if the version of this pair is not {@code null} and not an empty string, {@code false} otherwise + */ + public boolean hasNonEmptyVersion() { + return StringUtils.isNotEmpty(version); + } } diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/CanonicalPairTest.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/CanonicalPairTest.java new file mode 100644 index 000000000..3b67bf81b --- /dev/null +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/CanonicalPairTest.java @@ -0,0 +1,90 @@ +package org.hl7.fhir.utilities; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class CanonicalPairTest { + + @Test + void testCanonicalNull() { + var canonical = new CanonicalPair(null); + assertNull(canonical.getUrl()); + assertNull(canonical.getVersion()); + assertFalse(canonical.hasVersion()); + assertFalse(canonical.hasNonEmptyVersion()); + String expectedVer = "1.0"; + String actualVer = canonical.getVersionOr(expectedVer); + assertEquals(expectedVer, actualVer); + } + + @Test + void testCanonicalEmpty() { + var url = ""; + var canonical = new CanonicalPair(url); + assertEquals(url, canonical.getUrl()); + assertFalse(canonical.hasVersion()); + assertFalse(canonical.hasNonEmptyVersion()); + String expectedVer = "1.0"; + String actualVer = canonical.getVersionOr(expectedVer); + assertEquals(expectedVer, actualVer); + } + + @Test + void testCanonicalWithoutVersion() { + var url = "https://www.test.org"; + var canonical = new CanonicalPair(url); + assertEquals(url, canonical.getUrl()); + assertNull(canonical.getVersion()); + assertFalse(canonical.hasVersion()); + assertFalse(canonical.hasNonEmptyVersion()); + String expectedVer = "1.0"; + String actualVer = canonical.getVersionOr(expectedVer); + assertEquals(expectedVer, actualVer); + } + + @Test + void testCanonicalWithEmptyVersion() { + var expectedUrl = "https://www.test.org"; + var url = expectedUrl + "|"; + var canonical = new CanonicalPair(url); + assertEquals(expectedUrl, canonical.getUrl()); + assertEquals("", canonical.getVersion()); + assertTrue(canonical.hasVersion()); + assertFalse(canonical.hasNonEmptyVersion()); + String alternativeVer = "1.0"; + String actualVer = canonical.getVersionOr(alternativeVer); + assertEquals("", actualVer); + } + + @Test + void testCanonicalWithVersion() { + var expectedUrl = "https://www.test.org"; + var expectedVersion = "2.6"; + var url = expectedUrl + "|" + expectedVersion; + var canonical = new CanonicalPair(url); + assertEquals(expectedUrl, canonical.getUrl()); + assertEquals(expectedVersion, canonical.getVersion()); + assertTrue(canonical.hasVersion()); + assertTrue(canonical.hasNonEmptyVersion()); + String alternativeVer = "1.0"; + String actualVer = canonical.getVersionOr(alternativeVer); + assertEquals(expectedVersion, actualVer); + } + + @Test + void testCanonicalWithVersionIncludingPipe() { + var expectedUrl = "https://www.test.org"; + var expectedVersion = "2024|05"; + var url = expectedUrl + "|" + expectedVersion; + var canonical = new CanonicalPair(url); + assertEquals(expectedUrl, canonical.getUrl()); + assertEquals(expectedVersion, canonical.getVersion()); + assertTrue(canonical.hasVersion()); + assertTrue(canonical.hasNonEmptyVersion()); + String alternativeVer = "1.0"; + String actualVer = canonical.getVersionOr(alternativeVer); + assertEquals(expectedVersion, actualVer); + } + +} diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index 827710f3b..9e88c6b4c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -1428,25 +1428,7 @@ public class BaseValidator implements IValidationContextResourceLoader { return null; } - protected String versionFromCanonical(String system) { - if (system == null) { - return null; - } else if (system.contains("|")) { - return system.substring(0, system.indexOf("|")); - } else { - return system; - } - } - protected String systemFromCanonical(String system) { - if (system == null) { - return null; - } else if (system.contains("|")) { - return system.substring(system.indexOf("|")+1); - } else { - return system; - } - } @Override public Resource loadContainedResource(List errors, String path, Element resource, String id, Class class1) throws FHIRException { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java index 6363c37b6..e87456b7c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java @@ -13,6 +13,7 @@ import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; +import org.hl7.fhir.utilities.CanonicalPair; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.i18n.I18nConstants; @@ -620,7 +621,8 @@ public class CodeSystemValidator extends BaseValidator { private boolean validateSupplementConcept(List errors, Element concept, NodeStack stack, String supp, ValidationOptions options) { String code = concept.getChildValue("code"); if (!Utilities.noString(code)) { - org.hl7.fhir.r5.terminologies.utilities.ValidationResult res = context.validateCode(options, systemFromCanonical(supp), versionFromCanonical(supp), code, null); + var canonical = new CanonicalPair(supp); + org.hl7.fhir.r5.terminologies.utilities.ValidationResult res = context.validateCode(options, canonical.getUrl(), canonical.getVersion(), code, null); return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code); } else { return true; From bdfb5aa0503fe25d34db726a332f60859ff99961 Mon Sep 17 00:00:00 2001 From: markiantorno Date: Wed, 8 May 2024 03:10:50 +0000 Subject: [PATCH 3/7] Updating i18n-coverage csv and png table ***NO_CI*** --- i18n-coverage-table.png | Bin 31492 -> 31742 bytes i18n-coverage.csv | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n-coverage-table.png b/i18n-coverage-table.png index d735b184c9eacb5f992779ac72ea0aacc08a848f..7b00d33d691303fe16b6466d8eca591545cdecfb 100644 GIT binary patch literal 31742 zcmce;WmHws+b_BZDM^tKlu}6nK^mz|h;(-;Qj*dQ3L*_kN()GbNJ(RXbeEJtw{&x# z{eRzc#`$nQ+W+93#r4jvA? zGMx6=1^y9smDO|AbhLE!c;sw>C_i#_vU7B`vw6(mZsF`=iNJ}gFc1^pMpDsvDnCfJ385#fCA@xD;mFon9R<^G6alD&GWp%uPc9>_=WK71H?_lhgH0Q-sp z3J*Uw7L_qe?^C-re>{JMt7FH%X(OR)y?bqKW@^Tzva<3;Xe+gOBv0E~($}ss1pO2B zy=W|fHuQ_4?HIJ^SCZ5J21daf=H0!|TL1Ho<)V<;e?D93a{UAPoyZAc;_?4l=sK<) zdKGi`|A)&^@S;MWqwubvWSZ9M$KQCT%Hs|Ed}Fb%fcH$sc<~x{1J{u(UWH0i&#H;L zF*OG(!JmJncgaxQYMU1~;Y|Vj@vF2lHLTnZCfr8mW2)UIE`^b1zwnmm_MC8g6oSuK zUo@Lv1|Rg2I@0g^=gAx#N`^Y+3SPP$Ov>F*_A-GqJBaiTF5@?TMwu6+OqzKATttF%o~7h}*r*@4OUN+2F`G3WMj zO+NVe_3=jz%q))FgM#8PR}Y2}Vey#NxTMDvB$#SAl2nKxvPOye)cmcULIf4cjtZ?r z_7Q5#ES$hANCvWn-A~#|jpPTDz6vJ2ZE9d~&0Jt{_ajHET|}t=rLEPjvIqW5*-yC} zh!dHz&*7gsS()c4izqx?WCY_5_7+YcF=C08yyg5<_Y)o?4dysW>t#uTz}tub)+dxq z?##sq!bD@ zr18O>MADoo1tpUd7K(UXT*%6}U|?e%VrZ1Jn3u%<*a=j|8!!-VR>mV^3f8+B97>7G zEpBfrxr&M(h)Y6Bv@d9Lt){vO#k@{~Nh@EHQU#MfT&du{AYjzF%=k1#zug-Z8nsey z@f3%4;d(!JZ~=GlID7D?@|nbdm!uaIC{J3wm`c(=_IrnME-Sv*P@zJM-{?`H;>T_0 z1!Eq1b*9euN7)kJHZDoxsXxT4P{Jc)3zjEG-6ul@UuMk1XH-b8i|O{KA6dQ;Ou8OS zsu)a~KfHWz*xWIifDs}ijc82td-6>dNdJQy)U+}( zg)+NjfgIi|i-qTDwl$o}^6k$pP@!gG%MFDG_93yD4}yY8->p;?@7-}BMeS0c*3_#O zU!g+JzO+75O;_EyM#mcLq}#%+8%(M?Qm(6(U%4`#Vs0#jI?f0sH4ZNL%j3K0q<<3Y{lrKIJra5sm8N?io*l7U<|^TS z_s@6~;hiF__smywZcn@R@6gJ+Pu@((87eg9C25B6prNl)t&`!MXwedsOr1ZHjIlg+ zeOZ6hppsBS@Jw@WhXvuK=-R+!jk~#tC2#%_uhnJmqO(0;c(8@|S4DO=A<_|kF@&)z zsNPPu;+t#YK@)g$#T9F$`~k*c43lwoy?+XC8K#q91)cJds&iuvMWA%FuNB5E*1@?c zk_ZZ$c@Y}Va&HXJJl55R(HEOYfkW4UdU^{gdfm5Z#<6n@g>h9-%~3gJbb(8Avo`HS z;i!N3L_XSg^{Ry>rf0l4Z6?Oj>zk^YZf|W?_-wpK$FyFbhl)%SicS8-Ty{;e^y?eh zZ21^vkNK;Fr95wA74gmgQGRMf8n{<;Ucxa*s9Ta>Sh|uoZncA?sWnRABOm!U0~~(R z?nxg#sR<0$345hyd1NF%I8wZ#%f{aLX$7Y191}Bl!K`Fi$oD+ z%0Oqz;o=vM&#*XuSnd5&PQOsL4xqP0iR@**^DMQEzQ5|6E9j-9JC}}umFctRT>OW) z_~#2{0v-u7#lYRqC3&8Iz1hTBFNWd*7$UJ5!dR{b; z^Cd8=&5K@{PjDH&EqjJjKFsHYI3RMYG(A+_E8}>r&U>^*sDJe&xzAWqez{gvoLN7X zpq?^COtgnLg#v%BjNM=$qHM`G*%x%iP80B?@4_6D-hWtwn_q_j3DGK6xK`QRC4Nu5~eo`#rvE z#+!4U1i2{c3d87E*Cav85uq?DQ={^^9}QYfYw@qQ^V#=P)fzVnJZHI(CBjzaCZ$VR z5++7fAJtUr)WZ)>#dCSQd&3X(HFX@KOHDkVt)1Wwl4!g$86|C%wZ_GxaGuk}_*7=% zPA$oSl&x4~#Qv;fcA_!=?vtmb^Jq+rXR4p`V&Ua|>b}(y#R$N`8atBT^XCCE7=ktpish&R%cU>jSJ(6p> zKNx;?SSGSL+qRz*#!I-tjrj1p1szM~FMiEB8hKrLz^l8Nb8T`)^4~kQJgYj(=~7O8 zOEY7)Ev8RKw%<>x6w^J5GAvdjt4U<*Z}yXakg6Zl*r8jp?+O=4#K?+&zDIjM6jLbQ zqs%*5`gV$|X z+}^eI25S3e-vtEu1v4|8nc06TaboQ?yjQ8@Xy>))*ZVGclrmGUFKn`z?|&wOsA74o zN*`~l;Qq=q*N+zopbYe`8}~PF*HQlP7KcHmZ~F~G$G$K1@_N^W>e(?F^#;XCp2`ks zB0Vkts`9JzO8Rrpfy>8!(H7;b+qxrhf(W<&H^bexFDNi*odbMD^Gw`_)O+5f9@lMpg;i0$lV>5zy;fi`q##n&n1t)RV$M-Lb+OJl<+(vvVkqgCo=E3-_u>nkD=2IlWgAAuV5-3Vm4HR^*S%M%Wn3`^e_0|+ z=D9+tEip2##FE!@O^e+)J8bb8W!U8DRY>IXZNxujQ}>(z zwESzGa5+Lg(;8VNx^rTDRvVq*Hq02jb!Bk8Od3%rHZ`%!N}sE77z?$|cjM=u7`-wQ zps24lCn?{uaX>b38*3HH!mH!i{o_IEtm}e_W>U>*GnyCEDl)n*Tv}tBwtFo%;>`m? zm#*g0dj(z%v>`+BVXDcVZN>;wlIUC*%gH=EW|xy$#4rjP)|_pVJUb|iQ61%Vw_7hf zZ+IDc-djN^bCskpzmv2_;5;dmmne4vWBI}3hw>Oj{550)Zen{8LBkDrjh>nOU0hNt zVwVEnd3RpNUKYB7WmBKrXbI&IPyHHqbe$$)H4BG6^tNYHj}lLtU#wO=AKPThIMGvg zxVLADiv(P|W>_?#&n}PqMM%s>CAp#*+mGIkf4;`^X8V*G3J>;BTSR(AeDB5ZT^IJt zHdAq>jRcaF=ET$w4_I=CQr&_{dvS;*b(&&OcvJ{IvP4{H`;%%=N+kcIw@DYj8`4BB zDJ-Aw*Fdfw^1P~Cl3*c4`uO&8G}Q?=_v!>Z_Z>2^fuz7ty335cQcn+vcHgTnvS4-b zZN~9u^1r<+uD*{WpD(!EVLz?pFXu8a>Mljo$EPY5dqRag3Yodg-}7%#nK8JcuVf)R zh=F{hmTj-OAGBd_LF@4KPuz{%HO?jFz)qYv=TCY zyLxkVv~f0MKT3GB?t8n=Uh@DUfyC3?!<(_*gU)4@k=eb)FG<_{*EnVaq}$cZiQno8 zTna2F&1NE-*0^IxT&R3Ng;E;5zB5eq$hV-d;q48Ix`fofhMIe`i?O|w`nO1;mun(L zyWf;!q#o<0HIG$ZrM2xzc#&edOB`G8+4HF2perrC&_i_iDewTatkIC0l@0qg5;|`3c;g@*Pza%}6ZNBrA!^9uQ=0m}P`W1FfAhwmj~7O(9Fs_iM1=B+sMm_V-(FV&GZ}w5qD(kfQF2j`@6L1#{!LAVg>#DSJT4*@PCAknX)3Lt z7(5NV&3G0#QR3gk8K@8|PF`G668GNO#dl~ovW;9l{5D5Vj(I)jU*gKEiC*J;^q=&Y zu2_m^?^49KxA2alM6zV0RzePLGf|Ko#qr@6Ix9qeaktHU8QUyLFST;SDl79n>_CsTuxX_s(*P`9a@?unlvEIw#mz?kNk^yV*23LH1et<}Fouegn!HdF!Dav*obFsD%*4m2t zx09cG!}s)}atq!0R<$xHZ)Bf0B!xaUyD0Gr*xpWdsQmQR=;dv*p|lWIw%{KTCNW0j zsQ9lDT+`w*RmQ3$G0N?w^I4}apO#GOR^GW>M|3tM6Xjx5VTs?inCx8DoDNxub$Q!-;BaY}$`aqkr0$L9K!(nE zf&apfo_{?*H;)=c@)muj)JZV~ls#%He(2t7{!BJ#(Y#-f_NVUM=gM;04sMbeN;#E8 zTCy_MufM)!hKm?6eZ{iooX3@P2^6ea@1d}my#^e4(6OyRarg(=e+sC&3T}SSAMB1es6xKAi>dD_rtQB}O`^1O;x0QU;mG2D7-?RFz z%9{uAjx0}Hu6t_x<&bD~=wG&=oYyZ?tYt9{e4Df+DO3v4?4T%}ZxmI&Qvff&OFe1! zC(_4kRqb0gZJbRU!3FPGVnlOA*%1xLx4jgeD`R}RFAiS0u2fLxniNe74;9@^Y-f#obKdTJu=r) zj*JWzJ;h`yN|IimR&PCa{<0d|#zCQZha0Q#+tl9klXSVowY+WF`iw?nGNOHHIV(BaGjn(S zFUd&Pm8@hw9aVsi_efH`-#S0;cvqFg#+5d9OA$p<3@bKMetn-S z??4ucY9HKtUKHp``=M{^@s;uV@YBvPmmJ1DJnMZ$`^HZ$!M)$=gjWV0rgM=G27kmh zD}22h9a|=TTfV)#P)$jNVA*8^XAnCl%zOL6vQMUSZpV7Xh~Zf?dG4~J0o%SUmV8rG z8*{H)dqjsVIYwkKUx-TOlwwoM1+I+(jpD42M!er;4M(-!FhBgkn1pS)&SzgDL~oPk zwicGW-&2p*l~Ny-mv1*RC+P|Ph(`S1Bf?zDC26D!(}Zdnhsjwvw&(Vf#j!#bA61HM ze0Z9nKATA-?1GRLmeY69c?HcPDdH+7_KL4Hh0H7K$@;%z8@j4#RfaF>Ym zi90ph%Buy25<9)){jWvWy&Q`VzGAwp;@Mg2^14fgoG3IdB z2WCQMF3)!r^)*AZYx6plMQau+9pq+=Mta7@E42-~{x#d~H*D{`j=J7{!%ZAxndzmS z>`yKE_RNy&^8%HwvxQ^oH#D~1-BFyicgGu~C~X$r9(!^1+tb0^-?F3y6RMjj1wrH{ z*n%k!$jQAFBvVu#yk)^3TvVuQ;oX}XIT2rem^5i_>ta2-!Y2Fg!n`rrGYP?7=`f|? z-k^ME!xH1NX8OX7yvTN&-BCH=O-^$kgYl6=(H#rPCj;q3yYbqL?KN+`hqV_gj}P;D zFPN(wPZBVO;6ZwL{6f4Z$guV**f%~bsFSLMVGh2sV9cF}N@pb6AVftEsmQou4q``V zqEO3dJA(eG+*Mqwt@#!-^5z zp#NQ;58`C@&-pg{3FK=ZJ$pIa$_2`2p_QbSbK4Y?jdQnLtT)>q#xr*RqVpCuviUTp zp+p7A`n8|^H?4H5^P-GGu1<-delEr_`U%Amm4=4WNqff#O0QJxev8=)XA`{ z@ZEzkirWjj@YUSwRZY^`J`43t7Odnkk%I1-$R|edvr3RBl=AFXi-!PBzCobZXxji3_Xt^{PgVL3^ zBHBQ$?4=P(F1lvcIs4e%&i)%a(@-7j&B}k^WQ?`k{Y@f#4svfc=<4p?bH1Y;Kl#Z; zOtz&d{N?1w`_wXG4pQ|Rhd%NW*v1TJLZ|qH#tek%i8?>?JTo$>Xn#2S_}u<71xoC8 z52n0?9J|JOw5fTWmYO$Ofv@n*Z{GGOIiB_7u3)dr&gfk*-)rFz*5mN}k7Tcti_hqN znb8t-*Fs0#ON_yB-ZTl)$WuugmYPG0(IJBsHWN!!eWetEi4jjHLF{RB5-VKV(h(EG zx6D75^bb#Nu>}7?W)E^VlyHjiy9qwy%u82-VcbC>9wb>shQ!pQG`ae}E;YRVf^XT` zw((Oe2l=2D>nn^q?AD)CQbcptJAz$bcY4U|o^_R8siZV@{f`G>x#&sw|D)gV|H8Hq zp4a}2!oz6gEbp}H?zQ>pzoJ-r$^0m0Qk+o?3bjJ5qYCymllo7egs^dOv3}L`g;P45l&~s1d?+O;DVb5u zVu~q{pzxjENaqRbq)4rwPQ25k)t${PHue83{D07zsWey}EoBUrd`UoI;;xO3AXF5V zz-3ukSt&dWMr?yxhqI5xUkNIk2NXgyue&#ash zytCNXvi9^NW|2vgHz~?&e{I5`+;RK^1`6-+=;(RqcD2gXg1*CaqZj$bQC|QlDJi0> ztE*L{g-_0+@-2=pYOkymO?f2RpzDbIb~$LwvjAMNrY8c_$@(%VXeb! z%Laq$r+XiZcQmS>j)Ws>YHIymW#PtQQBm)ws?I_~@m9twa*RR>9|YkLEp7e&S~E+k zV||;M`Atv|7DiTozgnpUz5gL2M%Ko3gP~DbwSDH~{mPec^O|8-ZtvE-h1JzHG~NuH z+W)L#MEIQN-ns0d0< zQfg{EDk`dPZEb(1>Rb-b4ra;d=%QT~dmpt$UK4Vj`=MAW$|3aS%a_>n^r*+*!{4dr z$Qg7+(}@uv))OBsnulM)&0J#o5{QAdHP=CYcyjW$xV#yaz^?7I^-Ie4-*>7{-h1qM zN^f6mHlL_Co>$wB{efp>HLSU_(3_sxS1qV%BKzVOT@5P6XMDG^Ch7N=mzT8~J)a40 z#CyPLD7=i98E0(RqpKYqv~gCn(>zT06FUdG18 z1LdX?L0y~E4X@ZV^RoQUj<^2(dtO}3p^(HC)tfGAK3(tTd45_q<7?dD{*n|E?khAZ zieEnl66^=n+#Q1|c}E(iFZ=70|7LtP-=SU-IJvk4!KI6|i$h|>kMWYYO$F+Sm5<;! zu@R#d{~I?SM9Yj6Y5)HH8`9Q&ZJaSbV1Mlz{P6tu*H<}@zJ_e=?Y*q5yr&S)`Wznn z?^hCuZ*T8eDLJIJWr+FozgMKf#>PgU8T#Qf#r;SrDRGcw9`g{R_JRV|9E)^e7o4vl zMACaJBfpoI!_d*|d$heYQOV-IF=gYPerIoO;$E7V4`twnjjD3%Xrq^lkkH)v7@Vxb zPL178r{;<<1hN84dfWNgNyW3ja-QDak2~Jnt}Bwx=qfG~h2qw9es*9APnbA>QT;uF zDxZi}fSQv( zVW?%NSJbk4@892cS|b*+0jMDJpAV1eh>3~$0?vI?#Qo||f0i27?j|NACdy&q5Z={? zC>42o{g!~S35$w$ z(f`Q|IM;U+e)#aAR+G0|U0Q4`X^KRE_zhv_;4fdlE<-+6nSI853e{V?L{FXN;`C^z zqrLsr@xi7lhi+N?&KcxKmG6l{7>3Tyyu!l5WDJ*9uU)$)P}rWxX*lOCBq};o zpq{hTCvlMrb#Xvd;!K9qpei;A_tK?h>_zyb*2gCgF(utrhI#7CP7XHXa&m5BWO>YZ zJ=omlwdf>8oLyaWoBd7(Lx^aXzJ-yyt_-uGcSpzYEx&Ez%${}PSc!gIT6#L$-Mg_1 zJ*f}cqi^Kgv+9N1Uae{~fpx>!wTon+w7rj_71Yqvqkj47)livngZ0K#opU2V)695g#3jC- z1tBn0V?SA-n8dZc4Z#(cAraum>7B~00@nQu!khi?r1u13gK$YYrBY*JNW{FhWmuFi&d=tZy$?3* ztE^U_ICz`h4=D^>&xsL#BXR2$@r}V$W>L{pxfnXm@>SR?}xLpD^gWs6lpm*Kk=H|wf3MELKQV?*B-?qubNAP0tgoWaLmg%sZFVKo zAmrD7R^LSC=I3QqGsQ<9x~%`?KZ>YRddus&*n1e*(%Mb3v0cT>cCYEIM9q1m;}ZPF;OqM|alvZ63nZd&W< zr*Qql1e+~Z&G@*U^Rs7+h*rg8S?~R|x1Xz03g{6|lSVz;35ko-n*p(~u4Pr))Q|4& z_yC*e8=^XnH0BtFN=lKZjBf=UGX~t==jUshnK58wL0Oy3KIVqlpM(_V${#yWoTlj< zn$gTt;z{P>8?yU0S|dZ>9uyl6k=m(%09qkX@mG&rjsT}vbJFrW#>Qy#8Byk`g>n<{eDd^io&63}BPI_Ik5UmE zx{+ete27f)*RJ)tE=Ar8-EVbD6~oG}a6XB?F8m@gk`QUlk_!5@vhwuqI>3$jMaauB zgBtLiy;|3xMMNf=ms#~?Fp7xK!0xuga?kcww5L8j!?Nf~yu{EW?ogO6>cMpH9yzj= zd2!lqZ2%yN&vuj$ar*NOKVnR~pUvu*yN5^Z!?&I8_w2^+1}%qEaD+$&;b0)Vyu5Q# zi!|lU$LvtPiIDLs8*<1#*UnE)zcI^<>M$j}%hS`-s}rF`_aV8@{{WZ~G;lOEHTCjq z`-ytXYq52_T29NUmO9BAVYu9f%7D7Bdv9$cs(Sfg=DllR|NduE%)&toul}9ZIYmcZt z^|ZuJ3e0|bW}YVQ_a8I}jqUf^S|kAl`>!}vaVe-XfOQaL*6-j(Z-!U|4gXWK!Q6+= z=j)TTIkFLyTU%R!sj0LpW92chXEy8QNntF#JuICZ&zR{Ll7ury9M6mR{Wy7oYjFouJE@z->CS=9_55Xs8#@s*du{ zNK3Pe&(Hr0H5Unl zV!PtYvp8I!e$%MIU3rst-s;Pnhc@?kd1GT^5eW&2${p%#{7w_UJ?&D-W$2;X6!S+s zkGN{R&OY@hIu9+_4i`KJC`4^UM@}A8sF{z#dk(N&%0J+I^Wt2!S=kWavU-UgPw=Z( z=7(Fqg}k#Ro8UmZiz(vlg_1vXNknNJKzDnCww`{#?8m>7MFQ@90L0M{S9_nyX?8Xb=w9sV;v z8mn$;Y3VqH@`;nA-$1`R(q#~`@!09~@EPgrsp8nNPd%&c_A^dRb{5}4$vlsD*&v;n zGbe=oj`<)Ju_WvNO1Zl7K{2dwoD~O*`vd$K1uMpJw`ud+- zm#^^NyQh3!)T0VJXFc02=Ds--g-%>XMyc~{2#fO5n~wnqdGFZ%d{J9lJN4C^*j$V} zIy#zphhEfODPyv0Y>et}d&~nsXJpr}6RN7JdI?EEXE8D{$v9T?XGWt@g#`Au>AJI1 z8hKg;Y8bVSv!e}mpI=Yh!hnRzQ7q{$eWMH=g;#?NA0H9*iU@CoycwK zFrw#R_*XOgNX9Fbs)ukO1d!l^jm}5AA&YZ}B_tZ5(-cctWG21yXb-=!l}?yiV3@f3L3-{rb+94G`PQ zeVh1(2=#rxY@5pvFU*t8oHjp?Im#O!??!wXFWD?BE8C9Aj-cXRxe-{FTNe~4esuPB zyd^*asx*@XAI1ZqJk=(;Gd53Pj|{rt)fWJ}79K*zPnxJZ?zAbT@Zkfjkgj!@?k_bI zEVTgaiZGbQXXScvF5b9ef6igD}sq-nFoUq=;v;aVOfS59;iEQAu`|X^TG|K0XG6vHB_CjpTH} zn>Vp&1?>90l_wnH*V*!ScU?=28z=)^vqp{HC&U431H?rnDKZWP9t(POV!5w?duPdm z7`km2Ltma$#i51BY8S~B8-WE_51Zk}Z~)Zfpk?5B`3E{qG!V~0`S~o!uUGW`{q-8W z+z^77;NaiTr#zo?Z2T88x|%XWnV|3zGznYIV&FeB+&qTA1RQ;2n|f%0i-$l!WOP+?}gQf|kk_hnc-Tgr*q%@g)L{BWNIN>a?sL!t!o zt^MVp_N6<&g;{#Fd$pffTdo6Zw4Ofy*8lBO9&@j@irNIQ)wtS>pKw|?B>bnWQ(m;D z7;2J{0XDXs*05R`E@WmA5(g^Xbi7h5V$Z|I_R#jq07TYmPx;#^YJ}(-@3*D;co#0^ z6uvO%Z88X`1Y>hPC(wJlyrA>iZ6^vrRmg$Dw0vhMp2w^e$yvSW{Valx5&MRix0Ykd zM5UE&&q!{$(fqCK`Obu#r6uchJ~Vr&bui9x(U>=yO?7Ox*%r8;ubNrYVV^oUG&EmR zZPiCtY60p%+-jU*VvV1}&J~9p?(w1?TQo+6j*gFT8rQ?>jM5>b2)k)>h3z|p50YF67#yb*AmQCjRx&jA2FI9_4iQ_nvF zDwV5)ay8H<5r7HCpPZgULdbxYknO(yb9pLdWv0nzZec+#kZ)(V^*NReKn>UPQ!l8o zR77<5lhe}DSQ!{3Gx&f04CE9R)?XFS{rveepT~xgi02jqdO4LeAt{KjJSga02QG$n z&K3?cbPZj<}T;U6e;>LyfOe9^Q@`s1og=x{1&TgH7anusNH=!f`2g^8Aj` zCpCvkG*bc$IRp@|5F!*CD=yezdwy@yv87{KF`iXwC|@-ny&H8di`GMV%G*>=yAnB- z6N?*_V_I4ydNL(4LD^aYTw3M2tU*9b%*=?*?=YpOlJ7WrTvBoeEzG4cGcW|^siZ5M z?62p5q$mP?`wV~^pGD`@ql~XWS?fCN`ET>_#UrtCadExVntZ19z!Q7+yi05V@7MJ# z%BGGbqa~><%bt{Lgej`&BC;qvui3Skrc~nVLXu+MyRobGODD;pSON|23CHhvSrZf1 z)E}KduvYtjzUIAjIj_cUg6ZJTvQIp_b~tcy3tonMiwm2o8Ta3b`yD4&#{`pB!KU4t z#Xm_%4U7t9Wnw}#7ghd?`s- z0-_0%fl>1H>q7uY3Z-8WU!|s&2Tcjhzd*3bfwhJJ826O*(FdGLK_knDHvC%QJ(HD{ z)%L+bK5+BFDw`qnlR7p7e^qbsKPv#Bh}K1BW@fa?O~gRa5c%HTPX2m1usbbK`R4um zX}~R&-Bw3$)6>%fE58LAA?Rayz|~)!pUhqi0&BM2cb}}B!m*=S?90pt7^eZHzYx|% zYm%U)yl-uld^%D@fvy_Bi5x$sB_~s-@Y!5}?j8epd5%`zV{QEPXopwo`Hht8AS20yE8fj$Hv` zgU!3i%#0JrhpXG*zHZ_ib*<}$!_NLI^fyQDNqc*XfD961KUs54X$JrnTI)R0Woz3e zt@S$j@}FB!1G)`ia4F#Yhy_iDzzDhTy^9CugGWdx6UVIF-x3hu72?@OAc9`E{E9_) z+o6K6j@GkDD_Jtr+nxXUvI*k!-`__$_Up{As(k;k-_Em^S8%N!}^Yd&2T0LHpk!Y6#Ls zOAV#*o&)D>Tr0W@_j&XJeIk{E@1$Sdb^0Z#RjflqM@Q%6?jBNJ&Yi+<8)7q*2dw>P z_O`=x{mbQ{{2VYOwhj(np@r%M_Ls+dtLAe*UXRzgg(6f0Zd5ZJuh!L|M{k; z+EgZR`#t0%_98$*J|_WvUNOzfoxUrP8V|1dbBjD*iToA;^Ke{R=08hleL=XIIj(3)HPZ zx126Tz&>2WZ6ynuKBQkTDdxbyz<8}A{b;#q4EhG?#jmp`5J1-$W3%dvXZz&7P6Glf z4=7Ys_LG!?j&OuwI3h@v)Pet2_3iI|k@8Fj&m*YW2QU=N47Q*K+CA1^Jm$dy~ z=2lzsC6L{iCFpsd;B_W)77I>)c=Q!*HzBRyQM?9kFm3^)zhqtu0+@13d9RrCWnyCD zSG}>3(Qb3|(-HQgBXHqJpu^kx!H7}_6~LFQ(fI> z;JQ%czdoS%3x-=Su!Lxo_q6zH|X$2xzUl z#=-dmKtUde_|eYdK$VSV+QV{V92f&eZDE*o0GNFANvnj5Lp*`gM(e7?432cAszec~+0 z`zp|pL|hgK(WVWvYK9WT8;hf(V-c+T`Po&#o%vvi{LuXdW@!?bkdiDaX<4vM1F+!* z0BpCtougwuT%v2&{Ph0)dv%Z<@R6gF6HO4WXIufh$4!2Q#C1yq(K9rd6gv>ieq|Y% zVx7{#I^Hs{_R;v%d+XQp&mvwvKIDkAhetl#Ud~>*#`|!ieYnV-apxhxAHnHC-NU|U*= zSOkZJblTK=Y^wMj@A8Ncy#N-IF79XG=m)KlIbYOeA@Z|#`?qgDq?nKtUW@RaeS9)# z5@t}&wyS6ZF3xI4c@?p0$ZpC}+YbT8$pL1%(jy9(^gpHwn%EIszKo_+nv#-%r#U7& ze{aDY1G`p%B+{KC*FFlUMOFcRalUvA`me>^>9vVUB04_M=WcROHhNVK>;d48gPw_z z1&w;b?6S!(?$YevU?1}N?Arkw96qrahVJ^a*{|XAsi^x}><}e~P9&lRs`nCzgt_1( zC@3oC0D)2mQDx2*BuHEpyX!=D<{e%S{P(4!D| z2&di$Nvpb2%o=bGe}ecoF!Kxc&t?yYgC1IW7W9@*8>p`3wGZyL01yi&oROaq50R>qZe1F*( zgl)%jpeO1aO-V^fpXoWkL}^ZQ03s#QrKzF8DkP+*G6e31i0cyR``lbL0|Oc~{{^X< z=|InV5E%A&h)?jOztq8~p(7dcbo>LOg@wiPomxIK0Qq#rbWjwy90Kw-cL4<6w(=~ykfrwQg$)p)Z4x5suMh7KjT25l z`<%*f8R|++NVt8ml_Ba;c6to9|6D@|RAqI@vN^9=U}6?KSy79R%w^laUY=WoaA6+8 z#lcze6XW9QE!wlq(>CkA&Y@G%+7?BNfr$C+e*?c4Z4SaBpC=}+0lsL5xQhg(;45gP zY;0^xleOG`{{F4*{I|8$f7}Aa31@71b2A2qhz3FE#C=0yre`^~P^XlJ%ji=e8jiv- zvs?t@las>a45-vyxIp+IL6U`@F@YD9p1-;}Rd)}{^da{acwYY0ww1gczW}NQd85@^M+U$gFSWp=pBA+tFQh6 z-2Pj)Z+`|jz{torj!yMm*equn&;YrN>-8FYfqwl3y$b`en`yj;wt84Ez$rpQE+HWy z>uLX|aMqzQF|Po}Q*xW!X`#D*JrX^01Kd@w*5L*W1!(Oe979vRPhEJ zmAB~u48H)9$Po7n2V*lOEhe1D_H=K|6v;K=(3H}F0S~uro8aJJ^dN{Q%#R>8gVyHp zT|GzH{{TdQ=-<0))tmM@QxH7lC&DFLLrPg`DJkL5@lupP28aOx1&Q_d)Fc1!UoJ{V z?h?&SxkyO>Y@ilI!C`fjXG#RnA^llWSO7b0=50X5M%aEu!kGXf<22dq`j#&KVaSWw3$x5xbnEba*08k9>!ivz8hvuJ97~}vx-vu83Uvjf6 z%Sg|WL2tvYtJv2+R3!Dz&eDUzaR~uF(7#m9IWI=;vNDkK>eLr3i<%-ja|3`b*pl_M zp8@to=83s3#j1$E2N|%d4+`$n4{0zKWYp+M7Raa5(=Vi=2@29J3Hp1Mk=hm?zE}ay zT`*C?lU&grYP3||q~7|&MIX2yIWiDC?G8%D*}03F-i*b!~3imN!{C z{pkaQ)3sA9EF!X^gi?^%g^`^iy^8Gn(`{koEUtqvzNHTBf6mSSVA{ib%xWq6vdrL! zD|)EO2#rsBrVP5ACb_2~Z}^0TGBGh(_hpDNcj*HF6&4cuF?9C~Y#PfkseA7n%1xSf zxj-(ziNOFyN4j}~m9HWz1OS92zwdlmzUAQCb2%W zgg5v$W?RZfhAh`$WU|0bLc|c@!52`hG*&aJLg-L+xru)HV!SjyGV&Tf;=?FaTmeB)L$sH31;mK&RWjvz3P_5CvjY zKbTAfko$9R^T0Xhe*cyNg)bi((BMaluE-g+NrTh(+I*nd_k(@BJnb?2{?{)vjY6%t zxj7lM{s`~^J=kR2=sB>qy)o0I2#w@D9NC+sBr3FQ2hjFEzXb`B(jBldC7g2KiBRqwc*h_t ze2qPUU3K(pa#I+{Of1L($V*rLd(2neW~NL1=O8|JMJ}(#s~H zbA^fu7gR?2;>T<6BmP?s`!YR!c6&6W;`A%%RkF~Tjy}>!$#`jgAoWN7C^0`lk27;z zKMh-YWOB7TUj{v$-nM3Bl5s_OM_Q8xZ5x3Hw*LKJ!rE1sFtk2b=1&w5 z+_oT0Re1l0go}eW-aZ{Bs1-h~-%Ip3j7N`~|9|yg&QQ__IWYv2QcB$6dHfBpv=JoR zdmN^ZA2Y%5Yy_C@UjVb9r$6!WKSRJefpx=ClSttX(ldILm&fne)pcX)8voN_n9)Xz zjEsK${{0+^L^i-U^arG5ER%dzM>&-;#c#ks37Sp-{8cZ~VjC_urH3^524sSlVCr{9{j}-N5wY){3q1inqbbAg%@=_q82GevrI$AJU zdFB;!MQqhzI0c7<9m91{v`7e+(B@lHi zYySfF9c=PBh)hfZxdTATEx3mqi%T$l*OQr?EYEK{I-J@*G!%!H<6Y10S#~oZXa}yd zySvK0HW_VO=|7;DS2s%F77VZgVe|>Gl|z`_QqBX6OM{+6L0Vz9u!mjr_U%icW#N!9 zGB6;(?JVa{z`!3U)MWYA-VQ1yXp-4b`9Vi)hYp1{^`}|_=)qSCf}Dm;u+XV1v4){p zDQHM&uz;2jLBjzpLrz2E3ZSH57$W`+XbwaHX;7ijcoEd}<#=fs>ieE|N6U;aBS64; z#SedB!T1=SxVShPxs{o=M8oq#^FlcqqbI4skwimRxUe)-?Poi1K50T^Fb6|@*9_q@ zZ7!)DI|jIWxZTB#o=gW-?n_4@=}TcR3j7y7<9cM@n+PLAVYE7`v8f3kfzeA%fGhe( za?#fxB1;LnChuU>acYgO20g;4((w2@LHfMM#uOvyUYL>)Y_10z#Zk6}K4!GVBd?)vrXP@(T%cXD?AGS?9|e?dYo z{=ev8SRs7@Nf9M3|M`=>WAMM%ui(_m;ymEmctk|9YHFlli&(h&5HJysCmTnE zg?)w&9}U6q?*A(8%j2ou*MGkxib|7+RHTdzBsMKl8Wp91h*YZ0MoLtMvz>y+_jm8>o`3e)J6YEHem>9hyr;*(!mCG* z9YZ*RsXz5;vVv*)OwfY7-xoC0O7sF&oxa{H01K0 zT(7Gr>&2xdYT_XnRs}WtnYHd)H3xVA%~hRE(Hw)q1)*T?O9y~`UQ(hfEoj~%qaW!$ zGz11rz4%OjBOl&8Hxsor{7AQl3fn&6?0PU+4uL^rXclM4@SjwwIgU}-lR8N*ps2~A zE;FMeeO&nTLuttt<&yqx2JqBwf!(OO&>4o+p1!^nYV1_FAywj4!)G0UDY<9eIE;`{ z&`JFr$+P*m9n7nwBviL_qv*9bnex%zux6ysJyZ)X?(SsMC>q3Qp3KU^@Kj~A7aBIV z7Mdl9%*9zZ{rt3ufPpaK-}%I4ATi?-T-;$CAT(*F7Y)`jv;OHxTW&2-9|;GF?JjKf zOq8_2SrS=!LIKjcJ_MRq;j8B1ViDa%th3J?wdrJ2_wjjw>J+zP*-F?Z2m|8f8yXte z^sy4%O#%^4vN=3c!7v=xVv>5odq?SM!ig`&C4z>NM3ym_0oGT}Tje^3>~QW=ccHPESOH3b)pFX((OuRc-_htKUzWVT8L{$9T+}wubUzZ(v2dEy6 zLNkpS{FW=osRrREGg@l|TY9+z=$g93j9&&!;4uNv9d-Q7(uM#c(IUWM)4+}yo^KikR|JOHOy?*ymfIq)3v(QjS&z<;Zh{_vEA zQYN$swsW!)F%gFGdlzk8m||JU%fORJ*%~f(mFz7%*23s0kz&C>6KfuDWUm1Gdxh6Q1dSB*1OQ>CG4dm&&DK220jPpN%2NhG0 zS5XPXI5UA67#J|x6^Z0P=CW~cjvfY&av*$k?>ZC zROkaxHXC7+=wTfjKg~=s|Fe#PLEsQfD62Mf)n}Hxe#jCsh9*Lf5-<(cA3mrn$KaHO zXhTN6Y15|desWX-o$Bt2*;3|dw^-tXIeha(wgla{;RD2pGIVCxVUD`}M%(m zAZZH<3bFylx4~xt6=0!Z=l;()xlaIQnFwHHi<(Eba*|;IEO`BzmmwMjh6Y8W5#a9x z1V)&OWQn4sPr#u|E?F`KuA0@*8_Mr%T-)JD<*wOj_6{T~?hLWyEeI{@g`oh?RVD@YdEPZ}vACoQpb*po|qA=MOl$K#dG!Tvy;~ zQA3Sf$mlo9Ca=y`B4{*oo1 zKj-Gno9LKPYO)u&+XUM9xv3jmS2X8!pE_R>M9>US-OEBW)zyuyK5xTZh(Y;?GRmKG zbE}%5x{r~L)AfE|Z#~hf>3aizXex=~e zVbB-T{f-OT+woQaD2nMd+eyUAz|LVHlxD@hbnyLi$$;7(h>vePiIE zu5i|OYZ-Y8wy`|TJD(Ksjlx@Z#u~r<>`)t!kv=q&70XxbL6z5PdLHb3Wtg+K5S0XB zq5=$@B_@P7sWy8kFNC{V=m=n>w`Ky$=QJX9U`1X{P>H@8u*?$H>z+d&G2al=6j~J) zts>(@2WdcK^wZ^4)&_BDKc_F0^z!kMLYa5GT8U}A9E@r^o>(vDx*YBwT<^!{+0&4=sHyX!9I+$$NrUqrwpS zP?4{@3e#H~rstgyx!r8)b8^no;F~nad0~^a4;*&DyYHs>{H}n0vQ5qaFYOPmsL&3q zWyu3GxPQ=$eVH;KW1pxGna+<{`FmbdRc^yDeYi{bIL9zM5B{X5E8r%v@2r}PBAEx> z=PdpSt2q~2xoWYL6c0RMtC3<#<~7|4cL)$d?v(`_2$R2mdQuR5XXED0)R`X`#$Q6# zY6jd`9$8tV#kDMhjWF*TJZn1MkbSmi-SVZ{uoE3c{K#c=_~#e|!a-?3-;+UBh|E+N zOLpHJ^-}c3&oB)SY#p*1BZHkwX{g6AhLoln)Z%H=r=J51ybXdK$SR?*$EmmNZ1rB} z$-__MdB}VO$H=a8^N)$A#ZP z_zLHpV3a`bd$)6MTCdpbeKb{$DP$|R`sv&)^6y)A*p~VQGSh5OCB{#_Bt^S_0Yx=n^F2C+aKB}0b-=rfiIO;D0P$Et#>A0h#j`FVWQW!`G zkSst0fiH-mH|&9T?ga+~K81(@)wjEA-xmZaTFV7^t$Gquur1Yrh&Av`yXzbO9=HDw zHxSbg^uJkTY!E?K{WTMSEiknPnTq2}70kxmXK9ZBji}QiyGaQi92I>ON0**LX&@!# zke`4QyPvtJou4A^Mdyb)jeaB#u}6@>P$wF_mp;=%hb(kLz|?p|(Y%AGe=!>kdH%@A zNKi}?kHg{U3J&`Tu7j)w9aXUcU?>p;i3EVOsJJsxbGUa0`plbs^*Fwb2mr1DAKKW| zbPmD1MpUmn@Gx8ARB^YUDUT!>P8c7DPP4eKte4FBO`^&E1(9>Y;v8CFLKhZ*px{jgJ$gWtiOPX}XU2!JY89&rN z3>uwx3SYfaPK$%$0nhXdt_ZklohVywA2L_vxYMd0eo%%B<>b7eB~4^(KBT_|9fj6i zWQlgE3tY`x31>!U#tBeS)7MO8C^DH6INbl~G7q-T5kVD}fk~;S^$4*)HWo`bhJs?3 z_oG4xpsMM(KEu$5@!Uk(7baSA{&F*D1qskN!<3s8VFLWnOU@qXkSmAxA;vg`A5Ui;e#&hS0FXT3XGJLR0GT(l&1p+bNhR-ui|l*>(Fl3xgsJK%CYe9VO$`G9lTA{|3DR`TAcnz zuaVIJJdjteUE_h}2$)hRed*Fb5FBZ46K5=9n3mG;%iHhjTo33%m#;~+5n~!aPp*bu z#yJG^aB8Su(dG1M&>!Z>bMOt+wgMIzlm!L^c;KUC*zjZwsZZPAR(1r%XxG{>0UZV23oB2yfo+p(|rIfFtYME45z$GvhO$)1n=PLl6Uuv5GVHmiH7&G!|OY!A{gY z@9w@01AcuX4W-;#@dMz5bT$T0N?WB)xTVQ^ibxWf z|9qAR^7B6*GuZtBp}KJH^t|5os#r1RKA#QDI!=`qdL=Tl&ULSZFzbLLZ^AvS>iAGx z2>U8#BSqKI;giUg@qu}TUoj8dN%tA#8SLsYeUgUp_{rRuZ$#Qkhr4hy{Y~CW37~lQ zNJ~i-lp4kwdw?j6bn5FMei`{>cZ^GLU`3(<{N@a>QbeVqqQbri{Pk=QL$m_L2RJZ3 z^M@!t1W%0Xk+7&5f9e1u>~ZIg6ovlC8*#W&;QVjGL_u)3`mrOZkL%X2uK?%Uj-F}H zDH0lNyfCj>si&!0Iz$3vBSG`hljiBj!XiL_a*jm zy(IJI(SGfsqM`~TxZ)=FJ;L|i{E#meBfvF3zX<;&3l_NHa4m@51M;xG2NzWvjWr5) z^a|hry$F$ffTMOH(4Bo5KhOqHY&W_NLtyD`3AG(lKhx8EUV^OqH(nl4X@5Wh;zZa& zxJ`TT9k@!e`Yu@XG`Y?5piNYRFd0)fD#0N4MJWnBB74}wVQl!xX&8ieXMVI*S;X00 z4z9R^ILVh7T1wGe4Nxsx`l+R>Yb%~cP}dXK@b)CNtV-s=#P@0qFd@0|zEMa3t@3c# z*DbobCBM89*4&4c6|}Vy_U5>OJG59VfTN4UcdWNf-;u4%_!~ksN<03ikLU`1<{J(a z?ZGjq9tb;Gf2EV6wbEFcH0IqsNG96K(7n}-*7 zKa3l2QoP0QEB=Da> zdRP4_L&>~iwxfQp9O!1(uh{vd1X7m#24isJbiHj76u41*(D_ z&=A^cLi!CNoWd_7DK3(kzd&9c&;8)nm+mlHtthclb9VXY+@&#)cKD)~CZFKkYo#ZU zSgQEE^4Jg*zhJfFi{PMrWXI8gGWXZw>h}v9fzj0+v7P3&f86{=wyzLB9!Af;4j3K? zq^euu&7X%Z0?KVk*28>$i9_**dSF+m=QcZE!ip(cq42;U1V`ooXwF5|Nry{B;j!gq z+dq7Wzu0j{?PvqLu-gLkV>By&7USrrW}ZrWH`GK1QOc*zo_*hc5rSzC|9o{dH2KU> zcRpHrZh!YDSW8XAIFQo#n9sE-n_HKY(8FlKOfK-geH%L;pWXAE97F>qWn*X~T2tAw zf(MMS7B~SCj*tUXFiPYBuS#4bP_fyG03)ty+(FFrV^Man(UA8%!D!KX1+>#~v?z$F znB34>5*qD4iqWtQy2gW@_s;>JQS4a;zD{guqBcWwI7Vk<8wW5#6Q)e5lC^?rbPD0- zZWu*xp~hj~2`}cWD;RZ%yC#Ol6&r#E9+WAX=gs^&as9i^pFri~!taL?O@orC>JcAW zmjH_IJZd#6=LNX1jK5y*gx?XirGp0Vz&>Up7NCz7=%yOjRUJQ%%;-po+{P*toc`K=(t%0%znKHB1fCvBpjl+;t!KN8tw-YENH$INBJJmmgCy)=? z0F8r$k__bPXsuasoSZxlNHz~Tj<$*tgP~Ge94MjcmAISZ4W?8k9&n0Db}=qZjRekX7%am%)lo>3yA zhA6!RGk0jv?gd0hoavU;H<&*`f({nk|Mch%m)6ni3GuoF$e63-85Si(dJ&J(FQ-pz zhaxZgZ@=v6>3{Oep3+>>DpzC3D$UOwi@psw!t!9}IyaAh#cz94p}%FdeKY3;ey7WS z#V#}uXua))W@_M4^BQ!nGe?cC+_LV(C#;W8I3XkV@5ZD5(_cCDuLvKhlp`NR*G#~Q zipE2R9{9@Tp8sBy&cao~{pDqx@s7ov;19BIs2wkZ#P=r7R1Bbv(pW&@SdIZ$`!n???Q5(tq~r%n~vl+_4+pdt-ARz%%ihAIs@F|C7u0pcu1KxnrfOP}>~V=!D) z9U2^b5$J9{EDz9efs0)F8i<#)~R(zv%4E*i| zEr$?+Bwx{DEL}n#Vo6r%`MJPs$!HO7oM32xWY5Vw1lwpx0AN~2FQUwxLf6JrvwqB3 zJK#=8sr5_v)I!Fezb??<{LfQ!H>_v;P|Vw1UXJAF5X?3V>9izZkd+D}*O8CUe8XJ_ zCz8bgTaT#x0OQ_*0Ibe|ocppl9V`=!G6FEM=3u1>`b}Br>)hON1Rq3ItS1B*7+^fqcV2 zYb4zVHsfJ~w*0gHe9Ly%zDM06lqb!m&|Itb`AMq*cl)By=|r&Ba56&*A%dB)#vdX6 zHMbH=82tLiUiZ;oS)=~p^E6#*9t=K;H2+892OG43wa$YtSt zQFiI$#F%YPSb#G0zNW!Sf`|5TjUt5gS9dzGB#_+jTmHt4D^D=r;9a~;jtoF1Y2rSd zz|?fVq*%3T){Gf5IISV`G<4uZuGqv!4!8c#Nu>;fc8;WUqP`85Y*@!+OG>)* zmT#cxWDGvT;)WLbDdxHw3yMu^M4|~}70$cW z;-3f!>4a8-jQ~gaud`=?eDKW4UlzhztMOxDt_nQ(cCb=pd=5YT<2p<8`P;VvBO||T z!|brDH^~6ZS-|2wfn&fFV|SbGW2Ac0#NnSSZ|bAMK-`iNX7K&HW}~aw_cU)B1gpp? z9nYv^*nG*k4zBpbeY5exL1{%LT}#GLs4;x z_tN}VnXwoxeO~LlXA{V-rB(tGA~Na5IF&##;Uy-1ZYroIA(*T2$zCQIjvU%3!38!A z@JQSStTW2Egac4;2on7J$czxKy1}`qsOzIe3nv5re#EEAu~fAisYy}ZhlOhH5VV0G z*Mqrw8+sDl6QWKgCWOLg&YHCzCpa3FgIfy#D*}-@$*bH^;P9uiSypv`O9L;OGO3}=aq*mV!XhtHigH#vS+~|0yQ9D+>+CHn`@C#Di5XHC9P{z z`+_Ra_hUkfFqw~M;I-i+7}l*RFP}Cx#*-Ifz-Y0-S_F^8QJvOeA#Obf7I?~B!V+nH z?475lXAjF3VEVAxt>|O;p5&+j$%AfE=x9GF8sDUrzV7ZED2IwjTPWSv}70F;~L1Hc!KKC>Zg=HjIR7W zTWUhDUR?v)NQ&tNQYeZa#Sy`5y^vcAv}S?BaKM;z``s-fF-wINc1QfI`h%^!p>Awv z)$vEea0nj`ID_qxHz@qG4GI~htb&9aVn;Os>~Z zEk3(g<3DNjWNT4kiNmiSHnfu(SjhNscrA=NNSYyM?Txcg9FHSyj_=6aX@`=O81vv~ z@y?A$9=*g;1nuP`#UDSK-8}Ze52o*q=H-VdEB77##cVH8QA6w>9dO*ab0*Paq491) z3g9~#Hs#>w{84sr5M(%72_G{RdF$U@U0`tGf=g4G*t7aE}{d|jL#0~$B7MI1XrqjvIfwdIeV0pP22nQl?4=aWI00XQ(;Dd}i zA8G&(Lzowyv>@-04s^kZI5P`I&9KZhG_aIE3h4IwN)>VTn}<=3B_Z{SjIlNk`6-jW zV|#Xy;iDz6wn9)dE?#kRQ`!4NYiYYx&+*e-VVPsU9#(-?b`8+NN$YP>UolnrMbAEJ zZ@(6_o^GJcSKs>MgD3+j&wP3}A?ps_o5QBLRMk-@NOALfY>U91U2**gV4dBbli0GG zmh)5*O=mU@1nBp-aD>&1S5&HD4e|OvMb5Ptc;JV@j=Kl%I+KN2=kW__6_(*d(cUgd z9#k;&@y^Jz3U(Ul_vdJV2@uqtz5ZQ#;Hl`Yud znLsN|MjVv3bz|AkIfM$;Xk!pO|JDWr@I>aq9MSOQi!W|eo9=fEDiKf_3E%Fq&GbMz znif9SB>gD}%|?(BQMT9?*H!#WX=aA#^1PbOXbqm2ts>zKB#IP_hX>5eYi*4sc-H%f zoJ9u+RxpHH2OvcB#>`qj`1!!r%tPm0V&k!&n(2qqH`>OiqNIpl?WHzp@$39Vo2c_6KTpnk-a?Z*V zlRy-&wzgJ)&B5>b^@%w3v>lL^?;)q_jnPo_hL?N7d$`?agQaJqI5mO|Cb||l6lx4+N=v6AB`MvYpdyVlNC-noOE;*1bcdu$g9r>I z{a*8Xo^#e&>-=@j`>uDd#oBwrFf;e}zT#8EJ5^cJoo%e1vbvf%I$7D<@!Yw8hnJJp(%IR; zNr;Qf_J2O$j=iG=7t6IPF7PBI4hp*PWV9EsUpN+NgYZ(GFCNH9K6d}GKJDgB-Fif{ z*@u?8g9@X5E=Alxte!<1TSP7Sk4-7qxr9~L*PmBSwNsmYunG57dWM3Ur+>dNF)B_% z>H#t8CAIqZ?IY8TxCVnJgZB?H^~S|s3y#7(!gT^w`%{1Z6tJ@0ZM$q5%6+t;+D~H= z$_@Y1_M-Ve-!fmiZvsDQyIkhPSc3gQ=nuj3n>;!>|wT?)^V|no2e~Vs0H`NvWXRS4APW^QztjQrdFrnimIB$`8AwYWBNya7hJ` zuiDP2_PabOD7hKhUX>w3%>A(8EP~qE(B?u3JAaUkno;=YwY;u0%eBvB7f~`Lp5ooN zmTT{R4WyhN+0fX3RrJtE)pyiMB$Wj9G?2216m>|9l93#%$h{!td_l^aBe42TpaP}T zGg1^Y391)Pkr+BO8@TLE&7De+Tc?!^zJwYc4tLCY41IIXiN z<|36Q*RqgKa1h}oXC}vxAY8t_*Ocdx=ZMa^pL|FP(oJwT&*ZswIWdYJ=O3Owtv@x= zh1d`{#0DueoaIX&e!R;pp^q%6Rr^uiZKEcYreJ`(MWx11Wk|G1=-)KV)pR59C(G-a ztAU#Yn-|e0>&*VwWq8AaiYTdYFsEnHL5q0AIGeZ8Mk;MOR8dPf$&?vkj^4?XY>$ac zm5Hft2P$YscTBbk}~5n<K)kfiER%q=IgW9x2YwDTI5!lnR0uF%F~@ z7+$}rM7$MG`82H275zgTAKi_4_xm^_l_*|`;Yl$O+K5Hkr6Sj^(%DN?q z2aJhJZJ63GPMqOAs|`tVw0=CpIt~h zSgI^#@6ON;tuiTd^gB~zamnakp2k&Od40Qi>YWo(@;Zui8lTWH_ai3cVoZzNlco#XbGSw)Fnr5>l## zLmZP!Xk#a|g)T$SJ%#BVm65(QptBs_PBT&szh;HP-7^SjkUtIle|=IL*qybIzTTN4xrqvO0V z8LMQ}^(9}OPYN7k1I=C|M9n<1x+;#xenb-F`i&8*$1Q@D+j*W%?8anxs)G^@d{z?) zb&ncm9shDHNNa3d5yaT4#w3#bR13HDCQR237wH)`%g!4@ujm@{$R1udf0m!;Mx)!HMQ6>LoyCrN~V;;^hpfk&@2)x7dk^3$~2h=bJD=~d+W zX#H7@m31U;=A`GIPu%Z{E1noZMCX%5L#MX@4!&-6Qwp_I@cNHV1i1|3xgr^S58hg zngvU-j4K*jzc0t*r&m4IElE9=j0`_Y;{D-S`Qml#M)LJDN@Ra`SY_MDwL7X$I%<*W z%7WYDoDN*omRFtx9HZjnue`NbW`_@q-|p={xsKL2qYECZUHV>zlJ|^mcb1*ey}MbX z%~f^lZ^@_I<7molyh?lpmhRPHfue}t0T^-71EQ}ANQQ#8{B#h>;EF#z!Z^}(3-_Pg zmN_4H+6Ac{+hRT%036) zWR|WQ!^1ebA1W!Ezq_2(!_9_pyz$fdksGaIpR#5MU+ui)%+Hx3UtM5$RB%Roj>slt z^LM&9gMa*?i#@VUJz3ZM{qQ0y)6JQ&az3PSl|R2@wl^-#MK+0xdM(#3zm|RPhsLhy z-C@aip(Yi(NqT?2RkJf(%Lv+bN_hq2&MV}9_61kHOCxc$lng(hd|dD3#;3h~ncmXe zX!B|O1|i;cp3W^~GotpxWh8}f7umevAML)?x~m>u-!;;uOvmn5`?QIqbuB!2f1S<0 z2$>r0dW;bMZk6Q-*^Obya_`%arq5g|a8KhiTUZ=leNEfm*n~P^rCBu#LkwQI`crLkHkNv)|3Df%gEqAMmp1HUI97IT&< z)N_Yyjiw-X(u54Nu=r1lh0B-PIKY{4tei+5As=3-8XFQT6wU5?_0pfbCP=v8ka4Nf zpOHbvGp<6d9_MZPk_mwcqtWqmht5))yWM2t=RXbg2)viuCUeh;5=tHY;{bKRF=%@? za`E9VMuB5*PJgxDk8U#JdgtBhCgjh^F!?H8N-9ObqPBeROqW4Jgt?8EbnDyfz|@5# zm#Wfdi7#D7T0?$1HqdMg*{{|Q?Q%|<6!_d6WO|wEPd*qMm$WZoudh{JdJZu=S1|ii zlDb)N7c-(|bHr)7PC2LKODr zZ)6n?nrp)uITehP&D*xX$xRDc7jU&1!B4hAq;@&E$bWu(%7VY7bLzJ`7SZfbtV-dM z^tR-9JXhCVXeaGtvpvM9-`p@ggQffVp`_`42j6UiD;_=9%xk>Kb&-!mBqGQ*; zj&u9OEuO%nU#_aqM$7!wLD#dZJfo@xbUIF{)GI(7{teNNGEjrqyyL=ThaTcquN0oR(Bcq1~K5 z0|g>`3k74DLm9krOOqePt4%J21)1kjf$@=Tu1vV9S|=EFy!ES9E_KQ>bp`o(9hGsp zr}}NL*odSLU78|-?l9;qX&}NQXRiJ6ZOB4(DL$0oPUYdodA8a(r;oM1#<^$fXhu94 znH<)W?|5kBQ3z!QxBsVAzoxEI_uRt`QZ~gwZEiLpil0L0)Wb@`)g~1m@6U0irq=em zv$irj+Tmub8SVa23c_YnlpjqB!p$KwE$CYISc80mmt8cJv{`MK=tUH&t zPmRbevpW%^=M>JNSDs>$M%o2XGBow~7nOO2QwyHKYHNG(Ru^+bS~Nsx)Rg1?*HpHq zXT*;QIktLclV@&`$I3)Jw}TdZ(sp=Z$ERc@X7YC!qf-D0N`y5Yj>Uq z`h`j*<{r`$E@*Of+E*b*V2u>@ft=C5z?0=Q(p#P%!SUDFuz*%`=w?58#74f9? zCyi7-+Pj)@4$sQ?6?J!o|IWifCayhWqtUXDha0+Vo*7&?RHB!pJ_HQ^WmtWf*{ebr zXEk%fTFm<16Yq>aN|DO;%h8jyiN~Rf8HFc=Rw6^VyAprXkU$1cu3_Hxw6WKeZDM6f zA?IH`dOVvwd?a-dNk068H~3=5?B*TkSJXj0gqz`%Pvye*RW5!@xt^gPyelNNnu6!A zD-~oVH(Kb?M83}8G~*N!QMl@pNk{EFtgt1|x{F>gun?3@86!o7o{VcZp1leG*v5FT z)P^20M#)@bJJc?XU-61vH9YZqppbKFW292=o)+35-yE{v zG286uG?A;Ry>RR1q?{0XAH(L~Bjc>&cPV+eXW4=`-qsd{9#ZgORZlB9z6?t^F_zk%jV`J$>C)C#M^?DtEd=@`UCM7AaPCD%&U` z7v(w0SBSc`cGuRC$8UBLbxh4tIAfFNlCv#%Q-jnwb*-40{&Tunx!qs051LyqMBUw{ z$|_D5IgKr49>lpusxDB^MU@xyJq`UpAy(rlb%p*B=bIgZLt^zlc{;XR4`h60sB>q0 zdvJKTDt%D?0;sUG<*Yv>su!e&krMnt3sYgVWW%+f@A_(e6qu6K*Kf@Ia#vIa^`%`X}0^GDuKpE&F%2QHqTIUH9J#so~joC zG;5{w4>Z;-NApB(3mKfaaZ$B4pXzR(&M$CJo4S*wWp}28p%^{TpSRwfd}vj@{E9x%61a=}$KpQUCZHlBV~zo7atjHcCoh1euQ)%{lPn&j5YVxvu~|8N*em;6|}4tz7w&T z(azhajJJdt|1>3FMvlfQ#}m6|HrctRG5uyW(kZcV-;QRO)||x3sAkZ8AXV!}uJ7Xa zo~@pVje~lj>?N-$wad8tN^X^<-?e!fTc`%j8uxNv{jT}gQdUgg!9_81NlrPA;f18y zo0fOtG%nST-VpWcbyD~*BKDS(`Zov1Ln(i|C^-4z47OepiuPPg_ei@FeTuW~@39eG z(O|zc?8mV9;aE-D2j`v0rEi_P)SCSE)-o}&GDJAeFP%wcCF;m6!^Ml~lhcRkWnu`d zY7xYeE6~!+&S>{8lH2s5$g=b9d)YFjACcj-g0^p+pZ~ZhA>eZKC)+4)+xg~jdj!v_ zU)_R%owOE<{>YKsP{@zA??O9wH1-oLl{Xd^_;KHGeOJBnkac~_8bNmHUQ0(#{B=-h zK;MbHgM4-u(YZ6f`0rBDsrAafw_U`_oB97bkDg{3E@_gWn->PtRgnaXT$Cj-%8_q; zLa~!WFTRn)|_HtM(&C&?(T=tIy2oa3TXxA%=4IwK8)4Z~-?_A5f6{f|E4EYG^$ zxXhex$G3ZKXc86HK1pH{O!tF#LxaiZWoe{2r@iUbrjEVmUm_wsuPI6-1xuz`MYa)| zeHtpGbsQND++rBbnUl2-#WXjaAN10qAH2^M5Xj5WnB^w&50^{%m#_WvMQ4=E1JpN1 z%ZOh?q57T=iPiK~nB5fI9wX?Pdnp{7!^Kub_$HpIz!sc-tdGmvmq- zG4C$=xU?W5>bPR-spA)h$Tp5xRZcFVyrWZA$L_6Xl1xNjzkP7%PffnAvsH^{)Sd22 zE`itjS({ZUm(Ko~c(vr=7ghy<;Y)F&R1+7Mm;?5{)ue1aJ>|^2xTJR=_I$DL-Amqa zO&%)?TLpm%-#4^n(iHqv2GU)uJ|1#;#^MwbX6E{K#W(E*jUM@bdgZM8NUdJwaBu7G z?q~d)*TY7l{}S)Oq%+F?po7tb26(}12UoqnL7cIC?!wBlx;qqRZr_ zQ_<(7FA+}8CfYS|S_zHxk*bni+od z5e}u^m3E@k;^*`^dZH9wUo~>{B&xeHiNNey^8lNxt=eUZ{rF&pC`6z&HW8+ z11fP|a0WYb<0l>2K=_T(K`&HMdEFLA&5S%XegWaPVC&d@ful&EGjns*=t2 z7J5!aE8H74qXvW=R{k+^u=-ElyTWXulygPhQAl8_--E@9^ z($}ncr!dda=}}sik?S`JpMqfF0uSmp8X5jOPjt^&xtdxi1PBL2&Xr%JO7Z7?IVT@k zt9)_9DpfkzR{&?3!sMy%W1$;thvX6*3ON)PP)x_aQHH;U{n0P(wS~SMcIOpvDI&HK zPY~5f3#yb%aSxwCkgGbv%E|dhuC%U!*dNbk6#% zAK4Z!@@iNbqj2J#RhTG)b(MGBPmdNYo zX+&1tPwCM!pX(yuoYWId3$7K2Wha-49$a#>tkt9gVLkgT<YAO~yiYFV-&ySL_{71K^v6c#I zlnMf+b7FN;QI#q6g(myG(?cMF$-#zsniney;MEaE zfu!ZKTn%(Tx3a3zb7H}RoI~NcDU@nU1y!-8;O@TURX&H9Ul{oMDxaq8(tn(R;JR5> zrP?V%t~>LcfxI-GPmqVC`X$+m=dHZ%p$yR&J}MuL63wThzeCRdx1kX6`jLySVI7c>vR2T__-x!tdKH}0%@z3ew-6X6r_w)0Yv2U}C&f%X-m1L2_y4g8lQ1$-ZiR=!e-#iwR(lKHwN6wUPV(!F zj11O5e@a~2iE{Sk)e^QpUtW_XaGMh9RXl$kOvCY|r-%I7!#J5ApUnocl^7l+-XmD* zOXFI8{#oji@5v#hl*!+z8ogrsiEC`ew37yh_<%& z<01pP=o>0+@bzdhEHqT6G031qF}>!VPRQQ)EyI z*WU*O;Nhf~l-w;egP&YMhRZBeLb@s{*PW6rDjiObJ#J}!ikacpsB^VdR8+i|)MPtZ ziSOSQ&SX8{866!RyQZ$j+^Tutxb4=K;Ng3A;o*byc|uTVgB{&*Z1CDxpx81UbQUaa}4FZt@&=KgVF|%F4k(=5x3ssi#Me zm<(jdCJ5LwE5_V>!fSlAxBdb%|KJ>x5U=>Bj^H5E_HZ0Tugb1)w>I0Yr>l$1Wo@)) zNXP;10-A18r}U|8x#fVAweH#J2@b-}&K?vL)ZcM*dbBY&kSXuJR#>&!#$Z41V^;VL zM<3^VXXls0-L-+NhqN)b^)D3_6>V;9Nd^#--?g3Kooe!%{qs4TQSjBTuWvKu!ss_K zm{(+;1OOn@ZFdZeU!{kPEOD39}z)eU}&gTX`}1BK0(94Z_~WJ)VI61Hq#&+Na^6} zDraL;(BWw_S*g^>Y5{HFIYde2`e*!Q)vPZ=OG}G`lT$!lo$x2^;_&?$FAD7<1Mb@M zN(TW%6oklB^$R>WSJ{f^BR_xr!a?D?{+(ja@!R`D2mkR7&Mi|dQ*Lv2_cdI-V(hKg z^nA}v#!H^ucUlbXupJsNv!H;MdgJep#N1TFm6ViR9xG<~^7ShYQfA)se(f?1jahjC zk43M^{P(C_wM;@0QBk!F8Is2ZI#dl_`)x&rb=^hLS*fC4Z^|tCaQj8q^GL?^$}Mq- z-qxRZ{^akoor$wG@=z4bxo6h7j2`+o7a?Bav2E_|>G>4qN6jbc)UNy@;Z1h6hSP&3 zmQRLtl>;~xP_<~KWPZBaH^jtJp%N_}9f}%s;4wqEIa+Ox=Rlk|HBb zv_#*YXHr~QSy}umS7+YCK49LH)ZyW}F=Ja+Yco}?wiXlJD4!zaa`V>aMc56lP)=@*Eiip$C`ZH9wQ|PAauDuc5Wmg11QeK% z+41pqpW~sxtoKks3SDg3$=pO#9+sK7y!(cv2ztt-jUyseg(RXybCnzXL#Y(V7M@Pq>*IsEmIq!L2 zSa_)V#hfKPx%1yC!9(clJh*fWCOw@s<)_G%D*=k}ca)G^*b{PNE@!7cj?T_kk)6e4 z`&C1uA_GBOiSY37;U+&nn1L5l?!S1YoFXKfuT?nsoWp6cd!UZF2Lopn1$9n9NI3Y4 zfNXiZ)YN&gn{J}yNxzRuBra>=g-T#W5)4AFsoi^6&ooL zoo7skCm7mWpUl&*vcq7;jQvtl#r^D@XBkY3aTuyR?6xcIw%a3E;=As-gyg)*^Ivb+pNST~3f(Z6d|g;Lxh;Z)t9b3( zyNhybnwNFxOW29J_-!YKue&HbdUTbGiwjrc&Ye4+`+iX9qg=~RzP?#O(+SvpsGk~V z-FZz$+qn|cw8tmpybLRtmDRtW{LVW3&8XA{jb~$9d|nnMK@9+;310 z6zW%nG6xL}4(9qC?cw{^*VivY8wptz88_YW-(H|aM z^vt`Brn4E7hQ?#e!x~17hV?ddcDDMnXXw#PxWTZ7!x(aQYt2)PjEsal*sfgZ(Mzj= z)~OGiJSMBL-G&+cxKNJ|SHi3_=HuDPh95OEvodVm*d`76F#2mbP0lM9pcbR@^Esxg zUwr+&%l@L-Jg0zs{HdvFM{DbAL^Vq>cKJt{1>w;13}2+&c}2a@48TU!vE(PChS~u~ z$16NM8mC!;FMi83ScMYUaC38G-ac!2MIbj8o0_Wp^5si>f5P*OmLaROHy`3v8vC7S zDi?3W*Yd^WG~_5Ho8L8r#YjLv&|&N-sIvA!+|TGvyQ(lNn;`K`!`gCX`;J5&i}`z% zcGJ(xXSTMsFiX$cLg|FMVvWxq?QaO^#nnLFUX8DDT2f9~=;U%R-4*vaEFa)19v*&t zpjaMtMLwxO8@3)X0vn+7x9z>F*RIK)8k|CR>2<*~N&9aZxoC9T9!)J8|KvZDvYR~4 z)5!TgJ#Cn;oCGJtw+#0~=4#5{kq@6vcZO67_2MrWU(@@>DCmd}&5QV>q~A1;jEtB} zz%J?PJNq|BQE1k5vX?Ak;`$|!M6Qc_3?@G%6H^$2fZflD3Tv2N^ma4#?*N$KMVhlz z4a1IzOiUy}{`L8tn(`Kggpef(*q=x4zxW;4x_0YN439%yUEL)5ky#y`pd-4)`I=%( zb0kU{LEz;v=}uws#=dketHU^m&5zFny1KeTW(M`{RNBQx1gs5Xy}iA9U4F+~^2ngX z7OWxq!m8rp;(9St+m8k{j_$i7+F@~7eE=~jX=q-rjTLv9bUaN zsIN?|LOsHG7Ew>?2xd`SlS3XHiN@$oIHq&w-&Z|$cfWs+hv(P)d>||qtJ`E`WOzuq z&5yzBYxmwj4Z^v8w@tPmM3X3|iG_*z9Hu+33}SaW3=Og4P3ge5Z@&W6K{jD%%>DUM zmaAKKJ^N82+tO^QDUn{K4G9GWMRiThM}RJXfL@QD-ck^GVJD_$L=v+tk*J}nO4%8A zJH%`M?=Lt}y{?!lGpotU!jau~At7G}vmS22l$skY)Rz-ygzC8zUtCX`_p~+Ge5q`n z^hZVpG$>|!e*Rf^N6fS0^-(w@rL`$kp)7RS*D33n1ST`&qH62Cp&8i4V4- zqM}SycGI}XaK5(6Qixy<9P1pwGtYQ-@r!Yf6qBQ(UIqr@106_AX{S_D-GdEmO`sUT zA|6+KvoC_gsitSG-PY)RGQV+|xe_3uo}ZY6gv*c8#F(Ury^q$bFh|>dXZwB_+lkJ2 zu80fQ6n_FMxh(3*tDGwG4%_#a##%?K-`-BM^ff~yOia={c9OaxV-Jv@fB-SujtiZ- zn(;sZU|7(=v~GuTeRTT%fs#^%JJX97FSJH_l3Zw9vmVCBr6u#k`U~=|x4o~-?#{t3 zocn?gn$}~CA0tr5?{4c?BFO4!VF+B^+I(L~<#?Nc--A`X zFz>sXicU^Wlolz7iSJf-Pn@I|8;#y`rVW^Dj|d2wH+o&)W@{vFxBX_#jKj1ov}Gtq zg&TOnL3c0AO>X-c5oC~wA|o@CijM9bjMSEq5t><_eI@{gQ8#u=@%Kw;c;Nixij5i~ zV`A{-<>f;e1usn3xyfU(;L;Kia4cY~3Pihr4|PYF3Pi#jU>nA8>JFMustyn5X%HzZ zD`R0a)J0Tcq7_El)|d3$IT=_WC0_e>e)J1gc`#0n}Fe997Pkgp`w-t_f!Sz|_J*D2gY;NeDKQj#sFssIEUGhbG z)t!=>J32@<>bJvZ>V18Efx|Szja4hutMER0YE=4^0BLS%!I2MVlw6;v*v;k{?QLji zKm{UHi6i(@^tVa7u`w5UH-MY{QUgmOzZ)95~Xuk{bfy8@%6iY z3ai4P!Bf-M5;xp)ch#z)sD9`>Osa}F!v;?pIK;l_!xza_4Zmj=!xHbAk^Y^od&?~9 znGTd#uL~|3k!ZXr`CwbGSNJM5{`qmtgUL$Ug};Ay*T$}hicXv8^%P%40ODnieg?$Y zVff=={2e~MaIsDbV@1W_7H1f60tb?Oi-6x^)@q)0yf=u|WIT8IF7ol?M+D6g+yr=| zY}@?VGn1igCB0(y$*|9&3o)sw;qU@@k>`h#^2;3^U0h^m8+~vTh>ns4?4PcU7Gh%i z+LRM_S4STD+J$hLJ6TP9D0MxrAllPbe|orvpaTv8!rR=PhJC#=L#mt!eY?4{gO6ZG zn4Y%c;_FYE`5CV36Bucp$m5DJqajbjp~(#Oync`*3e8}6j2>Mxhn-?uTwUcM4MeOI zw1Jpgnxud$DtaB2n0Cog)lN(2k&_mK#;*JWspjpH75DvVw}twRhW*qT-nSGiaZB^C z3I>GpK04ygfFeVea!q9ETTN$8@VTA>A0P^alWCWeE{_ev_egFLox5y;8P$LtO2j1Y zJ7t;lr8!AogNn+q+Cg$HP6%pOK(J*CaK`dNyz!`22(Svh=pbe>ZykHzp7}P!^55n! zxv{JdPF9^U?86{x;7UOIU7wxQHull%6?R#D99{M8N28ChVUw?+MPha+EIK+vmVprc z9b(k-@<68NPya)uc03(DrP|0(4|D*S~@iHJ8_Aw`Xva^ zN6Bsy?$VvALQ$_h%iCUOC;JPB^Kn`K0}@s~-=>FVe4MX!8&?8qU@X}j-XOmJEvKU8D@lpTaSxcsvvfERFI znVr(^e8Vy8=MH++|Jc z5T@w-QB9#ygOGrIgkcH4$rZMVDti_WPtVSSuDII|S-dxKPJo9xgR~;#wa2+W(~!K_ zop{C1=B{*)AQ`^#wi zHw5d#C($CxQvxiDAd)!^y^AV-&b}3u*b&A!u*dL z!pFz&-&q;5f}V2z^@Tvl19SBRBmrK~Uk*~grg>xDb=dM<0x>PTxIRS(bu;W6}~NWp37v}*dy8hz2X%ER|#9h>>ex6(&C0ns>ny^mBfmO zK+1C4Nq(MLlB3vU|FEE&Y;01EdF6r;*-FXu^*%awc7cU`z%HFJX~J&31@-$IvjX`& zxPuL}U%!5J=`5M=3JJm}*k-Domjz9a>51@DtD z_>KS)t&P36T4~K~^SRS}5A*696k+K)io)heT-()|+^gwvO0IHAzVY5}NE4J7#}_XK zCcW}_eGZ)icIiaiO9tv0OMc`{5!%QM+NO;b89oH5Bcr)l!qL_BI*`0i#!X^MDMGP- zXBwGm>y)QtHs{ZT!wjzE^a&w z#_Bm`Rg^pr)jh0C6`9c4z0Lon1|x+eS95`ztcn{5;%?QdUNDdrH|cqZFP@+F;-JvZd!;JgEf{3)f=st zl>soezl*Es5r=jWuZQWsW72W_2Q9HZB&f&8dmO9l*5DP~SbNev^R2bDBl>~kB$v@d zrESO+`S5gr_=HOm9G%tcwBoG|J$Qq%%)!EMt1m`v<%<=3(*~;`f&BPrqX|Pzmqa&A z2M_F7;=;N>-GMnOY4j8ZtaGORmfE(Hfz0zLL;wu!}}FICpSfDslyK2#e%Az=o{ zESK*)q>D(4n7(GJ@;LemS7UDKoyEvegmqhjiZ7V`=d&ls|M+-{*Z;}KQ@Y~cInDk4 z?JmZwWrID|K2uZE*zN7RTId)5Wx}LBs>{B@b)$C|kJ92E3TsN~4E%)j&i4Q65 ze9`VGbb;xAx!wAXgpYb+jW?q4@H2ua) zilOQx;|6GEFkCELg&BpMb36K8FP4>hA29bm!E;_l848uk%G;eLT`88I@F zuN?u>K;g7^+0`32IM#A9M1u1n8NCt8trc^Q@jj*a$<9Tjd2*8B;tge)xwf!hYil8s zRrYhxnC&1$2ZDwJ<_I;=gyo5f{F%=|#L#T5Fm7=WIOvwTjm8k*(O=u!iNIuP1VOAn7;;}3tXQdSm<*wVG@Mh?!cjP!>VA|pwXf( zguVrCCnX_)fcT}9?dI$(b8@&lP@u~*T&PbA0-B_W32Pu_Pi_o@xp2k@0OJUUvU76Qe0;`=3?1pRfMs`SOL5nmQ0JDM54T%PTy7b8WcTaJZb0ps;W5?Y&XV zk{bD>$qkT0Mpib_@I2L%_HZV5ASG0cjOPRd1gh)mumi#!NQ483}zMU zSwV?4hA?MPgCh^N0obzf@zEf6ofaQ8%Ia|56~7-?i%>yD zrRup)!7^}Fn)A#e!~jM(jT@&H7vgVeD*6^3KY~~wA$<~ys3KI}zyl(rw6ydepg|mj zL#x1FG3&FM?YcCTU};zIt8d?AfSVJ5GpScBFDJ)#@7@JasJ_8{c@%dMq(`F$&tD*| z33aitu~AY{y@X1c17*AgzE^nq{#mOAT>HXOo39KdmECM3IRca{u&Jp@ISB?Ivp?_o zA{a@SHLRH8?JWYrHK->RpOpcJA&9ZDai*vODh6-){X^9IcoBCG532?-U=$+0$Csh? zq;r&0Z1gPZBDI(FT1>|i2%rk{pph~6{ge2t2Voek0Pb?0|4x-8&PQ};cHFM061 zgzaizai)P0dBd1$?0@$}GQia9T`f6H0QA`5o+IjGUsFxOV z(DUW=fsfKexDq%xIL-^5G!1K=-@ixZJOi~gJ2&@cvK^V96^##YvzP#WdwcsskhA|o zHLxBKKoTr#x5ER!haafpqnuDs0|k}(QbqH?OP9-$+yoi}YRSph=}*U$i?22hpDNlo=u@iyjD^$#O@~e zE%l~2P5_{!L~dypG5UZcK+VFUVr6B8HQQDPGT(lNJ>5<_ zvmAK=BZhyHMP_P`tZsSP64DUVIO*W&t#DRpHeaHrR|M^hZ-U_%3Z-zyWFZqoWvull zxK704on9q>x5=ToEtq^kvJtkI+>n_2X7f);Q_Oq^zCWy=Fy*lHfpkecT#5C`sy?M% zm(6&st&*p$q@UC>-?Yr&0qO%al>umnuKnpo8)189aVEF4$~?SmaKDWNV6b@iK9 zugWM7ebVFrLy8grmMXX^DIy;4q0q1I>wrzmBsBcSD{#{H$ylkWJgx*d8yN)!oGA-& zgf=i*Ghqu2!dO@V`dMz)b;%Rb1Pa8GFzPa~T%qR-uFVs)1ooRZgTN8)=w$TOjgHt`==kIDYuR80 zLq}7AoT`UIyD8i01C_S=nbR9@nE9+n%UAZ`1P1nw51dwKo0_yDMq$@tO_-RdD9I}O z*=%T3EGffbja8Hd;WJ-Z5N>e)^S3~S_^Nv$Un1C#+1?&XUIb`>vH04b3G)D3AO~mf zF5Z~1X|i1Hux)bCt8*&B_3x>g-hM~u4 z1Q=Fy3j{Y@1f0QOkSz3K&cO7=#;_O}8O!a&E5H!^*53YgY>XC!&sbv$5|WmBkL`XS zWH#d^I1l4E*`2EjZW&aV$-Z~ga&`Kvxer*Pq4?6C8btS%9OGrA|m9Qd`}PsaghR&ad7i*i&s5UcMjt=ZDYN5jR4M19zgKISYMhr z1p*2+YHDh#90TbmQh#a(IT@LB@Zl~MSFvuft7-i-@?5!gZ~#t7Saw)g7~j8NcKzu% zNM6qErTMzhAHmmku$n-kR^s&~3S#g+z>!lw6~A|H&{Eg$WH8|{Ix@I88WaH0& zPhpi-BQa1~Gq;aL{7ydr_f{S&Hm+L8-i&pWor0QO*x!%UHsZd&wFHA^;a~*Dnag$5 zH8xMk2?5i1kZLyv`&h^dmTfK;3kkvCv2Ix7ac(DITX|j!{6h6kCTsz7yFxRN9BkXd z8)RfaE-Hr^61`AhSQiIXId7E!wzGZNT6&^t6%?3fy!}i)NFf0M0llS$JiF1LiL}&^ z7Pbs|mOQ<-RG0@qLKYZWCK$+r;4WK1uwx!b8$?mA+bd<&uRnkuw%YpL>b$e8R_ngS z#w6?-%5OKN00Ee6AgGkcM3Y~WQq}9G^59BNP~GQj1=jy~qW#+bZLo;-PSHINlhN@Z=N6_M-Y|p6 zlL7vh{>FJaV8A_7{yiVw0vancZkqYyl9Q980arWC!=pmN9&CJXU1A@Tjn_z=<{K0^j z`4FI54ltG|n6+5x?f|p!pWgyXn%M0JkOzyHDj{%`(b%KuG@`G5QSExqjGS{G<(iT;;V@_!_;Uw{7^`ByyQJp1ox zvSMR_Jf+$UHD@4;|NUqZY$Uxcn9z^SGl7<1n_ca{{ss(Ky)qhnDj+T##N6cI|NZ+n z<%J8l{*z)HMp)(UChPz}?n!piie2y zkgdBjJ|Q9KV0-C*1SKH@3j2>6%uxvI%mf#j$r_rQU-v!P)$aZvcoFJL7Bpun$S{MP z8c|R- zurZK8%74E@xC*9k@4XGe%;QK9_#>)7ow&6OzO}Vofa0q2M z$3!P2D8SAiOr8P3yf;nU-q{N}QWgPq*Ao)HR?$As9yvOG{v3X*Gqd`ZvE6C!WmDM> z02P}9@+^su1OQ`V^N)x>B>j>!T_Laj<~$QA+kfjxJ)QeteWn8#35tk#ONo0$E)8wW! zS^%OfKsRv9TYhS$kzl&3(PX8@VJq`AvyG*49mmXsN;V+wGE5kZ z45T08FEZG<{6o~nzVRUYgDdC?LR}kEHPRsA;rj!eSq2w-)Fw_1s8kN1&>>I@!?HWN zyU|#WdSe5UqoyOZ0O@YUZ-KVH%-Q$-I~M07mc1VY^}4V^(-Jua#aKsjN{SLlj%>&d z1iADz#jWSHDHyPykth|}#3p`VjU)bme!tAl&OS>8ChNW3BLI1fZvf(Z{xbc8$83SK zfFNMGyaX9`8J&lPIelpqhyuVh*fu@W)LP#J@85?sg8TiSkZyv!Q|B3|T;rcy!2eYC zEh-)p1f&RJ8{!WFm-TJyfeZq$QHhaihhMLhX8_BxadMsmf)9>dxaMw|1(vv9x_B`_ zMeG0{#7a2`QDP(U5H7CYo3Pet^cEZ(8X{l(f13O9a4h$=?b{Ht6b)pks8&%KQ$mG8 zSwc~fDI!zI*wTZf0WEWxGNmFCp-ho6Aybh|ktt6|r3{5E-t%Xz{q4QKcYp7Gzhm$B zINtTwTC4Ef_x-!C>%7k4qN%1&QxnVHedH-nYCH-tm{hSiOliHV^V4fw7 zVg7E)u{i<)nr(h|oVb6qZ|_?a&|2xA30|n?rOR5EhKDCBSWa14F;TD`-pgn0fY-)r z4&a`7(IOkMQoLkTSzX=1kx7h${WvGY(G6g8%IPgT)8~`szuMra5paoTp`EI;QPk)$ z7yNtzCxuJ|#~xhlK(QKn`(!6kXjoZUi++55GBuo%K!hOF$F(ri zRN&17FXMM-hfqXE5a{8$Wx-N zlaivQ9E`-_3G;|L@I3J2mH>5n?n^HNaqi>Hk*a~MXscF1Xn1w!(N#6u(=l#6=k**4 zfu(AS%fOPf81SGzfQO@~6JFC6)05;H04fm%CDkG>`!c8n$W;CM6B6Bk&xAP5wZM3_1}PDu5DD3O0y8-nRnvmiW<~ z3J7kivu?WM)06{68hl)T|AGeqNb${MrwxmknYpO@=nNKCRx7S;?^TqQy+JjC;z)n< zz6)8Y;}3U0bHuYxL~Wb;ke12u?GpaaY8)UI$`h2&IpBFJRlqnAv(5fC`pAfFqJi`# zIRr=+cu#A@X3*P$lII7)4spR&hT-L8-%}r+%ux(lV=iuPZehcFcJH2eZ&A;?j#*)< z7Yj91hSqpk`lkjg2?ufKjp-jITqY1=${;~WQAMvJHpBMEPKmqkR->;Ht0g|)Nf@(u z+R`NZyn{L-px6*jgz|<#^2Y9nq{Yv1{0NGo8s#_U5SIM)O7rRR>j6vPd7-E6h>|eL z*m1AZ2<3gu1qUE(*x1;3^1THI1qRe<^20GWi@2l2ji2J7Nx6MCI(qLg16ofdtQJn- z2?A<0G&G(;VqsRADQ^U=o;ZBo)03RpqWQTWZ0ziR34>&sD8|XTut1|^riiT+-$NB# zb{1SWa`PZ{i7yAHMdH1KZ|KH03;$!Q)Y~J9J`^%R`qPzlpSX7{+k)v93e&}_SAm4@ zp{0(E;O`Pj2!lgNhs#MiO9Ic95~!!oTUw4OoDGkOIW1|A7DKEjR3jWB4|WF0rKm)t zWP#2zdlU@YN>sCiLC*8^Puo@j28`h0Od$2Mf&!CxOL2a-`D0O!=Xg+;xG$&RnXnm9 z7upLJ;D!W66R-224#un+>*@kdw`FKTB4PF>{{r8RjDG2IB3SAe8O62GK#ed^ct_id zJ$A;(*t1hpK)+u|<_IGK8ylMvpuZG|m{}NCWm2Wh`C);I%sl09vrw~TvJde9J3|<+ zJ7^Ip`!HCNe9;vjpOaue!Q51UJG&MU;e!u`b8Cvxk+i1PQ=x%$-!a#Fx6^v5&DI7* z=cK6K7Cn=Q6sl$z{c>y^0HrRU@iaWV;69m^%|UlR!)>J~c%=6t>co-UfEzWK2&aGmcq7Y4voJfD zVLqdhY?QY%2nd~DR#jQq2M+D(Z@)>&=lVHs2?2zSHj*$`$M=a$H~@i&qrLw3W#+&A z-^9(1ivVg%=&5_RZ|`CHBcLS`Zl8c;;uD=xuk+J9oAXM3x(EP$!sF8p*aUQJ8K1*1 z+wQt2{akH8v%>q+Zwqs0yV}JrgJ^JE5RPC4IQPoPQi`tfE?Fzp3U)lO?-Ye;9bP@5 zwvirO25M&zJNFjT?jqVB&cGq9`?2G>ac;keh(bXBwGsj;!io$+4c%TC_jl_bg3LKE z$SJ5$A9gmYpBTI5%s`}{@0njBGi2#wFqdIf^?fcBkfT1)wh*zr7d(}Go(qVq|QV1xT^gw zQOpfF^6Is>sTsyXLLXVWp%^S$$9$EIWTk*QgOWpngIhoR%88>2fE4&1xr30|uGf40 zq>hB|bO&7aD0w-mhjTQYGxyNE`U}Li4@tiT2S>6RMTzP!U$IH!d7J#UAGzRPLH-G7 zj)Ou45Mhmuj;1tBjxx2Ev`yobRKZi$m~u!EqM52y!TY%2O29;D?fJTa{{G8NKr;-*Tvcz=2Gm;%rB5wq#Y|=4GL)fU^`Rx<3O?k_x~mnCK8dY%`z= zwxvs}5EmHuCDo6EPe(*TmV%K|>PIeQr?D?zByE@G;nM1+!(H_FJTT-n;>+w#INS`l zf35(&WzVg-K#Z>d?(KE+FL( zX-3Lin4P+Pr=ImXG?0 z%NbrtRv5ejdM?bb0d4IPwAFAD8rxDqk@ghocP zVCs5(Pn!w4mHhrdUWN-7<}bb3t*er5QhK7K-vy6uOjUZ(Z9L(}Ucbu|x{AztQvkGI zKXyoi++YEus6;?+K);`_c?zj7;zdBX;T@(v6#!{CLa$=t0oGZ8?q`i!O0r6=IjdD9 z&P<43c|IwYNCH1yMYI*iPj3hynk~@`oF*M zR*qh+j+>1^V$A$lAU8r2vePu&8JzK-vSb43f@gj#Fh4a>lWgm2V=wu9`Ijt4LXh*u z9qvEODYzzK-VRU01xNjdx9vu7W1Mhf9u`%ks4Va_|Hf^->4)W<2iUG~A>@rlu*i4~ zZnmfi3!M#DT!E zHx-_>t-rZP0NV7X5t1sOt`1DC1|@BuGnp=nB76z@QI{8j>J2YEfc`XMwl7AhzMPpU zL4vhN2f{E|_Ws5&rOUlkeguuk8xW7#i_F+aPd{wSlnphb8CFu$NVTzC`)1&PgPk_mAkp=rRimVt+G6 z^*1v?R+Y8*xK2Zj>)_=T0JM)E@XK9__VW_hK?NwC|-sSj2oQqnfU403DrxzYh`pb zoFtT+zW2<}>3M~~P@;+{Ox^}B+dYV%3t2-E1%(sBnwFNyHD}i-dd1-%Hj3mxQKKi5 znLq!(T*47^Q{8@_{BKph|KYKKA=QpT9I*37*=fJ%vpNUX>)D46n&>o}6#&=zQ)Fl7s^mjyP2L)Dx=or1*CiLMxpw4^l*GSqQq)L=OtMJ!njOMszQsCvZ!4NkUMyxQvceu$Vgw@btd8; zKrrSsuf~rzwwdJ}9eflqYo@j7|Akyh7x$BL0XxNxh|LwCDb*Bi&?>$kKiaXalZ0N9 z)*64~2Ak4MQ`q={Ao!|0)lI^*NE(dLorG#a!z(MlZS5lq1j4-;?Ltjm{S|G`x^)cj z+{nVy4p8C?9cp;i*}Q%=35g}Jvas-LB3#c7$ppSlqG3Y2Q^xEeX3zt;LkJqm8wNPg zDrUMRAng!@EJrf}GpG8wE`SaL`d_^|cd)g>k`BBf2d!)=b#C}>)M0QTG=2Dg)+%~& zfd7ZI!z)$|ZskQ-M8sY0919DJb-0yOFO12hS}MF!X3X&ZNkMf(lBzmge$}Sg#g?kI zIB$f&A<}Pqfr~J@vJZ*R!)?V2`2v*!z1SBE0($XPi;RtR+2B~Kd+9Rw^yTJVy9Ce# zBj!utDb^n$>N%b$xf6IrYDb1)7O44&1%eN!qM{-($^x~sad2FLTtm(d;6-e%mu}G# zL50<%mm;<;iJ>Zc+_=Db5h3w}OuVxZPbcZDmoGUnTKJ%Pl4lLW3I9hikTMF?X4xN@ z(sLupE`xJ(vjw{HO8hZgXwp!rVHd5q^GR&`*lEYrQ+JpmSv53AAOW7-egVF_2rM)APcvA50FNH%}O-gn%2x0yyyf9xn2!G8I@pxzut_ODGKWf7E^2FU7uV2cxvR?#9*#_&mi}H z6CI@GA67FA3fnrApWaZ|<32$NP2M6FZU_E`RKATC4zUFQmk-g^X5mURDE5#8C2S51 zHHCrL3G5sx(Rc<1 z38{?&3!Qz*EHTNctM5b7AIf4Qye(82s4}0O-RGFVd&pbBq{RrqgscOBGvcz|3ECns zh?SUDwUagY9yp!F8?3COv)q@1?-H>HWDol&|4}a^Sw-Vz$-)kBHDttfMb9jBpWJdD zjz4EU+E?2^4?h1AxZkfsv!7Lf-8&xXRZaZV@VGb)qJ}{c2mS5jbgj7|TDsaa8ZTQ| zCkb@hAcHc|YUpr{>k>M_0eJN!4TQ~)2y-oaTSN;(FQ*sI;`Hd+Kam0hmJi^(oPsTX z8Qz~^(YB&|U-x!cjT2ig>*9q|S5s^JB?pb@^XlIsf zn|QXCTXJ&p`}38@uf2v76spA{U<#!IXL?Q~lH?~bCK2Lkw-Ud1P1?H&Jm9Tp-K^Bq z=!N+J+$%%lK?n^;GAh9SUW<>nKdYZUM5ZRf=TT(<2MwAJ$4jXy8F*!Nm~J zX2FR`T(t^+B;GTS4;(9f4ekz(p=T|y|N+BDRDGyiBNZtKgh`e9tialZN(td z!qT!IXNaOA)Gf}w^Z}EC>#$8@qYUIX_+F}P9QDEuF~PVRMiSb-Y=o3Y)*`n4XkGy0lao3tW61B39Y`ZPaN)138nB!=tgB@ zrk);Ou)uvkcdD`)&%M6*2AB8iv}Br?Rmdosf|z0(hj!B-V9{7dFwRc&dEwv-bJMH{ zL~RC=%R)y0);TTK*0r$@7+IbM$t^J~gHX%di}57JOg{iG_w`ly$=i@!G$80UV7EnS zTD8BBMW&t>AZmp-1Ji&OPEy|#|Oell2!~X6Ax}m9X#_&0b@nd-Mf94ITc9w%r$bS zbt6T6!8HwgZbGb(le&lNxxH%*`xjmrT@~1ZO`+)?2L*{nP9kMyun!YD6!eKBB5|UI zc^qh}g!MyDU@xpq4@D+g5X5q0v4`7sd~h#F@3@)M6}W6cHZ z9D?1G56xW_ki0SLq;mLHy`^y7qR%{qU`K%5gSvr_@D9T^NeF!sW^;aN1h`37 zGiBFyV_OS}0>g0E(HlfZ+|(Pa7ipY?P(T?Wp$L$KrpQH6-jFKW&5n$loM>3Zc+)S4 z&R{;Cg|VzIEP~&iLqH}FMsn+>fhUpu1^4_}kJvYqmtRCwz{c^8mW83rBt##nH@d9I zcIe8Xl#qZ{SlCB{fKIQbWSYa0hKl3~^zJakm7BiFV$({t@S~uR5Mf*sqY~M+5rdjl z8ZmgXZklY4`03MbyRM2Ve-6-psH*00H?}{r_=&jX;8Q6B8H`+5IcC5nI8L!IBk5LJ zt-m)+_@?L}WG;hxM~syBj&2E;Fj<>f{EeS13UMvc2gT_Gyh>C)kRZy4(G!vem>J~^ zbJZ<~#YhD(5saT`eg@kjE+Mbd3)YA%*XV!uj(k_HWl%!2!Q>&W$b-jmZLq{lR3eB^ znuYuzlD&#%D@B`zA|A?l++0rp|%p)**1Xpj}Q?iFj^)Tu=ck>d@KO$$OoIb0Z znySq=>V<-J`%clyCz2=V72s9$FQcB^gVA%Z*9nXhjOmMED~Y_oKKPrFZaP4IADAu# z--PKNWjN7GU{u@O?oX^T(^o*Qen-$W7!uFXxgN~5CJ_G^TCd_y>r6b=!@1e9dv0dt z4)h#i3+)*HMtC7r29u4oH-f%KIHy1EhZkqVpVpf|hTcDaYtiTbpWj*}Zt~fcYt^di zarl{0Z?wGD3J9ddCHOsD9|X@!u#OHCpdD*ya!will4(Y@WTU{!hanH>b-XeW>Xm{< zx^^O+@(7y6!JH#Hisf0jv_PqU`ByOg149w_LGTS1xfsFeEHdWCkE#E8Aw;MS-24>f zTD#c&Ea=fP42dxOT6Y)85#t3skHK@l%b-@?;vc-`=~Lv*^qLtKro8j>cW%;(yNV7(%)W4lS0ODBg4VbgBnYp( zs|ZcniwO;%LQpe#cVNp~p?fS%~JMh0FGA6aFYL8vL0S2w>JtipD{t!`O&wwy<#!T}; zzqkaCu$E358B23?a{!_G3eu4~)HfDZ{!f%onqNcQujgi`oSdDV*HbHbdDUP?ZZo)v zA!JL0Kh+31I42TLQ;m!R=gvLWf+3;fHAXW=CBUSTzaxDZG1P}8fU{Z+*|9D53|8cc z80Lvmy?}&Bbmg5s4_J!7fMkNHyo>v?xzYK#Ltb8>7t=me_=f;GuSXXIBX$5dq@mVa zYnL5fAWUnl6!Ab{0J)vJ`@eADbU-0hJ${@Q8w(`?9J4jW?ak}WjdTIZi6eCX!$mqANPc=id2h^WoYW3=PR9Kk>!i!G6q zkfbCR7?Zrm9Cz``)x3=8EI+P=%n#Aq`{;BZTybZSr@1`{TWzn5>88Y^m`LN1lM)aJ zz)~|_iX=SH_yk&7708DYTmRH!wAc^d{vFn%Rf4PlDSQz<7X$4Y>(+EWU?r2rmQ$)4 z3sEhQbS%xw{w}OlIf6ZIOaRFYYVY1V@8Yq71z~I)@6h0VQC(Lo++anHl#zm+~T?Rkt1TJGZyaJ)ETw*ZrWQqg~PbLYKqHz5jV&|AGhXAWx`eAJryQ&g4 zn0gH58o+Yi%Z_7`i4^$n<)Z5Q&%!mOB%TPIz(a50Xm9=Qc=qfL`4+V^sB^Q}vLklr z$+hw7jJpgZjS#5y32X+Z`^-dYchNt$w5*g|#LBwDd$(<86;8#CwYA<4fOX{cR@soL zLhvJC&XDM!cM!c5-^&L3;@}rf{a$wuFLRE0_0qJuc`Omz5S5E36fnlm-rh|cTr-22 zGd&}0GhrM4U+JX?Ch_y23{(IkT4GE8Q-0~ou{(j$lBQ*d?F~6Rg(t$AWDR=p#=m%Z z`k|Q_&S-lPO&W=f3Gq_LK1P_(uR_Z>ZuF~}*`3`lVs*(EI2=8=}8}ivYf|S=|ch-_TZnsgteq6aSRK@M@d!@dMELa?zHYmCzLrAIJ)oFs1c)DppDlC`{gWPC_i0S}7?r$yPXsHBNDJ501*jV`x`_t18;@Uu^EpX8S} z%fsX&F+DT0oPwBp3(z*Ecxgiv7X=$!_=Edept*o;u}~6gO2Q)|EV3W{hBl##S~iyY zJL;f-hE*Cie+(gC9bUJ~btv?hg(p^Fj(y>6xKa#~;b@_&4WkmCOqj_$2HjLRK(MDU zkS}axW-GEQa2qQVz9#_|9<|X2PLxe>9+()W(D$ZfnQgNj;~my7dJ*@jQ3rd>_QDv9)srEB z6Lp!kULVQX!~|+U17E#JiCuQX`t`&q6VPTDigPGcC3^Lv@5OiB#Wf3By0Iyg>omKtn0vkUJiWT5Lh%vIDO+(pb+2I$zoOLOQ92Z~g!?3Vm z;v#M^69pna5Q2t)rU&Gzc+aYj@ZpdJe-uFqczNnnHP0gB%#1R6Z9da5KSQ(5%BPvo z6Ki7OPdwIKWT`pIOFdY}h{VVBj%naH`qtxm>Bkx1lY2mqdGfRM=WTaf!30kilz6}B zUKkyCz-#->dV(fqarofX|76?&|b`;+TT1gm5a;;X@#K zG{0qG;gUICdCD7x@|#Jr1rCrhz5fEK9aRU||3gFo+8HN)m7*Ztf?)F2Pe%K7Ra0oE33jEM6>?HjCDO z5>|S|)2qPdO(fG`Vb;c}gR>mwt2P&Y&>J4YRBWpF58@V34Kdfpk60iy%l zC6`|;$>+*f zu^SYs7QXMg1ajQVAXLOY)K%3*?ZqoHV#nFIy-z9e@45{?!>K*^H2}oV&?flj z+)4J;`;Yarx~*5Q37Gt%%DS+V<=^-Ffd9cTN+$om`L)7vW9Az-Z>BlFbFcb%{ZX+C zwy!KE+gIp%hO1PrxytVHU%ujh@K+!I^Gp5rZHf777KYrF|8r4Y^GseA WHSF3;cI~0?&o8Q4DjEAsFZ~AtuX*AC diff --git a/i18n-coverage.csv b/i18n-coverage.csv index efd03c179..7801f8c0d 100644 --- a/i18n-coverage.csv +++ b/i18n-coverage.csv @@ -1,5 +1,5 @@ Locale,Coverage #,Coverage % de,869,43% -es,740,37% +es,740,36% ja,935,46% nl,873,43% From 962aee14a37464070a0b6ef66641f28838313571 Mon Sep 17 00:00:00 2001 From: Max Bureck Date: Tue, 7 May 2024 21:53:52 +0200 Subject: [PATCH 4/7] Added test case for CodeSystem.supplements with versioned canonical --- .../validation/ResourceValidationTests.java | 31 +++++++++++++++++-- pom.xml | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java index 3cf91da2e..2db355613 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java @@ -1,5 +1,9 @@ package org.hl7.fhir.validation; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.MatcherAssert.assertThat; + import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; @@ -25,7 +29,7 @@ public class ResourceValidationTests { private static InstanceValidator val; - private void runTest(String filename) throws IOException, FileNotFoundException, Exception { + private List runTest(String filename) throws IOException, FileNotFoundException, Exception { TestingUtilities.injectCorePackageLoader(); if (val == null) { ctxt = TestingUtilities.getSharedWorkerContext(); @@ -37,6 +41,7 @@ public class ResourceValidationTests { Resource res = (Resource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", filename)); val.validate(val, errors, res); Assertions.assertNotNull(errors); + return errors; } @@ -123,4 +128,26 @@ public class ResourceValidationTests { } -} + @Test + public void testCodesystemSupplementsVersion() throws Exception { + List errors = runTest("codesystem-example-supplement-version.xml"); + assertNoErrors(errors); + } + + + private void assertNoErrors(List errors) { + List errorMessages = new ArrayList<>(); + for(ValidationMessage message : errors) { + // we will skip the message that WG citation is needed + if("VALIDATION_HL7_WG_NEEDED".equals(message.getMessageId())) { + continue; + } + if(message.getLevel().isError()) { + errorMessages.add(message.getMessage()); + } + } + assertThat("No error message expected in validation outcome.", errorMessages, is(empty())); + } + + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index f414bd97e..4c169bd7f 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 1.26.0 32.0.1-jre 6.4.1 - 1.5.6 + 1.5.7-SNAPSHOT 2.17.0 5.9.2 1.8.2 From be0d718ac720bd8122bb5f33839ea543d6e670b1 Mon Sep 17 00:00:00 2001 From: Max Bureck Date: Wed, 8 May 2024 14:50:50 +0200 Subject: [PATCH 5/7] Changed use of message ID string in test to use constant instead --- .../java/org/hl7/fhir/validation/ResourceValidationTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java index 2db355613..e49726978 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/ResourceValidationTests.java @@ -14,6 +14,7 @@ import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.utilities.FhirPublication; +import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.settings.FhirSettings; import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.validation.instance.InstanceValidator; @@ -139,7 +140,7 @@ public class ResourceValidationTests { List errorMessages = new ArrayList<>(); for(ValidationMessage message : errors) { // we will skip the message that WG citation is needed - if("VALIDATION_HL7_WG_NEEDED".equals(message.getMessageId())) { + if(I18nConstants.VALIDATION_HL7_WG_NEEDED.equals(message.getMessageId())) { continue; } if(message.getLevel().isError()) { From 178f7b0fa13cea9464d609c48b2f2880a17ff37b Mon Sep 17 00:00:00 2001 From: dotasek Date: Wed, 8 May 2024 10:18:01 -0400 Subject: [PATCH 6/7] Use extension class on Exception to force try-catch blocks on checkCodeOnServer calls (#1609) * Catch missed exception from HAPI * Wrap general exception for IWorkerContext --- .../instance/InstanceValidator.java | 52 ++++++++++++------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 67212ab6e..7e0cbb35c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -1456,9 +1456,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat timeTracker.tx(t, "vc "+cc.toString()); } } - } catch (Exception e) { - if (STACK_TRACE) e.printStackTrace(); - warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getMessage()); + } catch (CheckCodeOnServerException e) { + if (STACK_TRACE) e.getCause().printStackTrace(); + warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getCause().getMessage()); } } } else if (binding.hasValueSet()) { @@ -1469,12 +1469,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } if (!noTerminologyChecks && theElementCntext != null && !checked) { // no binding check, so we just check the CodeableConcept generally - CodeableConcept cc = ObjectConverter.readAsCodeableConcept(element); - if (cc.hasCoding()) { - long t = System.nanoTime(); - ValidationResult vr = checkCodeOnServer(stack, null, cc); - bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, false, null)); - timeTracker.tx(t, "vc "+cc.toString()); + try { + CodeableConcept cc = ObjectConverter.readAsCodeableConcept(element); + if (cc.hasCoding()) { + long t = System.nanoTime(); + ValidationResult vr = checkCodeOnServer(stack, null, cc); + bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, false, null)); + timeTracker.tx(t, "vc " + cc.toString()); + } + } catch (CheckCodeOnServerException e) { + if (STACK_TRACE) e.getCause().printStackTrace(); + warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getCause().getMessage()); } } return checkDisp; @@ -1502,8 +1507,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat boolean ok = true; if (vr != null) { for (OperationOutcomeIssueComponent iss : vr.getIssues()) { - if (!iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-in-vs") && - !iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs") + if (!iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-in-vs") + && !iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs") && !(ignoreCantInfer || iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "cannot-infer"))) { OperationOutcomeIssueComponent i = iss.copy(); if (notFoundLevel != null && i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) { @@ -1653,9 +1658,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat timeTracker.tx(t, DataRenderer.display(context, cc)); } } - } catch (Exception e) { - if (STACK_TRACE) e.printStackTrace(); - warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getMessage()); + } catch (CheckCodeOnServerException e) { + if (STACK_TRACE) e.getCause().printStackTrace(); + warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT, e.getCause().getMessage()); } // special case: if the logical model has both CodeableConcept and Coding mappings, we'll also check the first coding. if (getMapping("http://hl7.org/fhir/terminology-pattern", logical, logical.getSnapshot().getElementFirstRep()).contains("Coding")) { @@ -1861,9 +1866,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat else ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_8, describeReference(maxVSUrl, valueset), ccSummary(cc)) && ok; } - } catch (Exception e) { - if (STACK_TRACE) e.printStackTrace(); - warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT_MAX, e.getMessage()); + } catch (CheckCodeOnServerException e) { + if (STACK_TRACE) e.getCause().printStackTrace(); + warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_ERROR_CODEABLECONCEPT_MAX, e.getCause().getMessage()); } } return ok; @@ -7484,6 +7489,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return checkForInactive(filterOutSpecials(stack.getLiteralPath(), vs, context.validateCode(options, value, vs)), new CodeType(value)); } + static class CheckCodeOnServerException extends Exception { + public CheckCodeOnServerException(Exception e) { + super(e); + } + } // no delay on this one? public ValidationResult checkCodeOnServer(NodeStack stack, String code, String system, String version, String display, boolean checkDisplay) { @@ -7500,9 +7510,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), c, valueset)), c); } - public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc) { + public ValidationResult checkCodeOnServer(NodeStack stack, ValueSet valueset, CodeableConcept cc) throws CheckCodeOnServerException { codingObserver.seeCode(stack, cc); - return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), cc, valueset)), cc); + try { + return checkForInactive(filterOutSpecials(stack.getLiteralPath(), valueset, context.validateCode(baseOptions.withLanguage(stack.getWorkingLang()), cc, valueset)), cc); + } catch (Exception e) { + throw new CheckCodeOnServerException(e); + } } private ValidationResult filterOutSpecials(String path, ValueSet vs, ValidationResult vr) { From 743b2fb33f7035ec2ac094da8c6b6553f8ba6d62 Mon Sep 17 00:00:00 2001 From: dotasek Date: Thu, 9 May 2024 09:46:24 -0400 Subject: [PATCH 7/7] Update RELEASE_NOTES.md ***NO_CI*** --- RELEASE_NOTES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..b13dfbf98 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,4 +4,5 @@ ## Other code changes -* no changes \ No newline at end of file +* More comprehensive internationalization phrase coverage reporting. +* Shim interfaces and classes to support clinical reasoning project updates.