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