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