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.param;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.model.api.IQueryParameterType;
025import ca.uhn.fhir.rest.api.Constants;
026import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
027
028import java.io.Serial;
029import java.util.Objects;
030
031import static org.apache.commons.lang3.StringUtils.defaultString;
032
033/**
034 * Implementation of the _has method parameter
035 */
036public class HasParam extends BaseParam implements IQueryParameterType {
037
038        @Serial
039        private static final long serialVersionUID = 1L;
040
041        private String myReferenceFieldName;
042        private String myParameterName;
043        private String myParameterValue;
044        private String myTargetResourceType;
045
046        public HasParam() {
047                super();
048        }
049
050        public HasParam(
051                        String theTargetResourceType,
052                        String theReferenceFieldName,
053                        String theParameterName,
054                        String theParameterValue) {
055                this();
056                myTargetResourceType = theTargetResourceType;
057                myReferenceFieldName = theReferenceFieldName;
058                myParameterName = theParameterName;
059                myParameterValue = theParameterValue;
060        }
061
062        @Override
063        String doGetQueryParameterQualifier() {
064                return ':' + myTargetResourceType + ':' + myReferenceFieldName + ':' + myParameterName;
065        }
066
067        @Override
068        String doGetValueAsQueryToken() {
069                return myParameterValue;
070        }
071
072        @Override
073        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
074                String qualifier = defaultString(theQualifier);
075                if (!qualifier.startsWith(":")) {
076                        throwInvalidSyntaxException(Constants.PARAM_HAS + qualifier);
077                }
078                int colonIndex0 = qualifier.indexOf(':', 1);
079                validateColon(qualifier, colonIndex0);
080                int colonIndex1 = qualifier.indexOf(':', colonIndex0 + 1);
081                validateColon(qualifier, colonIndex1);
082
083                myTargetResourceType = qualifier.substring(1, colonIndex0);
084                myReferenceFieldName = qualifier.substring(colonIndex0 + 1, colonIndex1);
085                myParameterName = qualifier.substring(colonIndex1 + 1);
086                myParameterValue = theValue;
087        }
088
089        public String getReferenceFieldName() {
090                return myReferenceFieldName;
091        }
092
093        public String getParameterName() {
094                return myParameterName;
095        }
096
097        public String getParameterValue() {
098                return myParameterValue;
099        }
100
101        public String getTargetResourceType() {
102                return myTargetResourceType;
103        }
104
105        @Override
106        public boolean equals(Object theO) {
107                if (!(theO instanceof HasParam hasParam)) {
108                        return false;
109                }
110                if (!super.equals(theO)) {
111                        return false;
112                }
113                return Objects.equals(myReferenceFieldName, hasParam.myReferenceFieldName)
114                                && Objects.equals(myParameterName, hasParam.myParameterName)
115                                && Objects.equals(myParameterValue, hasParam.myParameterValue)
116                                && Objects.equals(myTargetResourceType, hasParam.myTargetResourceType);
117        }
118
119        @Override
120        public int hashCode() {
121                return Objects.hash(
122                                super.hashCode(), myReferenceFieldName, myParameterName, myParameterValue, myTargetResourceType);
123        }
124
125        private static void validateColon(String theParameterName, int colonIndex) {
126                if (colonIndex == -1) {
127                        throwInvalidSyntaxException(theParameterName);
128                }
129        }
130
131        private static void throwInvalidSyntaxException(String theParameterName) {
132                throw new InvalidRequestException(Msg.code(1942) + "Invalid _has parameter syntax: " + theParameterName);
133        }
134}