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