001/*-
002 * #%L
003 * Smile CDR - CDR
004 * %%
005 * Copyright (C) 2016 - 2026 Smile CDR, Inc.
006 * %%
007 * All rights reserved.
008 * #L%
009 */
010package ca.cdr.api.fhirgw.model;
011
012import org.hl7.fhir.instance.model.api.IBaseResource;
013import org.slf4j.Logger;
014import org.slf4j.LoggerFactory;
015
016import java.util.Collection;
017import java.util.Collections;
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021
022import static java.util.Collections.emptyList;
023import static java.util.Objects.nonNull;
024import static org.apache.commons.lang3.ObjectUtils.getIfNull;
025
026public class OperationResponsesAccumulator implements IResultsAccumulator<OperationResponse> {
027
028        private static final Logger ourLog = LoggerFactory.getLogger(OperationResponsesAccumulator.class);
029
030        private final int myMaxResponsesCount;
031
032        private final Map<String, OperationResponse> myTargetIdToResponseMap = Collections.synchronizedMap(new HashMap<>());
033
034        public OperationResponsesAccumulator() {
035                this(Integer.MAX_VALUE);
036        }
037
038        public OperationResponsesAccumulator(int theMaxResponsesCount) {
039                myMaxResponsesCount = theMaxResponsesCount;
040        }
041
042        public boolean isAcceptingMoreOperationResponses() {
043                return getResults().size() < myMaxResponsesCount;
044        }
045
046        public Collection<OperationResponse> getResults() {
047                return myTargetIdToResponseMap.values();
048        }
049
050        /**
051         * Accumulates a list of resources that was originally obtained from the RESPONSE
052         * and processed by interceptors if applicable.
053         *
054         * @param theResults the list of resources processed by interceptors to accumulate
055         * @param theResponse the original response from which a list of resources was obtained and submitted to interceptors
056         * @param theTargetId the id of the target that returned the RESPONSE
057         */
058        @Override
059        public void accumulate(List<IBaseResource> theResults, OperationResponse theResponse, String theTargetId) {
060                // at this point, theResults is a list of resources (originally obtained from theResponse) that was processed
061                // by interceptors.  if applicable, we need to:
062                // 1- sanitize the list;
063                // 2- store it in theResponse;
064                // 3- accumulate theResponse;
065
066                if (!isAcceptingMoreOperationResponses()) {
067                        return;
068                }
069
070                List<IBaseResource> nonNullResultList = getIfNull(theResults, emptyList());
071                List<IBaseResource> sanitizedResultList = nonNullResultList.stream()
072                                .filter(theIBaseResource -> nonNull(theIBaseResource))
073                                .toList();
074
075                // the target response for an operation is one IBaseResource or nothing if there was an exception thrown by
076                // the invocation.  if we have anything to return, it will be at the first index.
077                IBaseResource resourceToReturn = sanitizedResultList.isEmpty() ? null : sanitizedResultList.get(0);
078
079                theResponse.setResponse(resourceToReturn);
080
081                myTargetIdToResponseMap.put(theTargetId, theResponse);
082        }
083
084        @Override
085        public void addResults(String theTargetId, List<IBaseResource> theResults, int theTotal) {
086                ourLog.debug("Can't add {} Resources to targetId {}.  Operation not supported", theResults.size(), theTargetId);
087        }
088
089        @Override
090        public List<IBaseResource> getResults(String theTargetId) {
091                ourLog.debug("Can't provide a list of Resources for targetId {}.  Operation not supported", theTargetId);
092                return emptyList();
093        }
094
095        @Override
096        public List<IBaseResource> getMatchedResults(String theTargetId) {
097                ourLog.debug("Can't provide matched results for targetId {}.  Operation not supported", theTargetId);
098                return emptyList();
099        }
100
101        @Override
102        public List<IBaseResource> getPageableResults(String theTargetId) {
103                ourLog.debug("Can't provide pageable results for targetId {}.  Operation not supported", theTargetId);
104                return emptyList();
105        }
106
107        @Override
108        public List<IBaseResource> getIncludeResults(String theTargetId) {
109                ourLog.debug("Can't provide a list of included results targetId {}.  Operation not supported", theTargetId);
110                return emptyList();
111        }
112
113        @Override
114        public List<IBaseResource> getOutcomeResults(String theTargetId) {
115                ourLog.debug("Can't provide a list of outcome results targetId {}.  Operation not supported", theTargetId);
116                return emptyList();
117        }
118
119        @Override
120        public List<IBaseResource> getUncategorizedResults(String theTargetId) {
121                ourLog.debug(
122                                "Can't provide a list of uncategorized included results targetId {}.  Operation not supported",
123                                theTargetId);
124                return emptyList();
125        }
126
127        @Override
128        public void removeResults(String theTargetId, List<IBaseResource> theResultsToBeRemoved) {
129                ourLog.debug("Can't remove results for targetId {}.  Operation not supported", theTargetId);
130        }
131
132        @Override
133        public int getTotal() {
134                ourLog.debug("Can't provide a total count.  A placeholder value of 0 is returned.  Operation not supported");
135                return 0;
136        }
137
138        @Override
139        public boolean getTotalOmitted() {
140                ourLog.debug(
141                                "Can't provide a total omitted count. A placeholder value of false is returned.  Operation not supported");
142                return false;
143        }
144
145        @Override
146        public void setTotalOmitted(boolean theTotalOmitted) {
147                ourLog.debug("Can't set the total omitted count to {}.  Operation not supported", theTotalOmitted);
148        }
149}