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