View Javadoc

1   /*
2    *   Copyright 2004-2005 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
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      /* (non-Javadoc)
88       * @see org.apache.asn1.ber.MutableTupleNode#insert(
89       * org.apache.asn1.ber.MutableTupleNode, int)
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     /* (non-Javadoc)
127      * @see org.apache.asn1.ber.MutableTupleNode#remove(int)
128      */
129     public void remove( int index )
130     {
131         children.remove( index ) ;
132     }
133 
134 
135     /* (non-Javadoc)
136      * @see org.apache.asn1.ber.MutableTupleNode#remove(
137      * org.apache.asn1.ber.MutableTupleNode)
138      */
139     public void remove( MutableTupleNode node )
140     {
141         children.remove( node ) ;
142     }
143 
144 
145     /* (non-Javadoc)
146      * @see org.apache.asn1.ber.MutableTupleNode#removeFromParent()
147      */
148     public void removeFromParent()
149     {
150         parent.remove( this ) ;
151         parent = null ;
152     }
153 
154 
155     /* (non-Javadoc)
156      * @see org.apache.asn1.ber.MutableTupleNode#setParent(
157      * org.apache.asn1.ber.MutableTupleNode)
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     /* (non-Javadoc)
171      * @see org.apache.asn1.ber.TupleNode#getParent()
172      */
173     public TupleNode getParentTupleNode()
174     {
175         return parent ;
176     }
177 
178 
179     /* (non-Javadoc)
180      * @see org.apache.asn1.ber.TupleNode#children()
181      */
182     public Iterator getChildren()
183     {
184         return Collections.unmodifiableList( children ).iterator() ;
185     }
186 
187 
188     /* (non-Javadoc)
189      * @see org.apache.asn1.ber.TupleNode#getChildAt()
190      */
191     public TupleNode getChildTupleNodeAt( int index )
192     {
193         return ( TupleNode ) children.get( index ) ;
194     }
195 
196 
197     /* (non-Javadoc)
198      * @see org.apache.asn1.ber.TupleNode#getIndex(
199      * org.apache.asn1.ber.TupleNode)
200      */
201     public int getIndex( TupleNode node )
202     {
203         return children.indexOf( node ) ;
204     }
205 
206 
207     /* (non-Javadoc)
208      * @see org.apache.asn1.ber.TupleNode#getChildCount()
209      */
210     public int getChildCount()
211     {
212         return children.size() ;
213     }
214 
215 
216     /* (non-Javadoc)
217      * @see org.apache.asn1.ber.TupleNode#size()
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     /* (non-Javadoc)
257      * @see org.apache.asn1.ber.TupleNode#getTuple()
258      */
259     public Tuple getTuple()
260     {
261         return tuple ;
262     }
263 
264 
265     /* (non-Javadoc)
266      * @see org.apache.asn1.ber.MutableTupleNode#setTuple(
267      * org.apache.asn1.ber.Tuple)
268      */
269     public void setTuple( Tuple t )
270     {
271         tuple = t ;
272         valueChunks.clear() ;
273     }
274 
275 
276     /*
277      * (non-Javadoc)
278      * @see org.apache.asn1.ber.MutableTupleNode#setTuple(
279      * org.apache.asn1.ber.Tuple, java.util.List)
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      * (non-Javadoc)
291      * @see org.apache.asn1.ber.TupleNode#getValueChunks()
292      */
293     public List getValueChunks()
294     {
295         return valueChunks ;
296     }
297 
298 
299     /*
300      * (non-Javadoc)
301      * @see org.apache.asn1.ber.MutableTupleNode#addValueChunk(
302      * java.nio.ByteBuffer)
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             // lay down the termination
343             dest.put( ( byte ) 0 ) ;
344             dest.put( ( byte ) 0 ) ;
345         }
346     }
347 
348 
349     /*
350      * Prinsts some informative information regarding the tlv node.
351      *
352      * (non-Javadoc)
353      * @see java.lang.Object#toString()
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     // java.lang.Object overrides & overloads
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 }