1 |
| package org.drools.reteoo; |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| |
18 |
| |
19 |
| |
20 |
| |
21 |
| |
22 |
| |
23 |
| |
24 |
| |
25 |
| |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| |
38 |
| |
39 |
| |
40 |
| |
41 |
| |
42 |
| |
43 |
| import java.io.BufferedReader; |
44 |
| import java.io.ByteArrayInputStream; |
45 |
| import java.io.IOException; |
46 |
| import java.io.InputStreamReader; |
47 |
| import java.io.PrintStream; |
48 |
| import java.util.HashSet; |
49 |
| import java.util.Iterator; |
50 |
| import java.util.Set; |
51 |
| |
52 |
| import org.drools.rule.Declaration; |
53 |
| |
54 |
| |
55 |
| |
56 |
| |
57 |
| |
58 |
| |
59 |
| |
60 |
| |
61 |
| |
62 |
| public class ReteooDotDumpVisitor extends ReflectiveVisitor |
63 |
| { |
64 |
| |
65 |
| private static final String NULL_STRING = "<NULL>"; |
66 |
| |
67 |
| |
68 |
| private static final String INDENT = " "; |
69 |
| |
70 |
| |
71 |
| private final PrintStream out; |
72 |
| |
73 |
| |
74 |
| |
75 |
| |
76 |
| |
77 |
| |
78 |
| |
79 |
| private Set visitedNodes = new HashSet( ); |
80 |
| |
81 |
| |
82 |
| private int nullDotId; |
83 |
| |
84 |
| |
85 |
| |
86 |
| |
87 |
0
| public ReteooDotDumpVisitor(PrintStream outPrintStream)
|
88 |
| { |
89 |
0
| out = outPrintStream;
|
90 |
| } |
91 |
| |
92 |
| |
93 |
| |
94 |
| |
95 |
0
| public void visitObject(Object object)
|
96 |
| { |
97 |
0
| makeNode( object,
|
98 |
| "Unknown Object", |
99 |
| "object: " + object + newline + "class: " + object.getClass( ) ); |
100 |
| } |
101 |
| |
102 |
| |
103 |
| |
104 |
| |
105 |
| |
106 |
0
| public void visitNull()
|
107 |
| { |
108 |
0
| makeNode( "NULL" + nullDotId++,
|
109 |
| NULL_STRING ); |
110 |
| } |
111 |
| |
112 |
| |
113 |
| |
114 |
| |
115 |
0
| public void visitRuleBaseImpl(RuleBaseImpl ruleBase)
|
116 |
| { |
117 |
0
| visit( ruleBase.getRete( ) );
|
118 |
| } |
119 |
| |
120 |
| |
121 |
| |
122 |
| |
123 |
0
| public void visitRete(Rete rete)
|
124 |
| { |
125 |
0
| makeNode( rete,
|
126 |
| "RETE-OO" ); |
127 |
0
| for ( Iterator i = rete.getObjectTypeNodeIterator( ); i.hasNext( ); )
|
128 |
| { |
129 |
0
| Object nextNode = i.next( );
|
130 |
0
| makeEdge( rete,
|
131 |
| nextNode ); |
132 |
0
| visitNode( nextNode );
|
133 |
| } |
134 |
| } |
135 |
| |
136 |
| |
137 |
| |
138 |
| |
139 |
| |
140 |
0
| public void visitObjectTypeNode(ObjectTypeNode node)
|
141 |
| { |
142 |
0
| makeNode( node,
|
143 |
| "ObjectTypeNode", |
144 |
| "objectType: " + node.getObjectType( ) ); |
145 |
0
| for ( Iterator i = node.getParameterNodeIterator( ); i.hasNext( ); )
|
146 |
| { |
147 |
0
| Object nextNode = i.next( );
|
148 |
0
| makeEdge( node,
|
149 |
| nextNode ); |
150 |
0
| visitNode( nextNode );
|
151 |
| } |
152 |
| } |
153 |
| |
154 |
| |
155 |
| |
156 |
| |
157 |
0
| public void visitParameterNode(ParameterNode node)
|
158 |
| { |
159 |
0
| makeTupleSourceNode( node, "ParameterNode", "TupleSource", "decl: " + format( node.getDeclaration( ) ) );
|
160 |
| } |
161 |
| |
162 |
0
| private void makeTupleSourceNode( TupleSource node, String nodeType, String tupleType, String label )
|
163 |
| { |
164 |
0
| makeNode( node,
|
165 |
| nodeType, |
166 |
| tupleType, |
167 |
| label ); |
168 |
0
| for ( Iterator i = node.getTupleSinks( ).iterator(); i.hasNext(); )
|
169 |
| { |
170 |
0
| Object nextNode = i.next();
|
171 |
0
| makeEdge( node,
|
172 |
| nextNode ); |
173 |
0
| visitNode( nextNode );
|
174 |
| } |
175 |
| } |
176 |
| |
177 |
| |
178 |
| |
179 |
| |
180 |
| |
181 |
0
| public void visitConditionNode(ConditionNode node)
|
182 |
| { |
183 |
0
| makeTupleSourceNode( node,
|
184 |
| "ConditionNode", |
185 |
| "TupleSource/TupleSink", |
186 |
| "condition: " + node.getCondition( ) + newline + format( node.getTupleDeclarations( ), |
187 |
| "tuple" ) ); |
188 |
| } |
189 |
| |
190 |
| |
191 |
| |
192 |
| |
193 |
| |
194 |
0
| public void visitJoinNodeInput(JoinNodeInput node)
|
195 |
| { |
196 |
0
| makeNode( node,
|
197 |
| "JoinNodeInput", |
198 |
| "TupleSink", |
199 |
0
| node.getSide( ) == JoinNodeInput.LEFT ? "LEFT" : "RIGHT" );
|
200 |
0
| Object nextNode = node.getJoinNode( );
|
201 |
0
| makeEdge( node,
|
202 |
| nextNode ); |
203 |
0
| visitNode( nextNode );
|
204 |
| } |
205 |
| |
206 |
| |
207 |
| |
208 |
| |
209 |
| |
210 |
0
| public void visitJoinNode(JoinNode node)
|
211 |
| { |
212 |
0
| makeTupleSourceNode( node,
|
213 |
| "JoinNode", |
214 |
| "TupleSource", |
215 |
| format( node.getCommonDeclarations( ), |
216 |
| "common" ) + newline + format( node.getTupleDeclarations( ), |
217 |
| "tuple" ) ); |
218 |
| } |
219 |
| |
220 |
| |
221 |
| |
222 |
| |
223 |
0
| public void visitTerminalNode(TerminalNode node)
|
224 |
| { |
225 |
0
| makeNode( node,
|
226 |
| "TerminalNode", |
227 |
| "TupleSink", |
228 |
| "rule: " + node.getRule( ).getName( ) ); |
229 |
| } |
230 |
| |
231 |
| |
232 |
| |
233 |
| |
234 |
0
| private void visitNode(Object node)
|
235 |
| { |
236 |
0
| if ( !visitedNodes.contains( dotId( node ) ) )
|
237 |
| { |
238 |
0
| visitedNodes.add( dotId( node ) );
|
239 |
0
| visit( node );
|
240 |
| } |
241 |
| } |
242 |
| |
243 |
| |
244 |
| |
245 |
| |
246 |
0
| private void makeNode(Object object,
|
247 |
| String type, |
248 |
| String label) |
249 |
| { |
250 |
0
| makeNode( object,
|
251 |
| type, |
252 |
| null, |
253 |
| label ); |
254 |
| } |
255 |
| |
256 |
| |
257 |
| |
258 |
| |
259 |
0
| private void makeNode(Object object,
|
260 |
| String nodeType, |
261 |
| String tupleType, |
262 |
| String label) |
263 |
| { |
264 |
0
| makeNode( object,
|
265 |
0
| nodeType + "@" + dotId( object ) + newline + (null == tupleType ? "" : "(" + tupleType + ")" + newline ) + label );
|
266 |
| } |
267 |
| |
268 |
| |
269 |
| |
270 |
| |
271 |
0
| private void makeNode(Object object,
|
272 |
| String label) |
273 |
| { |
274 |
0
| out.println( INDENT + "\"" + dotId( object ) + "\" " +
|
275 |
| "[" + getStyle( object ) + ", label=\"" + format( label ) + "\"];" ); |
276 |
| } |
277 |
| |
278 |
| |
279 |
| |
280 |
| |
281 |
0
| private void makeEdge(Object fromNode,
|
282 |
| Object toNode) |
283 |
| { |
284 |
0
| out.println( INDENT + "\"" + dotId( fromNode ) + "\" -> \"" + dotId( toNode ) + "\";" );
|
285 |
| } |
286 |
| |
287 |
| |
288 |
| |
289 |
| |
290 |
| |
291 |
0
| private static String dotId(Object object)
|
292 |
| { |
293 |
0
| return Integer.toHexString( System.identityHashCode( object ) ).toUpperCase( );
|
294 |
| } |
295 |
| |
296 |
| |
297 |
| |
298 |
| |
299 |
0
| private String format(Set declarationSet,
|
300 |
| String declString) |
301 |
| { |
302 |
0
| if ( declarationSet.isEmpty( ) )
|
303 |
| { |
304 |
0
| return "No " + declString + " declarations";
|
305 |
| } |
306 |
| |
307 |
0
| Declaration[] declarations = (Declaration[]) declarationSet.toArray( new Declaration[]{} );
|
308 |
| |
309 |
0
| StringBuffer label = new StringBuffer( );
|
310 |
0
| int i = 0;
|
311 |
0
| for ( int max = declarations.length - 1; i < max; i++ )
|
312 |
| { |
313 |
0
| label.append( declString + "Decl: " + format( declarations[i] ) + newline );
|
314 |
| } |
315 |
0
| label.append( declString + "Decl: " + format( declarations[i] ) );
|
316 |
| |
317 |
0
| return label.toString( );
|
318 |
| } |
319 |
| |
320 |
| |
321 |
| |
322 |
| |
323 |
0
| private static String format(Declaration declaration)
|
324 |
| { |
325 |
0
| return null == declaration ? NULL_STRING : declaration.getIdentifier( ) + " (" + declaration.getObjectType( ) + ")";
|
326 |
| } |
327 |
| |
328 |
| |
329 |
| |
330 |
| |
331 |
| |
332 |
| |
333 |
0
| private static String format(String label)
|
334 |
| { |
335 |
0
| if ( null == label )
|
336 |
| { |
337 |
0
| return NULL_STRING;
|
338 |
| } |
339 |
| |
340 |
0
| BufferedReader br = new BufferedReader( new InputStreamReader( new ByteArrayInputStream( label.getBytes( ) ) ) );
|
341 |
| |
342 |
0
| StringBuffer buffer = new StringBuffer( );
|
343 |
0
| try
|
344 |
| { |
345 |
0
| boolean firstLine = true;
|
346 |
0
| for ( String line = br.readLine( ); null != line; line = br.readLine( ) )
|
347 |
| { |
348 |
0
| if ( line.trim( ).length( ) == 0 )
|
349 |
| { |
350 |
0
| continue;
|
351 |
| } |
352 |
0
| if ( firstLine )
|
353 |
| { |
354 |
0
| firstLine = false;
|
355 |
| } |
356 |
| else |
357 |
| { |
358 |
0
| buffer.append( "\\n" );
|
359 |
| } |
360 |
| |
361 |
0
| if ( -1 == line.indexOf( '"' ) )
|
362 |
| { |
363 |
0
| buffer.append( line );
|
364 |
| } |
365 |
| else |
366 |
| { |
367 |
0
| for ( int i = 0, max = line.length( ); i < max; ++i )
|
368 |
| { |
369 |
0
| char c = line.charAt( i );
|
370 |
0
| if ( '"' == c )
|
371 |
| { |
372 |
0
| buffer.append( '\\' + c );
|
373 |
| } |
374 |
| else |
375 |
| { |
376 |
0
| buffer.append( c );
|
377 |
| } |
378 |
| } |
379 |
| } |
380 |
| } |
381 |
| } |
382 |
| catch ( IOException e ) |
383 |
| { |
384 |
0
| throw new RuntimeException( "Error formatting '" + label + "': " + e.getMessage( ) );
|
385 |
| } |
386 |
| |
387 |
0
| return buffer.toString( );
|
388 |
| } |
389 |
| |
390 |
| |
391 |
| |
392 |
| |
393 |
| |
394 |
| |
395 |
| |
396 |
| |
397 |
0
| private String getStyle( Object node )
|
398 |
| { |
399 |
0
| String style;
|
400 |
| |
401 |
0
| if ( node instanceof Rete )
|
402 |
| { |
403 |
| |
404 |
| |
405 |
0
| style = "style=\"filled\", shape=\"ellipse\"";
|
406 |
| } |
407 |
0
| else if ( node instanceof ObjectTypeNode )
|
408 |
| { |
409 |
0
| style = "style=\"filled\", fillcolor=\"cyan4\", shape=\"rectangle\"";
|
410 |
| } |
411 |
0
| else if ( node instanceof ParameterNode )
|
412 |
| { |
413 |
0
| style = "style=\"filled\", fillcolor=\"cyan3\", shape=\"rectangle\"";
|
414 |
| } |
415 |
0
| else if ( node instanceof ConditionNode )
|
416 |
| { |
417 |
0
| style = "style=\"filled\", fillcolor=\"yellow3\", shape=\"diamond\"";
|
418 |
| } |
419 |
0
| else if ( node instanceof JoinNodeInput )
|
420 |
| { |
421 |
0
| style = "style=\"filled\", fillcolor=\"chartreuse\", shape=\"invtriangle\"";
|
422 |
| } |
423 |
0
| else if ( node instanceof JoinNode )
|
424 |
| { |
425 |
0
| style = "style=\"filled\", fillcolor=\"green\", shape=\"house\"";
|
426 |
| } |
427 |
0
| else if ( node instanceof TerminalNode )
|
428 |
| { |
429 |
| |
430 |
| |
431 |
0
| style = "style=\"filled\", shape=\"ellipse\"";
|
432 |
| } |
433 |
| else |
434 |
| { |
435 |
| |
436 |
| |
437 |
0
| style = "style=\"filled\", fillcolor=\"yellow3\", shape=\"ellipse\"";
|
438 |
| } |
439 |
| |
440 |
0
| return style;
|
441 |
| } |
442 |
| } |