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