View Javadoc
1   package ca.uhn.fhir.jpa.dao.r4;
2   
3   /*
4    * #%L
5    * HAPI FHIR JPA Server
6    * %%
7    * Copyright (C) 2014 - 2019 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import ca.uhn.fhir.context.support.IContextValidationSupport;
24  import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
25  import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
26  import ca.uhn.fhir.jpa.entity.TermCodeSystem;
27  import ca.uhn.fhir.jpa.model.entity.ResourceTable;
28  import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
29  import ca.uhn.fhir.jpa.util.LogicUtil;
30  import ca.uhn.fhir.rest.api.server.RequestDetails;
31  import ca.uhn.fhir.rest.param.TokenParam;
32  import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
33  import org.hl7.fhir.instance.model.api.IBaseResource;
34  import org.hl7.fhir.instance.model.api.IIdType;
35  import org.hl7.fhir.instance.model.api.IPrimitiveType;
36  import org.hl7.fhir.r4.hapi.validation.ValidationSupportChain;
37  import org.hl7.fhir.r4.model.CodeSystem;
38  import org.hl7.fhir.r4.model.CodeableConcept;
39  import org.hl7.fhir.r4.model.Coding;
40  import org.hl7.fhir.r4.model.IdType;
41  import org.springframework.beans.factory.annotation.Autowired;
42  
43  import javax.annotation.Nonnull;
44  import java.util.ArrayList;
45  import java.util.Date;
46  import java.util.List;
47  import java.util.Set;
48  
49  import static org.apache.commons.lang3.StringUtils.isNotBlank;
50  
51  public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
52  
53  	private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4.class);
54  
55  	@Autowired
56  	private ITermCodeSystemDao myCsDao;
57  	@Autowired
58  	private ValidationSupportChain myValidationSupport;
59  
60  	@Override
61  	public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
62  		List<IIdType> valueSetIds;
63  		Set<Long> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
64  		valueSetIds = new ArrayList<>();
65  		for (Long next : ids) {
66  			valueSetIds.add(new IdType("CodeSystem", next));
67  		}
68  		return valueSetIds;
69  	}
70  
71  	@Nonnull
72  	@Override
73  	public IContextValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
74  		boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
75  		boolean haveCode = theCode != null && theCode.isEmpty() == false;
76  		boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
77  
78  		if (!haveCoding && !(haveSystem && haveCode)) {
79  			throw new InvalidRequestException("No code, coding, or codeableConcept provided to validate");
80  		}
81  		if (!LogicUtil.multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
82  			throw new InvalidRequestException("$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
83  		}
84  
85  		String code;
86  		String system;
87  		if (haveCoding) {
88  			code = theCoding.getCode();
89  			system = theCoding.getSystem();
90  		} else {
91  			code = theCode.getValue();
92  			system = theSystem.getValue();
93  		}
94  
95  		ourLog.info("Looking up {} / {}", system, code);
96  
97  		if (myValidationSupport.isCodeSystemSupported(getContext(), system)) {
98  
99  			ourLog.info("Code system {} is supported", system);
100 			IContextValidationSupport.LookupCodeResult retVal = myValidationSupport.lookupCode(getContext(), system, code);
101 			if (retVal != null) {
102 				return retVal;
103 			}
104 
105 		}
106 
107 		// We didn't find it..
108 		return IContextValidationSupport.LookupCodeResult.notFound(system, code);
109 
110 	}
111 
112 	@Override
113 	public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, RequestDetails theRequestDetails) {
114 		return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
115 	}
116 
117 	@Override
118 	protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
119 		super.preDelete(theResourceToDelete, theEntityToDelete);
120 
121 		String codeSystemUrl = theResourceToDelete.getUrl();
122 		if (isNotBlank(codeSystemUrl)) {
123 			TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
124 			if (persCs != null) {
125 				myTerminologySvc.deleteCodeSystem(persCs);
126 			}
127 		}
128 	}
129 
130 	@Override
131 	protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
132 													 boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
133 		ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
134 
135 		CodeSystem cs = (CodeSystem) theResource;
136 		addPidToResource(theEntity, theResource);
137 
138 		myTerminologySvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
139 
140 		return retVal;
141 	}
142 
143 
144 }