1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.avltree;
21
22
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.DataInputStream;
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28 import java.util.Comparator;
29
30 import org.apache.directory.server.i18n.I18n;
31
32
33
34
35
36
37
38 @SuppressWarnings("unchecked")
39 public class AvlTreeMarshaller<E> implements Marshaller<AvlTree<E>>
40 {
41
42 private static final byte[] EMPTY_TREE = new byte[1];
43
44
45 private Marshaller<E> keyMarshaller;
46
47
48 private Comparator<E> comparator;
49
50
51
52
53
54
55
56
57
58 public AvlTreeMarshaller( Comparator<E> comparator, Marshaller<E> keyMarshaller )
59 {
60 this.comparator = comparator;
61 this.keyMarshaller = keyMarshaller;
62 }
63
64
65
66
67
68
69
70
71 public AvlTreeMarshaller( Comparator<E> comparator )
72 {
73 this.comparator = comparator;
74 this.keyMarshaller = ( Marshaller<E> ) DefaultMarshaller.INSTANCE;
75 }
76
77
78
79
80
81
82 public byte[] serialize( AvlTree<E> tree )
83 {
84 if ( tree.isEmpty() )
85 {
86 return EMPTY_TREE;
87 }
88
89 LinkedAvlNode<E> x = tree.getFirst().next;
90
91 while ( x != null )
92 {
93 x.setIndex( x.previous.getIndex() + 1 );
94 x = x.next;
95 }
96
97 byte[] data = null;
98
99 try ( ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
100 DataOutputStream out = new DataOutputStream( byteStream ) )
101 {
102 out.writeByte( 0 );
103 out.writeInt( tree.getSize() );
104 writeTree( tree.getRoot(), out );
105 out.flush();
106 data = byteStream.toByteArray();
107 }
108 catch ( IOException e )
109 {
110 e.printStackTrace();
111 }
112
113 return data;
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128 private void writeTree( LinkedAvlNode<E> node, DataOutputStream out ) throws IOException
129 {
130 byte[] data = keyMarshaller.serialize( node.getKey() );
131
132 out.writeInt( data.length );
133 out.write( data );
134 out.writeInt( node.getIndex() );
135
136 if ( node.getLeft() != null )
137 {
138 out.writeInt( 2 );
139 writeTree( node.getLeft(), out );
140 }
141 else
142 {
143 out.writeInt( 0 );
144 }
145
146 if ( node.getRight() != null )
147 {
148 out.writeInt( 4 );
149 writeTree( node.getRight(), out );
150 }
151 else
152 {
153 out.writeInt( 0 );
154 }
155
156 }
157
158
159
160
161
162
163
164 public AvlTree<E> deserialize( byte[] data ) throws IOException
165 {
166 if ( data == null || data.length == 0 )
167 {
168 throw new IOException( I18n.err( I18n.ERR_439 ) );
169 }
170
171 if ( data.length == 1 && data[0] == 0 )
172 {
173 return new AvlTreeImpl<>( comparator );
174 }
175
176 ByteArrayInputStream bin = new ByteArrayInputStream( data );
177 DataInputStream din = new DataInputStream( bin );
178
179 byte startByte = din.readByte();
180
181 if ( startByte != 0 )
182 {
183 throw new IOException( I18n.err( I18n.ERR_443 ) );
184 }
185
186 int size = din.readInt();
187
188 LinkedAvlNodere/avltree/LinkedAvlNode.html#LinkedAvlNode">LinkedAvlNode[] nodes = new LinkedAvlNode[size];
189 LinkedAvlNode<E> root = readTree( din, nodes );
190
191 AvlTreeImpl<E> tree = new AvlTreeImpl<>( comparator );
192
193 tree.setRoot( root );
194
195 tree.setFirst( nodes[0] );
196
197
198 tree.setSize( size );
199
200 if ( nodes.length >= 1 )
201 {
202 tree.setLast( nodes[nodes.length - 1] );
203 }
204
205 for ( int i = 0; i < nodes.length - 1; i++ )
206 {
207 nodes[i].setNext( nodes[i + 1] );
208 nodes[i + 1].setPrevious( nodes[i] );
209 }
210
211 return tree;
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225 public LinkedAvlNode<E> readTree( DataInputStream in, LinkedAvlNode[] nodes )
226 throws IOException
227 {
228 int dLen = in.readInt();
229
230 byte[] data = new byte[dLen];
231
232
233 in.readFully( data );
234
235 E key = keyMarshaller.deserialize( data );
236 LinkedAvlNode<E> node = new LinkedAvlNode<>( key );
237
238 int index = in.readInt();
239 nodes[index] = node;
240
241 int childMarker = in.readInt();
242
243 if ( childMarker == 2 )
244 {
245 node.setLeft( readTree( in, nodes ) );
246 }
247
248 childMarker = in.readInt();
249
250 if ( childMarker == 4 )
251 {
252 node.setRight( readTree( in, nodes ) );
253 }
254
255 return node;
256 }
257 }