
001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2026 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.api; 021 022import ca.uhn.fhir.i18n.Msg; 023 024import java.io.Serial; 025import java.io.Serializable; 026import java.util.Objects; 027 028/** 029 * Represents values for <a href="http://hl7.org/implement/standards/fhir/search.html#sort">sorting</a> resources 030 * returned by a server. 031 */ 032public class SortSpec implements Serializable { 033 034 @Serial 035 private static final long serialVersionUID = 2866833099879713467L; 036 037 private SortSpec myChain; 038 private String myParamName; 039 private SortOrderEnum myOrder; 040 041 /** 042 * Constructor 043 */ 044 public SortSpec() { 045 super(); 046 } 047 048 /** 049 * Constructor 050 * 051 * @param theParamName The search name to sort on. See {@link #setParamName(String)} for more information. 052 */ 053 public SortSpec(String theParamName) { 054 super(); 055 myParamName = theParamName; 056 } 057 058 /** 059 * Constructor 060 * 061 * @param theParamName The search name to sort on. See {@link #setParamName(String)} for more information. 062 * @param theOrder The order, or <code>null</code>. See {@link #setOrder(SortOrderEnum)} for more information. 063 */ 064 public SortSpec(String theParamName, SortOrderEnum theOrder) { 065 super(); 066 myParamName = theParamName; 067 myOrder = theOrder; 068 } 069 070 /** 071 * Constructor 072 * 073 * @param theParamName The search name to sort on. See {@link #setParamName(String)} for more information. 074 * @param theOrder The order, or <code>null</code>. See {@link #setOrder(SortOrderEnum)} for more information. 075 * @param theChain The next sorting spec, to be applied only when this spec makes two entries equal. See 076 * {@link #setChain(SortSpec)} for more information. 077 */ 078 public SortSpec(String theParamName, SortOrderEnum theOrder, SortSpec theChain) { 079 super(); 080 myParamName = theParamName; 081 myOrder = theOrder; 082 myChain = theChain; 083 } 084 085 /** 086 * Gets the chained sort specification, or <code>null</code> if none. If multiple sort parameters are chained 087 * (indicating a sub-sort), the second level sort is chained via this property. 088 */ 089 public SortSpec getChain() { 090 return myChain; 091 } 092 093 /** 094 * Sets the chained sort specification, or <code>null</code> if none. If multiple sort parameters are chained 095 * (indicating a sub-sort), the second level sort is chained via this property. 096 */ 097 public SortSpec setChain(SortSpec theChain) { 098 if (theChain == this) { 099 throw new IllegalArgumentException(Msg.code(1966) + "Can not chain this to itself"); 100 } 101 myChain = theChain; 102 return this; 103 } 104 105 /** 106 * Returns the actual name of the search param to sort by 107 */ 108 public String getParamName() { 109 return myParamName; 110 } 111 112 /** 113 * Sets the actual name of the search param to sort by 114 */ 115 public SortSpec setParamName(String theFieldName) { 116 myParamName = theFieldName; 117 return this; 118 } 119 120 /** 121 * Returns the sort order specified by this parameter, or <code>null</code> if none is explicitly provided (which 122 * means {@link SortOrderEnum#ASC} according to the <a 123 * href="http://hl7.org/implement/standards/fhir/search.html#sort">FHIR specification</a>) 124 */ 125 public SortOrderEnum getOrder() { 126 return myOrder; 127 } 128 129 /** 130 * Sets the sort order specified by this parameter, or <code>null</code> if none should be explicitly defined (which 131 * means {@link SortOrderEnum#ASC} according to the <a 132 * href="http://hl7.org/implement/standards/fhir/search.html#sort">FHIR specification</a>) 133 */ 134 public SortSpec setOrder(SortOrderEnum theOrder) { 135 myOrder = theOrder; 136 return this; 137 } 138 139 @Override 140 public String toString() { 141 StringBuilder b = new StringBuilder(); 142 b.append(getParamName()); 143 if (getOrder() != null) { 144 b.append('(').append(getOrder()).append(')'); 145 } 146 if (myChain != null) { 147 b.append(',').append(myChain); 148 } 149 return b.toString(); 150 } 151 152 @Override 153 public boolean equals(Object theO) { 154 if (!(theO instanceof SortSpec sortSpec)) { 155 return false; 156 } 157 return Objects.equals(myChain, sortSpec.myChain) 158 && Objects.equals(myParamName, sortSpec.myParamName) 159 && myOrder == sortSpec.myOrder; 160 } 161 162 @Override 163 public int hashCode() { 164 return Objects.hash(myChain, myParamName, myOrder); 165 } 166 167 /** 168 * Convert strings like "-date" into a SortSpec object. 169 * Note: this does not account for DSTU2-style sort modifiers like "date:desc" or "date:asc" 170 * since those are on the parameter name, not the value. 171 * 172 * @param theParamValue a string like "-date" or "date" 173 * @return a parsed SortSpec object 174 */ 175 public static SortSpec fromR3OrLaterParameterValue(String theParamValue) { 176 SortOrderEnum direction = SortOrderEnum.ASC; 177 if (theParamValue.startsWith("-")) { 178 direction = SortOrderEnum.DESC; 179 theParamValue = theParamValue.substring(1); 180 } 181 return new SortSpec(theParamValue, direction); 182 } 183}