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.model.api.annotation.Child;
023import ca.uhn.fhir.model.api.annotation.Description;
024import org.apache.commons.lang3.Validate;
025import org.hl7.fhir.instance.model.api.IBaseDatatype;
026
027import java.util.ArrayList;
028import java.util.Collections;
029import java.util.HashMap;
030import java.util.List;
031import java.util.Map;
032
033public abstract class BaseElement implements /*IElement, */ ISupportsUndeclaredExtensions {
034
035        private static final long serialVersionUID = -3092659584634499332L;
036        private List<String> myFormatCommentsPost;
037        private List<String> myFormatCommentsPre;
038        private Map<String, Object> userData;
039
040        @Child(
041                        name = "extension",
042                        type = {ExtensionDt.class},
043                        order = 0,
044                        min = 0,
045                        max = Child.MAX_UNLIMITED,
046                        modifier = false,
047                        summary = false)
048        @Description(
049                        shortDefinition = "Additional Content defined by implementations",
050                        formalDefinition =
051                                        "May be used to represent additional information that is not part of the basic definition of the resource. In order to make the use of extensions safe and manageable, there is a strict set of governance  applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.")
052        private List<ExtensionDt> myUndeclaredExtensions;
053
054        /**
055         * May be used to represent additional information that is not part of the basic definition of the resource, and that modifies the understanding of the element that contains it. Usually modifier elements provide negation or qualification. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.
056         */
057        @Child(
058                        name = "modifierExtension",
059                        type = {ExtensionDt.class},
060                        order = 1,
061                        min = 0,
062                        max = Child.MAX_UNLIMITED,
063                        modifier = true,
064                        summary = false)
065        @Description(
066                        shortDefinition = "Extensions that cannot be ignored",
067                        formalDefinition =
068                                        "May be used to represent additional information that is not part of the basic definition of the resource, and that modifies the understanding of the element that contains it. Usually modifier elements provide negation or qualification. In order to make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer is allowed to define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.")
069        private List<ExtensionDt> myUndeclaredModifierExtensions;
070
071        @Override
072        public ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl) {
073                Validate.notEmpty(theUrl, "URL must be populated");
074
075                ExtensionDt retVal = new ExtensionDt(theIsModifier, theUrl);
076                if (theIsModifier) {
077                        getUndeclaredModifierExtensions();
078                        myUndeclaredModifierExtensions.add(retVal);
079                } else {
080                        getUndeclaredExtensions();
081                        myUndeclaredExtensions.add(retVal);
082                }
083                return retVal;
084        }
085
086        @Override
087        public ExtensionDt addUndeclaredExtension(boolean theIsModifier, String theUrl, IBaseDatatype theValue) {
088                Validate.notEmpty(theUrl, "URL must be populated");
089                Validate.notNull(theValue, "Value must not be null");
090                ExtensionDt retVal = new ExtensionDt(theIsModifier, theUrl, theValue);
091                if (theIsModifier) {
092                        getUndeclaredModifierExtensions();
093                        myUndeclaredModifierExtensions.add(retVal);
094                } else {
095                        getUndeclaredExtensions();
096                        myUndeclaredExtensions.add(retVal);
097                }
098                return retVal;
099        }
100
101        @Override
102        public void addUndeclaredExtension(ExtensionDt theExtension) {
103                Validate.notNull(theExtension, "Extension can not be null");
104                if (theExtension.isModifier()) {
105                        getUndeclaredModifierExtensions();
106                        myUndeclaredModifierExtensions.add(theExtension);
107                } else {
108                        getUndeclaredExtensions();
109                        myUndeclaredExtensions.add(theExtension);
110                }
111        }
112
113        @Override
114        public List<ExtensionDt> getAllUndeclaredExtensions() {
115                ArrayList<ExtensionDt> retVal = new ArrayList<ExtensionDt>();
116                if (myUndeclaredExtensions != null) {
117                        retVal.addAll(myUndeclaredExtensions);
118                }
119                if (myUndeclaredModifierExtensions != null) {
120                        retVal.addAll(myUndeclaredModifierExtensions);
121                }
122                return Collections.unmodifiableList(retVal);
123        }
124
125        @Override
126        public List<String> getFormatCommentsPost() {
127                if (myFormatCommentsPost == null) myFormatCommentsPost = new ArrayList<String>();
128                return myFormatCommentsPost;
129        }
130
131        @Override
132        public List<String> getFormatCommentsPre() {
133                if (myFormatCommentsPre == null) myFormatCommentsPre = new ArrayList<String>();
134                return myFormatCommentsPre;
135        }
136
137        @Override
138        public List<ExtensionDt> getUndeclaredExtensions() {
139                if (myUndeclaredExtensions == null) {
140                        myUndeclaredExtensions = new ArrayList<ExtensionDt>();
141                }
142                return (myUndeclaredExtensions);
143        }
144
145        @Override
146        public List<ExtensionDt> getUndeclaredExtensionsByUrl(String theUrl) {
147                org.apache.commons.lang3.Validate.notNull(theUrl, "URL can not be null");
148                ArrayList<ExtensionDt> retVal = new ArrayList<ExtensionDt>();
149                for (ExtensionDt next : getAllUndeclaredExtensions()) {
150                        if (theUrl.equals(next.getUrlAsString())) {
151                                retVal.add(next);
152                        }
153                }
154                return Collections.unmodifiableList(retVal);
155        }
156
157        @Override
158        public List<ExtensionDt> getUndeclaredModifierExtensions() {
159                if (myUndeclaredModifierExtensions == null) {
160                        myUndeclaredModifierExtensions = new ArrayList<ExtensionDt>();
161                }
162                return (myUndeclaredModifierExtensions);
163        }
164
165        @Override
166        public boolean hasFormatComment() {
167                return (myFormatCommentsPre != null && !myFormatCommentsPre.isEmpty())
168                                || (myFormatCommentsPost != null && !myFormatCommentsPost.isEmpty());
169        }
170
171        @Override
172        public Object getUserData(String name) {
173                if (userData == null) return null;
174                return userData.get(name);
175        }
176
177        @Override
178        public void setUserData(String name, Object value) {
179                if (userData == null) {
180                        userData = new HashMap<>();
181                }
182                userData.put(name, value);
183        }
184
185        /**
186         * Intended to be called by extending classes {@link #isEmpty()} implementations, returns <code>true</code> if all
187         * content in this superclass instance is empty per the semantics of {@link #isEmpty()}.
188         */
189        protected boolean isBaseEmpty() {
190                if (myUndeclaredExtensions != null) {
191                        for (ExtensionDt next : myUndeclaredExtensions) {
192                                if (next == null) {
193                                        continue;
194                                }
195                                if (!next.isEmpty()) {
196                                        return false;
197                                }
198                        }
199                }
200                if (myUndeclaredModifierExtensions != null) {
201                        for (ExtensionDt next : myUndeclaredModifierExtensions) {
202                                if (next == null) {
203                                        continue;
204                                }
205                                if (!next.isEmpty()) {
206                                        return false;
207                                }
208                        }
209                }
210                return true;
211        }
212}