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