001/* 002 * #%L 003 * HAPI FHIR - Client 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.client.method; 021 022import ca.uhn.fhir.context.ConfigurationException; 023import ca.uhn.fhir.context.FhirContext; 024import ca.uhn.fhir.context.FhirVersionEnum; 025import ca.uhn.fhir.i18n.Msg; 026import ca.uhn.fhir.rest.annotation.Sort; 027import ca.uhn.fhir.rest.api.Constants; 028import ca.uhn.fhir.rest.api.SortOrderEnum; 029import ca.uhn.fhir.rest.api.SortSpec; 030import ca.uhn.fhir.rest.param.ParameterUtil; 031import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 032import org.hl7.fhir.instance.model.api.IBaseResource; 033 034import java.lang.reflect.Method; 035import java.util.ArrayList; 036import java.util.Collection; 037import java.util.List; 038import java.util.Map; 039 040import static org.apache.commons.lang3.StringUtils.isNotBlank; 041 042public class SortParameter implements IParameter { 043 044 private FhirContext myContext; 045 046 public SortParameter(FhirContext theContext) { 047 myContext = theContext; 048 } 049 050 @Override 051 public void initializeTypes( 052 Method theMethod, 053 Class<? extends Collection<?>> theOuterCollectionType, 054 Class<? extends Collection<?>> theInnerCollectionType, 055 Class<?> theParameterType) { 056 if (theOuterCollectionType != null || theInnerCollectionType != null) { 057 throw new ConfigurationException(Msg.code(1463) + "Method '" + theMethod.getName() + "' in type '" 058 + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + Sort.class.getName() 059 + " but can not be of collection type"); 060 } 061 if (!theParameterType.equals(SortSpec.class)) { 062 throw new ConfigurationException(Msg.code(1464) + "Method '" + theMethod.getName() + "' in type '" 063 + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + Sort.class.getName() 064 + " but is an invalid type, must be: " + SortSpec.class.getCanonicalName()); 065 } 066 } 067 068 @Override 069 public void translateClientArgumentIntoQueryArgument( 070 FhirContext theContext, 071 Object theSourceClientArgument, 072 Map<String, List<String>> theTargetQueryArguments, 073 IBaseResource theTargetResource) 074 throws InternalErrorException { 075 SortSpec ss = (SortSpec) theSourceClientArgument; 076 077 if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2)) { 078 String string = createSortStringDstu3(ss); 079 if (string.length() > 0) { 080 if (!theTargetQueryArguments.containsKey(Constants.PARAM_SORT)) { 081 theTargetQueryArguments.put(Constants.PARAM_SORT, new ArrayList<String>()); 082 } 083 theTargetQueryArguments.get(Constants.PARAM_SORT).add(string); 084 } 085 086 } else { 087 088 while (ss != null) { 089 String name; 090 if (ss.getOrder() == null) { 091 name = Constants.PARAM_SORT; 092 } else if (ss.getOrder() == SortOrderEnum.ASC) { 093 name = Constants.PARAM_SORT_ASC; 094 } else { 095 name = Constants.PARAM_SORT_DESC; 096 } 097 098 if (ss.getParamName() != null) { 099 if (!theTargetQueryArguments.containsKey(name)) { 100 theTargetQueryArguments.put(name, new ArrayList<String>()); 101 } 102 103 theTargetQueryArguments.get(name).add(ss.getParamName()); 104 } 105 ss = ss.getChain(); 106 } 107 } 108 } 109 110 public static String createSortStringDstu3(SortSpec ss) { 111 StringBuilder val = new StringBuilder(); 112 while (ss != null) { 113 114 if (isNotBlank(ss.getParamName())) { 115 if (val.length() > 0) { 116 val.append(','); 117 } 118 if (ss.getOrder() == SortOrderEnum.DESC) { 119 val.append('-'); 120 } 121 val.append(ParameterUtil.escape(ss.getParamName())); 122 } 123 124 ss = ss.getChain(); 125 } 126 127 String string = val.toString(); 128 return string; 129 } 130}