001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2022 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 */
022import static org.apache.commons.lang3.StringUtils.isBlank;
023
024import java.util.List;
025
026import org.apache.commons.lang3.Validate;
027import org.apache.commons.lang3.builder.ToStringBuilder;
028import org.apache.commons.lang3.builder.ToStringStyle;
029
030import ca.uhn.fhir.context.ConfigurationException;
031import ca.uhn.fhir.context.FhirContext;
032import ca.uhn.fhir.model.api.IQueryParameterType;
033import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
034
035public class CompositeParam<A extends IQueryParameterType, B extends IQueryParameterType> extends BaseParam implements IQueryParameterType {
036
037        private A myLeftType;
038        private B myRightType;
039
040        public CompositeParam(A theLeftInstance, B theRightInstance) {
041                myLeftType = theLeftInstance;
042                myRightType = theRightInstance;
043        }
044
045        public CompositeParam(Class<A> theLeftType, Class<B> theRightType) {
046                Validate.notNull(theLeftType);
047                Validate.notNull(theRightType);
048                try {
049                        myLeftType = theLeftType.newInstance();
050                } catch (InstantiationException e) {
051                        throw new ConfigurationException("Failed to instantiate type: " + myLeftType, e);
052                } catch (IllegalAccessException e) {
053                        throw new ConfigurationException("Failed to instantiate type: " + myLeftType, e);
054                }
055                try {
056                        myRightType = theRightType.newInstance();
057                } catch (InstantiationException e) {
058                        throw new ConfigurationException("Failed to instantiate type: " + myRightType, e);
059                } catch (IllegalAccessException e) {
060                        throw new ConfigurationException("Failed to instantiate type: " + myRightType, e);
061                }
062        }
063
064        @Override
065        String doGetQueryParameterQualifier() {
066                return null;
067        }
068
069        @Override
070        String doGetValueAsQueryToken(FhirContext theContext) {
071                StringBuilder b = new StringBuilder();
072                if (myLeftType != null) {
073                        b.append(myLeftType.getValueAsQueryToken(theContext));
074                }
075                b.append('$');
076                if (myRightType != null) {
077                        b.append(myRightType.getValueAsQueryToken(theContext));
078                }
079                return b.toString();
080        }
081
082        @Override
083        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
084                if (isBlank(theValue)) {
085                        myLeftType.setValueAsQueryToken(theContext, theParamName, theQualifier, "");
086                        myRightType.setValueAsQueryToken(theContext, theParamName, theQualifier, "");
087                } else {
088                        List<String> parts = ParameterUtil.splitParameterString(theValue, '$', false);
089                        if (parts.size() > 2) {
090                                throw new InvalidRequestException("Invalid value for composite parameter (only one '$' is valid for this parameter, others must be escaped). Value was: " + theValue);
091                        }
092                        myLeftType.setValueAsQueryToken(theContext, theParamName, theQualifier, parts.get(0));
093                        if (parts.size() > 1) {
094                                myRightType.setValueAsQueryToken(theContext, theParamName, theQualifier, parts.get(1));
095                        }
096                }
097        }
098
099        /**
100         * @return Returns the left value for this parameter (the first of two parameters in this composite)
101         */
102        public A getLeftValue() {
103                return myLeftType;
104        }
105
106        /**
107         * @return Returns the right value for this parameter (the second of two parameters in this composite)
108         */
109        public B getRightValue() {
110                return myRightType;
111        }
112
113        @Override
114        public String toString() {
115                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
116                b.append("myLeftType", getLeftValue());
117                b.append("myRightType", getRightValue());
118                return b.toString();
119        }
120
121}