001package org.hl7.fhir.common.hapi.validation.validator;
002
003import ca.uhn.fhir.i18n.Msg;
004import ca.uhn.fhir.context.FhirContext;
005import ca.uhn.fhir.context.FhirVersionEnum;
006import ca.uhn.fhir.context.support.ConceptValidationOptions;
007import ca.uhn.fhir.context.support.IValidationSupport;
008import ca.uhn.fhir.context.support.ValidationSupportContext;
009import ca.uhn.fhir.rest.api.Constants;
010import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
011import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
012import com.github.benmanes.caffeine.cache.Caffeine;
013import com.github.benmanes.caffeine.cache.LoadingCache;
014import org.apache.commons.lang3.Validate;
015import org.apache.commons.lang3.builder.EqualsBuilder;
016import org.apache.commons.lang3.builder.HashCodeBuilder;
017import org.apache.commons.lang3.time.DateUtils;
018import org.fhir.ucum.UcumService;
019import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_10_50;
020import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
021import org.hl7.fhir.exceptions.FHIRException;
022import org.hl7.fhir.exceptions.TerminologyServiceException;
023import org.hl7.fhir.instance.model.api.IBaseResource;
024import org.hl7.fhir.r5.context.IWorkerContext;
025import org.hl7.fhir.r5.formats.IParser;
026import org.hl7.fhir.r5.formats.ParserType;
027import org.hl7.fhir.r5.model.CanonicalResource;
028import org.hl7.fhir.r5.model.CodeSystem;
029import org.hl7.fhir.r5.model.Coding;
030import org.hl7.fhir.r5.model.Resource;
031import org.hl7.fhir.r5.model.StructureDefinition;
032import org.hl7.fhir.r5.model.ValueSet;
033import org.hl7.fhir.r5.terminologies.ValueSetExpander;
034import org.hl7.fhir.r5.utils.validation.IResourceValidator;
035import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
036import org.hl7.fhir.utilities.TimeTracker;
037import org.hl7.fhir.utilities.TranslationServices;
038import org.hl7.fhir.utilities.i18n.I18nBase;
039import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
040import org.hl7.fhir.utilities.npm.NpmPackage;
041import org.hl7.fhir.utilities.validation.ValidationMessage;
042import org.hl7.fhir.utilities.validation.ValidationOptions;
043import org.slf4j.Logger;
044import org.slf4j.LoggerFactory;
045
046import javax.annotation.Nonnull;
047import javax.annotation.Nullable;
048import java.util.ArrayList;
049import java.util.List;
050import java.util.Locale;
051import java.util.Map;
052import java.util.Set;
053import java.util.concurrent.TimeUnit;
054
055import static org.apache.commons.lang3.StringUtils.isBlank;
056import static org.apache.commons.lang3.StringUtils.isNotBlank;
057
058public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWorkerContext {
059        public static final IVersionTypeConverter IDENTITY_VERSION_TYPE_CONVERTER = new VersionTypeConverterR5();
060        private static final Logger ourLog = LoggerFactory.getLogger(VersionSpecificWorkerContextWrapper.class);
061        private static final FhirContext ourR5Context = FhirContext.forR5();
062        private final ValidationSupportContext myValidationSupportContext;
063        private final IVersionTypeConverter myModelConverter;
064        private final LoadingCache<ResourceKey, IBaseResource> myFetchResourceCache;
065        private volatile List<StructureDefinition> myAllStructures;
066        private org.hl7.fhir.r5.model.Parameters myExpansionProfile;
067
068        public VersionSpecificWorkerContextWrapper(ValidationSupportContext theValidationSupportContext, IVersionTypeConverter theModelConverter) {
069                myValidationSupportContext = theValidationSupportContext;
070                myModelConverter = theModelConverter;
071
072                long timeoutMillis = 10 * DateUtils.MILLIS_PER_SECOND;
073                if (System.getProperties().containsKey(ca.uhn.fhir.rest.api.Constants.TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS)) {
074                        timeoutMillis = Long.parseLong(System.getProperty(Constants.TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS));
075                }
076
077                myFetchResourceCache = Caffeine.newBuilder()
078                        .expireAfterWrite(timeoutMillis, TimeUnit.MILLISECONDS)
079                        .maximumSize(10000)
080                        .build(key -> {
081
082                                String fetchResourceName = key.getResourceName();
083                                if (myValidationSupportContext.getRootValidationSupport().getFhirContext().getVersion().getVersion() == FhirVersionEnum.DSTU2) {
084                                        if ("CodeSystem".equals(fetchResourceName)) {
085                                                fetchResourceName = "ValueSet";
086                                        }
087                                }
088
089                                Class<? extends IBaseResource> fetchResourceType;
090                                if (fetchResourceName.equals("Resource")) {
091                                        fetchResourceType = null;
092                                } else {
093                                        fetchResourceType = myValidationSupportContext.getRootValidationSupport().getFhirContext().getResourceDefinition(fetchResourceName).getImplementingClass();
094                                }
095
096                                IBaseResource fetched = myValidationSupportContext.getRootValidationSupport().fetchResource(fetchResourceType, key.getUri());
097
098                                Resource canonical = myModelConverter.toCanonical(fetched);
099
100                                if (canonical instanceof StructureDefinition) {
101                                        StructureDefinition canonicalSd = (StructureDefinition) canonical;
102                                        if (canonicalSd.getSnapshot().isEmpty()) {
103                                                ourLog.info("Generating snapshot for StructureDefinition: {}", canonicalSd.getUrl());
104                                                fetched = myValidationSupportContext.getRootValidationSupport().generateSnapshot(theValidationSupportContext, fetched, "", null, "");
105                                                Validate.isTrue(fetched != null, "StructureDefinition %s has no snapshot, and no snapshot generator is configured", key.getUri());
106                                                canonical = myModelConverter.toCanonical(fetched);
107                                        }
108                                }
109
110                                return canonical;
111                        });
112
113                setValidationMessageLanguage(getLocale());
114        }
115
116        @Override
117        public List<CanonicalResource> allConformanceResources() {
118                throw new UnsupportedOperationException(Msg.code(650));
119        }
120
121        @Override
122        public String getLinkForUrl(String corePath, String url) {
123                throw new UnsupportedOperationException(Msg.code(651));
124        }
125
126        @Override
127        public Map<String, byte[]> getBinaries() {
128                return null;
129        }
130
131        @Override
132        public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FHIRException {
133                throw new UnsupportedOperationException(Msg.code(652));
134        }
135
136        @Override
137        public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader, String[] types) throws FHIRException {
138                throw new UnsupportedOperationException(Msg.code(653));
139        }
140
141        @Override
142        public int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FHIRException {
143                throw new UnsupportedOperationException(Msg.code(654));
144        }
145
146        @Override
147        public boolean hasPackage(String id, String ver) {
148                throw new UnsupportedOperationException(Msg.code(655));
149        }
150
151        @Override
152        public boolean hasPackage(PackageVersion packageVersion) {
153                return false;
154        }
155
156        @Override
157        public PackageDetails getPackage(PackageVersion packageVersion) {
158                return null;
159        }
160
161        @Override
162        public int getClientRetryCount() {
163                throw new UnsupportedOperationException(Msg.code(656));
164        }
165
166        @Override
167        public IWorkerContext setClientRetryCount(int value) {
168                throw new UnsupportedOperationException(Msg.code(657));
169        }
170
171        @Override
172        public TimeTracker clock() {
173                return null;
174        }
175
176        @Override
177        public PackageVersion getPackageForUrl(String s) {
178                return null;
179        }
180
181        @Override
182        public void generateSnapshot(StructureDefinition input) throws FHIRException {
183                if (input.hasSnapshot()) {
184                        return;
185                }
186
187                org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider profileKnowledgeProvider = new ProfileKnowledgeWorkerR5(ourR5Context);
188                ArrayList<ValidationMessage> messages = new ArrayList<>();
189                org.hl7.fhir.r5.model.StructureDefinition base = fetchResource(StructureDefinition.class, input.getBaseDefinition());
190                if (base == null) {
191                        throw new PreconditionFailedException(Msg.code(658) + "Unknown base definition: " + input.getBaseDefinition());
192                }
193                new org.hl7.fhir.r5.conformance.ProfileUtilities(this, messages, profileKnowledgeProvider).generateSnapshot(base, input, "", null, "");
194
195        }
196
197        @Override
198        public void generateSnapshot(StructureDefinition theStructureDefinition, boolean theB) {
199                // nothing yet
200        }
201
202        @Override
203        public org.hl7.fhir.r5.model.Parameters getExpansionParameters() {
204                return myExpansionProfile;
205        }
206
207        @Override
208        public void setExpansionProfile(org.hl7.fhir.r5.model.Parameters expParameters) {
209                myExpansionProfile = expParameters;
210        }
211
212        @Override
213        public List<StructureDefinition> allStructures() {
214
215                List<StructureDefinition> retVal = myAllStructures;
216                if (retVal == null) {
217                        retVal = new ArrayList<>();
218                        for (IBaseResource next : myValidationSupportContext.getRootValidationSupport().fetchAllStructureDefinitions()) {
219                                try {
220                                        Resource converted = myModelConverter.toCanonical(next);
221                                        retVal.add((StructureDefinition) converted);
222                                } catch (FHIRException e) {
223                                        throw new InternalErrorException(Msg.code(659) + e);
224                                }
225                        }
226                        myAllStructures = retVal;
227                }
228
229                return retVal;
230        }
231
232        @Override
233        public List<StructureDefinition> getStructures() {
234                return allStructures();
235        }
236
237        @Override
238        public void cacheResource(Resource res) {
239                throw new UnsupportedOperationException(Msg.code(660));
240        }
241
242        @Override
243        public void cacheResourceFromPackage(Resource res, PackageVersion packageDetails) throws FHIRException {
244
245        }
246
247        @Override
248        public void cachePackage(PackageDetails packageDetails, List<PackageVersion> list) {
249
250        }
251
252        @Nonnull
253        private ValidationResult convertValidationResult(String theSystem, @Nullable IValidationSupport.CodeValidationResult theResult) {
254                ValidationResult retVal = null;
255                if (theResult != null) {
256                        String code = theResult.getCode();
257                        String display = theResult.getDisplay();
258                        String issueSeverity = theResult.getSeverityCode();
259                        String message = theResult.getMessage();
260                        if (isNotBlank(code)) {
261                                retVal = new ValidationResult(theSystem, new org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent()
262                                        .setCode(code)
263                                        .setDisplay(display));
264                        } else if (isNotBlank(issueSeverity)) {
265                                retVal = new ValidationResult(ValidationMessage.IssueSeverity.fromCode(issueSeverity), message, ValueSetExpander.TerminologyServiceErrorClass.UNKNOWN);
266                        }
267
268                }
269
270                if (retVal == null) {
271                        retVal = new ValidationResult(ValidationMessage.IssueSeverity.ERROR, "Validation failed");
272                }
273
274                return retVal;
275        }
276
277        @Override
278        public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r5.model.ValueSet source, boolean cacheOk, boolean Hierarchical) {
279                IBaseResource convertedSource;
280                try {
281                        convertedSource = myModelConverter.fromCanonical(source);
282                } catch (FHIRException e) {
283                        throw new InternalErrorException(Msg.code(661) + e);
284                }
285                IValidationSupport.ValueSetExpansionOutcome expanded = myValidationSupportContext.getRootValidationSupport().expandValueSet(myValidationSupportContext, null, convertedSource);
286
287                org.hl7.fhir.r5.model.ValueSet convertedResult = null;
288                if (expanded.getValueSet() != null) {
289                        try {
290                                convertedResult = (ValueSet) myModelConverter.toCanonical(expanded.getValueSet());
291                        } catch (FHIRException e) {
292                                throw new InternalErrorException(Msg.code(662) + e);
293                        }
294                }
295
296                String error = expanded.getError();
297                ValueSetExpander.TerminologyServiceErrorClass result = null;
298
299                return new ValueSetExpander.ValueSetExpansionOutcome(convertedResult, error, result);
300        }
301
302        @Override
303        public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent binding, boolean cacheOk, boolean Hierarchical) {
304                throw new UnsupportedOperationException(Msg.code(663));
305        }
306
307        @Override
308        public ValueSetExpander.ValueSetExpansionOutcome expandVS(ValueSet.ConceptSetComponent inc, boolean hierarchical, boolean noInactive) throws TerminologyServiceException {
309                throw new UnsupportedOperationException(Msg.code(664));
310        }
311
312        @Override
313        public Locale getLocale() {
314                return myValidationSupportContext.getRootValidationSupport().getFhirContext().getLocalizer().getLocale();
315        }
316
317        @Override
318        public void setLocale(Locale locale) {
319                // ignore
320        }
321
322        @Override
323        public org.hl7.fhir.r5.model.CodeSystem fetchCodeSystem(String system) {
324                IBaseResource fetched = myValidationSupportContext.getRootValidationSupport().fetchCodeSystem(system);
325                if (fetched == null) {
326                        return null;
327                }
328                try {
329                        return (org.hl7.fhir.r5.model.CodeSystem) myModelConverter.toCanonical(fetched);
330                } catch (FHIRException e) {
331                        throw new InternalErrorException(Msg.code(665) + e);
332                }
333        }
334
335        @Override
336        public CodeSystem fetchCodeSystem(String system, String verison) {
337                IBaseResource fetched = myValidationSupportContext.getRootValidationSupport().fetchCodeSystem(system);
338                if (fetched == null) {
339                        return null;
340                }
341                try {
342                        return (org.hl7.fhir.r5.model.CodeSystem) myModelConverter.toCanonical(fetched);
343                } catch (FHIRException e) {
344                        throw new InternalErrorException(Msg.code(1992) + e);
345                }
346        }
347
348        @Override
349        public <T extends Resource> T fetchResource(Class<T> class_, String uri) {
350
351                if (isBlank(uri)) {
352                        return null;
353                }
354
355                ResourceKey key = new ResourceKey(class_.getSimpleName(), uri);
356                @SuppressWarnings("unchecked")
357                T retVal = (T) myFetchResourceCache.get(key);
358
359                return retVal;
360        }
361
362        @Override
363        public Resource fetchResourceById(String type, String uri) {
364                throw new UnsupportedOperationException(Msg.code(666));
365        }
366
367        @Override
368        public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException {
369                T retVal = fetchResource(class_, uri);
370                if (retVal == null) {
371                        throw new FHIRException(Msg.code(667) + "Can not find resource of type " + class_.getSimpleName() + " with uri " + uri);
372                }
373                return retVal;
374        }
375
376        @Override
377        public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version) {
378                return fetchResource(class_, uri + "|" + version);
379        }
380
381        @Override
382        public <T extends Resource> T fetchResource(Class<T> class_, String uri, CanonicalResource canonicalForSource) {
383                throw new UnsupportedOperationException(Msg.code(668));
384        }
385
386        @Override
387        public List<org.hl7.fhir.r5.model.ConceptMap> findMapsForSource(String url) {
388                throw new UnsupportedOperationException(Msg.code(669));
389        }
390
391        @Override
392        public String getAbbreviation(String name) {
393                throw new UnsupportedOperationException(Msg.code(670));
394        }
395
396        @Override
397        public IParser getParser(ParserType type) {
398                throw new UnsupportedOperationException(Msg.code(671));
399        }
400
401        @Override
402        public IParser getParser(String type) {
403                throw new UnsupportedOperationException(Msg.code(672));
404        }
405
406        @Override
407        public List<String> getResourceNames() {
408                return new ArrayList<>(myValidationSupportContext.getRootValidationSupport().getFhirContext().getResourceTypes());
409        }
410
411        @Override
412        public Set<String> getResourceNamesAsSet() {
413                return myValidationSupportContext.getRootValidationSupport().getFhirContext().getResourceTypes();
414        }
415
416        @Override
417        public org.hl7.fhir.r5.model.StructureMap getTransform(String url) {
418                throw new UnsupportedOperationException(Msg.code(673));
419        }
420
421        @Override
422        public String getOverrideVersionNs() {
423                return null;
424        }
425
426        @Override
427        public void setOverrideVersionNs(String value) {
428                throw new UnsupportedOperationException(Msg.code(674));
429        }
430
431        @Override
432        public StructureDefinition fetchTypeDefinition(String typeName) {
433                return fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
434        }
435
436        @Override
437        public StructureDefinition fetchRawProfile(String url) {
438                StructureDefinition retVal = fetchResource(StructureDefinition.class, url);
439
440                if (retVal != null && retVal.getSnapshot().isEmpty()) {
441                        generateSnapshot(retVal);
442                }
443
444                return retVal;
445        }
446
447        @Override
448        public List<String> getTypeNames() {
449                throw new UnsupportedOperationException(Msg.code(675));
450        }
451
452        @Override
453        public UcumService getUcumService() {
454                throw new UnsupportedOperationException(Msg.code(676));
455        }
456
457        @Override
458        public void setUcumService(UcumService ucumService) {
459                throw new UnsupportedOperationException(Msg.code(677));
460        }
461
462        @Override
463        public String getVersion() {
464                return myValidationSupportContext.getRootValidationSupport().getFhirContext().getVersion().getVersion().getFhirVersionString();
465        }
466
467        @Override
468        public String getSpecUrl() {
469                throw new UnsupportedOperationException(Msg.code(678));
470        }
471
472        @Override
473        public boolean hasCache() {
474                throw new UnsupportedOperationException(Msg.code(679));
475        }
476
477        @Override
478        public <T extends Resource> boolean hasResource(Class<T> class_, String uri) {
479                throw new UnsupportedOperationException(Msg.code(680));
480        }
481
482        @Override
483        public boolean isNoTerminologyServer() {
484                return false;
485        }
486
487        @Override
488        public Set<String> getCodeSystemsUsed() {
489                throw new UnsupportedOperationException(Msg.code(681));
490        }
491
492        @Override
493        public List<org.hl7.fhir.r5.model.StructureMap> listTransforms() {
494                throw new UnsupportedOperationException(Msg.code(682));
495        }
496
497        @Override
498        public IParser newJsonParser() {
499                throw new UnsupportedOperationException(Msg.code(683));
500        }
501
502        @Override
503        public IResourceValidator newValidator() {
504                throw new UnsupportedOperationException(Msg.code(684));
505        }
506
507        @Override
508        public IParser newXmlParser() {
509                throw new UnsupportedOperationException(Msg.code(685));
510        }
511
512        @Override
513        public String oid2Uri(String code) {
514                throw new UnsupportedOperationException(Msg.code(686));
515        }
516
517        @Override
518        public ILoggingService getLogger() {
519                return null;
520        }
521
522        @Override
523        public void setLogger(ILoggingService logger) {
524                throw new UnsupportedOperationException(Msg.code(687));
525        }
526
527        @Override
528        public boolean supportsSystem(String system) {
529                return myValidationSupportContext.getRootValidationSupport().isCodeSystemSupported(myValidationSupportContext, system);
530        }
531
532        @Override
533        public TranslationServices translator() {
534                throw new UnsupportedOperationException(Msg.code(688));
535        }
536
537        @Override
538        public ValueSetExpander.ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk) {
539                return null;
540        }
541
542        @Override
543        public ValidationResult validateCode(ValidationOptions theOptions, String system, String version, String code, String display) {
544                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions);
545                return doValidation(null, validationOptions, system, code, display);
546        }
547
548        @Override
549        public ValidationResult validateCode(ValidationOptions theOptions, String theSystem, String version, String theCode, String display, ValueSet theValueSet) {
550                IBaseResource convertedVs = null;
551
552                try {
553                        if (theValueSet != null) {
554                                convertedVs = myModelConverter.fromCanonical(theValueSet);
555                        }
556                } catch (FHIRException e) {
557                        throw new InternalErrorException(Msg.code(689) + e);
558                }
559
560                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions);
561
562                return doValidation(convertedVs, validationOptions, theSystem, theCode, display);
563        }
564
565        @Override
566        public ValidationResult validateCode(ValidationOptions theOptions, String code, org.hl7.fhir.r5.model.ValueSet theValueSet) {
567                IBaseResource convertedVs = null;
568                try {
569                        if (theValueSet != null) {
570                                convertedVs = myModelConverter.fromCanonical(theValueSet);
571                        }
572                } catch (FHIRException e) {
573                        throw new InternalErrorException(Msg.code(690) + e);
574                }
575
576                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions).setInferSystem(true);
577
578                return doValidation(convertedVs, validationOptions, null, code, null);
579        }
580
581        @Override
582        public ValidationResult validateCode(ValidationOptions theOptions, org.hl7.fhir.r5.model.Coding theCoding, org.hl7.fhir.r5.model.ValueSet theValueSet) {
583                IBaseResource convertedVs = null;
584
585                try {
586                        if (theValueSet != null) {
587                                convertedVs = myModelConverter.fromCanonical(theValueSet);
588                        }
589                } catch (FHIRException e) {
590                        throw new InternalErrorException(Msg.code(691) + e);
591                }
592
593                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions);
594                String system = theCoding.getSystem();
595                String code = theCoding.getCode();
596                String display = theCoding.getDisplay();
597
598                return doValidation(convertedVs, validationOptions, system, code, display);
599        }
600
601        @Override
602        public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt) {
603                return validateCode(options, code, vs);
604        }
605
606        @Override
607        public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs) {
608                for (CodingValidationRequest next : codes) {
609                        ValidationResult outcome = validateCode(options, next.getCoding(), vs);
610                        next.setResult(outcome);
611                }
612        }
613
614        @Nonnull
615        private ValidationResult doValidation(IBaseResource theValueSet, ConceptValidationOptions theValidationOptions, String theSystem, String theCode, String theDisplay) {
616                IValidationSupport.CodeValidationResult result;
617                if (theValueSet != null) {
618                        result = myValidationSupportContext.getRootValidationSupport().validateCodeInValueSet(myValidationSupportContext, theValidationOptions, theSystem, theCode, theDisplay, theValueSet);
619                } else {
620                        result = myValidationSupportContext.getRootValidationSupport().validateCode(myValidationSupportContext, theValidationOptions, theSystem, theCode, theDisplay, null);
621                }
622                return convertValidationResult(theSystem, result);
623        }
624
625        @Override
626        public ValidationResult validateCode(ValidationOptions theOptions, org.hl7.fhir.r5.model.CodeableConcept code, org.hl7.fhir.r5.model.ValueSet theVs) {
627                for (Coding next : code.getCoding()) {
628                        ValidationResult retVal = validateCode(theOptions, next, theVs);
629                        if (retVal.isOk()) {
630                                return retVal;
631                        }
632                }
633
634                return new ValidationResult(ValidationMessage.IssueSeverity.ERROR, null);
635        }
636
637        public void invalidateCaches() {
638                myFetchResourceCache.invalidateAll();
639        }
640
641        public interface IVersionTypeConverter {
642
643                org.hl7.fhir.r5.model.Resource toCanonical(IBaseResource theNonCanonical);
644
645                IBaseResource fromCanonical(org.hl7.fhir.r5.model.Resource theCanonical);
646
647        }
648
649        private static class ResourceKey {
650                private final int myHashCode;
651                private final String myResourceName;
652                private final String myUri;
653
654                private ResourceKey(String theResourceName, String theUri) {
655                        myResourceName = theResourceName;
656                        myUri = theUri;
657                        myHashCode = new HashCodeBuilder(17, 37)
658                                .append(myResourceName)
659                                .append(myUri)
660                                .toHashCode();
661                }
662
663                @Override
664                public boolean equals(Object theO) {
665                        if (this == theO) {
666                                return true;
667                        }
668
669                        if (theO == null || getClass() != theO.getClass()) {
670                                return false;
671                        }
672
673                        ResourceKey that = (ResourceKey) theO;
674
675                        return new EqualsBuilder()
676                                .append(myResourceName, that.myResourceName)
677                                .append(myUri, that.myUri)
678                                .isEquals();
679                }
680
681                public String getResourceName() {
682                        return myResourceName;
683                }
684
685                public String getUri() {
686                        return myUri;
687                }
688
689                @Override
690                public int hashCode() {
691                        return myHashCode;
692                }
693        }
694
695        private static class VersionTypeConverterR5 implements IVersionTypeConverter {
696                @Override
697                public Resource toCanonical(IBaseResource theNonCanonical) {
698                        return (Resource) theNonCanonical;
699                }
700
701                @Override
702                public IBaseResource fromCanonical(Resource theCanonical) {
703                        return theCanonical;
704                }
705        }
706
707        public static ConceptValidationOptions convertConceptValidationOptions(ValidationOptions theOptions) {
708                ConceptValidationOptions retVal = new ConceptValidationOptions();
709                if (theOptions.isGuessSystem()) {
710                        retVal = retVal.setInferSystem(true);
711                }
712                return retVal;
713        }
714
715        @Nonnull
716        public static VersionSpecificWorkerContextWrapper newVersionSpecificWorkerContextWrapper(IValidationSupport theValidationSupport) {
717                IVersionTypeConverter converter;
718
719                switch (theValidationSupport.getFhirContext().getVersion().getVersion()) {
720                        case DSTU2:
721                        case DSTU2_HL7ORG: {
722                                converter = new IVersionTypeConverter() {
723                                        @Override
724                                        public Resource toCanonical(IBaseResource theNonCanonical) {
725                                                Resource retVal = VersionConvertorFactory_10_50.convertResource((org.hl7.fhir.dstu2.model.Resource) theNonCanonical, new BaseAdvisor_10_50(false));
726                                                if (theNonCanonical instanceof org.hl7.fhir.dstu2.model.ValueSet) {
727                                                        org.hl7.fhir.dstu2.model.ValueSet valueSet = (org.hl7.fhir.dstu2.model.ValueSet) theNonCanonical;
728                                                        if (valueSet.hasCodeSystem() && valueSet.getCodeSystem().hasSystem()) {
729                                                                if (!valueSet.hasCompose()) {
730                                                                        ValueSet valueSetR5 = (ValueSet) retVal;
731                                                                        valueSetR5.getCompose().addInclude().setSystem(valueSet.getCodeSystem().getSystem());
732                                                                }
733                                                        }
734                                                }
735                                                return retVal;
736                                        }
737
738                                        @Override
739                                        public IBaseResource fromCanonical(Resource theCanonical) {
740                                                return VersionConvertorFactory_10_50.convertResource(theCanonical, new BaseAdvisor_10_50(false));
741                                        }
742                                };
743                                break;
744                        }
745
746                        case DSTU2_1: {
747                                converter = new VersionTypeConverterDstu21();
748                                break;
749                        }
750
751                        case DSTU3: {
752                                converter = new VersionTypeConverterDstu3();
753                                break;
754                        }
755
756                        case R4: {
757                                converter = new VersionTypeConverterR4();
758                                break;
759                        }
760
761                        case R5: {
762                                converter = IDENTITY_VERSION_TYPE_CONVERTER;
763                                break;
764                        }
765
766                        default:
767                                throw new IllegalStateException(Msg.code(692));
768                }
769
770                return new VersionSpecificWorkerContextWrapper(new ValidationSupportContext(theValidationSupport), converter);
771        }
772}
773
774
775