001package ca.uhn.fhir.model.view; 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 */ 022 023import java.util.List; 024 025import org.hl7.fhir.instance.model.api.IBase; 026import org.hl7.fhir.instance.model.api.IBaseExtension; 027 028import ca.uhn.fhir.context.BaseRuntimeChildDefinition; 029import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 030import ca.uhn.fhir.context.ConfigurationException; 031import ca.uhn.fhir.context.FhirContext; 032import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition; 033import ca.uhn.fhir.context.RuntimeResourceDefinition; 034import ca.uhn.fhir.model.api.BaseElement; 035import ca.uhn.fhir.model.api.ExtensionDt; 036import ca.uhn.fhir.model.api.IResource; 037 038public class ViewGenerator { 039 040 private FhirContext myCtx; 041 042 public ViewGenerator(FhirContext theFhirContext) { 043 myCtx=theFhirContext; 044 } 045 046 public <T extends IResource> T newView(IResource theResource, Class<T> theTargetType) { 047 Class<? extends IResource> 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 (InstantiationException e) { 061 throw new ConfigurationException("Failed to instantiate " + theTargetType, e); 062 } catch (IllegalAccessException e) { 063 throw new ConfigurationException("Failed to instantiate " + theTargetType, e); 064 } 065 066 copyChildren(sourceDef, (BaseElement) theResource, targetDef, (BaseElement) retVal); 067 068 return retVal; 069 } 070 071 private void copyChildren(BaseRuntimeElementCompositeDefinition<?> theSourceDef, BaseElement theSource, BaseRuntimeElementCompositeDefinition<?> theTargetDef, BaseElement theTarget) { 072 if (!theSource.isEmpty()) { 073 List<BaseRuntimeChildDefinition> targetChildren = theTargetDef.getChildren(); 074 List<RuntimeChildDeclaredExtensionDefinition> targetExts = theTargetDef.getExtensions(); 075 076 for (BaseRuntimeChildDefinition nextChild : targetChildren) { 077 078 String elementName = nextChild.getElementName(); 079 if (nextChild.getValidChildNames().size() > 1) { 080 elementName = nextChild.getValidChildNames().iterator().next(); 081 } 082 083 BaseRuntimeChildDefinition sourceChildEquivalent = theSourceDef.getChildByNameOrThrowDataFormatException(elementName); 084 if (sourceChildEquivalent == null) { 085 continue; 086 } 087 088 List<? extends IBase> sourceValues = sourceChildEquivalent.getAccessor().getValues(theSource); 089 for (IBase nextElement : sourceValues) { 090 boolean handled = false; 091 if (nextElement instanceof IBaseExtension) { 092 String url = ((IBaseExtension<?,?>) nextElement).getUrl(); 093 for (RuntimeChildDeclaredExtensionDefinition nextExt : targetExts) { 094 String nextTargetUrl = nextExt.getExtensionUrl(); 095 if (!nextTargetUrl.equals(url)) { 096 continue; 097 } 098 addExtension(theSourceDef, theSource, theTarget, nextExt, url); 099 handled = true; 100 } 101 } 102 if (!handled) { 103 nextChild.getMutator().addValue(theTarget, nextElement); 104 } 105 } 106 } 107 108 for (RuntimeChildDeclaredExtensionDefinition nextExt : targetExts) { 109 String url = nextExt.getExtensionUrl(); 110 addExtension(theSourceDef, theSource, theTarget, nextExt, url); 111 } 112 113 114 } 115 } 116 117 private void addExtension(BaseRuntimeElementCompositeDefinition<?> theSourceDef, BaseElement theSource, BaseElement theTarget, RuntimeChildDeclaredExtensionDefinition nextExt, String url) { 118 RuntimeChildDeclaredExtensionDefinition sourceDeclaredExt = theSourceDef.getDeclaredExtension(url, ""); 119 if (sourceDeclaredExt == null) { 120 121 for (ExtensionDt next : theSource.getAllUndeclaredExtensions()) { 122 if (next.getUrlAsString().equals(url)) { 123 nextExt.getMutator().addValue(theTarget, next.getValue()); 124 } 125 } 126 127 } else { 128 129 List<? extends IBase> values = sourceDeclaredExt.getAccessor().getValues(theSource); 130 for (IBase nextElement : values) { 131 nextExt.getMutator().addValue(theTarget, nextElement); 132 } 133 134 } 135 } 136}