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