View Javadoc
1   package ca.uhn.fhir.jpa.provider.dstu3;
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.RuntimeResourceDefinition;
24  import ca.uhn.fhir.context.RuntimeSearchParam;
25  import ca.uhn.fhir.jpa.dao.DaoConfig;
26  import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
27  import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
28  import ca.uhn.fhir.rest.api.Constants;
29  import ca.uhn.fhir.rest.api.server.RequestDetails;
30  import ca.uhn.fhir.rest.server.RestfulServer;
31  import ca.uhn.fhir.util.CoverageIgnore;
32  import ca.uhn.fhir.util.ExtensionConstants;
33  import org.hl7.fhir.dstu3.model.*;
34  import org.hl7.fhir.dstu3.model.CapabilityStatement.*;
35  import org.hl7.fhir.dstu3.model.Enumerations.SearchParamType;
36  
37  import javax.servlet.http.HttpServletRequest;
38  import java.util.Collection;
39  import java.util.Collections;
40  import java.util.Map;
41  
42  import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
43  import static org.apache.commons.lang3.StringUtils.isNotBlank;
44  
45  public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider {
46  
47  	private volatile CapabilityStatement myCachedValue;
48  	private DaoConfig myDaoConfig;
49  	private ISearchParamRegistry mySearchParamRegistry;
50  	private String myImplementationDescription;
51  	private boolean myIncludeResourceCounts;
52  	private RestfulServer myRestfulServer;
53  	private IFhirSystemDao<Bundle, Meta> mySystemDao;
54  	/**
55  	 * Constructor
56  	 */
57  	@CoverageIgnore
58  	public JpaConformanceProviderDstu3() {
59  		super();
60  		super.setCache(false);
61  		setIncludeResourceCounts(true);
62  	}
63  
64  	/**
65  	 * Constructor
66  	 */
67  	public JpaConformanceProviderDstu3(RestfulServer theRestfulServer, IFhirSystemDao<Bundle, Meta> theSystemDao, DaoConfig theDaoConfig) {
68  		super(theRestfulServer);
69  		myRestfulServer = theRestfulServer;
70  		mySystemDao = theSystemDao;
71  		myDaoConfig = theDaoConfig;
72  		super.setCache(false);
73  		setSearchParamRegistry(theSystemDao.getSearchParamRegistry());
74  		setIncludeResourceCounts(true);
75  	}
76  
77  	public void setSearchParamRegistry(ISearchParamRegistry theSearchParamRegistry) {
78  		mySearchParamRegistry = theSearchParamRegistry;
79  	}
80  
81  	@Override
82  	public CapabilityStatement getServerConformance(HttpServletRequest theRequest, RequestDetails theRequestDetails) {
83  		CapabilityStatement retVal = myCachedValue;
84  
85  		Map<String, Long> counts = null;
86  		if (myIncludeResourceCounts) {
87  			counts = mySystemDao.getResourceCountsFromCache();
88  		}
89  		counts = defaultIfNull(counts, Collections.emptyMap());
90  
91  		retVal = super.getServerConformance(theRequest, theRequestDetails);
92  		for (CapabilityStatementRestComponent nextRest : retVal.getRest()) {
93  
94  			for (CapabilityStatementRestResourceComponent nextResource : nextRest.getResource()) {
95  
96  				nextResource.setVersioning(ResourceVersionPolicy.VERSIONEDUPDATE);
97  
98  				ConditionalDeleteStatus conditionalDelete = nextResource.getConditionalDelete();
99  				if (conditionalDelete == ConditionalDeleteStatus.MULTIPLE && myDaoConfig.isAllowMultipleDelete() == false) {
100 					nextResource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
101 				}
102 
103 				// Add resource counts
104 				Long count = counts.get(nextResource.getTypeElement().getValueAsString());
105 				if (count != null) {
106 					nextResource.addExtension(new Extension(ExtensionConstants.CONF_RESOURCE_COUNT, new DecimalType(count)));
107 				}
108 
109 				nextResource.getSearchParam().clear();
110 				String resourceName = nextResource.getType();
111 				RuntimeResourceDefinition resourceDef = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
112 				Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
113 				for (RuntimeSearchParam runtimeSp : searchParams) {
114 					CapabilityStatementRestResourceSearchParamComponent confSp = nextResource.addSearchParam();
115 
116 					confSp.setName(runtimeSp.getName());
117 					confSp.setDocumentation(runtimeSp.getDescription());
118 					confSp.setDefinition(runtimeSp.getUri());
119 					switch (runtimeSp.getParamType()) {
120 						case COMPOSITE:
121 							confSp.setType(SearchParamType.COMPOSITE);
122 							break;
123 						case DATE:
124 							confSp.setType(SearchParamType.DATE);
125 							break;
126 						case NUMBER:
127 							confSp.setType(SearchParamType.NUMBER);
128 							break;
129 						case QUANTITY:
130 							confSp.setType(SearchParamType.QUANTITY);
131 							break;
132 						case REFERENCE:
133 							confSp.setType(SearchParamType.REFERENCE);
134 							break;
135 						case STRING:
136 							confSp.setType(SearchParamType.STRING);
137 							break;
138 						case TOKEN:
139 							confSp.setType(SearchParamType.TOKEN);
140 							break;
141 						case URI:
142 							confSp.setType(SearchParamType.URI);
143 							break;
144 						case HAS:
145 							// Shouldn't happen
146 							break;
147 					}
148 
149 				}
150 
151 			}
152 		}
153 
154 		massage(retVal);
155 
156 		if (myDaoConfig.getSupportedSubscriptionTypes().contains(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET)) {
157 			if (isNotBlank(myDaoConfig.getWebsocketContextPath())) {
158 				Extension websocketExtension = new Extension();
159 				websocketExtension.setUrl(Constants.CAPABILITYSTATEMENT_WEBSOCKET_URL);
160 				websocketExtension.setValue(new UriType(myDaoConfig.getWebsocketContextPath()));
161 				retVal.getRestFirstRep().addExtension(websocketExtension);
162 			}
163 		}
164 
165 		retVal.getImplementation().setDescription(myImplementationDescription);
166 		myCachedValue = retVal;
167 		return retVal;
168 	}
169 
170 	public boolean isIncludeResourceCounts() {
171 		return myIncludeResourceCounts;
172 	}
173 
174 	public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
175 		myIncludeResourceCounts = theIncludeResourceCounts;
176 	}
177 
178 	/**
179 	 * Subclasses may override
180 	 */
181 	protected void massage(CapabilityStatement theStatement) {
182 		// nothing
183 	}
184 
185 	public void setDaoConfig(DaoConfig myDaoConfig) {
186 		this.myDaoConfig = myDaoConfig;
187 	}
188 
189 	@CoverageIgnore
190 	public void setImplementationDescription(String theImplDesc) {
191 		myImplementationDescription = theImplDesc;
192 	}
193 
194 	@Override
195 	public void setRestfulServer(RestfulServer theRestfulServer) {
196 		this.myRestfulServer = theRestfulServer;
197 		super.setRestfulServer(theRestfulServer);
198 	}
199 
200 	@CoverageIgnore
201 	public void setSystemDao(IFhirSystemDao<Bundle, Meta> mySystemDao) {
202 		this.mySystemDao = mySystemDao;
203 	}
204 }