001/*-
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2025 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.context;
021
022import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
023import com.google.common.collect.Sets;
024import org.apache.commons.lang3.Validate;
025import org.hl7.fhir.instance.model.api.IBase;
026import org.hl7.fhir.instance.model.api.IBaseExtension;
027import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
028
029import java.util.Collections;
030import java.util.HashMap;
031import java.util.List;
032import java.util.Map;
033import java.util.Set;
034
035public class RuntimeChildExt extends BaseRuntimeChildDefinition {
036
037        private Map<String, BaseRuntimeElementDefinition<?>> myNameToChild;
038        private Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myDatatypeToChild;
039        private Map<Class<? extends IBase>, String> myDatatypeToChildName;
040
041        @Override
042        public IAccessor getAccessor() {
043                return new IAccessor() {
044                        @SuppressWarnings({"unchecked", "rawtypes"})
045                        @Override
046                        public List<IBase> getValues(IBase theTarget) {
047                                if (theTarget instanceof IBaseHasExtensions hasExtensions) {
048                                        List extension = hasExtensions.getExtension();
049                                        return Collections.unmodifiableList(extension);
050                                } else {
051                                        // DSTU2 only
052                                        List extension = ((ISupportsUndeclaredExtensions) theTarget).getAllUndeclaredExtensions();
053                                        return Collections.unmodifiableList(extension);
054                                }
055                        }
056                };
057        }
058
059        @Override
060        public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
061                return myNameToChild.get(theName);
062        }
063
064        @Override
065        public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theType) {
066                return myDatatypeToChild.get(theType);
067        }
068
069        @Override
070        public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
071                return myDatatypeToChildName.get(theDatatype);
072        }
073
074        @Override
075        public String getElementName() {
076                return "extension";
077        }
078
079        @Override
080        public int getMax() {
081                return -1;
082        }
083
084        @Override
085        public int getMin() {
086                return 0;
087        }
088
089        @Override
090        public IMutator getMutator() {
091                return new IMutator() {
092                        @Override
093                        public void addValue(IBase theTarget, IBase theValue) {
094                                List extensions = ((IBaseHasExtensions) theTarget).getExtension();
095                                IBaseExtension<?, ?> value = (IBaseExtension<?, ?>) theValue;
096                                extensions.add(value);
097                        }
098
099                        @Override
100                        public void setValue(IBase theTarget, IBase theValue) {
101                                List extensions = ((IBaseHasExtensions) theTarget).getExtension();
102                                extensions.clear();
103                                if (theValue != null) {
104                                        IBaseExtension<?, ?> value = (IBaseExtension<?, ?>) theValue;
105                                        extensions.add(value);
106                                }
107                        }
108                };
109        }
110
111        @Override
112        public Set<String> getValidChildNames() {
113                return Sets.newHashSet("extension");
114        }
115
116        @Override
117        public boolean isSummary() {
118                return false;
119        }
120
121        @Override
122        void sealAndInitialize(
123                        FhirContext theContext,
124                        Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
125                myNameToChild = new HashMap<>();
126                myDatatypeToChild = new HashMap<>();
127                myDatatypeToChildName = new HashMap<>();
128
129                for (BaseRuntimeElementDefinition<?> next : theClassToElementDefinitions.values()) {
130                        if (next.getName().equals("Extension")) {
131                                myNameToChild.put("extension", next);
132                                myDatatypeToChild.put(next.getImplementingClass(), next);
133                                myDatatypeToChildName.put(next.getImplementingClass(), "extension");
134                        }
135                }
136
137                Validate.isTrue(!myNameToChild.isEmpty());
138        }
139}