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