All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.rules.tools.reteviewer.RetePanel Maven / Gradle / Ivy

There is a newer version: 4.0.267
Show newest version
package jadex.rules.tools.reteviewer;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ConstantTransformer;

import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.GraphMouseListener;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import jadex.commons.ChangeEvent;
import jadex.commons.IBreakpointPanel;
import jadex.commons.IChangeListener;
import jadex.commons.ICommand;
import jadex.commons.ISteppable;
import jadex.rules.rulesystem.Activation;
import jadex.rules.rulesystem.IAgendaListener;
import jadex.rules.rulesystem.IRule;
import jadex.rules.rulesystem.RuleSystem;
import jadex.rules.rulesystem.rete.RetePatternMatcherFunctionality;
import jadex.rules.rulesystem.rete.RetePatternMatcherState;
import jadex.rules.rulesystem.rete.nodes.AlphaNode;
import jadex.rules.rulesystem.rete.nodes.BetaNode;
import jadex.rules.rulesystem.rete.nodes.INode;
import jadex.rules.rulesystem.rete.nodes.IObjectConsumerNode;
import jadex.rules.rulesystem.rete.nodes.IObjectSourceNode;
import jadex.rules.rulesystem.rete.nodes.ITupleConsumerNode;
import jadex.rules.rulesystem.rete.nodes.ITupleSourceNode;
import jadex.rules.rulesystem.rete.nodes.InitialFactNode;
import jadex.rules.rulesystem.rete.nodes.LeftInputAdapterNode;
import jadex.rules.rulesystem.rete.nodes.NotNode;
import jadex.rules.rulesystem.rete.nodes.ReteMemory;
import jadex.rules.rulesystem.rete.nodes.ReteNode;
import jadex.rules.rulesystem.rete.nodes.RightInputAdapterNode;
import jadex.rules.rulesystem.rete.nodes.SplitNode;
import jadex.rules.rulesystem.rete.nodes.TerminalNode;
import jadex.rules.rulesystem.rete.nodes.TestNode;
import jadex.rules.rulesystem.rete.nodes.TypeNode;


/**
 *  Can be used to visualize a rete network.
 */
public class RetePanel extends JPanel
{
	//-------- constants --------

	/** The name of the node details panel. */
	public static final String	NODE_DETAILS_NAME	= "Node Details";
	
	/** The name of the agenda panel. */
	public static final String	AGENDA_NAME	= "Agenda";
	
	//-------- attributes --------
	
	/** Flag if node text should be shown. */
	protected boolean showtxt;
	
	/** The rulebase panel. */
	protected IBreakpointPanel rulebasepanel;

	/** The agenda panel. */
	protected AgendaPanel ap;

	/** The info panels on the right hand side. */
	protected JTabbedPane infopanels;
	
	/** The currently removed nodes and edges. */
	protected List	remnodes;
	protected List	remedges;
	
	/** The graph. */
	protected DirectedSparseGraph g;
	
	/** The viewer. */
	protected VisualizationViewer vv;
	
	/** The layout. */
	protected ReteLayout	layout;
	
	/** The agenda listener. */
	protected IAgendaListener	agendalistener;
	
	/** The rule system. */
	protected RuleSystem	system;
	
	//-------- constructors --------
	
	/**
	 *  Create a new rete panel.
	 *  Set steppable to null for panel without breakpoints and step mode.
	 */
	public RetePanel(final RuleSystem system, final ISteppable steppable, final IBreakpointPanel rulebasepanel)
	{
		this.rulebasepanel = rulebasepanel;
		this.infopanels = new JTabbedPane();
		this.system	= system;
		
		final ReteNode root = ((RetePatternMatcherFunctionality)system.getMatcherFunctionality()).getReteNode();
		final ReteMemory mem = ((RetePatternMatcherState)system.getMatcherState()).getReteMemory();
		this.g = new DirectedSparseGraph();
		buildGraph(g, root);
		hideMarkedNodes(Collections.EMPTY_SET);
		
		final NodePanel np = new NodePanel(null, mem, system.getState());
		
		this.layout = new ReteLayout(g);
		this.vv =  new VisualizationViewer(layout, new Dimension(600,600));
		vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
		vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
		vv.getRenderContext().setVertexLabelTransformer(new Transformer()
		{
			public Object transform(Object arg0)
			{
				return showtxt? arg0.toString(): null;
			}
		});
		vv.getRenderContext().setVertexStrokeTransformer(new Transformer()
		{
			public Object transform(Object node)
			{
				Collection	coll	= ((INode)node).getNodeMemory(mem);
				return (coll==null || coll.isEmpty())
					? new BasicStroke(1) : new BasicStroke(2);
			}
		});
		vv.getRenderContext().setVertexFillPaintTransformer(new Transformer()
		{
			public Object transform(Object node)
			{
				Color	fg;
				if(node instanceof ReteNode)
					fg	= Color.WHITE;
				else if(node instanceof TypeNode)
					fg	= Color.PINK;
				else if(node instanceof AlphaNode)
					fg	= Color.RED;
				else if(node instanceof LeftInputAdapterNode)
					fg	= Color.ORANGE;
				else if(node instanceof RightInputAdapterNode)
					fg	= Color.ORANGE;
				else if(node instanceof NotNode)
					fg	= Color.YELLOW;
				else if(node instanceof BetaNode)
					fg	= Color.GREEN;
				else if(node instanceof SplitNode)
					fg	= Color.MAGENTA;
				else if(node instanceof TerminalNode)
					fg	= Color.CYAN;
				else if(node instanceof TestNode)
					fg	= new Color(0, 255, 100);
				else if(node instanceof InitialFactNode)
					fg	= new Color(255, 100, 0);
				else
					fg	= Color.GRAY;
				
				return fg;
//				Collection	coll	= ((INode)node).getNodeMemory(mem);
//				return (coll==null || coll.isEmpty())
//					? fg : new LinearGradientPaint(0,0, 5,5, new float[]{0.8f, 1f}, new Color[]{fg,Color.BLACK});
			}
		});
		vv.getRenderContext().setEdgeDrawPaintTransformer(new Transformer()
		{
			public Object transform(Object edge)
			{
				if(edge instanceof ReteEdge)
				{
					if(((ReteEdge)edge).isTuple())
					{
						return Color.GREEN;
					}
					else
					{
						return Color.RED;
					}
				}
				else
				{
					return Color.GRAY;
				}
			}
		});
		vv.setVertexToolTipTransformer(new ToStringLabeller());
		vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
		
		DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
		gm.setMode(ModalGraphMouse.Mode.PICKING);
		vv.setGraphMouse(gm);
		
		vv.addGraphMouseListener(new GraphMouseListener()
		{
			public void graphClicked(Object arg0, MouseEvent arg1)
			{
				//System.out.println("clicked: "+arg0+" "+arg1);
				if(arg0 instanceof INode)
				{
					np.setNode((INode)arg0);
					infopanels.setSelectedComponent(getInfoPanel(NODE_DETAILS_NAME));
				}
			}

			public void graphPressed(Object arg0, MouseEvent arg1)
			{
//				System.out.println("pressed: "+arg0+" "+arg1);
			}

			public void graphReleased(Object arg0, MouseEvent arg1)
			{
//				System.out.println("released: "+arg0+" "+arg1);
			}
		});
		
		final JButton hidenodes = new JButton("Show Subgraph");
		hidenodes.setMargin(new Insets(2,4,2,4));
		hidenodes.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				Set subgraph	= new HashSet(vv.getPickedVertexState().getPicked());
				hideMarkedNodes(subgraph);
				layout.graphChanged();
				vv.repaint();
			}
		});
 
		/*final JButton showdesc = new JButton("Show text");
		showdesc.setMargin(new Insets(0,0,0,0));
		showdesc.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				showtxt = !showtxt;
				vv.repaint();
				showdesc.setText(showtxt? "Hide text": "Show text");
			}
		});*/
		
		JButton refresh = new JButton("Refresh");
//		refresh.setMargin(new Insets(0,0,0,0));
		refresh.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				np.refresh();
				vv.repaint();
			}
		});
		
//		JButton remrule = new JButton("Remove rule");
//		remrule.setMargin(new Insets(0,0,0,0));
		/*remrule.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				Set subgraph	= new HashSet(vv.getPickedVertexState().getPicked());
				if(subgraph.isEmpty())
				{
					System.out.println("Please select a terminal node(s) first.");
				}
				else
				{
					for(Iterator it=subgraph.iterator(); it.hasNext(); )
					{
						INode node = (INode)it.next();
						if(node instanceof TerminalNode)
						{
							TerminalNode tn = (TerminalNode)node;
							root.removeRule(tn.getRule());
							buildGraph(g, root);
						}
					}
					vv.repaint();
				}
			}
		});*/
		
		int mw = (int)hidenodes.getMinimumSize().getWidth();
		int pw = (int)hidenodes.getPreferredSize().getWidth();
		int mh = (int)hidenodes.getMinimumSize().getHeight();
		int ph = (int)hidenodes.getPreferredSize().getHeight();
		hidenodes.setMinimumSize(new Dimension(mw, mh));
		hidenodes.setPreferredSize(new Dimension(pw, ph));
//		showdesc.setMinimumSize(new Dimension(mw, mh));
//		showdesc.setPreferredSize(new Dimension(pw, ph));
		refresh.setMinimumSize(new Dimension(mw, mh));
		refresh.setPreferredSize(new Dimension(pw, ph));
//		remrule.setMinimumSize(new Dimension(mw, mh));
//		remrule.setPreferredSize(new Dimension(pw, ph));
		
		JPanel buts = new JPanel(new GridBagLayout());
//		buts.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(
//			BevelBorder.LOWERED), "Node Settings"));
		buts.add(hidenodes, new GridBagConstraints(0,0,1,1,1,0,GridBagConstraints.EAST,
			GridBagConstraints.NONE,new Insets(2,4,4,2),0,0));
//		buts.add(showdesc, new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.EAST,
//			GridBagConstraints.NONE,new Insets(2,4,4,2),0,0));
		buts.add(refresh, new GridBagConstraints(0,1,1,1,1,0,GridBagConstraints.EAST,
			GridBagConstraints.NONE,new Insets(2,4,4,2),0,0));
//		buts.add(remrule, new GridBagConstraints(0,3,1,1,0,0,GridBagConstraints.EAST,
//			GridBagConstraints.NONE,new Insets(2,4,4,2),0,0));
			
		JPanel tmp = new JPanel(new BorderLayout());
		tmp.add(np, BorderLayout.CENTER);
		tmp.add(buts, BorderLayout.SOUTH);
		this.ap = new AgendaPanel(system.getAgenda());
		JPanel tmp3 = new JPanel(new BorderLayout());
		final JCheckBox followact = new JCheckBox("Follow activation", true);
		followact.setToolTipText("Follow the selected activation by displaying the rule.");
		tmp3.add(ap, BorderLayout.CENTER);
//		tmp3.add(followact, BorderLayout.SOUTH);
		
		// The step action
		final JButton	step	= new JButton("Step");
		if(steppable!=null)
		{
			JPanel tmp4 = new JPanel(new GridBagLayout());
			step.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					steppable.doStep();
				}
			});
			step.setEnabled(steppable.isStepmode() && !system.getAgenda().isEmpty());		
			final JCheckBox	stepmode = new JCheckBox("Step Mode", steppable.isStepmode());
			stepmode.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					steppable.setStepmode(stepmode.isSelected());
					step.setEnabled(steppable.isStepmode() && !system.getAgenda().isEmpty());		
				}
			});
			steppable.addBreakpointCommand(new ICommand()
			{
				public void execute(Object args)
				{
					SwingUtilities.invokeLater(new Runnable()
					{
						public void run()
						{
							stepmode.setSelected(steppable.isStepmode());
							step.setEnabled(steppable.isStepmode() && !system.getAgenda().isEmpty());		
						}
					});
				}
			});
			int row	= 0;
			int	col	= 0;
			tmp4.add(followact, new GridBagConstraints(col, row++, 2, 1,
				1,0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(1,1,1,1), 0,0));
			tmp4.add(stepmode, new GridBagConstraints(col++, row, 1, 1,
				1,0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(1,1,1,1), 0,0));
			tmp4.add(step, new GridBagConstraints(col, row++, GridBagConstraints.REMAINDER, 1,
				0,0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(1,1,1,1), 0,0));
			
			tmp3.add(tmp4, BorderLayout.SOUTH);
		}
		
		addInfoPanel(NODE_DETAILS_NAME, tmp);
		addInfoPanel(AGENDA_NAME, tmp3);
		
		JSplitPane sp2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
		sp2.setOneTouchExpandable(true);
		sp2.setResizeWeight(1);
		sp2.setDividerLocation(500);
		sp2.add(vv);
		sp2.add(infopanels);
		this.setLayout(new BorderLayout());
		this.add(sp2, BorderLayout.CENTER);
		
		vv.addComponentListener(new ComponentAdapter()
		{
			public void componentResized(ComponentEvent e)
			{
				layout.setSize(vv.getSize());
			}
		});
		
		rulebasepanel.addBreakpointListener(new IChangeListener()
		{
			 public void changeOccurred(ChangeEvent e)
			 {
				 String[] rules = (String[])rulebasepanel.getSelectedBreakpoints();
//				 System.out.println("Selected: "+SUtil.arrayToString(rules)+" "+e);
				 
				 if(rules!=null && rules.length>0)
				 {
					 // Show all nodes
					 if(remnodes!=null)
						 showHiddenNodes();
				 
					 // Build subgraph of selected rules (terminal nodes).
					 Set subgraph = new HashSet();
					 for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy