001package org.hl7.fhir.r4b.formats; 002 003import java.io.FileNotFoundException; 004import java.io.IOException; 005 006/* 007 Copyright (c) 2011+, HL7, Inc. 008 All rights reserved. 009 010 Redistribution and use in source and binary forms, with or without modification, 011 are permitted provided that the following conditions are met: 012 013 * Redistributions of source code must retain the above copyright notice, this 014 list of conditions and the following disclaimer. 015 * Redistributions in binary form must reproduce the above copyright notice, 016 this list of conditions and the following disclaimer in the documentation 017 and/or other materials provided with the distribution. 018 * Neither the name of HL7 nor the names of its contributors may be used to 019 endorse or promote products derived from this software without specific 020 prior written permission. 021 022 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 023 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 024 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 025 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 026 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 027 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 028 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 029 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 030 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 031 POSSIBILITY OF SUCH DAMAGE. 032 033 */ 034 035 036 037/* 038Copyright (c) 2011+, HL7, Inc 039All rights reserved. 040 041Redistribution and use in source and binary forms, with or without modification, 042are permitted provided that the following conditions are met: 043 044 * Redistributions of source code must retain the above copyright notice, this 045 list of conditions and the following disclaimer. 046 * Redistributions in binary form must reproduce the above copyright notice, 047 this list of conditions and the following disclaimer in the documentation 048 and/or other materials provided with the distribution. 049 * Neither the name of HL7 nor the names of its contributors may be used to 050 endorse or promote products derived from this software without specific 051 prior written permission. 052 053THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 054ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 055WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 056IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 057INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 058NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 059PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 060WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 061ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 062POSSIBILITY OF SUCH DAMAGE. 063 064*/ 065 066import java.math.BigDecimal; 067import java.net.URI; 068 069import org.apache.commons.codec.binary.Base64; 070import org.hl7.fhir.exceptions.FHIRException; 071import org.hl7.fhir.r4b.elementmodel.Manager.FhirFormat; 072import org.hl7.fhir.r4b.model.Resource; 073import org.hl7.fhir.utilities.TextFile; 074 075public abstract class FormatUtilities { 076 public static final String ID_REGEX = "[A-Za-z0-9\\-\\.]{1,64}"; 077 public static final String FHIR_NS = "http://hl7.org/fhir"; 078 public static final String XHTML_NS = "http://www.w3.org/1999/xhtml"; 079 public static final String NS_XSI = "http://www.w3.org/2001/XMLSchema-instance"; 080 private static final int MAX_SCAN_LENGTH = 1000; // how many characters to scan into content when autodetermining format 081 082 protected String toString(String value) { 083 return value; 084 } 085 086 protected String toString(int value) { 087 return java.lang.Integer.toString(value); 088 } 089 090 protected String toString(boolean value) { 091 return java.lang.Boolean.toString(value); 092 } 093 094 protected String toString(BigDecimal value) { 095 return value.toString(); 096 } 097 098 protected String toString(URI value) { 099 return value.toString(); 100 } 101 102 public static String toString(byte[] value) { 103 byte[] encodeBase64 = Base64.encodeBase64(value); 104 return new String(encodeBase64); 105 } 106 107 public static boolean isValidId(String tail) { 108 return tail.matches(ID_REGEX); 109 } 110 111 public static String makeId(String candidate) { 112 StringBuilder b = new StringBuilder(); 113 for (char c : candidate.toCharArray()) 114 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '.' || c == '-') 115 b.append(c); 116 return b.toString(); 117 } 118 119 public static ParserBase makeParser(FhirFormat format) { 120 switch (format) { 121 case XML : return new XmlParser(); 122 case JSON : return new JsonParser(); 123 case TURTLE : throw new Error("unsupported Format "+format.toString()); // return new TurtleParser(); 124 case VBAR : throw new Error("unsupported Format "+format.toString()); // 125 case TEXT : throw new Error("unsupported Format "+format.toString()); // 126 } 127 throw new Error("unsupported Format "+format.toString()); 128 } 129 130 public static ParserBase makeParser(String format) { 131 if ("XML".equalsIgnoreCase(format)) return new XmlParser(); 132 if ("JSON".equalsIgnoreCase(format)) return new JsonParser(); 133 if ("TURTLE".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); // return new TurtleParser(); 134 if ("JSONLD".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); // return new JsonLdParser(); 135 if ("VBAR".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); // 136 if ("TEXT".equalsIgnoreCase(format)) throw new Error("unsupported Format "+format.toString()); // 137 throw new Error("unsupported Format "+format); 138 } 139 140 public static FhirFormat determineFormat(byte[] source) throws FHIRException { 141 return determineFormat(source, MAX_SCAN_LENGTH); 142 } 143 144 public static FhirFormat determineFormat(byte[] source, int scanLength) throws FHIRException { 145 if (scanLength == -1) 146 scanLength = source.length; 147 int lt = firstIndexOf(source, '<', scanLength); 148 int ps = firstIndexOf(source, '{', scanLength); 149 int at = firstIndexOf(source, '@', scanLength); 150 if (at < ps && at < lt) return FhirFormat.TURTLE; 151 if (ps < lt) return FhirFormat.JSON; 152 if (lt < ps) return FhirFormat.XML; 153 throw new FHIRException("unable to determine format"); 154 } 155 156 private static int firstIndexOf(byte[] source, char c, int scanLength) { 157 for (int i = 0; i < Math.min(source.length, scanLength); i++) { 158 if (source[i] == c) 159 return i; 160 } 161 return Integer.MAX_VALUE; 162 } 163 164 public static Resource loadFile(String path) throws FileNotFoundException, IOException, FHIRException { 165 byte[] src = TextFile.fileToBytes(path); 166 FhirFormat fmt = determineFormat(src); 167 ParserBase parser = makeParser(fmt); 168 return parser.parse(src); 169 } 170 171 172}