1 package be
.nikiroo
.utils
.serial
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.io
.OutputStream
;
7 import be
.nikiroo
.utils
.streams
.BufferedInputStream
;
8 import be
.nikiroo
.utils
.streams
.ReplaceInputStream
;
9 import be
.nikiroo
.utils
.streams
.ReplaceOutputStream
;
12 * A {@link CustomSerializer} supports and generates values in the form:
14 * <li><tt>custom^<i>TYPE</i>^<i>ENCODED_VALUE</i></tt></li>
17 * In this scheme, the values are:
19 * <li><tt>custom</tt>: a fixed keyword</li>
20 * <li><tt>^</tt>: a fixed separator character (the
21 * <tt><i>ENCODED_VALUE</i></tt> can still use it inside its content, though</li>
22 * <li><tt><i>TYPE</i></tt>: the object type of this value</li>
23 * <li><tt><i>ENCODED_VALUE</i></tt>: the custom encoded value</li>
26 * To create a new {@link CustomSerializer}, you are expected to implement the
27 * abstract methods of this class. The rest should be taken care of bythe
32 public abstract class CustomSerializer
{
34 * Generate the custom <tt><i>ENCODED_VALUE</i></tt> from this
37 * The <tt>value</tt> will always be of the supported type.
40 * the {@link OutputStream} to write the value to
42 * the value to serialize
45 * in case of I/O error
47 protected abstract void toStream(OutputStream out
, Object value
)
51 * Regenerate the value from the custom <tt><i>ENCODED_VALUE</i></tt>.
53 * The value in the {@link InputStream} <tt>in</tt> will always be of the
57 * the {@link InputStream} containing the
58 * <tt><i>ENCODED_VALUE</i></tt>
60 * @return the regenerated object
63 * in case of I/O error
65 protected abstract Object
fromStream(InputStream in
) throws IOException
;
68 * Return the supported type name.
70 * It <b>must</b> be the name returned by {@link Object#getClass()
71 * #getCanonicalName()}.
73 * @return the supported class name
75 protected abstract String
getType();
78 * Encode the object into the given {@link OutputStream}, i.e., generate the
79 * <tt><i>ENCODED_VALUE</i></tt> part.
81 * Use whatever scheme you wish, the system shall ensure that the content is
82 * correctly encoded and that you will receive the same content at decode
86 * the builder to append to
88 * the object to encode
91 * in case of I/O error
93 public void encode(OutputStream out
, Object value
) throws IOException
{
94 ReplaceOutputStream replace
= new ReplaceOutputStream(out
, //
95 new String
[] { "\\", "\n" }, //
96 new String
[] { "\\\\", "\\n" });
99 SerialUtils
.write(replace
, "custom^");
100 SerialUtils
.write(replace
, getType());
101 SerialUtils
.write(replace
, "^");
102 toStream(replace
, value
);
104 replace
.close(false);
109 * Decode the value back into the supported object type.
111 * We do <b>not</b> expect the full content here but only:
116 * That is, we do not expect the "<tt>custom</tt>^<tt><i>TYPE</i></tt>^"
124 * @throws IOException
125 * in case of I/O error
127 public Object
decode(InputStream in
) throws IOException
{
128 ReplaceInputStream replace
= new ReplaceInputStream(in
, //
129 new String
[] { "\\\\", "\\n" }, //
130 new String
[] { "\\", "\n" });
133 return fromStream(replace
);
135 replace
.close(false);
139 public static boolean isCustom(BufferedInputStream in
) throws IOException
{
140 return in
.startsWith("custom^");
143 public static String
typeOf(String encodedValue
) {
144 int pos1
= encodedValue
.indexOf('^');
145 int pos2
= encodedValue
.indexOf('^', pos1
+ 1);
146 String type
= encodedValue
.substring(pos1
+ 1, pos2
);