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