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}