
001package org.hl7.fhir.r5.elementmodel; 002 003import java.io.IOException; 004import java.io.InputStream; 005import java.io.OutputStream; 006import java.util.List; 007 008import org.apache.commons.lang3.NotImplementedException; 009import org.hl7.fhir.exceptions.DefinitionException; 010import org.hl7.fhir.exceptions.FHIRException; 011import org.hl7.fhir.exceptions.FHIRFormatError; 012import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; 013import org.hl7.fhir.r5.context.IWorkerContext; 014import org.hl7.fhir.r5.elementmodel.Element.SpecialElement; 015import org.hl7.fhir.r5.formats.IParser.OutputStyle; 016import org.hl7.fhir.r5.model.Base; 017import org.hl7.fhir.r5.model.Resource; 018import org.hl7.fhir.r5.model.StructureDefinition; 019import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage; 020import org.hl7.fhir.utilities.Utilities; 021import org.hl7.fhir.utilities.i18n.I18nConstants; 022import org.hl7.fhir.utilities.xhtml.XhtmlComposer; 023 024@MarkedToMoveToAdjunctPackage 025public class ResourceParser extends ParserBase { 026 027 public ResourceParser(IWorkerContext context) { 028 super(context); 029 } 030 031 @Override 032 public List<ValidatedFragment> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { 033 throw new NotImplementedException("parse(InputStream stream)"); // doesns't make sense 034 } 035 036 @Override 037 public void compose(Element e, OutputStream destination, OutputStyle style, String base) 038 throws FHIRException, IOException { 039 throw new NotImplementedException("compose(Element e, OutputStream destination, OutputStyle style, String base)"); // doesns't make sense 040 } 041 042 /** 043 * It's possible to get an element model from an resource by writing it to a stream, and reading it, 044 * but this loads it directly, and links to the element model from the resource model 045 * 046 * @param resource 047 * @return 048 * @throws IOException 049 */ 050 public Element parse(Resource resource) { 051 StructureDefinition sd = context.fetchTypeDefinition(resource.fhirType()); 052 if (sd == null) { 053 throw new FHIRException("No definition exists for "+resource.fhirType()); 054 } 055 Property p = new Property(context, sd.getSnapshot().getElement().get(0), sd, getProfileUtilities(), getContextUtilities()); 056 String path = resource.fhirType(); 057 058 Element e = new Element(resource.fhirType(), p); 059 e.setPath(path); 060 e.setType(resource.fhirType()); 061 parseChildren(path, resource, e); 062 e.numberChildren(); 063 return e; 064 } 065 066 private void parseChildren(String path, Base src, Element dst) { 067 dst.setSource(src); 068 dst.copyFormatComments(src); 069 List<Property> properties = dst.getProperty().getChildProperties(dst.getName(), null); 070 for (org.hl7.fhir.r5.model.Property c : src.children()) { 071 if (c.hasValues()) { 072 Property p = getPropertyByName(properties, c.getName()); 073 if (p == null) { 074 throw new FHIRException("Unable to find property for "+path+"."+c.getName()); 075 } 076 int i = 0; 077 for (Base v : c.getValues()) { 078 String npath = path+"."+c.getName()+(p.isList() ? "["+i+"]" : ""); 079 i++; 080 String name = c.getName(); 081 if (name.endsWith("[x]")) { 082 name = name.substring(0, name.length()-3)+Utilities.capitalize(v.fhirType()); 083 } 084 Element n = new Element(name, p); 085 dst.getChildren().add(n); 086 if (v.isPrimitive()) { 087 if (v.fhirType().equals("xhtml")) { 088 n.setXhtml(v.getXhtml()); 089 try { 090 n.setValue(new XhtmlComposer(true).compose(n.getXhtml())); 091 } catch (Exception e) { 092 // won't happen here 093 } 094 } else { 095 n.setValue(v.primitiveValue()); 096 } 097// if (!n.getProperty().isChoice() && n.getType().equals("xhtml")) { 098// try { 099// n.setXhtml(new XhtmlParser().setValidatorMode(policy == ValidationPolicy.EVERYTHING).parse(n.getValue(), null).getDocumentElement()); 100// } catch (Exception e) { 101// logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR); 102// } 103// } 104// } 105 } 106 n.setPath(npath); 107 if (p.isResource()) { 108 StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(v.fhirType(), null)); 109 if (sd == null) 110 throw new FHIRFormatError(context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, v.fhirType())); 111 n.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, getProfileUtilities(), getContextUtilities()), SpecialElement.fromProperty(n.getProperty()), p); 112 n.setType(v.fhirType()); 113 parseChildren(npath, v, n); 114 } else { 115 parseChildren(npath, v, n); 116 } 117 } 118 } 119 } 120 121 } 122 123 private Property getPropertyByName(List<Property> properties, String name) { 124 for (Property p : properties) { 125 if (p.getName().equals(name)) { 126 return p; 127 } 128 } 129 return null; 130 131 } 132} 133