001/*
002 * #%L
003 * HAPI FHIR Structures - DSTU2 (FHIR v1.0.0)
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.model.dstu2.composite;
021
022import ca.uhn.fhir.model.api.IBoundCodeableConcept;
023import ca.uhn.fhir.model.api.IValueSetEnumBinder;
024import ca.uhn.fhir.model.api.annotation.DatatypeDef;
025import org.apache.commons.lang3.Validate;
026
027import java.util.Collection;
028import java.util.HashSet;
029import java.util.Set;
030
031import static org.apache.commons.lang3.StringUtils.defaultString;
032
033@DatatypeDef(name = "CodeableConcept", isSpecialization = true)
034public class BoundCodeableConceptDt<T extends Enum<?>> extends CodeableConceptDt implements IBoundCodeableConcept {
035
036        private IValueSetEnumBinder<T> myBinder;
037
038        /**
039         * @deprecated This constructor is provided only for serialization support. Do not call it directly!
040         */
041        @Deprecated
042        public BoundCodeableConceptDt() {
043                // nothing
044        }
045
046        /**
047         * Constructor
048         */
049        public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder) {
050                Validate.notNull(theBinder, "theBinder must not be null");
051                myBinder = theBinder;
052        }
053
054        /**
055         * Constructor
056         */
057        public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder, T theValue) {
058                Validate.notNull(theBinder, "theBinder must not be null");
059                myBinder = theBinder;
060                setValueAsEnum(theValue);
061        }
062
063        /**
064         * Constructor
065         */
066        public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder, Collection<T> theValues) {
067                Validate.notNull(theBinder, "theBinder must not be null");
068                myBinder = theBinder;
069                setValueAsEnum(theValues);
070        }
071
072        /**
073         * Sets the {@link #getCoding()} to contain a coding with the code and
074         * system defined by the given enumerated types, AND clearing any existing
075         * codings first. If theValue is null, existing codings are cleared and no
076         * codings are added.
077         *
078         * @param theValues
079         *            The value to add, or <code>null</code>
080         */
081        public void setValueAsEnum(Collection<T> theValues) {
082                Validate.notNull(
083                                myBinder,
084                                "This object does not have a binder. Constructor BoundCodeableConceptDt() should not be called!");
085                getCoding().clear();
086                if (theValues != null) {
087                        for (T next : theValues) {
088                                getCoding().add(new CodingDt(myBinder.toSystemString(next), myBinder.toCodeString(next)));
089                        }
090                }
091        }
092
093        /**
094         * Sets the {@link #getCoding()} to contain a coding with the code and
095         * system defined by the given enumerated type, AND clearing any existing
096         * codings first. If theValue is null, existing codings are cleared and no
097         * codings are added.
098         *
099         * @param theValue
100         *            The value to add, or <code>null</code>
101         */
102        public void setValueAsEnum(T theValue) {
103                Validate.notNull(
104                                myBinder,
105                                "This object does not have a binder. Constructor BoundCodeableConceptDt() should not be called!");
106                getCoding().clear();
107                if (theValue == null) {
108                        return;
109                }
110                getCoding().add(new CodingDt(myBinder.toSystemString(theValue), myBinder.toCodeString(theValue)));
111        }
112
113        /**
114         * Loops through the {@link #getCoding() codings} in this codeable concept
115         * and returns the first bound enumerated type that matches. <b>Use
116         * caution</b> using this method, see the return description for more
117         * information.
118         *
119         * @return Returns the bound enumerated type, or <code>null</code> if none
120         *         are found. Note that a null return value doesn't neccesarily
121         *         imply that this Codeable Concept has no codes, only that it has
122         *         no codes that match the enum.
123         */
124        public Set<T> getValueAsEnum() {
125                Validate.notNull(
126                                myBinder,
127                                "This object does not have a binder. Constructor BoundCodeableConceptDt() should not be called!");
128                Set<T> retVal = new HashSet<T>();
129                for (CodingDt next : getCoding()) {
130                        if (next == null) {
131                                continue;
132                        }
133                        T nextT = myBinder.fromCodeString(
134                                        defaultString(next.getCodeElement().getValue()),
135                                        defaultString(next.getSystemElement().getValueAsString()));
136                        if (nextT != null) {
137                                retVal.add(nextT);
138                        } else {
139                                // TODO: throw special exception type?
140                        }
141                }
142                return retVal;
143        }
144}