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 - 2016 University Health Network
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;
034import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
035import ca.uhn.fhir.model.dstu2.composite.CodingDt;
036
037@DatatypeDef(name = "CodeableConcept", isSpecialization = true)
038public class BoundCodeableConceptDt<T extends Enum<?>> extends CodeableConceptDt implements IBoundCodeableConcept {
039
040        private IValueSetEnumBinder<T> myBinder;
041
042        /**
043         * @deprecated This constructor is provided only for serialization support. Do not call it directly!
044         */
045        @Deprecated
046        public BoundCodeableConceptDt() {
047                // nothing
048        }
049
050        /**
051         * Constructor
052         */
053        public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder) {
054                Validate.notNull(theBinder, "theBinder must not be null");
055                myBinder = theBinder;
056        }
057
058        /**
059         * Constructor
060         */
061        public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder, T theValue) {
062                Validate.notNull(theBinder, "theBinder must not be null");
063                myBinder = theBinder;
064                setValueAsEnum(theValue);
065        }
066
067        /**
068         * Constructor
069         */
070        public BoundCodeableConceptDt(IValueSetEnumBinder<T> theBinder, Collection<T> theValues) {
071                Validate.notNull(theBinder, "theBinder must not be null");
072                myBinder = theBinder;
073                setValueAsEnum(theValues);
074        }
075
076        /**
077         * Sets the {@link #getCoding()} to contain a coding with the code and
078         * system defined by the given enumerated types, AND clearing any existing
079         * codings first. If theValue is null, existing codings are cleared and no
080         * codings are added.
081         * 
082         * @param theValues
083         *            The value to add, or <code>null</code>
084         */
085        public void setValueAsEnum(Collection<T> theValues) {
086                Validate.notNull(myBinder, "This object does not have a binder. Constructor BoundCodeableConceptDt() should not be called!");
087                getCoding().clear();
088                if (theValues != null) {
089                        for (T next : theValues) {
090                                getCoding().add(new CodingDt(myBinder.toSystemString(next), myBinder.toCodeString(next)));
091                        }
092                }
093        }
094
095        /**
096         * Sets the {@link #getCoding()} to contain a coding with the code and
097         * system defined by the given enumerated type, AND clearing any existing
098         * codings first. If theValue is null, existing codings are cleared and no
099         * codings are added.
100         * 
101         * @param theValue
102         *            The value to add, or <code>null</code>
103         */
104        public void setValueAsEnum(T theValue) {
105                Validate.notNull(myBinder, "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(myBinder, "This object does not have a binder. Constructor BoundCodeableConceptDt() should not be called!");
126                Set<T> retVal = new HashSet<T>();
127                for (CodingDt next : getCoding()) {
128                        if (next == null) {
129                                continue;
130                        }
131                        T nextT = myBinder.fromCodeString(defaultString(next.getCodeElement().getValue()), defaultString(next.getSystemElement().getValueAsString()));
132                        if (nextT != null) {
133                                retVal.add(nextT);
134                        } else {
135                                // TODO: throw special exception type?
136                        }
137                }
138                return retVal;
139        }
140
141}