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}