package com.algomagic.atn; import att.grappa.*; import java.util.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; public class VisualizationPanel extends JPanel implements Observer, VisualizationConstants { private int _side; private Properties _properties; private GrappaPanel _grappaPanel; private Graph _graph; private JPanel _complete; private JPanel _graphPanel; private CredentialPanel _credentialPanel; private ImageIcon _collapse; private ImageIcon _expand; private HashMap _nodeStates; private Subgraph _currentCluster; private boolean _local; private java.util.List _bolded; private HashMap _remoteClusters; private HashMap _remoteEvidence; private HashMap _localClusters; private String _shadowColor; private int _currentIndex; private BatchGraphUpdate _batchUpdate; private boolean _ignoreProcessing; private HashSet _boldedNodes; private boolean _basicProps; private String _name; public void setName( String name ) { _name = name; PanelHelper.setBorder( _graphPanel, "Trust Target Graph: " + name ); // _graph.setAttribute( TIP_ATTR, "Trust Target Graph: " + name ); // _graph.setAttribute( TIP_ATTR, null ); _grappaPanel.setToolTipText( null ); } class CredentialPanel extends JPanel { JTabbedPane _tabs; JList _local; JList _remote; JList _policy; DefaultListModel _localCreds; DefaultListModel _remoteCreds; DefaultListModel _policyCreds; boolean _autoRaise; public CredentialPanel( ) { super( ); _autoRaise = true; _tabs = new JTabbedPane( ); _localCreds = new DefaultListModel( ); _remoteCreds = new DefaultListModel( ); _policyCreds = new DefaultListModel( ); _local = new JList( _localCreds ); _remote = new JList( _remoteCreds ); _policy = new JList( _policyCreds ); _tabs.addTab( "Local Credentials", new JScrollPane( _local ) ); _tabs.addTab( "Remote Credentials", new JScrollPane( _remote ) ); _tabs.addTab( "Policies", new JScrollPane( _policy ) ); setLayout( new BorderLayout( ) ); add( _tabs, BorderLayout.CENTER ); PanelHelper.setBorder( this, "Credentials" ); } public void clearSelection( ) { _local.clearSelection( ); _remote.clearSelection( ); } public void setAutoRaise( boolean state ) { _autoRaise = state; } public void setRaised( int tab ) { clearSelection( ); if( _autoRaise ) { // System.out.println( "side: " + _side + " tab: " + tab ); _tabs.setSelectedIndex( tab ); } } public void setRaised( boolean local ) { clearSelection( ); if( _autoRaise ) { if( local ) { _tabs.setSelectedIndex( 0 ); } else { _tabs.setSelectedIndex( 1 ); } } } public void addCredentials( Collection evidence, int tab ) { clearSelection( ); DefaultListModel m; if( tab == 0 ) { m = _localCreds; } else if( tab == 1 ) { m = _remoteCreds; } else { m = _policyCreds; } for( Iterator i = evidence.iterator( ); i.hasNext( ); ) { Object o = i.next( ); if( !m.contains( o ) ) { m.addElement( o ); } // m.addElement( i.next( ) ); } } public void removeCredentials( Collection evidence, int tab ) { clearSelection( ); DefaultListModel m; if( tab == 0 ) { m = _localCreds; } else if( tab == 1 ) { m = _remoteCreds; } else { m = _policyCreds; } for( Iterator i = evidence.iterator( ); i.hasNext( ); ) { Object o = i.next( ); if( m.contains( o ) ) { m.removeElement( o ); } // m.addElement( i.next( ) ); } } public void addCredentials( Collection evidence, boolean local ) { clearSelection( ); DefaultListModel m; if( local ) { m = _localCreds; } else { m = _remoteCreds; } for( Iterator i = evidence.iterator( ); i.hasNext( ); ) { Object o = i.next( ); if( !m.contains( o ) ) { m.addElement( o ); } } } public void removeCredentials( Collection evidence, boolean local ) { clearSelection( ); DefaultListModel m; if( local ) { m = _localCreds; } else { m = _remoteCreds; } for( Iterator i = evidence.iterator( ); i.hasNext( ); ) { Object o = i.next( ); if( m.contains( o ) ) { m.removeElement( o ); } } } public void highlightCredentials( Collection evidence, int tab ) { DefaultListModel m; JList l; if( tab == 0 ) { m = _localCreds; l = _local; } else { m = _remoteCreds; l = _remote; } clearSelection( ); int[] indices = new int[evidence.size( )]; int count = 0; for( Iterator i = evidence.iterator( ); i.hasNext( ); ) { indices[count] = m.indexOf( i.next( ) ); count++; } l.setSelectedIndices( indices ); } public void highlightCredentials( Collection evidence, boolean local ) { DefaultListModel m; JList l; if( local ) { m = _localCreds; l = _local; } else { m = _remoteCreds; l = _remote; } clearSelection( ); int[] indices = new int[evidence.size( )]; int count = 0; for( Iterator i = evidence.iterator( ); i.hasNext( ); ) { indices[count] = m.indexOf( i.next( ) ); count++; } l.setSelectedIndices( indices ); } public void removeRemoteCreds( ) { // System.out.println( "removing remote creds" ); _remoteCreds.clear( ); } } public void setAutoRaise( boolean state ) { _credentialPanel.setAutoRaise( state ); } public void clearSelection( ) { _credentialPanel.clearSelection( ); } public void setRaised( boolean local ) { _credentialPanel.setRaised( local ); } public void setRaised( int tab ) { _credentialPanel.setRaised( tab ); } public void addCredentials( Collection evidence, boolean local ) { if( evidence != null ) { _credentialPanel.addCredentials( evidence, local ); } } public void removeCredentials( Collection evidence, boolean local ) { if( evidence != null ) { _credentialPanel.removeCredentials( evidence, local ); } } public void highlightCredentials( Collection evidence, boolean local ) { if( evidence != null ) { _credentialPanel.highlightCredentials( evidence, local ); } } public void addCredentials( Collection evidence, int tab ) { if( evidence != null ) { _credentialPanel.addCredentials( evidence, tab ); } } public void removeCredentials( Collection evidence, int tab ) { if( evidence != null ) { _credentialPanel.removeCredentials( evidence, tab ); } } public void highlightCredentials( Collection evidence, int tab ) { if( evidence != null ) { _credentialPanel.highlightCredentials( evidence, tab ); } } public VisualizationPanel( int side, Properties properties ) { super( ); _side = side; _properties = properties; _currentCluster = null; _local = true; _basicProps = false; _nodeStates = new HashMap( ); _bolded = new ArrayList( ); _remoteClusters = new HashMap( ); _remoteEvidence = new HashMap( ); _localClusters = new HashMap( ); _batchUpdate = new BatchGraphUpdate( ); _boldedNodes = new HashSet( ); _ignoreProcessing = (new Boolean( _properties.getProperty( IGNOREPROC_PROP, IGNOREPROC_DEFAULT ) )).booleanValue( ); // System.out.println( _properties.getProperty( IGNOREPROC_PROP, IGNOREPROC_DEFAULT ) ); // System.out.println( _ignoreProcessing ); _shadowColor = _properties.getProperty( SHADOW_PROP, SHADOW_DEFAULT ); Class clazz = this.getClass( ); _collapse = new ImageIcon( clazz.getResource( "/resources/collapse.gif" ), "collapse" ); _expand = new ImageIcon( clazz.getResource( "/resources/expand.gif" ), "expand" ); JPanel hiderPanel = new JPanel( ); hiderPanel.setLayout( new BoxLayout( hiderPanel, BoxLayout.X_AXIS ) ); JButton hider = new JButton( _collapse ); hider.setMaximumSize( new Dimension( 2000, 10 ) ); hider.setPreferredSize( new Dimension( 2000, 10 ) ); hider.setMinimumSize( new Dimension( 0, 10 ) ); hider.addActionListener( new ActionListener( ) { boolean removed = false; public void actionPerformed( ActionEvent e ) { JButton button = (JButton)e.getSource( ); if( ! removed ) { _complete.remove( _credentialPanel ); button.setIcon( _expand ); removed = true; } else { _complete.add( _credentialPanel, 2 ); button.setIcon( _collapse ); removed = false; } validate( ); repaint( ); } } ); hiderPanel.add( hider ); _graph = new Graph( "Trust Target Graph: " + _side ); _grappaPanel = new GrappaPanel( _graph ); _grappaPanel.setScaleToFit( false ); // JScrollPane jsp = new JScrollPane( ); // jsp.getViewport( ).setScrollMode( JViewport.BACKINGSTORE_SCROLL_MODE ); // jsp.getViewport( ).setBackground( Color.white ); // jsp.setViewportView( _grappaPanel ); JScrollPane jsp = new JScrollPane( _grappaPanel ); // jsp.getViewport( ).setScrollMode( JViewport.BACKINGSTORE_SCROLL_MODE ); jsp.getViewport( ).setBackground( Color.white ); // jsp.setViewportView( _grappaPanel ); _graphPanel = new JPanel( new BorderLayout( ) ); PanelHelper.setBorder( _graphPanel, "Trust Target Graph" ); _graphPanel.add( jsp, BorderLayout.CENTER ); _credentialPanel = new CredentialPanel( ); _credentialPanel.setMaximumSize( new Dimension( 2000, 150 ) ); _credentialPanel.setPreferredSize( new Dimension( 2000, 150 ) ); _credentialPanel.setMinimumSize( new Dimension( 0, 150 ) ); _complete = new JPanel( ); _complete.setLayout( new BoxLayout( _complete, BoxLayout.Y_AXIS ) ); _complete.add( _graphPanel ); _complete.add( hiderPanel ); _complete.add( _credentialPanel ); _grappaPanel.addGrappaListener( new TipAdapter( ) ); setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) ); add( _complete ); } public boolean addNodeState( NodeState ns ) { if( _nodeStates.containsKey( ns.getName( ) ) ) { return false; } _nodeStates.put( ns.getName( ), ns ); return true; } public NodeState getNodeState( String name ) { return (NodeState)_nodeStates.get( name ); } public void reset( java.util.List updates ) { _basicProps = true; for( ListIterator i = updates.listIterator( ); i.hasNext( ); ) { Update u = (Update)i.next( ); if( u.getSide( ) == _side ) { u.apply( this ); } } _basicProps = false; hideGraph( _graph ); } public java.util.List initialize( java.util.List updates ) { java.util.List filteredUpdates = new ArrayList( ); for( ListIterator i = updates.listIterator( ); i.hasNext( ); ) { Update u = (Update)i.next( ); if( u.getSide( ) == _side ) { int changed = u.initialize( this ); // if changed == 1, processing state changed // changed == 2, satisfaction state changed // changed == 3, processing and satisfaction changed // changed == 0, no change if( changed == 3 || (!_ignoreProcessing && changed >= 1 ) || (_ignoreProcessing && changed >= 2 ) ) { filteredUpdates.add( u ); } } else { filteredUpdates.add( u ); } } boolean isRemoteCluster = false; int clusterNumber = -1; HashSet remoteCluster = null; Collection remoteEvidence = null; for( ListIterator i = filteredUpdates.listIterator( ); i.hasNext( ); ) { Update u = (Update)i.next( ); if( u.getSide( ) == _side ) { // if( u instanceof NodeUpdate ) { // System.out.println( u ); // } u.apply( this ); if( u instanceof ClusterUpdate ) { ClusterUpdate cu = (ClusterUpdate)u; if( !cu.getLocal( ) ) { if( cu.getStart( ) ) { isRemoteCluster = true; clusterNumber = cu.getCluster( ); remoteCluster = new HashSet( ); remoteEvidence = new ArrayList( ); } else { isRemoteCluster = false; _remoteClusters.put( new Integer( clusterNumber ), remoteCluster ); _remoteEvidence.put( new Integer( clusterNumber ), remoteEvidence ); } } } else if( isRemoteCluster ) { remoteCluster.add( u ); if( u instanceof EdgeUpdate ) { Collection c = ((EdgeUpdate)u).getEvidence( ); remoteEvidence.addAll( c ); } } } } formatGraph( _graph ); hideGraph( _graph ); _credentialPanel.removeRemoteCreds( ); String scaleStr = _properties.getProperty( SCALE_PROP, SCALE_DEFAULT ); double scale = Double.parseDouble( scaleStr ); _grappaPanel.multiplyScaleFactor( scale ); _graph.resync( ); _graph.repaint( ); return filteredUpdates; } public PanelUpdate apply( Update u ) { _batchUpdate = new BatchGraphUpdate( ); if( u.getSide( ) != _side ) { throw new RuntimeException( ); } u.apply( this ); boolean raise = false; int tab = -1; boolean add = false; boolean hl = true; Collection c = null; if( u instanceof ClusterUpdate ) { ClusterUpdate cu = (ClusterUpdate)u; if( !cu.getStart( ) && cu.getLocal( ) ) { unSetBolded( !cu.getUndo( ), cu.getCluster( ) ); } else if( cu.getStart( ) && !cu.getLocal( ) ) { setShadowed( !cu.getUndo( ), cu.getCluster( ) ); c = (Collection) _remoteEvidence.get( new Integer( cu.getCluster( ) ) ); add = true; hl = false; } } if( u.getLocal( ) ) { tab = 0; raise = true; } else { tab = 1; raise = true; } if( u instanceof EdgeUpdate ) { EdgeUpdate eu = (EdgeUpdate)u; c = eu.getEvidence( ); if( eu.getType( ).equals( CONTROL_EDGE ) ) { if( u.getLocal( ) ) { tab = 2; raise = true; } } } return new PanelUpdate( _batchUpdate, _side, tab, c, raise, add, hl ); } public void update( Observable o, Object arg ) { clearSelection( ); if( arg instanceof PanelUpdate ) { PanelUpdate u = (PanelUpdate)arg; if( u.getSide( ) != _side ) { return; } // if( u instanceof ClusterUpdate ) { // ClusterUpdate cu = (ClusterUpdate)u; // if( !cu.getStart( ) && cu.getLocal( ) ) { // unSetBolded( !cu.getUndo( ), cu.getCluster( ) ); // } else if( cu.getStart( ) && !cu.getLocal( ) ) { // setShadowed( !cu.getUndo( ), cu.getCluster( ) ); // } // } u.apply( this ); _graph.resync( ); _graph.repaint( ); // if( u.getUndo( ) ) { // // System.out.println( "UNDO" ); // u.undo( this ); // } else { // u.apply( this ); // } // _graph.resync( ); // _graph.repaint( ); } else if( arg instanceof String ) { String s = (String)arg; if( s.equals( "CLEAR" ) ) { // System.out.println( "CLEAR" ); hideGraph( _graph ); // _credentialPanel.removeRemoteCreds( ); } } } public Graph getGraph( ) { return _graph; } public Subgraph getCurrentCluster( ) { return _currentCluster; } public void setCurrentCluster( Subgraph sg ) { _currentCluster = sg; } private void setShadowed( boolean shadow, int clusterNum ) { HashSet cluster = (HashSet)_remoteClusters.get( new Integer( clusterNum ) ); for( Iterator i = cluster.iterator( ); i.hasNext( ); ) { Update u = (Update)i.next( ); if( u instanceof NodeUpdate ) { NodeUpdate nu = (NodeUpdate)u; NodeState ns = getNodeState( nu.getName( ) ); if( ns.getHidden( ) == false ) { continue; } } Element e = u.getElement( this ); if( shadow ) { setShadow( e ); } else { setInvis( e ); } if( u instanceof EdgeUpdate ) { EdgeUpdate eu = (EdgeUpdate)u; NodeState ns = getNodeState( eu.getChildName( ) ); if( ns.getHidden( ) == false ) { continue; } e = eu.getChild( this ); if( shadow ) { setShadow( e ); } else { setInvis( e ); } } } } public void setShadow( Element e ) { setAttribute( e, "color", _shadowColor ); setAttribute( e, "style", "solid" ); setAttribute( e, "fontcolor", _shadowColor ); } private void unSetBolded( boolean unbold, int cluster ) { _boldedNodes = new HashSet( ); if( !unbold ) { _local = true; _bolded = (java.util.List)_localClusters.get( new Integer( cluster ) ); } if( unbold ) { for( Iterator i = _bolded.iterator( ); i.hasNext( ); ) { ElementAtt e = (ElementAtt)i.next( ); e.apply( ); } } else { for( int i=_bolded.size()-1; i>=0;i-- ) { ElementAtt e = (ElementAtt)_bolded.get(i); e.undo( ); } } if( !unbold ) { _local = false; } else { _localClusters.put( new Integer( cluster ), _bolded ); _bolded = new ArrayList( ); } } private class ElementAtt { private Element _e; private String _att; private String _value; private Object _undoValue; public ElementAtt( Element e, String att, String value, String undoValue ) { _e = e; _att = att; _value = value; _undoValue = undoValue; } public void apply( ) { _undoValue = setAttribute( _e, _att, _value ); } public void undo( ) { _e.setAttribute( _att, _undoValue ); } } private Object setAttribute( Element e, String attr, Object value ) { Object previousValue = e.setAttribute( attr, value ); if( _batchUpdate != null ) { _batchUpdate.add( new ElementAttribute( e, attr, value, previousValue ) ); } return previousValue; } private void setNodeProps( Node n, String prefix, boolean setBold ) { for( int i=0; i < NODE_ATTRS.length; i++ ) { String strValue = _properties.getProperty( prefix + NODE_ATTRS_PROP[i] ); if( strValue == null ) { continue; } if( NODE_ATTRS_INT[i] ) { setAttribute( n, NODE_ATTRS[i], new Integer( strValue ) ); } else { if( NODE_ATTRS[i].equals( FONTSTYLE_ATTR ) && ( setBold || _boldedNodes.contains( n ) ) ) { _bolded.add( new ElementAtt( n, FONTSTYLE_ATTR, strValue,"bold" ) ); strValue = "bold"; } setAttribute( n, NODE_ATTRS[i], strValue ); } } } private void setEdgeProps( Edge e, String prefix, boolean local ) { for( int i=0; i < EDGE_ATTRS.length; i++ ) { String strValue = _properties.getProperty( prefix + EDGE_ATTRS_PROP[i] ); String undoValue = _properties.getProperty( prefix + EDGE_ATTRS_PROP[i] + ".bold" ); String change = strValue; if( strValue == null ) { continue; } if( local ) { if( undoValue != null ) { _bolded.add( new ElementAtt( e, EDGE_ATTRS[i], strValue, undoValue ) ); change = undoValue; } } setAttribute( e, EDGE_ATTRS[i], change ); } } public void setNodeProperties( Node n, NodeState ns, boolean local, boolean newNode ) { if( ns.getHidden( ) ) { if( _local == false ) { setShadow( n ); } else { setInvis( n ); } return; } if( ns.getBolded( ) == false && ( local && newNode ) ) { ns.setBolded( true ); } if( local&&newNode ) { _boldedNodes.add( n ); } setNodeProperties( n, ns.getType( ), ns.getSatisfied( ), ns.getProcessed( ), local&&newNode ); } private void setNodeProperties( Node n, String type, String satisfaction, String process, boolean setBold ) { setNodeProps( n, DEFAULT_NODE, setBold ); setNodeProps( n, SYSTEM_PREFIX + "node." + type + ".", setBold ); if( _basicProps ) { return; } setNodeProps( n, SYSTEM_PREFIX + "node.satisfied." + satisfaction + ".", setBold ); if( !_ignoreProcessing ) { setNodeProps( n, SYSTEM_PREFIX + "node.processed." + process + ".", setBold ); } } public void setEdgeProperties( Edge e, String type, boolean local ) { setEdgeProps( e, DEFAULT_EDGE, local ); setEdgeProps( e, SYSTEM_PREFIX + "edge." + type + ".", local ); } private void formatGraph( Graph g ) { try { Process formater = Runtime.getRuntime( ).exec( "dot" ); GrappaSupport.filterGraph( g, formater ); formater.destroy( ); g.repaint( ); } catch( Exception e ) { e.printStackTrace( ); } } public void hideGraph( ) { hideSubgraph( _graph ); _graph.resync( ); _graph.repaint( ); _credentialPanel.removeRemoteCreds( ); } public void updateGraph( ) { _graph.resync( ); _graph.repaint( ); } public void hideGraph( Graph g) { _credentialPanel.removeRemoteCreds( ); hideSubgraph( g ); for( Iterator i = _nodeStates.values( ).iterator( ); i.hasNext( ); ) { NodeState ns = (NodeState) i.next( ); ns.clearState( ); } g.resync( ); g.repaint( ); } private void hideSubgraph( Subgraph sg ) { // System.out.println( "HIDING GRAPH" ); Enumeration nodes = sg.nodeElements( ); Enumeration edges = sg.edgeElements( ); while( nodes.hasMoreElements( ) ) { Node n = (Node) nodes.nextElement( ); setInvis( n ); } while( edges.hasMoreElements( ) ) { Edge e = (Edge) edges.nextElement( ); setInvis( e ); } } public void setInvis( Element e ) { e.setAttribute( FONTSTYLE_ATTR, "normal" ); e.setAttribute( STYLE_ATTR, "invis" ); } public void setLocal( boolean local ) { _local = local; } public boolean getLocal( ) { return _local; } }