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
23 import org.apache.asn1.codec.EncoderException;
24 import org.apache.asn1.codec.stateful.AbstractStatefulEncoder;
25
26
27 /***
28 * A tuple tree visitor that encodes tuples in prefix order into a buffer, and
29 * chunking the buffer via callbacks as it is filled. This encoder will work
30 * on both determinate and indeterminate tuples. However all indeterminate
31 * tuples must be followed in sequence by an indeterminate terminator tuple.
32 *
33 * @todo might eventually want to make this encoder use a buffer pool to get
34 * its chunk buffers rather than having it create its own
35 * @author <a href="mailto:dev@directory.apache.org"> Apache Directory
36 * Project</a> $Rev: 157644 $
37 */
38 public class TupleEncodingVisitor extends AbstractStatefulEncoder
39 implements TupleNodeVisitor
40 {
41 /*** An empty buffer array so we do not recreate every time on toArray */
42 private static final ByteBuffer[] EMPTY_ARRAY = new ByteBuffer[0];
43
44 /*** The List storing the ByteBuffers collected during a visitation */
45 private ArrayList buffers = new ArrayList();
46
47 /*** The visitor monitor used by this TupleNodeVisitor */
48 private VisitorMonitor visitorMonitor = VisitorMonitor.NOOP;
49
50
51
52
53
54
55
56 public void encode( Object obj ) throws EncoderException
57 {
58 if ( obj instanceof DefaultMutableTupleNode )
59 {
60 ( ( DefaultMutableTupleNode ) obj ).accept( this );
61
62 return;
63 }
64
65 throw new IllegalArgumentException( "Expected an argument of type"
66 + " DefaultMutableTupleNode but instead got an instance of "
67 + obj.getClass().getName() );
68 }
69
70
71
72
73
74
75
76 /***
77 * Visits a tree of tuple nodes using a specific visitation order.
78 *
79 * @todo major kludge in this method please see warnings inline
80 * @param node the node to visit
81 */
82 public void visit( TupleNode node )
83 {
84 Tuple tlv = node.getTuple();
85
86 int size = tlv.getTagLength() + tlv.getLengthLength();
87 ByteBuffer buf = ByteBuffer.wrap( new byte[size] );
88 tlv.setTag( buf, tlv.getTagLength() );
89 tlv.setLength( buf, tlv.getLengthLength() );
90 buffers.add( buf.flip() );
91
92
93
94
95
96
97
98
99
100
101
102
103
104 if ( tlv.isPrimitive() )
105 {
106 buffers.add( tlv.getLastValueChunk() );
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120 visitorMonitor.visited( this, node );
121 }
122
123
124 /***
125 * Checks to see if a node can be visited.
126 *
127 * @param node the node to be visited
128 * @return whether or node the node should be visited
129 */
130 public boolean canVisit( TupleNode node )
131 {
132 return true;
133 }
134
135
136 /***
137 * Determines whether the visitation order is prefix or postfix.
138 *
139 * @return true if the visitation is in prefix order, false otherwise.
140 */
141 public boolean isPrefix()
142 {
143 return true;
144 }
145
146
147 /***
148 * Get the array of children to visit sequentially to determine the order of
149 * child visitations. Some children may not be returned at all if
150 * canVisit() returns false on them.
151 *
152 * @param node the parent branch node
153 * @param children the child node array
154 * @return the new reordered array of children
155 */
156 public ArrayList getOrder( TupleNode node, ArrayList children )
157 {
158 return children;
159 }
160
161
162 /***
163 * Flushes out the array of ByteBuffer's collected during the visitation.
164 * This is done by calling encodeOccurred in one shot.
165 */
166 public void flush()
167 {
168 ByteBuffer[] array = ( ByteBuffer [] ) buffers.toArray( EMPTY_ARRAY );
169 buffers.clear();
170 super.encodeOccurred( array );
171 }
172
173
174 public void setMonitor( VisitorMonitor monitor )
175 {
176 visitorMonitor = monitor;
177 }
178 }