001package ca.uhn.fhir.test.utilities.server;
002
003/*-
004 * #%L
005 * HAPI FHIR Test Utilities
006 * %%
007 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.rest.api.MethodOutcome;
024import ca.uhn.fhir.rest.api.server.RequestDetails;
025import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
026import org.hl7.fhir.instance.model.api.IBaseResource;
027import org.junit.jupiter.api.extension.AfterEachCallback;
028import org.junit.jupiter.api.extension.BeforeEachCallback;
029import org.junit.jupiter.api.extension.ExtensionContext;
030
031import java.util.ArrayList;
032import java.util.Collections;
033import java.util.List;
034
035import static org.awaitility.Awaitility.await;
036import static org.hamcrest.MatcherAssert.assertThat;
037import static org.hamcrest.Matchers.equalTo;
038import static org.hamcrest.Matchers.greaterThanOrEqualTo;
039
040public class HashMapResourceProviderExtension<T extends IBaseResource> extends HashMapResourceProvider<T> implements BeforeEachCallback, AfterEachCallback {
041
042        private final RestfulServerExtension myRestfulServerExtension;
043        private boolean myClearBetweenTests = true;
044        private final List<T> myUpdates = new ArrayList<>();
045
046        /**
047         * Constructor
048         *
049         * @param theResourceType The resource type to support
050         */
051        public HashMapResourceProviderExtension(RestfulServerExtension theRestfulServerExtension, Class<T> theResourceType) {
052                super(theRestfulServerExtension.getFhirContext(), theResourceType);
053
054                myRestfulServerExtension = theRestfulServerExtension;
055        }
056
057        @Override
058        public void afterEach(ExtensionContext context) throws Exception {
059                myRestfulServerExtension.getRestfulServer().unregisterProvider(HashMapResourceProviderExtension.this);
060        }
061
062        @Override
063        public synchronized void clear() {
064                super.clear();
065                if (myUpdates != null) {
066                        myUpdates.clear();
067                }
068        }
069
070        @Override
071        public void beforeEach(ExtensionContext context) throws Exception {
072                if (myClearBetweenTests) {
073                        clear();
074                        clearCounts();
075                }
076                myRestfulServerExtension.getRestfulServer().registerProvider(HashMapResourceProviderExtension.this);
077        }
078
079        @Override
080        public synchronized MethodOutcome update(T theResource, String theConditional, RequestDetails theRequestDetails) {
081                T resourceClone = getFhirContext().newTerser().clone(theResource);
082                myUpdates.add(resourceClone);
083                return super.update(theResource, theConditional, theRequestDetails);
084        }
085
086        public HashMapResourceProviderExtension<T> dontClearBetweenTests() {
087                myClearBetweenTests = false;
088                return this;
089        }
090
091        public void waitForUpdateCount(long theCount) {
092                assertThat(theCount, greaterThanOrEqualTo(getCountUpdate()));
093                await().until(this::getCountUpdate, equalTo(theCount));
094        }
095
096        public void waitForCreateCount(long theCount) {
097                assertThat(theCount, greaterThanOrEqualTo(getCountCreate()));
098                await().until(this::getCountCreate, equalTo(theCount));
099        }
100
101        public void waitForDeleteCount(long theCount) {
102                assertThat(theCount, greaterThanOrEqualTo(getCountDelete()));
103                await().until(this::getCountDelete, equalTo(theCount));
104        }
105
106        public List<T> getResourceUpdates() {
107                return Collections.unmodifiableList(myUpdates);
108        }
109}