001package org.hl7.fhir.r4.formats; 002 003import java.io.IOException; 004import java.io.OutputStreamWriter; 005import java.math.BigDecimal; 006import java.util.ArrayList; 007import java.util.Collections; 008import java.util.List; 009import java.util.Stack; 010 011public class JsonCreatorCanonical implements JsonCreator { 012 013 public class JsonCanValue { 014 String name; 015 private JsonCanValue(String name) { 016 this.name = name; 017 } 018 } 019 020 private class JsonCanNumberValue extends JsonCanValue { 021 private BigDecimal value; 022 private JsonCanNumberValue(String name, BigDecimal value) { 023 super(name); 024 this.value = value; 025 } 026 } 027 028 private class JsonCanPresentedNumberValue extends JsonCanValue { 029 private String value; 030 private JsonCanPresentedNumberValue(String name, String value) { 031 super(name); 032 this.value = value; 033 } 034 } 035 036 private class JsonCanIntegerValue extends JsonCanValue { 037 private Integer value; 038 private JsonCanIntegerValue(String name, Integer value) { 039 super(name); 040 this.value = value; 041 } 042 } 043 044 private class JsonCanBooleanValue extends JsonCanValue { 045 private Boolean value; 046 private JsonCanBooleanValue(String name, Boolean value) { 047 super(name); 048 this.value = value; 049 } 050 } 051 052 private class JsonCanStringValue extends JsonCanValue { 053 private String value; 054 private JsonCanStringValue(String name, String value) { 055 super(name); 056 this.value = value; 057 } 058 } 059 060 private class JsonCanNullValue extends JsonCanValue { 061 private JsonCanNullValue(String name) { 062 super(name); 063 } 064 } 065 066 public class JsonCanObject extends JsonCanValue { 067 068 boolean array; 069 List<JsonCanValue> children = new ArrayList<JsonCanValue>(); 070 071 public JsonCanObject(String name, boolean array) { 072 super(name); 073 this.array = array; 074 } 075 076 public void addProp(JsonCanValue obj) { 077 children.add(obj); 078 } 079 } 080 081 Stack<JsonCanObject> stack; 082 JsonCanObject root; 083 JsonCreatorDirect jj; 084 String name; 085 086 public JsonCreatorCanonical(OutputStreamWriter osw) { 087 stack = new Stack<JsonCreatorCanonical.JsonCanObject>(); 088 jj = new JsonCreatorDirect(osw); 089 name = null; 090 } 091 092 private String takeName() { 093 String res = name; 094 name = null; 095 return res; 096 } 097 098 @Override 099 public void setIndent(String indent) { 100 if (!indent.equals("")) 101 throw new Error("do not use pretty when canonical is set"); 102 jj.setIndent(indent); 103 } 104 105 @Override 106 public void beginObject() throws IOException { 107 JsonCanObject obj = new JsonCanObject(takeName(), false); 108 if (stack.isEmpty()) 109 root = obj; 110 else 111 stack.peek().addProp(obj); 112 stack.push(obj); 113 } 114 115 @Override 116 public void endObject() throws IOException { 117 stack.pop(); 118 } 119 120 @Override 121 public void nullValue() throws IOException { 122 stack.peek().addProp(new JsonCanNullValue(takeName())); 123 } 124 125 @Override 126 public void name(String name) throws IOException { 127 this.name = name; 128 } 129 130 @Override 131 public void value(String value) throws IOException { 132 stack.peek().addProp(new JsonCanStringValue(takeName(), value)); 133 } 134 135 @Override 136 public void value(Boolean value) throws IOException { 137 stack.peek().addProp(new JsonCanBooleanValue(takeName(), value)); 138 } 139 140 @Override 141 public void value(BigDecimal value) throws IOException { 142 stack.peek().addProp(new JsonCanNumberValue(takeName(), value)); 143 } 144 @Override 145 public void valueNum(String value) throws IOException { 146 stack.peek().addProp(new JsonCanPresentedNumberValue(takeName(), value)); 147 } 148 149 150 @Override 151 public void value(Integer value) throws IOException { 152 stack.peek().addProp(new JsonCanIntegerValue(takeName(), value)); 153 } 154 155 @Override 156 public void beginArray() throws IOException { 157 JsonCanObject obj = new JsonCanObject(takeName(), true); 158 if (!stack.isEmpty()) 159 stack.peek().addProp(obj); 160 stack.push(obj); 161 162 } 163 164 @Override 165 public void endArray() throws IOException { 166 stack.pop(); 167 } 168 169 @Override 170 public void finish() throws IOException { 171 writeObject(root); 172 } 173 174 private void writeObject(JsonCanObject obj) throws IOException { 175 jj.beginObject(); 176 List<String> names = new ArrayList<String>(); 177 for (JsonCanValue v : obj.children) 178 names.add(v.name); 179 Collections.sort(names); 180 for (String n : names) { 181 jj.name(n); 182 JsonCanValue v = getPropForName(n, obj.children); 183 if (v instanceof JsonCanNumberValue) 184 jj.value(((JsonCanNumberValue) v).value); 185 else if (v instanceof JsonCanPresentedNumberValue) 186 jj.valueNum(((JsonCanPresentedNumberValue) v).value); 187 else if (v instanceof JsonCanIntegerValue) 188 jj.value(((JsonCanIntegerValue) v).value); 189 else if (v instanceof JsonCanBooleanValue) 190 jj.value(((JsonCanBooleanValue) v).value); 191 else if (v instanceof JsonCanStringValue) 192 jj.value(((JsonCanStringValue) v).value); 193 else if (v instanceof JsonCanNullValue) 194 jj.nullValue(); 195 else if (v instanceof JsonCanObject) { 196 JsonCanObject o = (JsonCanObject) v; 197 if (o.array) 198 writeArray(o); 199 else 200 writeObject(o); 201 } else 202 throw new Error("not possible"); 203 } 204 jj.endObject(); 205 } 206 207 private JsonCanValue getPropForName(String name, List<JsonCanValue> children) { 208 for (JsonCanValue child : children) 209 if (child.name.equals(name)) 210 return child; 211 return null; 212 } 213 214 private void writeArray(JsonCanObject arr) throws IOException { 215 jj.beginArray(); 216 for (JsonCanValue v : arr.children) { 217 if (v instanceof JsonCanNumberValue) 218 jj.value(((JsonCanNumberValue) v).value); 219 else if (v instanceof JsonCanIntegerValue) 220 jj.value(((JsonCanIntegerValue) v).value); 221 else if (v instanceof JsonCanBooleanValue) 222 jj.value(((JsonCanBooleanValue) v).value); 223 else if (v instanceof JsonCanStringValue) 224 jj.value(((JsonCanStringValue) v).value); 225 else if (v instanceof JsonCanNullValue) 226 jj.nullValue(); 227 else if (v instanceof JsonCanObject) { 228 JsonCanObject o = (JsonCanObject) v; 229 if (o.array) 230 writeArray(o); 231 else 232 writeObject(o); 233 } else 234 throw new Error("not possible"); 235 } 236 jj.endArray(); 237 } 238 239 @Override 240 public void link(String href) { 241 // not used 242 } 243 244 245}