001/* 002 * #%L 003 * HAPI FHIR - Server Framework 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.rest.server.method; 021 022import ca.uhn.fhir.context.ConfigurationException; 023import ca.uhn.fhir.i18n.Msg; 024import ca.uhn.fhir.rest.api.Constants; 025import ca.uhn.fhir.rest.api.SummaryEnum; 026import ca.uhn.fhir.rest.api.server.RequestDetails; 027import ca.uhn.fhir.rest.param.binder.CollectionBinder; 028import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 029import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 030 031import java.lang.reflect.Method; 032import java.util.Collection; 033import java.util.Collections; 034import java.util.HashSet; 035import java.util.Set; 036 037import static org.apache.commons.lang3.StringUtils.isBlank; 038 039public class SummaryEnumParameter implements IParameter { 040 041 @SuppressWarnings("rawtypes") 042 private Class<? extends Collection> myInnerCollectionType; 043 044 @Override 045 @SuppressWarnings({"rawtypes", "unchecked"}) 046 public Object translateQueryParametersIntoServerArgument( 047 RequestDetails theRequest, BaseMethodBinding theMethodBinding) 048 throws InternalErrorException, InvalidRequestException { 049 Set<SummaryEnum> value = getSummaryValueOrNull(theRequest); 050 if (value == null || value.isEmpty()) { 051 return null; 052 } 053 054 if (myInnerCollectionType == null) { 055 return value.iterator().next(); 056 } 057 058 try { 059 Collection retVal = myInnerCollectionType.newInstance(); 060 retVal.addAll(value); 061 return retVal; 062 } catch (InstantiationException e) { 063 throw new InternalErrorException(Msg.code(378) + "Failed to instantiate " + myInnerCollectionType, e); 064 } catch (IllegalAccessException e) { 065 throw new InternalErrorException(Msg.code(379) + "Failed to instantiate " + myInnerCollectionType, e); 066 } 067 } 068 069 public static Set<SummaryEnum> getSummaryValueOrNull(RequestDetails theRequest) { 070 String[] summary = theRequest.getParameters().get(Constants.PARAM_SUMMARY); 071 072 Set<SummaryEnum> retVal; 073 if (summary == null || summary.length == 0) { 074 retVal = null; 075 } else if (isBlank(summary[0])) { 076 retVal = null; 077 } else if (summary.length == 1 && summary[0].indexOf(',') == -1) { 078 retVal = toCollectionOrNull(SummaryEnum.fromCode(summary[0])); 079 if (retVal == null) { 080 retVal = toCollectionOrNull(SummaryEnum.fromCode(summary[0].toLowerCase())); 081 } 082 } else { 083 retVal = new HashSet<>(); 084 for (String nextParamValue : summary) { 085 for (String nextParamValueTok : nextParamValue.split(",")) { 086 SummaryEnum value = SummaryEnum.fromCode(nextParamValueTok); 087 if (value == null) { 088 value = SummaryEnum.fromCode(nextParamValueTok.toLowerCase()); 089 } 090 if (value != null) { 091 retVal.add(value); 092 } 093 } 094 } 095 } 096 097 if (retVal != null) { 098 if (retVal.contains(SummaryEnum.TEXT)) { 099 if (retVal.size() > 1) { 100 String msg = theRequest 101 .getServer() 102 .getFhirContext() 103 .getLocalizer() 104 .getMessage(SummaryEnumParameter.class, "cantCombineText"); 105 throw new InvalidRequestException(Msg.code(380) + msg); 106 } 107 } 108 } 109 110 return retVal; 111 } 112 113 private static Set<SummaryEnum> toCollectionOrNull(SummaryEnum theFromCode) { 114 if (theFromCode == null) { 115 return null; 116 } 117 return Collections.singleton(theFromCode); 118 } 119 120 @Override 121 public void initializeTypes( 122 Method theMethod, 123 Class<? extends Collection<?>> theOuterCollectionType, 124 Class<? extends Collection<?>> theInnerCollectionType, 125 Class<?> theParameterType) { 126 if (theOuterCollectionType != null) { 127 throw new ConfigurationException(Msg.code(381) + "Method '" + theMethod.getName() + "' in type '" 128 + theMethod.getDeclaringClass().getCanonicalName() + "' is of type " + SummaryEnum.class 129 + " but can not be a collection of collections"); 130 } 131 if (theInnerCollectionType != null) { 132 myInnerCollectionType = CollectionBinder.getInstantiableCollectionType( 133 theInnerCollectionType, SummaryEnum.class.getSimpleName()); 134 } 135 } 136}