Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 1 | package aQute.lib.json; |
| 2 | |
| 3 | import java.io.*; |
| 4 | import java.lang.reflect.*; |
| 5 | import java.security.*; |
| 6 | import java.util.*; |
| 7 | |
| 8 | public class Encoder implements Appendable, Closeable, Flushable { |
| 9 | final JSONCodec codec; |
| 10 | Appendable app; |
| 11 | MessageDigest digest; |
| 12 | boolean writeDefaults; |
| 13 | String encoding = "UTF-8"; |
| 14 | |
| 15 | Encoder(JSONCodec codec) { |
| 16 | this.codec = codec; |
| 17 | } |
| 18 | |
| 19 | public Encoder put(Object object) throws Exception { |
| 20 | if (app == null) |
| 21 | to(); |
| 22 | |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame^] | 23 | codec.encode(this, object, null, new IdentityHashMap<Object,Type>()); |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 24 | return this; |
| 25 | } |
| 26 | |
| 27 | public Encoder mark() throws NoSuchAlgorithmException { |
| 28 | if (digest == null) |
| 29 | digest = MessageDigest.getInstance("SHA1"); |
| 30 | digest.reset(); |
| 31 | return this; |
| 32 | } |
| 33 | |
| 34 | public byte[] digest() throws NoSuchAlgorithmException, IOException { |
| 35 | if (digest == null) |
| 36 | return null; |
| 37 | append('\n'); |
| 38 | return digest.digest(); |
| 39 | } |
| 40 | |
| 41 | public Encoder to() throws IOException { |
| 42 | to(new StringWriter()); |
| 43 | return this; |
| 44 | } |
| 45 | |
| 46 | public Encoder to(File file) throws IOException { |
| 47 | return to(new FileOutputStream(file)); |
| 48 | } |
| 49 | |
| 50 | public Encoder charset(String encoding) { |
| 51 | this.encoding = encoding; |
| 52 | return this; |
| 53 | } |
| 54 | |
| 55 | public Encoder to(OutputStream out) throws IOException { |
| 56 | return to(new OutputStreamWriter(out, encoding)); |
| 57 | } |
| 58 | |
| 59 | public Encoder to(Appendable out) throws IOException { |
| 60 | app = out; |
| 61 | return this; |
| 62 | } |
| 63 | |
| 64 | public Appendable append(char c) throws IOException { |
| 65 | if (digest != null) { |
| 66 | digest.update((byte) (c / 256)); |
| 67 | digest.update((byte) (c % 256)); |
| 68 | } |
| 69 | app.append(c); |
| 70 | return this; |
| 71 | } |
| 72 | |
| 73 | public Appendable append(CharSequence sq) throws IOException { |
| 74 | return append(sq, 0, sq.length()); |
| 75 | } |
| 76 | |
| 77 | public Appendable append(CharSequence sq, int start, int length) throws IOException { |
| 78 | if (digest != null) { |
| 79 | for (int i = start; i < length; i++) { |
| 80 | char c = sq.charAt(i); |
| 81 | digest.update((byte) (c / 256)); |
| 82 | digest.update((byte) (c % 256)); |
| 83 | } |
| 84 | } |
| 85 | app.append(sq, start, length); |
| 86 | return this; |
| 87 | } |
| 88 | |
| 89 | public String toString() { |
| 90 | return app.toString(); |
| 91 | } |
| 92 | |
| 93 | public void close() throws IOException { |
| 94 | if (app != null && app instanceof Closeable) |
| 95 | ((Closeable) app).close(); |
| 96 | } |
| 97 | |
Stuart McCulloch | 2286f23 | 2012-06-15 13:27:53 +0000 | [diff] [blame^] | 98 | void encode(Object object, Type type, Map<Object,Type> visited) throws Exception { |
Stuart McCulloch | bb01437 | 2012-06-07 21:57:32 +0000 | [diff] [blame] | 99 | codec.encode(this, object, type, visited); |
| 100 | } |
| 101 | |
| 102 | public Encoder writeDefaults() { |
| 103 | writeDefaults = true; |
| 104 | return this; |
| 105 | } |
| 106 | |
| 107 | public void flush() throws IOException { |
| 108 | if (app instanceof Flushable) { |
| 109 | ((Flushable) app).flush(); |
| 110 | } |
| 111 | } |
| 112 | } |