001package ca.uhn.fhir.context; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2017 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 */ 022import static org.apache.commons.lang3.StringUtils.isBlank; 023 024import java.lang.reflect.ParameterizedType; 025import java.lang.reflect.Type; 026import java.util.Map; 027 028import org.hl7.fhir.instance.model.api.IBase; 029import org.hl7.fhir.instance.model.api.IBaseDatatype; 030import org.hl7.fhir.instance.model.api.IPrimitiveType; 031 032import ca.uhn.fhir.model.api.annotation.DatatypeDef; 033import ca.uhn.fhir.model.api.annotation.ResourceDef; 034 035public class RuntimePrimitiveDatatypeDefinition extends BaseRuntimeElementDefinition<IPrimitiveType<?>> implements IRuntimeDatatypeDefinition { 036 037 private Class<?> myNativeType; 038 private BaseRuntimeElementDefinition<?> myProfileOf; 039 private Class<? extends IBaseDatatype> myProfileOfType; 040 private boolean mySpecialization; 041 042 public RuntimePrimitiveDatatypeDefinition(DatatypeDef theDef, Class<? extends IPrimitiveType<?>> theImplementingClass, boolean theStandardType) { 043 super(theDef.name(), theImplementingClass, theStandardType); 044 045 String resourceName = theDef.name(); 046 if (isBlank(resourceName)) { 047 throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource name: " + theImplementingClass.getCanonicalName()); 048 } 049 050 mySpecialization = theDef.isSpecialization(); 051 myProfileOfType = theDef.profileOf(); 052 if (myProfileOfType.equals(IBaseDatatype.class)) { 053 myProfileOfType = null; 054 } 055 056 determineNativeType(theImplementingClass); 057 } 058 059 private void determineNativeType(Class<? extends IPrimitiveType<?>> theImplementingClass) { 060 Class<?> clazz = theImplementingClass; 061 while (clazz.equals(Object.class) == false) { 062 Type type = clazz.getGenericSuperclass(); 063 if (type instanceof ParameterizedType) { 064 ParameterizedType superPt = (ParameterizedType) type; 065 Type rawType = superPt.getRawType(); 066 if (rawType instanceof Class) { 067 Class<?> rawClass = (Class<?>) rawType; 068 if (rawClass.getName().endsWith(".BasePrimitive") || rawClass.getName().endsWith(".PrimitiveType")) { 069 Type typeVariable = superPt.getActualTypeArguments()[0]; 070 if (typeVariable instanceof Class) { 071 myNativeType = (Class<?>) typeVariable; 072 break; 073 } 074 } 075 } 076 } 077 clazz = clazz.getSuperclass(); 078 } 079 } 080 081 @Override 082 public ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum getChildType() { 083 return ChildTypeEnum.PRIMITIVE_DATATYPE; 084 } 085 086 public Class<?> getNativeType() { 087 return myNativeType; 088 } 089 090 @Override 091 public Class<? extends IBaseDatatype> getProfileOf() { 092 return myProfileOfType; 093 } 094 095 @Override 096 public boolean isProfileOf(Class<? extends IBaseDatatype> theType) { 097 if (myProfileOfType != null) { 098 if (myProfileOfType.equals(theType)) { 099 return true; 100 } else if (myProfileOf instanceof IRuntimeDatatypeDefinition) { 101 return ((IRuntimeDatatypeDefinition) myProfileOf).isProfileOf(theType); 102 } 103 } 104 return false; 105 } 106 107 @Override 108 public boolean isSpecialization() { 109 return mySpecialization; 110 } 111 112 @Override 113 void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) { 114 super.sealAndInitialize(theContext, theClassToElementDefinitions); 115 116 if (myProfileOfType != null) { 117 myProfileOf = theClassToElementDefinitions.get(myProfileOfType); 118 if (myProfileOf == null) { 119 StringBuilder b = new StringBuilder(); 120 b.append("Unknown profileOf value: "); 121 b.append(myProfileOfType); 122 b.append(" in type "); 123 b.append(getImplementingClass().getName()); 124 b.append(" - Valid types: "); 125 b.append(theClassToElementDefinitions.keySet()); 126 throw new ConfigurationException(b.toString()); 127 } 128 } 129 } 130 131}