001package org.hl7.fhir.r5.formats; 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.IOException; 035import java.io.Writer; 036import java.math.BigDecimal; 037import java.util.ArrayList; 038import java.util.List; 039 040import org.hl7.fhir.utilities.Utilities; 041 042/** 043 * A little implementation of a json write to replace Gson .... because Gson screws up decimal values, and *we care* 044 * 045 * @author Grahame Grieve 046 * 047 */ 048public class JsonCreatorDirect implements JsonCreator { 049 050 private Writer writer; 051 private boolean pretty; 052 private boolean comments; 053 private boolean named; 054 private List<Boolean> valued = new ArrayList<Boolean>(); 055 private int indent; 056 private List<String> commentList = new ArrayList<>(); 057 058 public JsonCreatorDirect(Writer writer, boolean pretty, boolean comments) { 059 super(); 060 this.writer = writer; 061 this.pretty = pretty; 062 this.comments = pretty && comments; 063 } 064 065 @Override 066 public void comment(String content) { 067 if (comments) { 068 commentList.add(content); 069 } 070 } 071 072 @Override 073 public void beginObject() throws IOException { 074 checkState(); 075 writer.write("{"); 076 stepIn(); 077 if (!valued.isEmpty()) { 078 valued.set(0, true); 079 } 080 valued.add(0, false); 081 } 082 083 private void commitComments() throws IOException { 084 if (comments) { 085 for (String s : commentList) { 086 writer.write("// "); 087 writer.write(s); 088 writer.write("\r\n"); 089 for (int i = 0; i < indent; i++) { 090 writer.write(" "); 091 } 092 } 093 commentList.clear(); 094 } 095 } 096 097 098 public void stepIn() throws IOException { 099 if (pretty) { 100 indent++; 101 writer.write("\r\n"); 102 for (int i = 0; i < indent; i++) { 103 writer.write(" "); 104 } 105 } 106 } 107 108 public void stepOut() throws IOException { 109 if (pretty) { 110 indent--; 111 writer.write("\r\n"); 112 for (int i = 0; i < indent; i++) { 113 writer.write(" "); 114 } 115 } 116 } 117 118 private void checkState() throws IOException { 119 commitComments(); 120 if (named) { 121 if (pretty) 122 writer.write(" : "); 123 else 124 writer.write(":"); 125 named = false; 126 } 127 if (!valued.isEmpty() && valued.get(0)) { 128 writer.write(","); 129 if (pretty) { 130 writer.write("\r\n"); 131 for (int i = 0; i < indent; i++) { 132 writer.write(" "); 133 } 134 } 135 valued.set(0, false); 136 } 137 } 138 139 @Override 140 public void endObject() throws IOException { 141 stepOut(); 142 writer.write("}"); 143 valued.remove(0); 144 } 145 146 @Override 147 public void nullValue() throws IOException { 148 checkState(); 149 writer.write("null"); 150 valued.set(0, true); 151 } 152 153 @Override 154 public void name(String name) throws IOException { 155 checkState(); 156 writer.write("\""+name+"\""); 157 named = true; 158 } 159 160 @Override 161 public void value(String value) throws IOException { 162 checkState(); 163 writer.write("\""+Utilities.escapeJson(value)+"\""); 164 valued.set(0, true); 165 } 166 167 @Override 168 public void value(Boolean value) throws IOException { 169 checkState(); 170 if (value == null) 171 writer.write("null"); 172 else if (value.booleanValue()) 173 writer.write("true"); 174 else 175 writer.write("false"); 176 valued.set(0, true); 177 } 178 179 @Override 180 public void value(BigDecimal value) throws IOException { 181 checkState(); 182 if (value == null) 183 writer.write("null"); 184 else 185 writer.write(value.toString()); 186 valued.set(0, true); 187 } 188 189 @Override 190 public void valueNum(String value) throws IOException { 191 checkState(); 192 if (value == null) 193 writer.write("null"); 194 else 195 writer.write(value); 196 valued.set(0, true); 197 } 198 199 @Override 200 public void value(Integer value) throws IOException { 201 checkState(); 202 if (value == null) 203 writer.write("null"); 204 else 205 writer.write(value.toString()); 206 valued.set(0, true); 207 } 208 209 @Override 210 public void beginArray() throws IOException { 211 checkState(); 212 writer.write("["); 213 if (!valued.isEmpty()) { 214 valued.set(0, true); 215 } 216 valued.add(0, false); 217 } 218 219 @Override 220 public void endArray() throws IOException { 221 writer.write("]"); 222 valued.remove(0); 223 } 224 225 @Override 226 public void finish() throws IOException { 227 writer.flush(); 228 } 229 230 @Override 231 public void link(String href) { 232 // not used 233 234 } 235 236 @Override 237 public void anchor(String name) { 238 // not used 239 } 240 241 242 @Override 243 public void externalLink(String string) { 244 // not used 245 } 246 247 @Override 248 public boolean canElide() { return false; } 249 250 @Override 251 public void elide() { 252 // not used 253 } 254}