001/*
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.provider;
021
022import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
023import ca.uhn.fhir.jpa.model.util.JpaConstants;
024import ca.uhn.fhir.model.api.annotation.Description;
025import ca.uhn.fhir.rest.annotation.Operation;
026import ca.uhn.fhir.rest.annotation.OperationParam;
027import ca.uhn.fhir.rest.annotation.Transaction;
028import ca.uhn.fhir.rest.annotation.TransactionParam;
029import ca.uhn.fhir.rest.api.server.RequestDetails;
030import ca.uhn.fhir.rest.server.provider.ProviderConstants;
031import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
032import ca.uhn.fhir.util.ParametersUtil;
033import org.hl7.fhir.instance.model.api.IBaseBundle;
034import org.hl7.fhir.instance.model.api.IBaseParameters;
035import org.hl7.fhir.instance.model.api.IBaseResource;
036import org.hl7.fhir.instance.model.api.IPrimitiveType;
037
038import java.util.Collections;
039import java.util.Map;
040import java.util.TreeMap;
041
042import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
043import static org.apache.commons.lang3.StringUtils.isNotBlank;
044
045public final class JpaSystemProvider<T, MT> extends BaseJpaSystemProvider<T, MT> {
046
047        @Description(
048                        "Marks all currently existing resources of a given type, or all resources of all types, for reindexing.")
049        @Operation(
050                        name = MARK_ALL_RESOURCES_FOR_REINDEXING,
051                        idempotent = false,
052                        returnParameters = {@OperationParam(name = "status")})
053        /**
054         * @deprecated
055         * @see ReindexProvider#Reindex(List, IPrimitiveType, RequestDetails)
056         */
057        @Deprecated
058        public IBaseResource markAllResourcesForReindexing(
059                        @OperationParam(name = "type", min = 0, max = 1, typeName = "code") IPrimitiveType<String> theType) {
060
061                if (theType != null && isNotBlank(theType.getValueAsString())) {
062                        getResourceReindexingSvc().markAllResourcesForReindexing(theType.getValueAsString());
063                } else {
064                        getResourceReindexingSvc().markAllResourcesForReindexing();
065                }
066
067                IBaseParameters retVal = ParametersUtil.newInstance(getContext());
068
069                IPrimitiveType<?> string = ParametersUtil.createString(getContext(), "Marked resources");
070                ParametersUtil.addParameterToParameters(getContext(), retVal, "status", string);
071
072                return retVal;
073        }
074
075        @Description("Forces a single pass of the resource reindexing processor")
076        @Operation(
077                        name = PERFORM_REINDEXING_PASS,
078                        idempotent = false,
079                        returnParameters = {@OperationParam(name = "status")})
080        /**
081         * @deprecated
082         * @see ReindexProvider#Reindex(List, IPrimitiveType, RequestDetails)
083         */
084        @Deprecated
085        public IBaseResource performReindexingPass() {
086                Integer count = getResourceReindexingSvc().runReindexingPass();
087
088                IBaseParameters retVal = ParametersUtil.newInstance(getContext());
089
090                IPrimitiveType<?> string;
091                if (count == null) {
092                        string = ParametersUtil.createString(getContext(), "Index pass already proceeding");
093                } else {
094                        string = ParametersUtil.createString(getContext(), "Indexed " + count + " resources");
095                }
096                ParametersUtil.addParameterToParameters(getContext(), retVal, "status", string);
097
098                return retVal;
099        }
100
101        @Operation(name = JpaConstants.OPERATION_GET_RESOURCE_COUNTS, idempotent = true)
102        @Description(
103                        shortDefinition =
104                                        "Provides the number of resources currently stored on the server, broken down by resource type")
105        public IBaseParameters getResourceCounts() {
106                IBaseParameters retVal = ParametersUtil.newInstance(getContext());
107
108                Map<String, Long> counts = getDao().getResourceCountsFromCache();
109                counts = defaultIfNull(counts, Collections.emptyMap());
110                counts = new TreeMap<>(counts);
111                for (Map.Entry<String, Long> nextEntry : counts.entrySet()) {
112                        ParametersUtil.addParameterToParametersInteger(
113                                        getContext(),
114                                        retVal,
115                                        nextEntry.getKey(),
116                                        nextEntry.getValue().intValue());
117                }
118
119                return retVal;
120        }
121
122        @Operation(
123                        name = ProviderConstants.OPERATION_META,
124                        idempotent = true,
125                        returnParameters = {@OperationParam(name = "return", typeName = "Meta")})
126        public IBaseParameters meta(RequestDetails theRequestDetails) {
127                IBaseParameters retVal = ParametersUtil.newInstance(getContext());
128                ParametersUtil.addParameterToParameters(
129                                getContext(), retVal, "return", getDao().metaGetOperation(theRequestDetails));
130                return retVal;
131        }
132
133        @SuppressWarnings("unchecked")
134        @Transaction
135        public IBaseBundle transaction(RequestDetails theRequestDetails, @TransactionParam IBaseBundle theResources) {
136                startRequest(((ServletRequestDetails) theRequestDetails).getServletRequest());
137                try {
138                        IFhirSystemDao<T, MT> dao = getDao();
139                        return (IBaseBundle) dao.transaction(theRequestDetails, (T) theResources);
140                } finally {
141                        endRequest(((ServletRequestDetails) theRequestDetails).getServletRequest());
142                }
143        }
144}