001package org.hl7.fhir.dstu2016may.metamodel; 002 003/* 004 Copyright (c) 2011+, HL7, Inc. 005 All rights reserved. 006 007 Redistribution and use in source and binary forms, with or without modification, 008 are permitted provided that the following conditions are met: 009 010 * Redistributions of source code must retain the above copyright notice, this 011 list of conditions and the following disclaimer. 012 * Redistributions in binary form must reproduce the above copyright notice, 013 this list of conditions and the following disclaimer in the documentation 014 and/or other materials provided with the distribution. 015 * Neither the name of HL7 nor the names of its contributors may be used to 016 endorse or promote products derived from this software without specific 017 prior written permission. 018 019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 022 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 023 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 024 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 025 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 POSSIBILITY OF SUCH DAMAGE. 029 030 */ 031 032 033 034import java.io.InputStream; 035import java.io.OutputStream; 036 037import org.apache.commons.lang3.NotImplementedException; 038import org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle; 039import org.hl7.fhir.dstu2016may.formats.RdfGenerator; 040import org.hl7.fhir.dstu2016may.formats.RdfGenerator.Complex; 041import org.hl7.fhir.dstu2016may.formats.RdfGenerator.Section; 042import org.hl7.fhir.dstu2016may.formats.RdfGenerator.Subject; 043import org.hl7.fhir.dstu2016may.utils.IWorkerContext; 044import org.hl7.fhir.utilities.Utilities; 045 046public class TurtleParser extends ParserBase { 047 048 private String base; 049 050 public TurtleParser(IWorkerContext context) { 051 super(context); 052 } 053 @Override 054 public Element parse(InputStream stream) throws Exception { 055 throw new NotImplementedException("not done yet"); 056 } 057 @Override 058 public void compose(Element e, OutputStream stream, OutputStyle style, String base) throws Exception { 059 this.base = base; 060 061 RdfGenerator ttl = new RdfGenerator(stream); 062 // ttl.setFormat(FFormat); 063 ttl.prefix("fhir", "http://hl7.org/fhir/"); 064 ttl.prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); 065 ttl.prefix("owl", "http://www.w3.org/2002/07/owl#"); 066 ttl.prefix("xs", "http://www.w3.org/2001/XMLSchema#"); 067 068 Section section = ttl.section("resource"); 069 Subject subject; 070 String id = e.getChildValue("id"); 071 if (base != null && id != null) 072 subject = section.triple("<"+base+"/"+e.getType()+"/"+id+">", "a", "fhir:"+e.getType()); 073 else 074 subject = section.triple("_", "a", "fhir:"+e.getType()); 075 subject.predicate("fhir:nodeRole", "fhir:treeRoot"); 076 077 for (Element child : e.getChildren()) { 078 composeElement(subject, child); 079 } 080 ttl.commit(false); 081 } 082 083 protected void decorateReference(Complex t, Element coding) { 084 String ref = coding.getChildValue("reference"); 085 if (ref != null && (ref.startsWith("http://") || ref.startsWith("https://"))) 086 t.predicate("fhir:reference", "<"+ref+">"); 087 else if (base != null && ref != null && ref.contains("/")) { 088 t.predicate("fhir:reference", "<"+Utilities.appendForwardSlash(base)+ref+">"); 089 } 090 } 091 092 protected void decorateCoding(Complex t, Element coding) { 093 String system = coding.getChildValue("system"); 094 String code = coding.getChildValue("code"); 095 096 if (system == null) 097 return; 098 if ("http://snomed.info/sct".equals(system)) { 099 t.prefix("sct", "http://snomed.info/sct/"); 100 t.predicate("a", "sct:"+code); 101 } else if ("http://loinc.org".equals(system)) { 102 t.prefix("loinc", "http://loinc.org/rdf#"); 103 t.predicate("a", "loinc:"+code); 104 } 105 } 106 107 private void decorateCodeableConcept(Complex t, Element element) { 108 for (Element c : element.getChildren("coding")) { 109 decorateCoding(t, c); 110 } 111 } 112 113 private void composeElement(Complex ctxt, Element element) { 114 if ("xhtml".equals(element.getType())) // need to decide what to do with this 115 return; 116 String en = element.getProperty().getDefinition().getBase().getPath(); 117 if (en == null) 118 en = element.getProperty().getDefinition().getPath(); 119 boolean doType = false; 120 if (en.endsWith("[x]")) { 121 en = en.substring(0, en.length()-3); 122 doType = true; 123 } 124 if (doType || element.getProperty().getDefinition().getType().size() > 1) 125 en = en + Utilities.capitalize(element.getType()); 126 127 Complex t = ctxt.predicate("fhir:"+en); 128 if (element.hasValue()) 129 t.predicate("fhir:value", ttlLiteral(element.getValue(), element.getType())); 130 if (element.hasIndex()) 131 t.predicate("fhir:index", Integer.toString(element.getIndex())); 132 133 if ("Coding".equals(element.getType())) 134 decorateCoding(t, element); 135 if ("CodeableConcept".equals(element.getType())) 136 decorateCodeableConcept(t, element); 137 if ("Reference".equals(element.getType())) 138 decorateReference(t, element); 139 140 for (Element child : element.getChildren()) { 141 composeElement(t, child); 142 } 143 } 144 145 protected String ttlLiteral(String value, String type) { 146 String xst = ""; 147 if (type.equals("boolean")) 148 xst = "^^xs:boolean"; 149 else if (type.equals("integer") || type.equals("unsignedInt") || type.equals("positiveInt")) 150 xst = "^^xs:int"; 151 else if (type.equals("decimal")) 152 xst = "^^xs:decimal"; 153 else if (type.equals("base64Binary")) 154 xst = "^^xs:base64Binary"; 155 else if (type.equals("instant")) 156 xst = "^^xs:dateTime"; 157 else if (type.equals("time")) 158 xst = "^^xs:time"; 159 else if (type.equals("date") || type.equals("dateTime") ) { 160 String v = value; 161 if (v.length() > 10) { 162 int i = value.substring(10).indexOf("-"); 163 if (i == -1) 164 i = value.substring(10).indexOf("+"); 165 v = i == -1 ? value : value.substring(0, 10+i); 166 } 167 if (v.length() > 10) 168 xst = "^^xs:dateTime"; 169 else if (v.length() == 10) 170 xst = "^^xs:date"; 171 else if (v.length() == 7) 172 xst = "^^xs:gYearMonth"; 173 else if (v.length() == 4) 174 xst = "^^xs:gYear"; 175 } 176 177 return "\"" +RdfGenerator.escape(value, true) + "\""+xst; 178 } 179 180}