001package org.hl7.fhir.dstu3.hapi.validation;
002
003import static org.apache.commons.lang3.StringUtils.isBlank;
004
005import java.util.ArrayList;
006import java.util.HashSet;
007import java.util.List;
008import java.util.Set;
009
010import org.hl7.fhir.dstu3.model.CodeSystem;
011import org.hl7.fhir.dstu3.model.StructureDefinition;
012import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
013import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
014import org.hl7.fhir.instance.model.api.IBaseResource;
015
016import ca.uhn.fhir.context.FhirContext;
017
018public class ValidationSupportChain implements IValidationSupport {
019
020        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationSupportChain.class);
021
022        private List<IValidationSupport> myChain;
023
024        /**
025         * Constructor
026         */
027        public ValidationSupportChain() {
028                myChain = new ArrayList<IValidationSupport>();
029        }
030
031        /**
032         * Constructor
033         */
034        public ValidationSupportChain(IValidationSupport... theValidationSupportModules) {
035                this();
036                for (IValidationSupport next : theValidationSupportModules) {
037                        if (next != null) {
038                                myChain.add(next);
039                        }
040                }
041        }
042
043        public void addValidationSupport(IValidationSupport theValidationSupport) {
044                myChain.add(theValidationSupport);
045        }
046
047        @Override
048        public ValueSetExpansionComponent expandValueSet(FhirContext theCtx, ConceptSetComponent theInclude) {
049                for (IValidationSupport next : myChain) {
050                        if (next.isCodeSystemSupported(theCtx, theInclude.getSystem())) {
051                                return next.expandValueSet(theCtx, theInclude);
052                        }
053                }
054                return myChain.get(0).expandValueSet(theCtx, theInclude);
055        }
056
057        @Override
058        public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) {
059                for (IValidationSupport next : myChain) {
060                        CodeSystem retVal = next.fetchCodeSystem(theCtx, theSystem);
061                        if (retVal != null) {
062                                return retVal;
063                        }
064                }
065                return null;
066        }
067
068        @Override
069        public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
070                for (IValidationSupport next : myChain) {
071                        T retVal = next.fetchResource(theContext, theClass, theUri);
072                        if (retVal != null) {
073                                return retVal;
074                        }
075                }
076                return null;
077        }
078
079        @Override
080        public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
081                for (IValidationSupport next : myChain) {
082                        StructureDefinition retVal = next.fetchStructureDefinition(theCtx, theUrl);
083                        if (retVal != null) {
084                                return retVal;
085                        }
086                }
087                return null;
088        }
089
090        @Override
091        public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) {
092                for (IValidationSupport next : myChain) {
093                        if (next.isCodeSystemSupported(theCtx, theSystem)) {
094                                return true;
095                        }
096                }
097                return false;
098        }
099
100        @Override
101        public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) {
102                
103                ourLog.info("Validating code {} in chain with {} items", theCode, myChain.size());
104                
105                for (IValidationSupport next : myChain) {
106                        if (next.isCodeSystemSupported(theCtx, theCodeSystem)) {
107                                CodeValidationResult result = next.validateCode(theCtx, theCodeSystem, theCode, theDisplay);
108                                ourLog.info("Chain item {} returned outcome {}", next, result.isOk());
109                                return result;
110                        } else {
111                                ourLog.info("Chain item {} does not support code system {}", next, theCodeSystem);
112                        }
113                }
114                return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay);
115        }
116
117        @Override
118        public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
119                ArrayList<StructureDefinition> retVal = new ArrayList<StructureDefinition>();
120                Set<String> urls= new HashSet<String>();
121                for (IValidationSupport nextSupport : myChain) {
122                        for (StructureDefinition next : nextSupport.fetchAllStructureDefinitions(theContext)) {
123                                if (isBlank(next.getUrl()) || urls.add(next.getUrl())) {
124                                        retVal.add(next);
125                                }
126                        }
127                }
128                return retVal;
129        }
130
131}