View Javadoc
1   package ca.uhn.fhir.jpa.dao.r4;
2   
3   import ca.uhn.fhir.context.FhirContext;
4   import ca.uhn.fhir.context.FhirVersionEnum;
5   import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
6   import ca.uhn.fhir.jpa.dao.DaoConfig;
7   import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
8   import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
9   import ca.uhn.fhir.jpa.entity.ResourceTable;
10  import ca.uhn.fhir.parser.DataFormatException;
11  import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
12  import ca.uhn.fhir.util.ElementUtil;
13  import org.hl7.fhir.instance.model.api.IBase;
14  import org.hl7.fhir.instance.model.api.IBaseResource;
15  import org.hl7.fhir.instance.model.api.IPrimitiveType;
16  import org.hl7.fhir.r4.model.*;
17  import org.springframework.beans.factory.annotation.Autowired;
18  
19  import java.util.List;
20  
21  import static org.apache.commons.lang3.StringUtils.isBlank;
22  
23  /*
24   * #%L
25   * HAPI FHIR JPA Server
26   * %%
27   * Copyright (C) 2014 - 2018 University Health Network
28   * %%
29   * Licensed under the Apache License, Version 2.0 (the "License");
30   * you may not use this file except in compliance with the License.
31   * You may obtain a copy of the License at
32   * 
33   * http://www.apache.org/licenses/LICENSE-2.0
34   * 
35   * Unless required by applicable law or agreed to in writing, software
36   * distributed under the License is distributed on an "AS IS" BASIS,
37   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
38   * See the License for the specific language governing permissions and
39   * limitations under the License.
40   * #L%
41   */
42  
43  public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
44  
45  	@Autowired
46  	private IFhirSystemDao<Bundle, Meta> mySystemDao;
47  
48  	protected void markAffectedResources(SearchParameter theResource) {
49  		Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
50  		String expression = theResource != null ? theResource.getExpression() : null;
51  		markResourcesMatchingExpressionAsNeedingReindexing(reindex, expression);
52  	}
53  
54  
55  	@Override
56  	protected void postPersist(ResourceTable theEntity, SearchParameter theResource) {
57  		super.postPersist(theEntity, theResource);
58  		markAffectedResources(theResource);
59  	}
60  
61  	@Override
62  	protected void postUpdate(ResourceTable theEntity, SearchParameter theResource) {
63  		super.postUpdate(theEntity, theResource);
64  		markAffectedResources(theResource);
65  	}
66  
67  	@Override
68  	protected void preDelete(SearchParameter theResourceToDelete, ResourceTable theEntityToDelete) {
69  		super.preDelete(theResourceToDelete, theEntityToDelete);
70  		markAffectedResources(theResourceToDelete);
71  	}
72  
73  	@Override
74  	protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
75  		super.validateResourceForStorage(theResource, theEntityToSave);
76  
77  		Enum<?> status = theResource.getStatus();
78  		List<CodeType> base = theResource.getBase();
79  		String expression = theResource.getExpression();
80  		FhirContext context = getContext();
81  		Enum<?> type = theResource.getType();
82  
83  		FhirResourceDaoSearchParameterR4.validateSearchParam(type, status, base, expression, context, getConfig());
84  	}
85  
86  	public static void validateSearchParam(Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
87  		if (theStatus == null) {
88  			throw new UnprocessableEntityException("SearchParameter.status is missing or invalid");
89  		}
90  
91  		if (ElementUtil.isEmpty(theBase)) {
92  			throw new UnprocessableEntityException("SearchParameter.base is missing");
93  		}
94  
95  		if (theType != null && theType.name().equals(Enumerations.SearchParamType.COMPOSITE.name()) && isBlank(theExpression)) {
96  
97  			// this is ok
98  
99  		} else if (isBlank(theExpression)) {
100 
101 			throw new UnprocessableEntityException("SearchParameter.expression is missing");
102 
103 		} else {
104 
105 			theExpression = theExpression.trim();
106 
107 			String[] expressionSplit = BaseSearchParamExtractor.SPLIT.split(theExpression);
108 			for (String nextPath : expressionSplit) {
109 				nextPath = nextPath.trim();
110 
111 				int dotIdx = nextPath.indexOf('.');
112 				if (dotIdx == -1) {
113 					throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". Must start with a resource name");
114 				}
115 
116 				String resourceName = nextPath.substring(0, dotIdx);
117 				try {
118 					theContext.getResourceDefinition(resourceName);
119 				} catch (DataFormatException e) {
120 					throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\": " + e.getMessage());
121 				}
122 
123 				if (theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
124 					if (theDaoConfig.isValidateSearchParameterExpressionsOnSave()) {
125 						IBaseResource temporaryInstance = theContext.getResourceDefinition(resourceName).newInstance();
126 						try {
127 							theContext.newFluentPath().evaluate(temporaryInstance, nextPath, IBase.class);
128 						} catch (Exception e) {
129 							String msg = theContext.getLocalizer().getMessage(FhirResourceDaoSearchParameterR4.class, "invalidSearchParamExpression", nextPath, e.getMessage());
130 							throw new UnprocessableEntityException(msg, e);
131 						}
132 					}
133 				}
134 			}
135 
136 		} // if have expression
137 	}
138 
139 }