1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.asn1.ber ;
18
19
20 import java.nio.ByteBuffer;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.List;
25
26 import org.apache.asn1.codec.binary.Hex;
27 import org.apache.commons.lang.StringUtils;
28
29
30 /***
31 * The default mutable tuple node.
32 *
33 * @author <a href="mailto:dev@directory.apache.org">
34 * Apache Directory Project</a>
35 * @version $Rev: 157644 $
36 */
37 public class DefaultMutableTupleNode implements MutableTupleNode
38 {
39 /*** this node's tuple user object */
40 private Tuple tuple ;
41 /*** a list of this node's children */
42 private ArrayList children = new ArrayList() ;
43 /*** this node's parent node */
44 private DefaultMutableTupleNode parent ;
45 /*** this node's accumulated ByteBuffer value chunks */
46 private List valueChunks = new ArrayList( 2 ) ;
47
48
49 /***
50 * Creates a node without a parent and without a tuple.
51 */
52 public DefaultMutableTupleNode()
53 {
54 }
55
56
57 /***
58 * Creates a node without a parent using a tuple. If the tuple is primitive
59 * and has a non-null last value chunk, that value chunk is added to the
60 * list of value chunks.
61 *
62 * @param tuple the tuple to set for this node
63 */
64 public DefaultMutableTupleNode( Tuple tuple )
65 {
66 this.tuple = tuple ;
67
68 if ( tuple.isPrimitive() && tuple.getLastValueChunk() != null )
69 {
70 valueChunks.add( tuple.getLastValueChunk() );
71 }
72 }
73
74
75 /***
76 * Creates a node without a parent.
77 *
78 * @param tuple the tuple to set for this node
79 */
80 public DefaultMutableTupleNode( Tuple tuple, List valueChunks )
81 {
82 this.tuple = tuple ;
83 this.valueChunks.addAll( valueChunks ) ;
84 }
85
86
87
88
89
90
91 public void insert( MutableTupleNode child, int index )
92 {
93 children.add( index, child ) ;
94 }
95
96
97 /***
98 * Adds a child node to the front of the child list.
99 *
100 * @param child the child to add to the front
101 */
102 public void addFront( DefaultMutableTupleNode child )
103 {
104 if ( children.isEmpty() )
105 {
106 children.add( child ) ;
107 }
108 else
109 {
110 children.add( 0, child ) ;
111 }
112 }
113
114
115 /***
116 * Adds a child node to the end of the child list.
117 *
118 * @param child the child to add to the end
119 */
120 public void addLast( DefaultMutableTupleNode child )
121 {
122 children.add( child ) ;
123 }
124
125
126
127
128
129 public void remove( int index )
130 {
131 children.remove( index ) ;
132 }
133
134
135
136
137
138
139 public void remove( MutableTupleNode node )
140 {
141 children.remove( node ) ;
142 }
143
144
145
146
147
148 public void removeFromParent()
149 {
150 parent.remove( this ) ;
151 parent = null ;
152 }
153
154
155
156
157
158
159 public void setParent( MutableTupleNode newParent )
160 {
161 if ( parent != null )
162 {
163 parent.remove( this ) ;
164 }
165
166 parent = ( DefaultMutableTupleNode ) newParent ;
167 }
168
169
170
171
172
173 public TupleNode getParentTupleNode()
174 {
175 return parent ;
176 }
177
178
179
180
181
182 public Iterator getChildren()
183 {
184 return Collections.unmodifiableList( children ).iterator() ;
185 }
186
187
188
189
190
191 public TupleNode getChildTupleNodeAt( int index )
192 {
193 return ( TupleNode ) children.get( index ) ;
194 }
195
196
197
198
199
200
201 public int getIndex( TupleNode node )
202 {
203 return children.indexOf( node ) ;
204 }
205
206
207
208
209
210 public int getChildCount()
211 {
212 return children.size() ;
213 }
214
215
216
217
218
219 public int size()
220 {
221 if ( tuple.isPrimitive() )
222 {
223 return tuple.size() ;
224 }
225 else
226 {
227 int size = tuple.size() ;
228
229 if ( tuple.isIndefinite() )
230 {
231 TupleNode child = null ;
232 for ( int ii = 0; ii < children.size(); ii++ )
233 {
234 child = ( TupleNode ) children.get( ii ) ;
235 size += child.size() ;
236 }
237
238 if ( child != null )
239 {
240 if ( ! child.getTuple().isIndefiniteTerminator() )
241 {
242 size += 2 ;
243 }
244 }
245 else
246 {
247 size += 2 ;
248 }
249 }
250
251 return size ;
252 }
253 }
254
255
256
257
258
259 public Tuple getTuple()
260 {
261 return tuple ;
262 }
263
264
265
266
267
268
269 public void setTuple( Tuple t )
270 {
271 tuple = t ;
272 valueChunks.clear() ;
273 }
274
275
276
277
278
279
280
281 public void setTuple( Tuple t, List valueChunks )
282 {
283 tuple = t ;
284 this.valueChunks.clear() ;
285 this.valueChunks.addAll( valueChunks ) ;
286 }
287
288
289
290
291
292
293 public List getValueChunks()
294 {
295 return valueChunks ;
296 }
297
298
299
300
301
302
303
304 public void addValueChunk( ByteBuffer valueChunk )
305 {
306 valueChunks.add( valueChunk ) ;
307 }
308
309
310 /***
311 * Depth first generation of this tlv tuple node's encoded image.
312 *
313 * @see org.apache.asn1.ber.TupleNode#encode(ByteBuffer)
314 */
315 public void encode( ByteBuffer dest )
316 {
317 dest.put( tuple.toEncodedBuffer( this.valueChunks ) ) ;
318
319 if ( tuple.isPrimitive() )
320 {
321 return ;
322 }
323
324 TupleNode child = null ;
325 for ( int ii = 0; ii < children.size(); ii++ )
326 {
327 child = ( TupleNode ) children.get( ii ) ;
328 child.encode( dest ) ;
329 }
330
331 if ( child != null )
332 {
333 Tuple childTuple = child.getTuple() ;
334 if ( childTuple.isIndefiniteTerminator() )
335 {
336 return ;
337 }
338 }
339
340 if ( tuple.isIndefinite() )
341 {
342
343 dest.put( ( byte ) 0 ) ;
344 dest.put( ( byte ) 0 ) ;
345 }
346 }
347
348
349
350
351
352
353
354
355 public String toString()
356 {
357 StringBuffer buf = new StringBuffer() ;
358 buf.append( tuple.getId() ) ;
359 buf.append( ' ' ).append( tuple.typeClass ) ;
360 buf.append( '[' ).append( tuple.length ).append( ']' ) ;
361 buf.append( '[' ).append( new String( tuple.getLastValueChunk().array() ) ) ;
362 buf.append( ']' ) ;
363
364 return buf.toString() ;
365 }
366
367
368 /***
369 * Generates a depth first traversal of this node.
370 *
371 * @return a depth first traversal print out for this node
372 */
373 public String toDepthFirstString()
374 {
375 StringBuffer buf = new StringBuffer() ;
376 printDepthFirst( buf, 0 ) ;
377 return buf.toString() ;
378 }
379
380
381 /***
382 * Gets the hex encoding of an integer with the most significant
383 * bites first.
384 *
385 * @param val the integer to break up into 4 bytes and hex encode
386 * @return the hex encoded 4 bytes of an integer
387 */
388 private String getHex( int val )
389 {
390 byte[] bites = new byte[4] ;
391
392 bites[0] = (byte) ( ( val & 0xff000000 ) >> 24 ) ;
393 bites[1] = (byte) ( ( val & 0x00ff0000 ) >> 16 ) ;
394 bites[2] = (byte) ( ( val & 0x0000ff00 ) >> 8 ) ;
395 bites[3] = (byte) ( val & 0x000000ff ) ;
396
397 return new String( Hex.encodeHex( bites ) ) ;
398 }
399
400
401 /***
402 * Generates a depth first traversal of this node.
403 *
404 * @param buf the buffer to capture the traversal into
405 * @param level the level down into the tree
406 */
407 public void printDepthFirst( StringBuffer buf, int level )
408 {
409 DefaultMutableTupleNode child = null ;
410 String levelTab = StringUtils.repeat( "\t", level ) ;
411
412 if ( level != 0 )
413 {
414 buf.append( "\n" ) ;
415 }
416
417 buf.append( levelTab ).append( tuple.getId() ) ;
418 buf.append( " [" ).append( "0x" ) ;
419 buf.append( getHex( tuple.getRawPrimitiveTag() ) ) ;
420 buf.append( ']' ) ;
421 buf.append( '[' ).append( tuple.length ).append( ']' ) ;
422 for ( int ii = 0; ii < children.size(); ii++ )
423 {
424 child = ( DefaultMutableTupleNode ) children.get( ii ) ;
425 child.printDepthFirst( buf, level + 1 ) ;
426 }
427 }
428
429
430
431
432
433
434
435 /***
436 * Checks to see if this node and its children equal another exactly.
437 *
438 * @see java.lang.Object#equals(java.lang.Object)
439 */
440 public boolean equals( Object obj )
441 {
442 if ( obj instanceof DefaultMutableTupleNode )
443 {
444 return equals( this, ( DefaultMutableTupleNode ) obj ) ;
445 }
446
447 return false ;
448 }
449
450
451 /***
452 * Checks to see if two nodes equal one another. The nodes must be exactly
453 * the same even in terms of the order of their children and the children
454 * of their descendants.
455 *
456 * @param n1 the first node
457 * @param n2 the second node
458 * @return true if <code>n1.equals(n2)</code> exactly otherwise false
459 */
460 public static boolean equals( DefaultMutableTupleNode n1,
461 DefaultMutableTupleNode n2 )
462 {
463 if ( n1 == n2 )
464 {
465 return true ;
466 }
467
468 if ( ! n1.getTuple().equals( n2.getTuple() ) )
469 {
470 return false ;
471 }
472
473 if ( n1.getChildCount() != n2.getChildCount() )
474 {
475 return false ;
476 }
477
478 DefaultMutableTupleNode n1Child = null ;
479 DefaultMutableTupleNode n2Child = null ;
480 for ( int ii = 0; ii < n1.getChildCount() ; ii++ )
481 {
482 n1Child = ( DefaultMutableTupleNode )
483 n1.getChildTupleNodeAt( ii ) ;
484 n2Child = ( DefaultMutableTupleNode )
485 n2.getChildTupleNodeAt( ii ) ;
486
487 if ( ! equals( n1Child, n2Child ) )
488 {
489 return false ;
490 }
491 }
492
493 return true ;
494 }
495
496
497 /***
498 * Recursively descends the tree at this node based on the order of the
499 * visitor.
500 *
501 * @see TupleNode#accept(TupleNodeVisitor)
502 */
503 public void accept( TupleNodeVisitor visitor )
504 {
505 if ( visitor.canVisit( this ) )
506 {
507 if ( visitor.isPrefix() )
508 {
509 ArrayList l_children = visitor.getOrder( this, children ) ;
510
511 if ( visitor.canVisit( this ) )
512 {
513 visitor.visit( this ) ;
514 }
515
516 for ( int ii = 0; ii < l_children.size(); ii++ )
517 {
518 ( ( TupleNode ) l_children.get( ii ) ).accept( visitor ) ;
519 }
520 }
521 else
522 {
523 ArrayList l_children = visitor.getOrder( this, children ) ;
524
525 for ( int ii = 0; ii < l_children.size(); ii++ )
526 {
527 ( ( TupleNode ) l_children.get( ii ) ).accept( visitor ) ;
528 }
529
530 if ( visitor.canVisit( this ) )
531 {
532 visitor.visit( this ) ;
533 }
534 }
535 }
536 }
537 }