001package ca.uhn.fhir.rest.method; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2016 University Health Network 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.isNotBlank; 023 024import java.lang.reflect.Method; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Map; 030import java.util.Set; 031import java.util.StringTokenizer; 032 033import org.apache.commons.lang3.StringUtils; 034import org.hl7.fhir.instance.model.api.IBaseResource; 035 036import ca.uhn.fhir.context.ConfigurationException; 037import ca.uhn.fhir.context.FhirContext; 038import ca.uhn.fhir.rest.api.SummaryEnum; 039import ca.uhn.fhir.rest.param.CollectionBinder; 040import ca.uhn.fhir.rest.server.Constants; 041import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 042import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 043 044public class ElementsParameter implements IParameter { 045 046 @SuppressWarnings("rawtypes") 047 private Class<? extends Collection> myInnerCollectionType; 048 049 @SuppressWarnings("unchecked") 050 @Override 051 public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException { 052 if (theSourceClientArgument instanceof Collection) { 053 StringBuilder values = new StringBuilder(); 054 for (String next : (Collection<String>) theSourceClientArgument) { 055 if (isNotBlank(next)) { 056 if (values.length() > 0) { 057 values.append(','); 058 } 059 values.append(next); 060 } 061 } 062 theTargetQueryArguments.put(Constants.PARAM_ELEMENTS, Collections.singletonList(values.toString())); 063 } else { 064 String elements = (String) theSourceClientArgument; 065 if (elements != null) { 066 theTargetQueryArguments.put(Constants.PARAM_ELEMENTS, Collections.singletonList(elements)); 067 } 068 } 069 } 070 071 @Override 072 @SuppressWarnings({ "rawtypes", "unchecked" }) 073 public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException { 074 Set<String> value = getElementsValueOrNull(theRequest); 075 if (value == null || value.isEmpty()) { 076 return null; 077 } 078 079 if (myInnerCollectionType == null) { 080 return StringUtils.join(value, ','); 081 } 082 083 try { 084 Collection retVal = myInnerCollectionType.newInstance(); 085 retVal.addAll(value); 086 return retVal; 087 } catch (InstantiationException e) { 088 throw new InternalErrorException("Failed to instantiate " + myInnerCollectionType, e); 089 } catch (IllegalAccessException e) { 090 throw new InternalErrorException("Failed to instantiate " + myInnerCollectionType, e); 091 } 092 } 093 094 public static Set<String> getElementsValueOrNull(RequestDetails theRequest) { 095 String[] summary = theRequest.getParameters().get(Constants.PARAM_ELEMENTS); 096 097 if (summary != null && summary.length > 0) { 098 Set<String> retVal = new HashSet<String>(); 099 for (String next : summary) { 100 StringTokenizer tok = new StringTokenizer(next, ","); 101 while (tok.hasMoreTokens()) { 102 String token = tok.nextToken(); 103 if (isNotBlank(token)) { 104 retVal.add(token); 105 } 106 } 107 } 108 if (retVal.isEmpty()) { 109 return null; 110 } 111 return retVal; 112 } else { 113 return null; 114 } 115 } 116 117 @Override 118 public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) { 119 if (theOuterCollectionType != null) { 120 throw new ConfigurationException("Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is of type " + SummaryEnum.class + " but can not be a collection of collections"); 121 } 122 if (theInnerCollectionType != null) { 123 myInnerCollectionType = CollectionBinder.getInstantiableCollectionType(theInnerCollectionType, SummaryEnum.class.getSimpleName()); 124 } 125 } 126 127}