001package ca.uhn.fhir.context;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
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 java.util.ArrayList;
024import java.util.Collections;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028import java.util.TreeSet;
029
030import org.hl7.fhir.instance.model.api.IBase;
031
032import ca.uhn.fhir.parser.DataFormatException;
033
034public abstract class BaseRuntimeElementCompositeDefinition<T extends IBase> extends BaseRuntimeElementDefinition<T> {
035
036        private List<BaseRuntimeChildDefinition> myChildren = new ArrayList<BaseRuntimeChildDefinition>();
037        private List<BaseRuntimeChildDefinition> myChildrenAndExtensions;
038        private Map<String, BaseRuntimeChildDefinition> myNameToChild = new HashMap<String, BaseRuntimeChildDefinition>();
039
040        public BaseRuntimeElementCompositeDefinition(String theName, Class<? extends T> theImplementingClass, boolean theStandardType) {
041                super(theName, theImplementingClass, theStandardType);
042        }
043
044        void addChild(BaseRuntimeChildDefinition theNext) {
045                if (theNext == null) {
046                        throw new NullPointerException();
047                }
048                if (theNext.getExtensionUrl() != null) {
049                        throw new IllegalArgumentException("Shouldn't haven an extension URL, use addExtension instead");
050                }
051                myChildren.add(theNext);
052        }
053
054        public BaseRuntimeChildDefinition getChildByNameOrThrowDataFormatException(String theName) throws DataFormatException {
055                BaseRuntimeChildDefinition retVal = myNameToChild.get(theName);
056                if (retVal == null) {
057                        throw new DataFormatException("Unknown child name '" + theName + "' in element " + getName() + " - Valid names are: " + new TreeSet<String>(myNameToChild.keySet()));
058                }
059                return retVal;
060        }
061
062        public BaseRuntimeChildDefinition getChildByName(String theName){
063                BaseRuntimeChildDefinition retVal = myNameToChild.get(theName);
064                return retVal;
065        }
066
067        public List<BaseRuntimeChildDefinition> getChildren() {
068                return myChildren;
069        }
070
071        public List<BaseRuntimeChildDefinition> getChildrenAndExtension() {
072                return myChildrenAndExtensions;
073        }
074
075        @Override
076        public void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
077                super.sealAndInitialize(theContext, theClassToElementDefinitions);
078
079                for (BaseRuntimeChildDefinition next : myChildren) {
080                        next.sealAndInitialize(theContext, theClassToElementDefinitions);
081                }
082
083                myNameToChild = new HashMap<String, BaseRuntimeChildDefinition>();
084                for (BaseRuntimeChildDefinition next : myChildren) {    
085                        if (next instanceof RuntimeChildChoiceDefinition) {
086                                String key = ((RuntimeChildChoiceDefinition) next).getElementName()+"[x]";
087                                myNameToChild.put(key, next);
088                        }
089                        for (String nextName : next.getValidChildNames()) {
090                                if (myNameToChild.containsKey(nextName)) {
091                                        throw new ConfigurationException("Duplicate child name[" + nextName + "] in Element[" + getName() + "]");
092                                } else {
093                                        myNameToChild.put(nextName, next);
094                                }
095                        }
096                }
097
098                myChildren = Collections.unmodifiableList(myChildren);
099                myNameToChild = Collections.unmodifiableMap(myNameToChild);
100                
101                List<BaseRuntimeChildDefinition> children = new ArrayList<BaseRuntimeChildDefinition>();
102                children.addAll(myChildren);
103                children.addAll(getExtensionsModifier());
104                children.addAll(getExtensionsNonModifier());
105                myChildrenAndExtensions=Collections.unmodifiableList(children);
106        }
107
108}