ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition.java Source code

Java tutorial

Introduction

Here is the source code for ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition.java

Source

package ca.uhn.fhir.context;

/*
 * #%L
 * HAPI FHIR - Core Library
 * %%
 * Copyright (C) 2014 - 2016 University Health Network
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;

import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.Extension;

public class RuntimeChildDeclaredExtensionDefinition extends BaseRuntimeDeclaredChildDefinition {

    private BaseRuntimeElementDefinition<?> myChildDef;
    private Class<? extends IBase> myChildType;
    private String myDatatypeChildName;
    private boolean myDefinedLocally;
    private String myExtensionUrl;
    private boolean myModifier;
    private Map<String, RuntimeChildDeclaredExtensionDefinition> myUrlToChildExtension;
    private volatile Object myInstanceConstructorArguments;
    private Class<?> myEnumerationType;

    /**
     * @param theBoundTypeBinder
     *            If the child is of a type that requires a constructor argument to instantiate, this is the argument to
     *            use
     * @param theDefinedLocally
     *            See {@link Extension#definedLocally()}
     */
    RuntimeChildDeclaredExtensionDefinition(Field theField, Child theChild, Description theDescriptionAnnotation,
            Extension theExtension, String theElementName, String theExtensionUrl,
            Class<? extends IBase> theChildType, Object theBoundTypeBinder) throws ConfigurationException {
        super(theField, theChild, theDescriptionAnnotation, theElementName);
        assert isNotBlank(theExtensionUrl);
        myExtensionUrl = theExtensionUrl;
        myChildType = theChildType;
        myDefinedLocally = theExtension.definedLocally();
        myModifier = theExtension.isModifier();
        myInstanceConstructorArguments = theBoundTypeBinder;
    }

    @Override
    public Object getInstanceConstructorArguments() {
        Object retVal = myInstanceConstructorArguments;
        if (retVal == null && myEnumerationType != null) {
            retVal = RuntimeChildPrimitiveEnumerationDatatypeDefinition.toEnumFactory(myEnumerationType);
            myInstanceConstructorArguments = retVal;
        }
        return retVal;
    }

    public void setEnumerationType(Class<?> theEnumerationType) {
        myEnumerationType = theEnumerationType;
    }

    @Override
    public BaseRuntimeElementDefinition<?> getChildByName(String theName) {
        if (myDatatypeChildName != null) {
            if (myDatatypeChildName.equals(theName)) {
                return myChildDef;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    @Override
    public BaseRuntimeElementDefinition<?> getChildElementDefinitionByDatatype(Class<? extends IBase> theType) {
        if (myChildType.equals(theType)) {
            return myChildDef;
        }
        return null;
    }

    public RuntimeChildDeclaredExtensionDefinition getChildExtensionForUrl(String theUrl) {
        return myUrlToChildExtension.get(theUrl);
    }

    @Override
    public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
        if (myChildType.equals(theDatatype) && myDatatypeChildName != null) {
            return myDatatypeChildName;
        } else {
            return "extension";
        }
    }

    public Class<? extends IBase> getChildType() {
        return myChildType;
    }

    @Override
    public String getExtensionUrl() {
        return myExtensionUrl;
    }

    @Override
    public BaseRuntimeElementDefinition<?> getSingleChildOrThrow() {
        return myChildDef;
    }

    @Override
    public Set<String> getValidChildNames() {
        return Collections.emptySet();
    }

    public boolean isDefinedLocally() {
        return myDefinedLocally;
    }

    @Override
    public boolean isModifier() {
        return myModifier;
    }

    public IBase newInstance() {
        try {
            return myChildType.newInstance();
        } catch (InstantiationException e) {
            throw new ConfigurationException("Failed to instantiate type:" + myChildType.getName(), e);
        } catch (IllegalAccessException e) {
            throw new ConfigurationException("Failed to instantiate type:" + myChildType.getName(), e);
        }
    }

    @Override
    void sealAndInitialize(FhirContext theContext,
            Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
        myUrlToChildExtension = new HashMap<String, RuntimeChildDeclaredExtensionDefinition>();

        BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);

        /*
         * This will happen for any type that isn't defined in the base set of 
         * built-in types, e.g. custom structures or custom extensions
         */
        if (elementDef == null) {
            elementDef = theContext.getElementDefinition(myChildType);
        }

        if (elementDef instanceof RuntimePrimitiveDatatypeDefinition
                || elementDef instanceof RuntimeCompositeDatatypeDefinition) {
            myDatatypeChildName = "value" + elementDef.getName().substring(0, 1).toUpperCase()
                    + elementDef.getName().substring(1);
            if ("valueResourceReference".equals(myDatatypeChildName)) {
                // Per one of the examples here: http://hl7.org/implement/standards/fhir/extensibility.html#extension
                myDatatypeChildName = "valueResource";
                List<Class<? extends IBaseResource>> types = new ArrayList<Class<? extends IBaseResource>>();
                types.add(IResource.class);
                myChildDef = findResourceReferenceDefinition(theClassToElementDefinitions);
            } else {
                myChildDef = elementDef;
            }
        } else {
            RuntimeResourceBlockDefinition extDef = ((RuntimeResourceBlockDefinition) elementDef);
            for (RuntimeChildDeclaredExtensionDefinition next : extDef.getExtensions()) {
                myUrlToChildExtension.put(next.getExtensionUrl(), next);
            }
            myChildDef = extDef;
        }

        myUrlToChildExtension = Collections.unmodifiableMap(myUrlToChildExtension);
    }

}