View Javadoc
1   package ca.uhn.fhir.jpa.provider;
2   
3   /*
4    * #%L
5    * HAPI FHIR JPA Server
6    * %%
7    * Copyright (C) 2014 - 2018 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  import java.util.*;
23  
24  import javax.servlet.http.HttpServletRequest;
25  
26  import ca.uhn.fhir.context.FhirContext;
27  import ca.uhn.fhir.context.RuntimeResourceDefinition;
28  import ca.uhn.fhir.context.RuntimeSearchParam;
29  import ca.uhn.fhir.jpa.dao.DaoConfig;
30  import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
31  import ca.uhn.fhir.jpa.util.ResourceCountCache;
32  import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
33  import ca.uhn.fhir.model.dstu2.composite.MetaDt;
34  import ca.uhn.fhir.model.dstu2.resource.Bundle;
35  import ca.uhn.fhir.model.dstu2.resource.Conformance;
36  import ca.uhn.fhir.model.dstu2.resource.Conformance.Rest;
37  import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResource;
38  import ca.uhn.fhir.model.dstu2.resource.Conformance.RestResourceSearchParam;
39  import ca.uhn.fhir.model.dstu2.valueset.ConditionalDeleteStatusEnum;
40  import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
41  import ca.uhn.fhir.model.dstu2.valueset.SearchParamTypeEnum;
42  import ca.uhn.fhir.model.primitive.BoundCodeDt;
43  import ca.uhn.fhir.model.primitive.DecimalDt;
44  import ca.uhn.fhir.rest.server.RestfulServer;
45  import ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider;
46  import ca.uhn.fhir.util.CoverageIgnore;
47  import ca.uhn.fhir.util.ExtensionConstants;
48  
49  import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
50  
51  public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
52  
53  	private volatile Conformance myCachedValue;
54  	private DaoConfig myDaoConfig;
55  	private String myImplementationDescription;
56  	private boolean myIncludeResourceCounts;
57  	private RestfulServer myRestfulServer;
58  	private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
59  	private ResourceCountCache myResourceCountsCache;
60  
61  	/**
62  	 * Constructor
63  	 */
64  	@CoverageIgnore
65  	public JpaConformanceProviderDstu2(){
66  		super();
67  		super.setCache(false);
68  		setIncludeResourceCounts(true);
69  	}
70  
71  	/**
72  	 * Constructor
73  	 */
74  	public JpaConformanceProviderDstu2(RestfulServer theRestfulServer, IFhirSystemDao<Bundle, MetaDt> theSystemDao, DaoConfig theDaoConfig) {
75  		super(theRestfulServer);
76  		myRestfulServer = theRestfulServer;
77  		mySystemDao = theSystemDao;
78  		myDaoConfig = theDaoConfig;
79  		super.setCache(false);
80  		setIncludeResourceCounts(true);
81  	}
82  
83  	@Override
84  	public Conformance getServerConformance(HttpServletRequest theRequest) {
85  		Conformance retVal = myCachedValue;
86  
87  		Map<String, Long> counts = null;
88  		if (myIncludeResourceCounts) {
89  			counts = mySystemDao.getResourceCountsFromCache();
90  		}
91  		counts = defaultIfNull(counts, Collections.emptyMap());
92  
93  		FhirContext ctx = myRestfulServer.getFhirContext();
94  
95  		retVal = super.getServerConformance(theRequest);
96  		for (Rest nextRest : retVal.getRest()) {
97  
98  			for (RestResource nextResource : nextRest.getResource()) {
99  
100 				ConditionalDeleteStatusEnum conditionalDelete = nextResource.getConditionalDeleteElement().getValueAsEnum();
101 				if (conditionalDelete == ConditionalDeleteStatusEnum.MULTIPLE_DELETES_SUPPORTED && myDaoConfig.isAllowMultipleDelete() == false) {
102 					nextResource.setConditionalDelete(ConditionalDeleteStatusEnum.SINGLE_DELETES_SUPPORTED);
103 				}
104 
105 				// Add resource counts
106 				Long count = counts.get(nextResource.getTypeElement().getValueAsString());
107 				if (count != null) {
108 					nextResource.addUndeclaredExtension(false, ExtensionConstants.CONF_RESOURCE_COUNT, new DecimalDt(count));
109 				}
110 
111 				// Add chained params
112 				for (RestResourceSearchParam nextParam : nextResource.getSearchParam()) {
113 					if (nextParam.getTypeElement().getValueAsEnum() == SearchParamTypeEnum.REFERENCE) {
114 						List<BoundCodeDt<ResourceTypeEnum>> targets = nextParam.getTarget();
115 						for (BoundCodeDt<ResourceTypeEnum> next : targets) {
116 							RuntimeResourceDefinition def = ctx.getResourceDefinition(next.getValue());
117 							for (RuntimeSearchParam nextChainedParam : def.getSearchParams()) {
118 								nextParam.addChain(nextChainedParam.getName());
119 							}
120 						}
121 					}
122 				}
123 
124 			}
125 		}
126 
127 		retVal.getImplementation().setDescription(myImplementationDescription);
128 		myCachedValue = retVal;
129 		return retVal;
130 	}
131 
132 	public boolean isIncludeResourceCounts() {
133 		return myIncludeResourceCounts;
134 	}
135 
136 	public void setDaoConfig(DaoConfig myDaoConfig) {
137 		this.myDaoConfig = myDaoConfig;
138 	}
139 
140 	@CoverageIgnore
141 	public void setImplementationDescription(String theImplDesc) {
142 		myImplementationDescription = theImplDesc;
143 	}
144 
145 	public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
146 		myIncludeResourceCounts = theIncludeResourceCounts;
147 	}
148 
149 	@Override
150 	public void setRestfulServer(RestfulServer theRestfulServer) {
151 		this.myRestfulServer = theRestfulServer;
152 		super.setRestfulServer(theRestfulServer);
153 	}
154 
155 	@CoverageIgnore
156 	public void setSystemDao(IFhirSystemDao<Bundle, MetaDt> mySystemDao) {
157 		this.mySystemDao = mySystemDao;
158 	}
159 }