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