001package ca.uhn.fhir.model.base.composite;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
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 */
022
023import org.apache.commons.lang3.StringUtils;
024
025import ca.uhn.fhir.context.FhirContext;
026import ca.uhn.fhir.model.api.BaseIdentifiableElement;
027import ca.uhn.fhir.model.api.ICompositeDatatype;
028import ca.uhn.fhir.model.api.IQueryParameterType;
029import ca.uhn.fhir.model.primitive.CodeDt;
030import ca.uhn.fhir.model.primitive.StringDt;
031import ca.uhn.fhir.model.primitive.UriDt;
032import ca.uhn.fhir.rest.param.ParameterUtil;
033import ca.uhn.fhir.rest.param.TokenParam;
034
035public abstract class BaseCodingDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
036
037        private static final long serialVersionUID = 4425182816398730643L;
038
039        /**
040         * Gets the value(s) for <b>code</b> (Symbol in syntax defined by the system). creating it if it does not exist. Will not return <code>null</code>.
041         *
042         * <p>
043         * <b>Definition:</b> A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post-coordination)
044         * </p>
045         */
046        public abstract CodeDt getCodeElement();
047
048        @Override
049        public String getQueryParameterQualifier() {
050                return null;
051        }
052
053        /**
054         * Gets the value(s) for <b>system</b> (Identity of the terminology system). creating it if it does not exist. Will not return <code>null</code>.
055         *
056         * <p>
057         * <b>Definition:</b> The identification of the code system that defines the meaning of the symbol in the code.
058         * </p>
059         */
060        public abstract UriDt getSystemElement();
061
062        /**
063         * Gets the value(s) for <b>display</b> (Representation defined by the system).
064         * creating it if it does
065         * not exist. Will not return <code>null</code>.
066         *
067     * <p>
068     * <b>Definition:</b>
069     * A representation of the meaning of the code in the system, following the rules of the system.
070     * </p> 
071         */
072        public abstract StringDt getDisplayElement();
073
074        public abstract BaseCodingDt setDisplay( String theString);
075
076        /*
077        todo: handle version
078        public abstract StringDt getVersion();
079
080        public abstract BaseCodingDt setVersion ( String theString);
081        */
082
083        /**
084         * {@inheritDoc}
085         */
086        @Override
087        public String getValueAsQueryToken(FhirContext theContext) {
088                if (getSystemElement().getValueAsString() != null) {
089                        return ParameterUtil.escape(StringUtils.defaultString(getSystemElement().getValueAsString())) + '|' + ParameterUtil.escape(getCodeElement().getValueAsString());
090                } 
091                return ParameterUtil.escape(getCodeElement().getValueAsString());
092        }
093
094        /**
095         * {@inheritDoc}
096         */
097        @Override
098        public void setValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theParameter) {
099                int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
100                if (barIndex != -1) {
101                        setSystem(theParameter.substring(0, barIndex));
102                        setCode(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
103                } else {
104                        setCode(ParameterUtil.unescape(theParameter));
105                }
106        }
107
108        /**
109         * Returns true if <code>this</code> Coding has the same {@link #getCodeElement() Code} and {@link #getSystemElement() system} (as compared by simple equals comparison). Does not compare other
110         * Codes (e.g. getUseElement()) or any extensions.
111         */
112        public boolean matchesSystemAndCode(BaseCodingDt theCoding) {
113                if (theCoding == null) {
114                        return false;
115                }
116                return getCodeElement().equals(theCoding.getCodeElement()) && getSystemElement().equals(theCoding.getSystemElement());
117        }
118
119        /**
120         * returns true if <code>this</code> Coding matches a search for the coding specified by <code>theSearchParam</code>, according
121         * to the following:
122         * <ul>
123         *              <li>[parameter]=[namespace]|[code] matches a code/value in the given system namespace</li>
124         *              <li>[parameter]=[code] matches a code/value irrespective of it's system namespace</li>
125         *              <li>[parameter]=|[code] matches a code/value that has no system namespace</li>
126         * </ul>
127         * @param theSearchParam - coding to test <code>this</code> against
128         * @return true if the coding matches, false otherwise
129         */
130        public boolean matchesToken(BaseCodingDt theSearchParam) {
131                if (theSearchParam.isSystemPresent()) {
132                        if (theSearchParam.isSystemBlank()) {
133                                //  [parameter]=|[code] matches a code/value that has no system namespace
134                                if (isSystemPresent() && !isSystemBlank())
135                                        return false;
136                        } else {
137                                //  [parameter]=[namespace]|[code] matches a code/value in the given system namespace
138                                if (!isSystemPresent())
139                                        return false;
140                                if (!getSystemElement().equals(theSearchParam.getSystemElement()))
141                                        return false;
142                        }
143                } else {
144                        //  [parameter]=[code] matches a code/value irrespective of it's system namespace
145                        // (nothing to do for system for this case)
146                }
147
148                return getCodeElement().equals(theSearchParam.getCodeElement());
149        }
150
151        private boolean isSystemPresent() {
152                return !getSystemElement().isEmpty();
153        }
154
155        private boolean isSystemBlank() {
156                return isSystemPresent() && getSystemElement().getValueAsString().equals("");
157        }
158
159        /**
160         * Sets the value for <b>code</b> (Symbol in syntax defined by the system)
161         *
162         * <p>
163         * <b>Definition:</b> A symbol in syntax defined by the system. The symbol may be a predefined code or an expression in a syntax defined by the coding system (e.g. post-coordination)
164         * </p>
165         */
166        public abstract BaseCodingDt setCode(String theCode);
167
168        /**
169         * Sets the value for <b>system</b> (Identity of the terminology system)
170         *
171         * <p>
172         * <b>Definition:</b> The identification of the code system that defines the meaning of the symbol in the code.
173         * </p>
174         */
175        public abstract BaseCodingDt setSystem(String theUri);
176
177
178        /**
179         * <b>Not supported!</b>
180         * 
181         * @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
182         * need this functionality
183         */
184        @Deprecated
185        @Override
186        public Boolean getMissing() {
187                return null;
188        }
189
190        /**
191         * <b>Not supported!</b>
192         * 
193         * @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
194         * need this functionality
195         */
196        @Deprecated
197        @Override
198        public IQueryParameterType setMissing(Boolean theMissing) {
199                throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
200        }
201
202}