From d3ef2d7624c38690d63a9fe001f62da8e143935b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 10 Apr 2019 11:02:06 +1000 Subject: [PATCH] NPMPackage direct loading, + refactor JSON parser Location --- .../fhir/dstu3/elementmodel/JsonParser.java | 4 +- .../utils/formats/JsonTrackingParser.java | 519 ---------------- .../hl7/fhir/r4/elementmodel/JsonParser.java | 4 +- .../org/hl7/fhir/r4/formats/JsonParser.java | 2 +- .../hl7/fhir/r4/formats/JsonParserBase.java | 2 +- .../r4/utils/formats/JsonTrackingParser.java | 556 ------------------ .../hl7/fhir/r5/elementmodel/JsonParser.java | 4 +- .../org/hl7/fhir/r5/formats/JsonParser.java | 2 +- .../hl7/fhir/r5/formats/JsonParserBase.java | 2 +- .../hl7/fhir/utilities/cache/NpmPackage.java | 38 ++ .../utilities/json}/JsonTrackingParser.java | 2 +- 11 files changed, 49 insertions(+), 1086 deletions(-) delete mode 100644 org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/formats/JsonTrackingParser.java delete mode 100644 org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/formats/JsonTrackingParser.java rename {org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/formats => org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json}/JsonTrackingParser.java (99%) diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/JsonParser.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/JsonParser.java index 0c6ecb5d0..f47281b2b 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/JsonParser.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/JsonParser.java @@ -41,13 +41,13 @@ import org.hl7.fhir.dstu3.formats.JsonCreatorCanonical; import org.hl7.fhir.dstu3.formats.JsonCreatorGson; import org.hl7.fhir.dstu3.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.dstu3.model.StructureDefinition; -import org.hl7.fhir.dstu3.utils.formats.JsonTrackingParser; -import org.hl7.fhir.dstu3.utils.formats.JsonTrackingParser.LocationData; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser; +import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.xhtml.XhtmlParser; diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/formats/JsonTrackingParser.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/formats/JsonTrackingParser.java deleted file mode 100644 index 57ba5a529..000000000 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/formats/JsonTrackingParser.java +++ /dev/null @@ -1,519 +0,0 @@ -package org.hl7.fhir.dstu3.utils.formats; - -/*- - * #%L - * org.hl7.fhir.dstu3 - * %% - * Copyright (C) 2014 - 2019 Health Level 7 - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - - -import java.math.BigDecimal; -import java.util.Map; -import java.util.Stack; - -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.utilities.Utilities; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - - -/** - * This is created to get a json parser that can track line numbers... grr... - * - * @author Grahame Grieve - * - */ -public class JsonTrackingParser { - - public enum TokenType { - Open, Close, String, Number, Colon, Comma, OpenArray, CloseArray, Eof, Null, Boolean; - } - - public class LocationData { - private int line; - private int col; - - protected LocationData(int line, int col) { - super(); - this.line = line; - this.col = col; - } - - public int getLine() { - return line; - } - - public int getCol() { - return col; - } - - public void newLine() { - line++; - col = 1; - } - - public LocationData copy() { - return new LocationData(line, col); - } - } - - private class State { - private String name; - private boolean isProp; - protected State(String name, boolean isProp) { - super(); - this.name = name; - this.isProp = isProp; - } - public String getName() { - return name; - } - public boolean isProp() { - return isProp; - } - } - - private class Lexer { - private String source; - private int cursor; - private String peek; - private String value; - private TokenType type; - private Stack states = new Stack(); - private LocationData lastLocationBWS; - private LocationData lastLocationAWS; - private LocationData location; - private StringBuilder b = new StringBuilder(); - - public Lexer(String source) throws FHIRException { - this.source = source; - cursor = -1; - location = new LocationData(1, 1); - start(); - } - - private boolean more() { - return peek != null || cursor < source.length(); - } - - private String getNext(int length) throws FHIRException { - String result = ""; - if (peek != null) { - if (peek.length() > length) { - result = peek.substring(0, length); - peek = peek.substring(length); - } else { - result = peek; - peek = null; - } - } - if (result.length() < length) { - int len = length - result.length(); - if (cursor > source.length() - len) - throw error("Attempt to read past end of source"); - result = result + source.substring(cursor+1, cursor+len+1); - cursor = cursor + len; - } - for (char ch : result.toCharArray()) - if (ch == '\n') - location.newLine(); - else - location.col++; - return result; - } - - private char getNextChar() throws FHIRException { - if (peek != null) { - char ch = peek.charAt(0); - peek = peek.length() == 1 ? null : peek.substring(1); - return ch; - } else { - cursor++; - if (cursor >= source.length()) - return (char) 0; - char ch = source.charAt(cursor); - if (ch == '\n') { - location.newLine(); - } else { - location.col++; - } - return ch; - } - } - - private void push(char ch){ - peek = peek == null ? String.valueOf(ch) : String.valueOf(ch)+peek; - } - - private void parseWord(String word, char ch, TokenType type) throws FHIRException { - this.type = type; - value = ""+ch+getNext(word.length()-1); - if (!value.equals(word)) - throw error("Syntax error in json reading special word "+word); - } - - private FHIRException error(String msg) { - return new FHIRException("Error parsing JSON source: "+msg+" at Line "+Integer.toString(location.line)+" (path=["+path()+"])"); - } - - private String path() { - if (states.empty()) - return value; - else { - String result = ""; - for (State s : states) - result = result + '/'+ s.getName(); - result = result + value; - return result; - } - } - - public void start() throws FHIRException { -// char ch = getNextChar(); -// if (ch = '\.uEF') -// begin -// // skip BOM -// getNextChar(); -// getNextChar(); -// end -// else -// push(ch); - next(); - } - - public TokenType getType() { - return type; - } - - public String getValue() { - return value; - } - - - public LocationData getLastLocationBWS() { - return lastLocationBWS; - } - - public LocationData getLastLocationAWS() { - return lastLocationAWS; - } - - public void next() throws FHIRException { - lastLocationBWS = location.copy(); - char ch; - do { - ch = getNextChar(); - } while (more() && Utilities.charInSet(ch, ' ', '\r', '\n', '\t')); - lastLocationAWS = location.copy(); - - if (!more()) { - type = TokenType.Eof; - } else { - switch (ch) { - case '{' : - type = TokenType.Open; - break; - case '}' : - type = TokenType.Close; - break; - case '"' : - type = TokenType.String; - b.setLength(0); - do { - ch = getNextChar(); - if (ch == '\\') { - ch = getNextChar(); - switch (ch) { - case '"': b.append('"'); break; - case '\\': b.append('\\'); break; - case '/': b.append('/'); break; - case 'n': b.append('\n'); break; - case 'r': b.append('\r'); break; - case 't': b.append('\t'); break; - case 'u': b.append((char) Integer.parseInt(getNext(4), 16)); break; - default : - throw error("unknown escape sequence: \\"+ch); - } - ch = ' '; - } else if (ch != '"') - b.append(ch); - } while (more() && (ch != '"')); - if (!more()) - throw error("premature termination of json stream during a string"); - value = b.toString(); - break; - case ':' : - type = TokenType.Colon; - break; - case ',' : - type = TokenType.Comma; - break; - case '[' : - type = TokenType.OpenArray; - break; - case ']' : - type = TokenType.CloseArray; - break; - case 't' : - parseWord("true", ch, TokenType.Boolean); - break; - case 'f' : - parseWord("false", ch, TokenType.Boolean); - break; - case 'n' : - parseWord("null", ch, TokenType.Null); - break; - default: - if ((ch >= '0' && ch <= '9') || ch == '-') { - type = TokenType.Number; - b.setLength(0); - while (more() && ((ch >= '0' && ch <= '9') || ch == '-' || ch == '.')) { - b.append(ch); - ch = getNextChar(); - } - value = b.toString(); - push(ch); - } else - throw error("Unexpected char '"+ch+"' in json stream"); - } - } - } - - public String consume(TokenType type) throws FHIRException { - if (this.type != type) - throw error("JSON syntax error - found "+type.toString()+" expecting "+type.toString()); - String result = value; - next(); - return result; - } - - } - - enum ItemType { - Object, String, Number, Boolean, Array, End, Eof, Null; - } - private Map map; - private Lexer lexer; - private ItemType itemType = ItemType.Object; - private String itemName; - private String itemValue; - - public static JsonObject parse(String source, Map map) throws FHIRException { - JsonTrackingParser self = new JsonTrackingParser(); - self.map = map; - return self.parse(source); - } - - private JsonObject parse(String source) throws FHIRException { - lexer = new Lexer(source); - JsonObject result = new JsonObject(); - LocationData loc = lexer.location.copy(); - if (lexer.getType() == TokenType.Open) { - lexer.next(); - lexer.states.push(new State("", false)); - } - else - throw lexer.error("Unexpected content at start of JSON: "+lexer.getType().toString()); - - parseProperty(); - readObject(result, true); - map.put(result, loc); - return result; - } - - private void readObject(JsonObject obj, boolean root) throws FHIRException { - map.put(obj, lexer.location.copy()); - - while (!(itemType == ItemType.End) || (root && (itemType == ItemType.Eof))) { - if (obj.has(itemName)) - throw lexer.error("Duplicated property name: "+itemName); - - switch (itemType) { - case Object: - JsonObject child = new JsonObject(); //(obj.path+'.'+ItemName); - LocationData loc = lexer.location.copy(); - obj.add(itemName, child); - next(); - readObject(child, false); - map.put(obj, loc); - break; - case Boolean : - JsonPrimitive v = new JsonPrimitive(Boolean.valueOf(itemValue)); - obj.add(itemName, v); - map.put(v, lexer.location.copy()); - break; - case String: - v = new JsonPrimitive(itemValue); - obj.add(itemName, v); - map.put(v, lexer.location.copy()); - break; - case Number: - v = new JsonPrimitive(new BigDecimal(itemValue)); - obj.add(itemName, v); - map.put(v, lexer.location.copy()); - break; - case Null: - JsonNull n = new JsonNull(); - obj.add(itemName, n); - map.put(n, lexer.location.copy()); - break; - case Array: - JsonArray arr = new JsonArray(); // (obj.path+'.'+ItemName); - loc = lexer.location.copy(); - obj.add(itemName, arr); - next(); - readArray(arr, false); - map.put(arr, loc); - break; - case Eof : - throw lexer.error("Unexpected End of File"); - } - next(); - } - } - - private void readArray(JsonArray arr, boolean root) throws FHIRException { - while (!((itemType == ItemType.End) || (root && (itemType == ItemType.Eof)))) { - switch (itemType) { - case Object: - JsonObject obj = new JsonObject(); // (arr.path+'['+inttostr(i)+']'); - LocationData loc = lexer.location.copy(); - arr.add(obj); - next(); - readObject(obj, false); - map.put(obj, loc); - break; - case String: - JsonPrimitive v = new JsonPrimitive(itemValue); - arr.add(v); - map.put(v, lexer.location.copy()); - break; - case Number: - v = new JsonPrimitive(new BigDecimal(itemValue)); - arr.add(v); - map.put(v, lexer.location.copy()); - break; - case Null : - JsonNull n = new JsonNull(); - arr.add(n); - map.put(n, lexer.location.copy()); - break; - case Array: - JsonArray child = new JsonArray(); // (arr.path+'['+inttostr(i)+']'); - loc = lexer.location.copy(); - arr.add(child); - next(); - readArray(child, false); - map.put(arr, loc); - break; - case Eof : - throw lexer.error("Unexpected End of File"); - } - next(); - } - } - - private void next() throws FHIRException { - switch (itemType) { - case Object : - lexer.consume(TokenType.Open); - lexer.states.push(new State(itemName, false)); - if (lexer.getType() == TokenType.Close) { - itemType = ItemType.End; - lexer.next(); - } else - parseProperty(); - break; - case Null: - case String: - case Number: - case End: - case Boolean : - if (itemType == ItemType.End) - lexer.states.pop(); - if (lexer.getType() == TokenType.Comma) { - lexer.next(); - parseProperty(); - } else if (lexer.getType() == TokenType.Close) { - itemType = ItemType.End; - lexer.next(); - } else if (lexer.getType() == TokenType.CloseArray) { - itemType = ItemType.End; - lexer.next(); - } else if (lexer.getType() == TokenType.Eof) { - itemType = ItemType.Eof; - } else - throw lexer.error("Unexpected JSON syntax"); - break; - case Array : - lexer.next(); - lexer.states.push(new State(itemName+"[]", true)); - parseProperty(); - break; - case Eof : - throw lexer.error("JSON Syntax Error - attempt to read past end of json stream"); - default: - throw lexer.error("not done yet (a): "+itemType.toString()); - } - } - - private void parseProperty() throws FHIRException { - if (!lexer.states.peek().isProp) { - itemName = lexer.consume(TokenType.String); - itemValue = null; - lexer.consume(TokenType.Colon); - } - switch (lexer.getType()) { - case Null : - itemType = ItemType.Null; - itemValue = lexer.value; - lexer.next(); - break; - case String : - itemType = ItemType.String; - itemValue = lexer.value; - lexer.next(); - break; - case Boolean : - itemType = ItemType.Boolean; - itemValue = lexer.value; - lexer.next(); - break; - case Number : - itemType = ItemType.Number; - itemValue = lexer.value; - lexer.next(); - break; - case Open : - itemType = ItemType.Object; - break; - case OpenArray : - itemType = ItemType.Array; - break; - case CloseArray : - itemType = ItemType.End; - break; - // case Close, , case Colon, case Comma, case OpenArray, ! - default: - throw lexer.error("not done yet (b): "+lexer.getType().toString()); - } - } -} diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/elementmodel/JsonParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/elementmodel/JsonParser.java index e30389195..e20880064 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/elementmodel/JsonParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/elementmodel/JsonParser.java @@ -44,10 +44,10 @@ import org.hl7.fhir.r4.formats.JsonCreatorCanonical; import org.hl7.fhir.r4.formats.JsonCreatorGson; import org.hl7.fhir.r4.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r4.model.StructureDefinition; -import org.hl7.fhir.r4.utils.formats.JsonTrackingParser; -import org.hl7.fhir.r4.utils.formats.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser; +import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.xhtml.XhtmlParser; diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java index 9d72a08cb..d6570069b 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParser.java @@ -55,8 +55,8 @@ import org.hl7.fhir.exceptions.FHIRFormatError; // Generated on Thu, Dec 13, 2018 14:07+1100 for FHIR v4.0.0 import org.hl7.fhir.r4.model.*; -import org.hl7.fhir.r4.utils.formats.JsonTrackingParser.PresentedBigDecimal; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser.PresentedBigDecimal; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import com.google.gson.JsonArray; diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParserBase.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParserBase.java index 28893e0d1..0869a7943 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParserBase.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/formats/JsonParserBase.java @@ -64,9 +64,9 @@ import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.Type; -import org.hl7.fhir.r4.utils.formats.JsonTrackingParser; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser; import org.hl7.fhir.utilities.xhtml.XhtmlComposer; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/formats/JsonTrackingParser.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/formats/JsonTrackingParser.java deleted file mode 100644 index 46b7171ae..000000000 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/formats/JsonTrackingParser.java +++ /dev/null @@ -1,556 +0,0 @@ -package org.hl7.fhir.r4.utils.formats; - -/*- - * #%L - * org.hl7.fhir.r4 - * %% - * Copyright (C) 2014 - 2019 Health Level 7 - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - - -import java.io.IOException; -import java.math.BigDecimal; -import java.util.Map; -import java.util.Stack; - -import org.hl7.fhir.utilities.Utilities; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; - - -/** - * This is created to get a json parser that can track line numbers... grr... - * - * @author Grahame Grieve - * - */ -public class JsonTrackingParser { - - public class PresentedBigDecimal extends BigDecimal { - - public String presentation; - - public PresentedBigDecimal(String value) { - super(value); - presentation = value; - } - - public String getPresentation() { - return presentation; - } - - - } - - public enum TokenType { - Open, Close, String, Number, Colon, Comma, OpenArray, CloseArray, Eof, Null, Boolean; - } - - public class LocationData { - private int line; - private int col; - - protected LocationData(int line, int col) { - super(); - this.line = line; - this.col = col; - } - - public int getLine() { - return line; - } - - public int getCol() { - return col; - } - - public void newLine() { - line++; - col = 1; - } - - public LocationData copy() { - return new LocationData(line, col); - } - } - - private class State { - private String name; - private boolean isProp; - protected State(String name, boolean isProp) { - super(); - this.name = name; - this.isProp = isProp; - } - public String getName() { - return name; - } - public boolean isProp() { - return isProp; - } - } - - private class Lexer { - private String source; - private int cursor; - private String peek; - private String value; - private TokenType type; - private Stack states = new Stack(); - private LocationData lastLocationBWS; - private LocationData lastLocationAWS; - private LocationData location; - private StringBuilder b = new StringBuilder(); - - public Lexer(String source) throws IOException { - this.source = source; - cursor = -1; - location = new LocationData(1, 1); - start(); - } - - private boolean more() { - return peek != null || cursor < source.length(); - } - - private String getNext(int length) throws IOException { - String result = ""; - if (peek != null) { - if (peek.length() > length) { - result = peek.substring(0, length); - peek = peek.substring(length); - } else { - result = peek; - peek = null; - } - } - if (result.length() < length) { - int len = length - result.length(); - if (cursor > source.length() - len) - throw error("Attempt to read past end of source"); - result = result + source.substring(cursor+1, cursor+len+1); - cursor = cursor + len; - } - for (char ch : result.toCharArray()) - if (ch == '\n') - location.newLine(); - else - location.col++; - return result; - } - - private char getNextChar() throws IOException { - if (peek != null) { - char ch = peek.charAt(0); - peek = peek.length() == 1 ? null : peek.substring(1); - return ch; - } else { - cursor++; - if (cursor >= source.length()) - return (char) 0; - char ch = source.charAt(cursor); - if (ch == '\n') { - location.newLine(); - } else { - location.col++; - } - return ch; - } - } - - private void push(char ch){ - peek = peek == null ? String.valueOf(ch) : String.valueOf(ch)+peek; - } - - private void parseWord(String word, char ch, TokenType type) throws IOException { - this.type = type; - value = ""+ch+getNext(word.length()-1); - if (!value.equals(word)) - throw error("Syntax error in json reading special word "+word); - } - - private IOException error(String msg) { - return new IOException("Error parsing JSON source: "+msg+" at Line "+Integer.toString(location.line)+" (path=["+path()+"])"); - } - - private String path() { - if (states.empty()) - return value; - else { - String result = ""; - for (State s : states) - result = result + '/'+ s.getName(); - result = result + value; - return result; - } - } - - public void start() throws IOException { -// char ch = getNextChar(); -// if (ch = '\.uEF') -// begin -// // skip BOM -// getNextChar(); -// getNextChar(); -// end -// else -// push(ch); - next(); - } - - public TokenType getType() { - return type; - } - - public String getValue() { - return value; - } - - - public LocationData getLastLocationBWS() { - return lastLocationBWS; - } - - public LocationData getLastLocationAWS() { - return lastLocationAWS; - } - - public void next() throws IOException { - lastLocationBWS = location.copy(); - char ch; - do { - ch = getNextChar(); - } while (more() && Utilities.charInSet(ch, ' ', '\r', '\n', '\t')); - lastLocationAWS = location.copy(); - - if (!more()) { - type = TokenType.Eof; - } else { - switch (ch) { - case '{' : - type = TokenType.Open; - break; - case '}' : - type = TokenType.Close; - break; - case '"' : - type = TokenType.String; - b.setLength(0); - do { - ch = getNextChar(); - if (ch == '\\') { - ch = getNextChar(); - switch (ch) { - case '"': b.append('"'); break; - case '\'': b.append('\''); break; - case '\\': b.append('\\'); break; - case '/': b.append('/'); break; - case 'n': b.append('\n'); break; - case 'r': b.append('\r'); break; - case 't': b.append('\t'); break; - case 'u': b.append((char) Integer.parseInt(getNext(4), 16)); break; - default : - throw error("unknown escape sequence: \\"+ch); - } - ch = ' '; - } else if (ch != '"') - b.append(ch); - } while (more() && (ch != '"')); - if (!more()) - throw error("premature termination of json stream during a string"); - value = b.toString(); - break; - case ':' : - type = TokenType.Colon; - break; - case ',' : - type = TokenType.Comma; - break; - case '[' : - type = TokenType.OpenArray; - break; - case ']' : - type = TokenType.CloseArray; - break; - case 't' : - parseWord("true", ch, TokenType.Boolean); - break; - case 'f' : - parseWord("false", ch, TokenType.Boolean); - break; - case 'n' : - parseWord("null", ch, TokenType.Null); - break; - default: - if ((ch >= '0' && ch <= '9') || ch == '-') { - type = TokenType.Number; - b.setLength(0); - while (more() && ((ch >= '0' && ch <= '9') || ch == '-' || ch == '.') || ch == '+' || ch == 'e' || ch == 'E') { - b.append(ch); - ch = getNextChar(); - } - value = b.toString(); - push(ch); - } else - throw error("Unexpected char '"+ch+"' in json stream"); - } - } - } - - public String consume(TokenType type) throws IOException { - if (this.type != type) - throw error("JSON syntax error - found "+type.toString()+" expecting "+type.toString()); - String result = value; - next(); - return result; - } - - } - - enum ItemType { - Object, String, Number, Boolean, Array, End, Eof, Null; - } - private Map map; - private Lexer lexer; - private ItemType itemType = ItemType.Object; - private String itemName; - private String itemValue; - - public static JsonObject parse(String source, Map map) throws IOException { - JsonTrackingParser self = new JsonTrackingParser(); - self.map = map; - return self.parse(source); - } - - private JsonObject parse(String source) throws IOException { - lexer = new Lexer(source); - JsonObject result = new JsonObject(); - LocationData loc = lexer.location.copy(); - if (lexer.getType() == TokenType.Open) { - lexer.next(); - lexer.states.push(new State("", false)); - } - else - throw lexer.error("Unexpected content at start of JSON: "+lexer.getType().toString()); - - parseProperty(); - readObject(result, true); - if (map != null) - map.put(result, loc); - return result; - } - - private void readObject(JsonObject obj, boolean root) throws IOException { - if (map != null) - map.put(obj, lexer.location.copy()); - - while (!(itemType == ItemType.End) || (root && (itemType == ItemType.Eof))) { - if (obj.has(itemName)) - throw lexer.error("Duplicated property name: "+itemName); - - switch (itemType) { - case Object: - JsonObject child = new JsonObject(); //(obj.path+'.'+ItemName); - LocationData loc = lexer.location.copy(); - obj.add(itemName, child); - next(); - readObject(child, false); - if (map != null) - map.put(obj, loc); - break; - case Boolean : - JsonPrimitive v = new JsonPrimitive(Boolean.valueOf(itemValue)); - obj.add(itemName, v); - if (map != null) - map.put(v, lexer.location.copy()); - break; - case String: - v = new JsonPrimitive(itemValue); - obj.add(itemName, v); - if (map != null) - map.put(v, lexer.location.copy()); - break; - case Number: - v = new JsonPrimitive(new PresentedBigDecimal(itemValue)); - obj.add(itemName, v); - if (map != null) - map.put(v, lexer.location.copy()); - break; - case Null: - JsonNull n = new JsonNull(); - obj.add(itemName, n); - if (map != null) - map.put(n, lexer.location.copy()); - break; - case Array: - JsonArray arr = new JsonArray(); // (obj.path+'.'+ItemName); - loc = lexer.location.copy(); - obj.add(itemName, arr); - next(); - readArray(arr, false); - if (map != null) - map.put(arr, loc); - break; - case Eof : - throw lexer.error("Unexpected End of File"); - case End: - // TODO GG: This isn't handled. Should it be? - break; - } - next(); - } - } - - private void readArray(JsonArray arr, boolean root) throws IOException { - while (!((itemType == ItemType.End) || (root && (itemType == ItemType.Eof)))) { - switch (itemType) { - case Object: - JsonObject obj = new JsonObject(); // (arr.path+'['+inttostr(i)+']'); - LocationData loc = lexer.location.copy(); - arr.add(obj); - next(); - readObject(obj, false); - if (map != null) - map.put(obj, loc); - break; - case String: - JsonPrimitive v = new JsonPrimitive(itemValue); - arr.add(v); - if (map != null) - map.put(v, lexer.location.copy()); - break; - case Number: - v = new JsonPrimitive(new BigDecimal(itemValue)); - arr.add(v); - if (map != null) - map.put(v, lexer.location.copy()); - break; - case Null : - JsonNull n = new JsonNull(); - arr.add(n); - if (map != null) - map.put(n, lexer.location.copy()); - break; - case Array: - JsonArray child = new JsonArray(); // (arr.path+'['+inttostr(i)+']'); - loc = lexer.location.copy(); - arr.add(child); - next(); - readArray(child, false); - if (map != null) - map.put(arr, loc); - break; - case Eof : - throw lexer.error("Unexpected End of File"); - case End: - case Boolean: - // TODO GG: These aren't handled. SHould they be? - break; - } - next(); - } - } - - private void next() throws IOException { - switch (itemType) { - case Object : - lexer.consume(TokenType.Open); - lexer.states.push(new State(itemName, false)); - if (lexer.getType() == TokenType.Close) { - itemType = ItemType.End; - lexer.next(); - } else - parseProperty(); - break; - case Null: - case String: - case Number: - case End: - case Boolean : - if (itemType == ItemType.End) - lexer.states.pop(); - if (lexer.getType() == TokenType.Comma) { - lexer.next(); - parseProperty(); - } else if (lexer.getType() == TokenType.Close) { - itemType = ItemType.End; - lexer.next(); - } else if (lexer.getType() == TokenType.CloseArray) { - itemType = ItemType.End; - lexer.next(); - } else if (lexer.getType() == TokenType.Eof) { - itemType = ItemType.Eof; - } else - throw lexer.error("Unexpected JSON syntax"); - break; - case Array : - lexer.next(); - lexer.states.push(new State(itemName+"[]", true)); - parseProperty(); - break; - case Eof : - throw lexer.error("JSON Syntax Error - attempt to read past end of json stream"); - default: - throw lexer.error("not done yet (a): "+itemType.toString()); - } - } - - private void parseProperty() throws IOException { - if (!lexer.states.peek().isProp) { - itemName = lexer.consume(TokenType.String); - itemValue = null; - lexer.consume(TokenType.Colon); - } - switch (lexer.getType()) { - case Null : - itemType = ItemType.Null; - itemValue = lexer.value; - lexer.next(); - break; - case String : - itemType = ItemType.String; - itemValue = lexer.value; - lexer.next(); - break; - case Boolean : - itemType = ItemType.Boolean; - itemValue = lexer.value; - lexer.next(); - break; - case Number : - itemType = ItemType.Number; - itemValue = lexer.value; - lexer.next(); - break; - case Open : - itemType = ItemType.Object; - break; - case OpenArray : - itemType = ItemType.Array; - break; - case CloseArray : - itemType = ItemType.End; - break; - // case Close, , case Colon, case Comma, case OpenArray, ! - default: - throw lexer.error("not done yet (b): "+lexer.getType().toString()); - } - } -} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java index 8bffbc6e9..ca30a980e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java @@ -44,10 +44,10 @@ import org.hl7.fhir.r5.formats.JsonCreatorCanonical; import org.hl7.fhir.r5.formats.JsonCreatorGson; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.utils.formats.JsonTrackingParser; -import org.hl7.fhir.r5.utils.formats.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser; +import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.xhtml.XhtmlParser; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java index b5aa0de02..e6b8ac07e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParser.java @@ -55,8 +55,8 @@ import org.hl7.fhir.exceptions.FHIRFormatError; // Generated on Thu, Dec 13, 2018 14:07+1100 for FHIR v4.0.0 import org.hl7.fhir.r5.model.*; -import org.hl7.fhir.r5.utils.formats.JsonTrackingParser.PresentedBigDecimal; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser.PresentedBigDecimal; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import com.google.gson.JsonArray; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParserBase.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParserBase.java index dfc847143..7d0820700 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParserBase.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/formats/JsonParserBase.java @@ -64,9 +64,9 @@ import org.hl7.fhir.r5.model.IdType; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.Type; -import org.hl7.fhir.r5.utils.formats.JsonTrackingParser; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonTrackingParser; import org.hl7.fhir.utilities.xhtml.XhtmlComposer; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java index 2112d307f..2337ae85c 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java @@ -37,11 +37,16 @@ import java.util.Map.Entry; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.io.FileUtils; import org.hl7.fhir.utilities.IniFile; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.cache.PackageCacheManager.PackageEntry; import org.hl7.fhir.utilities.cache.PackageGenerator.PackageType; +import org.hl7.fhir.utilities.json.JsonTrackingParser; import com.google.gson.JsonObject; @@ -91,6 +96,39 @@ import com.google.gson.JsonObject; return names; } + private static final int BUFFER_SIZE = 1024; + public static NpmPackage fromPackage(InputStream tgz) throws IOException { + NpmPackage res = new NpmPackage(null); + GzipCompressorInputStream gzipIn = new GzipCompressorInputStream(tgz); + try (TarArchiveInputStream tarIn = new TarArchiveInputStream(gzipIn)) { + TarArchiveEntry entry; + + int i = 0; + int c = 12; + while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) { + i++; + if (entry.isDirectory()) { + res.folders.add(entry.getName()); + } else { + int count; + byte data[] = new byte[BUFFER_SIZE]; + + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) { + while ((count = tarIn.read(data, 0, BUFFER_SIZE)) != -1) { + dest.write(data, 0, count); + } + } + fos.close(); + res.content.put(entry.getName(), fos.toByteArray()); + } + } + } + res.npm = JsonTrackingParser.parseJson(res.content.get("package/package.json")); + return res; + } + + public static NpmPackage fromZip(InputStream stream, boolean dropRootFolder) throws IOException { NpmPackage res = new NpmPackage(null); ZipInputStream zip = new ZipInputStream(stream); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/formats/JsonTrackingParser.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java similarity index 99% rename from org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/formats/JsonTrackingParser.java rename to org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java index 0f747cd90..952813c79 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/formats/JsonTrackingParser.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/json/JsonTrackingParser.java @@ -1,4 +1,4 @@ -package org.hl7.fhir.r5.utils.formats; +package org.hl7.fhir.utilities.json; import java.io.File;