blob: 034ea6af75e5749186530b875aff77c774cd25b4 [file] [log] [blame]
Stuart McCullochf3173222012-06-07 21:57:32 +00001package aQute.lib.json;
2
3import java.io.*;
4import java.lang.reflect.*;
5import java.security.*;
6import java.util.*;
Stuart McCulloch528a65d2012-07-20 16:50:39 +00007import java.util.zip.*;
Stuart McCullochf3173222012-06-07 21:57:32 +00008
9public class Encoder implements Appendable, Closeable, Flushable {
10 final JSONCodec codec;
11 Appendable app;
12 MessageDigest digest;
13 boolean writeDefaults;
14 String encoding = "UTF-8";
Stuart McCulloch528a65d2012-07-20 16:50:39 +000015 boolean deflate;
16
Stuart McCullochf3173222012-06-07 21:57:32 +000017 Encoder(JSONCodec codec) {
18 this.codec = codec;
19 }
20
21 public Encoder put(Object object) throws Exception {
22 if (app == null)
23 to();
24
Stuart McCulloch4482c702012-06-15 13:27:53 +000025 codec.encode(this, object, null, new IdentityHashMap<Object,Type>());
Stuart McCulloch528a65d2012-07-20 16:50:39 +000026 flush();
Stuart McCullochf3173222012-06-07 21:57:32 +000027 return this;
28 }
29
30 public Encoder mark() throws NoSuchAlgorithmException {
31 if (digest == null)
32 digest = MessageDigest.getInstance("SHA1");
33 digest.reset();
34 return this;
35 }
36
37 public byte[] digest() throws NoSuchAlgorithmException, IOException {
38 if (digest == null)
39 return null;
40 append('\n');
41 return digest.digest();
42 }
43
44 public Encoder to() throws IOException {
45 to(new StringWriter());
46 return this;
47 }
48
49 public Encoder to(File file) throws IOException {
50 return to(new FileOutputStream(file));
51 }
52
53 public Encoder charset(String encoding) {
54 this.encoding = encoding;
55 return this;
56 }
57
58 public Encoder to(OutputStream out) throws IOException {
Stuart McCulloch528a65d2012-07-20 16:50:39 +000059 if ( deflate)
60 out = new DeflaterOutputStream(out);
61
Stuart McCullochf3173222012-06-07 21:57:32 +000062 return to(new OutputStreamWriter(out, encoding));
63 }
64
65 public Encoder to(Appendable out) throws IOException {
66 app = out;
67 return this;
68 }
69
70 public Appendable append(char c) throws IOException {
71 if (digest != null) {
72 digest.update((byte) (c / 256));
73 digest.update((byte) (c % 256));
74 }
75 app.append(c);
76 return this;
77 }
78
79 public Appendable append(CharSequence sq) throws IOException {
80 return append(sq, 0, sq.length());
81 }
82
83 public Appendable append(CharSequence sq, int start, int length) throws IOException {
84 if (digest != null) {
85 for (int i = start; i < length; i++) {
86 char c = sq.charAt(i);
87 digest.update((byte) (c / 256));
88 digest.update((byte) (c % 256));
89 }
90 }
91 app.append(sq, start, length);
92 return this;
93 }
94
Stuart McCulloch2929e2d2012-08-07 10:57:21 +000095 @Override
Stuart McCullochf3173222012-06-07 21:57:32 +000096 public String toString() {
97 return app.toString();
98 }
99
100 public void close() throws IOException {
101 if (app != null && app instanceof Closeable)
102 ((Closeable) app).close();
103 }
104
Stuart McCulloch4482c702012-06-15 13:27:53 +0000105 void encode(Object object, Type type, Map<Object,Type> visited) throws Exception {
Stuart McCullochf3173222012-06-07 21:57:32 +0000106 codec.encode(this, object, type, visited);
107 }
108
109 public Encoder writeDefaults() {
110 writeDefaults = true;
111 return this;
112 }
113
114 public void flush() throws IOException {
115 if (app instanceof Flushable) {
116 ((Flushable) app).flush();
117 }
118 }
Stuart McCulloch528a65d2012-07-20 16:50:39 +0000119 public Encoder deflate() {
120 if ( app != null)
121 throw new IllegalStateException("Writer already set, deflate must come before to(...)");
122 deflate = true;
123 return this;
124 }
Stuart McCullochf3173222012-06-07 21:57:32 +0000125}