001/*
002 * #%L
003 * HAPI FHIR - Core Library
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.api;
021
022import ca.uhn.fhir.i18n.Msg;
023import ca.uhn.fhir.model.api.annotation.Child;
024import ca.uhn.fhir.model.api.annotation.DatatypeDef;
025import ca.uhn.fhir.model.primitive.StringDt;
026import org.apache.commons.lang3.Validate;
027import org.apache.commons.lang3.builder.ToStringBuilder;
028import org.apache.commons.lang3.builder.ToStringStyle;
029import org.hl7.fhir.instance.model.api.IBaseDatatype;
030import org.hl7.fhir.instance.model.api.IBaseExtension;
031
032import java.util.ArrayList;
033import java.util.List;
034
035@DatatypeDef(name = "Extension")
036public class ExtensionDt extends BaseIdentifiableElement
037                implements ICompositeDatatype, IBaseExtension<ExtensionDt, IDatatype> {
038
039        private static final long serialVersionUID = 6399491332783085935L;
040
041        private boolean myModifier;
042
043        @Child(name = "url", type = StringDt.class, order = 0, min = 1, max = 1)
044        private StringDt myUrl;
045
046        @Child(name = "value", type = IDatatype.class, order = 1, min = 0, max = 1)
047        private IBaseDatatype myValue;
048
049        public ExtensionDt() {}
050
051        public ExtensionDt(boolean theIsModifier) {
052                myModifier = theIsModifier;
053        }
054
055        public ExtensionDt(boolean theIsModifier, String theUrl) {
056                Validate.notEmpty(theUrl, "URL must be populated");
057
058                myModifier = theIsModifier;
059                myUrl = new StringDt(theUrl);
060        }
061
062        public ExtensionDt(boolean theIsModifier, String theUrl, IBaseDatatype theValue) {
063                Validate.notEmpty(theUrl, "URL must be populated");
064                Validate.notNull(theValue, "Value must not be null");
065
066                myModifier = theIsModifier;
067                myUrl = new StringDt(theUrl);
068                myValue = theValue;
069        }
070
071        /**
072         * Returns the URL for this extension.
073         * <p>
074         * Note that before HAPI 0.9 this method returned a {@link StringDt} but as of
075         * HAPI 0.9 this method returns a plain string. This was changed because it does not make sense to use a StringDt here
076         * since the URL itself can not contain extensions and it was therefore misleading.
077         * </p>
078         */
079        @Override
080        public String getUrl() {
081                return myUrl != null ? myUrl.getValue() : null;
082        }
083
084        /**
085         * Retained for backward compatibility
086         *
087         * @see ExtensionDt#getUrl()
088         */
089        public String getUrlAsString() {
090                return getUrl();
091        }
092
093        /**
094         * Returns the value of this extension, if one exists.
095         * <p>
096         * Note that if this extension contains extensions (instead of a datatype) then <b>this method will return null</b>. In that case, you must use {@link #getUndeclaredExtensions()} and
097         * {@link #getUndeclaredModifierExtensions()} to retrieve the child extensions.
098         * </p>
099         */
100        @Override
101        public IBaseDatatype getValue() {
102                return myValue;
103        }
104
105        /**
106         * Returns the value of this extension, casted to a primitive datatype. This is a convenience method which should only be called if you are sure that the value for this particular extension will
107         * be a primitive.
108         * <p>
109         * Note that if this extension contains extensions (instead of a datatype) then <b>this method will return null</b>. In that case, you must use {@link #getUndeclaredExtensions()} and
110         * {@link #getUndeclaredModifierExtensions()} to retrieve the child extensions.
111         * </p>
112         *
113         * @throws ClassCastException
114         *             If the value of this extension is not a primitive datatype
115         */
116        public IPrimitiveDatatype<?> getValueAsPrimitive() {
117                if (!(getValue() instanceof IPrimitiveDatatype)) {
118                        throw new ClassCastException(
119                                        Msg.code(1887) + "Extension with URL[" + myUrl + "] can not be cast to primitive type, type is: "
120                                                        + getClass().getCanonicalName());
121                }
122                return (IPrimitiveDatatype<?>) getValue();
123        }
124
125        @Override
126        public boolean isEmpty() {
127                return super.isBaseEmpty() && (myValue == null || myValue.isEmpty());
128        }
129
130        public boolean isModifier() {
131                return myModifier;
132        }
133
134        public void setModifier(boolean theModifier) {
135                myModifier = theModifier;
136        }
137
138        @Override
139        public ExtensionDt setUrl(String theUrl) {
140                myUrl = theUrl != null ? new StringDt(theUrl) : myUrl;
141                return this;
142        }
143
144        public ExtensionDt setUrl(StringDt theUrl) {
145                myUrl = theUrl;
146                return this;
147        }
148
149        @Override
150        public ExtensionDt setValue(IBaseDatatype theValue) {
151                myValue = theValue;
152                return this;
153        }
154
155        @Override
156        @Deprecated // override deprecated method
157        public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(Class<T> theType) {
158                return new ArrayList<T>();
159        }
160
161        @Override
162        public List<ExtensionDt> getExtension() {
163                return getAllUndeclaredExtensions();
164        }
165
166        @Override
167        public String toString() {
168                ToStringBuilder retVal = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
169                retVal.append("url", getUrl());
170                retVal.append("value", getValue());
171                return retVal.build();
172        }
173}