001package ca.uhn.fhir.model.view; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 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 ca.uhn.fhir.context.BaseRuntimeChildDefinition; 024import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 025import ca.uhn.fhir.context.ConfigurationException; 026import ca.uhn.fhir.context.FhirContext; 027import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition; 028import ca.uhn.fhir.context.RuntimeResourceDefinition; 029import ca.uhn.fhir.i18n.Msg; 030import org.hl7.fhir.instance.model.api.IBase; 031import org.hl7.fhir.instance.model.api.IBaseExtension; 032import org.hl7.fhir.instance.model.api.IBaseHasExtensions; 033import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions; 034import org.hl7.fhir.instance.model.api.IBaseResource; 035 036import java.util.List; 037 038public class ViewGenerator { 039 040 private FhirContext myCtx; 041 042 public ViewGenerator(FhirContext theFhirContext) { 043 myCtx = theFhirContext; 044 } 045 046 public <T extends IBaseResource> T newView(IBaseResource theResource, Class<T> theTargetType) { 047 Class<? extends IBaseResource> sourceType = theResource.getClass(); 048 RuntimeResourceDefinition sourceDef = myCtx.getResourceDefinition(theResource); 049 RuntimeResourceDefinition targetDef = myCtx.getResourceDefinition(theTargetType); 050 051 if (sourceType.equals(theTargetType)) { 052 @SuppressWarnings("unchecked") 053 T resource = (T) theResource; 054 return resource; 055 } 056 057 T retVal; 058 try { 059 retVal = theTargetType.newInstance(); 060 } catch (Exception e) { 061 throw new ConfigurationException(Msg.code(1886) + "Failed to instantiate " + theTargetType, e); 062 } 063 064 copyChildren(sourceDef, (IBase) theResource, targetDef, (IBase) retVal); 065 066 return retVal; 067 } 068 069 private void copyChildren(BaseRuntimeElementCompositeDefinition<?> theSourceDef, IBase theSource, BaseRuntimeElementCompositeDefinition<?> theTargetDef, IBase theTarget) { 070 if (!theSource.isEmpty()) { 071 List<BaseRuntimeChildDefinition> targetChildren = theTargetDef.getChildren(); 072 List<RuntimeChildDeclaredExtensionDefinition> targetExts = theTargetDef.getExtensions(); 073 074 for (BaseRuntimeChildDefinition nextChild : targetChildren) { 075 076 String elementName = nextChild.getElementName(); 077 if (nextChild.getValidChildNames().size() > 1) { 078 elementName = nextChild.getValidChildNames().iterator().next(); 079 } 080 081 BaseRuntimeChildDefinition sourceChildEquivalent = theSourceDef.getChildByNameOrThrowDataFormatException(elementName); 082 if (sourceChildEquivalent == null) { 083 continue; 084 } 085 086 List<? extends IBase> sourceValues = sourceChildEquivalent.getAccessor().getValues(theSource); 087 for (IBase nextElement : sourceValues) { 088 boolean handled = false; 089 if (nextElement instanceof IBaseExtension) { 090 String url = ((IBaseExtension<?, ?>) nextElement).getUrl(); 091 for (RuntimeChildDeclaredExtensionDefinition nextExt : targetExts) { 092 String nextTargetUrl = nextExt.getExtensionUrl(); 093 if (!nextTargetUrl.equals(url)) { 094 continue; 095 } 096 addExtension(theSourceDef, theSource, theTarget, nextExt, url); 097 handled = true; 098 } 099 } 100 if (!handled) { 101 nextChild.getMutator().addValue(theTarget, nextElement); 102 } 103 } 104 } 105 106 for (RuntimeChildDeclaredExtensionDefinition nextExt : targetExts) { 107 String url = nextExt.getExtensionUrl(); 108 addExtension(theSourceDef, theSource, theTarget, nextExt, url); 109 } 110 111 112 } 113 } 114 115 private void addExtension(BaseRuntimeElementCompositeDefinition<?> theSourceDef, IBase theSource, IBase theTarget, RuntimeChildDeclaredExtensionDefinition nextExt, String url) { 116 RuntimeChildDeclaredExtensionDefinition sourceDeclaredExt = theSourceDef.getDeclaredExtension(url, ""); 117 if (sourceDeclaredExt == null) { 118 119 if (theSource instanceof IBaseHasExtensions) { 120 for (IBaseExtension<?, ?> next : ((IBaseHasExtensions) theSource).getExtension()) { 121 if (next.getUrl().equals(url)) { 122 nextExt.getMutator().addValue(theTarget, next.getValue()); 123 } 124 } 125 } 126 if (theSource instanceof IBaseHasModifierExtensions) { 127 for (IBaseExtension<?, ?> next : ((IBaseHasModifierExtensions) theSource).getModifierExtension()) { 128 if (next.getUrl().equals(url)) { 129 nextExt.getMutator().addValue(theTarget, next.getValue()); 130 } 131 } 132 } 133 134 } else { 135 136 List<? extends IBase> values = sourceDeclaredExt.getAccessor().getValues(theSource); 137 for (IBase nextElement : values) { 138 nextExt.getMutator().addValue(theTarget, nextElement); 139 } 140 141 } 142 } 143}