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                throw new UnsupportedOperationException(Msg.code(663));
326        }
327
328        @Override
329        public ValueSetExpansionOutcome expandVS(ValueSet.ConceptSetComponent inc, boolean hierarchical, boolean noInactive)
330                        throws TerminologyServiceException {
331                throw new UnsupportedOperationException(Msg.code(664));
332        }
333
334        @Override
335        public Locale getLocale() {
336                return myValidationSupportContext
337                                .getRootValidationSupport()
338                                .getFhirContext()
339                                .getLocalizer()
340                                .getLocale();
341        }
342
343        @Override
344        public void setLocale(Locale locale) {
345                // ignore
346        }
347
348        @Override
349        public org.hl7.fhir.r5.model.CodeSystem fetchCodeSystem(String system) {
350                IBaseResource fetched =
351                                myValidationSupportContext.getRootValidationSupport().fetchCodeSystem(system);
352                if (fetched == null) {
353                        return null;
354                }
355                try {
356                        return (org.hl7.fhir.r5.model.CodeSystem) myVersionCanonicalizer.codeSystemToValidatorCanonical(fetched);
357                } catch (FHIRException e) {
358                        throw new InternalErrorException(Msg.code(665) + e);
359                }
360        }
361
362        @Override
363        public CodeSystem fetchCodeSystem(String system, String verison) {
364                IBaseResource fetched =
365                                myValidationSupportContext.getRootValidationSupport().fetchCodeSystem(system);
366                if (fetched == null) {
367                        return null;
368                }
369                try {
370                        return (org.hl7.fhir.r5.model.CodeSystem) myVersionCanonicalizer.codeSystemToValidatorCanonical(fetched);
371                } catch (FHIRException e) {
372                        throw new InternalErrorException(Msg.code(1992) + e);
373                }
374        }
375
376        @Override
377        public CodeSystem fetchSupplementedCodeSystem(String system) {
378                return null;
379        }
380
381        @Override
382        public CodeSystem fetchSupplementedCodeSystem(String system, String version) {
383                return null;
384        }
385
386        @Override
387        public <T extends Resource> T fetchResourceRaw(Class<T> class_, String uri) {
388                return fetchResource(class_, uri);
389        }
390
391        @Override
392        public <T extends Resource> T fetchResource(Class<T> class_, String uri) {
393
394                if (isBlank(uri)) {
395                        return null;
396                }
397
398                ResourceKey key = new ResourceKey(class_.getSimpleName(), uri);
399                @SuppressWarnings("unchecked")
400                T retVal = (T) myFetchResourceCache.get(key);
401
402                return retVal;
403        }
404
405        @Override
406        public Resource fetchResourceById(String type, String uri) {
407                throw new UnsupportedOperationException(Msg.code(666));
408        }
409
410        @Override
411        public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException {
412                T retVal = fetchResource(class_, uri);
413                if (retVal == null) {
414                        throw new FHIRException(
415                                        Msg.code(667) + "Can not find resource of type " + class_.getSimpleName() + " with uri " + uri);
416                }
417                return retVal;
418        }
419
420        @Override
421        public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version) {
422                return fetchResource(class_, uri + "|" + version);
423        }
424
425        @Override
426        public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource canonicalForSource) {
427                return fetchResource(class_, uri);
428        }
429
430        @Override
431        public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceOfReference)
432                        throws FHIRException {
433                throw new UnsupportedOperationException(Msg.code(2214));
434        }
435
436        @Override
437        public List<String> getResourceNames() {
438                return new ArrayList<>(myValidationSupportContext
439                                .getRootValidationSupport()
440                                .getFhirContext()
441                                .getResourceTypes());
442        }
443
444        @Override
445        public Set<String> getResourceNamesAsSet() {
446                return myValidationSupportContext
447                                .getRootValidationSupport()
448                                .getFhirContext()
449                                .getResourceTypes();
450        }
451
452        @Override
453        public StructureDefinition fetchTypeDefinition(String typeName) {
454                return fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName);
455        }
456
457        @Override
458        public List<StructureDefinition> fetchTypeDefinitions(String typeName) {
459                List<StructureDefinition> allStructures = new ArrayList<>(allStructures());
460                allStructures.removeIf(sd -> !sd.hasType() || !sd.getType().equals(typeName));
461                return allStructures;
462        }
463
464        @Override
465        public UcumService getUcumService() {
466                throw new UnsupportedOperationException(Msg.code(676));
467        }
468
469        @Override
470        public void setUcumService(UcumService ucumService) {
471                throw new UnsupportedOperationException(Msg.code(677));
472        }
473
474        @Override
475        public String getVersion() {
476                return myValidationSupportContext
477                                .getRootValidationSupport()
478                                .getFhirContext()
479                                .getVersion()
480                                .getVersion()
481                                .getFhirVersionString();
482        }
483
484        @Override
485        public <T extends Resource> boolean hasResource(Class<T> class_, String uri) {
486                throw new UnsupportedOperationException(Msg.code(680));
487        }
488
489        @Override
490        public boolean isNoTerminologyServer() {
491                return false;
492        }
493
494        @Override
495        public Set<String> getCodeSystemsUsed() {
496                throw new UnsupportedOperationException(Msg.code(681));
497        }
498
499        @Override
500        public IResourceValidator newValidator() {
501                throw new UnsupportedOperationException(Msg.code(684));
502        }
503
504        @Override
505        public Map<String, NamingSystem> getNSUrlMap() {
506                throw new UnsupportedOperationException(Msg.code(2265));
507        }
508
509        @Override
510        public ILoggingService getLogger() {
511                return null;
512        }
513
514        @Override
515        public void setLogger(ILoggingService logger) {
516                throw new UnsupportedOperationException(Msg.code(687));
517        }
518
519        @Override
520        public boolean supportsSystem(String system) {
521                return myValidationSupportContext
522                                .getRootValidationSupport()
523                                .isCodeSystemSupported(myValidationSupportContext, system);
524        }
525
526        @Override
527        public TranslationServices translator() {
528                throw new UnsupportedOperationException(Msg.code(688));
529        }
530
531        @Override
532        public ValueSetExpansionOutcome expandVS(
533                        ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk) {
534                return null;
535        }
536
537        @Override
538        public ValidationResult validateCode(
539                        ValidationOptions theOptions, String system, String version, String code, String display) {
540                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions);
541                return doValidation(null, validationOptions, system, code, display);
542        }
543
544        @Override
545        public ValidationResult validateCode(
546                        ValidationOptions theOptions,
547                        String theSystem,
548                        String version,
549                        String theCode,
550                        String display,
551                        ValueSet theValueSet) {
552                IBaseResource convertedVs = null;
553
554                try {
555                        if (theValueSet != null) {
556                                convertedVs = myVersionCanonicalizer.valueSetFromValidatorCanonical(theValueSet);
557                        }
558                } catch (FHIRException e) {
559                        throw new InternalErrorException(Msg.code(689) + e);
560                }
561
562                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions);
563
564                return doValidation(convertedVs, validationOptions, theSystem, theCode, display);
565        }
566
567        @Override
568        public ValidationResult validateCode(
569                        ValidationOptions theOptions, String code, org.hl7.fhir.r5.model.ValueSet theValueSet) {
570                IBaseResource convertedVs = null;
571                try {
572                        if (theValueSet != null) {
573                                convertedVs = myVersionCanonicalizer.valueSetFromValidatorCanonical(theValueSet);
574                        }
575                } catch (FHIRException e) {
576                        throw new InternalErrorException(Msg.code(690) + e);
577                }
578
579                ConceptValidationOptions validationOptions =
580                                convertConceptValidationOptions(theOptions).setInferSystem(true);
581
582                return doValidation(convertedVs, validationOptions, null, code, null);
583        }
584
585        @Override
586        public ValidationResult validateCode(
587                        ValidationOptions theOptions,
588                        org.hl7.fhir.r5.model.Coding theCoding,
589                        org.hl7.fhir.r5.model.ValueSet theValueSet) {
590                IBaseResource convertedVs = null;
591
592                try {
593                        if (theValueSet != null) {
594                                convertedVs = myVersionCanonicalizer.valueSetFromValidatorCanonical(theValueSet);
595                        }
596                } catch (FHIRException e) {
597                        throw new InternalErrorException(Msg.code(691) + e);
598                }
599
600                ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions);
601                String system = theCoding.getSystem();
602                String code = theCoding.getCode();
603                String display = theCoding.getDisplay();
604
605                return doValidation(convertedVs, validationOptions, system, code, display);
606        }
607
608        @Override
609        public ValidationResult validateCode(
610                        ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt) {
611                return validateCode(options, code, vs);
612        }
613
614        @Override
615        public void validateCodeBatch(
616                        ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs) {
617                for (CodingValidationRequest next : codes) {
618                        ValidationResult outcome = validateCode(options, next.getCoding(), vs);
619                        next.setResult(outcome);
620                }
621        }
622
623        @Override
624        public void validateCodeBatchByRef(
625                        ValidationOptions validationOptions, List<? extends CodingValidationRequest> list, String s) {
626                ValueSet valueSet = fetchResource(ValueSet.class, s);
627                validateCodeBatch(validationOptions, list, valueSet);
628        }
629
630        @Nonnull
631        private ValidationResult doValidation(
632                        IBaseResource theValueSet,
633                        ConceptValidationOptions theValidationOptions,
634                        String theSystem,
635                        String theCode,
636                        String theDisplay) {
637                IValidationSupport.CodeValidationResult result;
638                if (theValueSet != null) {
639                        result = myValidationSupportContext
640                                        .getRootValidationSupport()
641                                        .validateCodeInValueSet(
642                                                        myValidationSupportContext,
643                                                        theValidationOptions,
644                                                        theSystem,
645                                                        theCode,
646                                                        theDisplay,
647                                                        theValueSet);
648                } else {
649                        result = myValidationSupportContext
650                                        .getRootValidationSupport()
651                                        .validateCode(
652                                                        myValidationSupportContext, theValidationOptions, theSystem, theCode, theDisplay, null);
653                }
654                return convertValidationResult(theSystem, result);
655        }
656
657        @Override
658        public ValidationResult validateCode(
659                        ValidationOptions theOptions,
660                        org.hl7.fhir.r5.model.CodeableConcept code,
661                        org.hl7.fhir.r5.model.ValueSet theVs) {
662                List<ValidationResult> validationResultsOk = new ArrayList<>();
663                for (Coding next : code.getCoding()) {
664                        ValidationResult retVal = validateCode(theOptions, next, theVs);
665                        if (retVal.isOk()) {
666                                if (myValidationSupportContext.isEnabledValidationForCodingsLogicalAnd()) {
667                                        validationResultsOk.add(retVal);
668                                } else {
669                                        return retVal;
670                                }
671                        }
672                }
673
674                if (code.getCoding().size() > 0
675                                && validationResultsOk.size() == code.getCoding().size()) {
676                        return validationResultsOk.get(0);
677                }
678
679                return new ValidationResult(ValidationMessage.IssueSeverity.ERROR, null, null);
680        }
681
682        public void invalidateCaches() {
683                myFetchResourceCache.invalidateAll();
684        }
685
686        @Override
687        public <T extends Resource> List<T> fetchResourcesByType(Class<T> theClass) {
688                if (theClass.equals(StructureDefinition.class)) {
689                        return (List<T>) allStructures();
690                }
691                throw new UnsupportedOperationException(Msg.code(650) + "Unable to fetch resources of type: " + theClass);
692        }
693
694        @Override
695        public boolean isForPublication() {
696                return false;
697        }
698
699        @Override
700        public void setForPublication(boolean b) {
701                throw new UnsupportedOperationException(Msg.code(2351));
702        }
703
704        public static ConceptValidationOptions convertConceptValidationOptions(ValidationOptions theOptions) {
705                ConceptValidationOptions retVal = new ConceptValidationOptions();
706                if (theOptions.isGuessSystem()) {
707                        retVal = retVal.setInferSystem(true);
708                }
709                return retVal;
710        }
711
712        @Nonnull
713        public static VersionSpecificWorkerContextWrapper newVersionSpecificWorkerContextWrapper(
714                        IValidationSupport theValidationSupport) {
715                VersionCanonicalizer versionCanonicalizer = new VersionCanonicalizer(theValidationSupport.getFhirContext());
716                return new VersionSpecificWorkerContextWrapper(
717                                new ValidationSupportContext(theValidationSupport), versionCanonicalizer);
718        }
719
720        private static class ResourceKey {
721                private final int myHashCode;
722                private final String myResourceName;
723                private final String myUri;
724
725                private ResourceKey(String theResourceName, String theUri) {
726                        myResourceName = theResourceName;
727                        myUri = theUri;
728                        myHashCode = new HashCodeBuilder(17, 37)
729                                        .append(myResourceName)
730                                        .append(myUri)
731                                        .toHashCode();
732                }
733
734                @Override
735                public boolean equals(Object theO) {
736                        if (this == theO) {
737                                return true;
738                        }
739
740                        if (theO == null || getClass() != theO.getClass()) {
741                                return false;
742                        }
743
744                        ResourceKey that = (ResourceKey) theO;
745
746                        return new EqualsBuilder()
747                                        .append(myResourceName, that.myResourceName)
748                                        .append(myUri, that.myUri)
749                                        .isEquals();
750                }
751
752                public String getResourceName() {
753                        return myResourceName;
754                }
755
756                public String getUri() {
757                        return myUri;
758                }
759
760                @Override
761                public int hashCode() {
762                        return myHashCode;
763                }
764        }
765}