001    package toolbus.viewer;
002    
003    import java.awt.BorderLayout;
004    import java.awt.Color;
005    import java.awt.Component;
006    import java.awt.FlowLayout;
007    import java.awt.GridLayout;
008    import java.awt.event.ActionEvent;
009    import java.awt.event.ActionListener;
010    import java.awt.event.WindowAdapter;
011    import java.awt.event.WindowEvent;
012    import java.util.Iterator;
013    import java.util.List;
014    
015    import javax.swing.Box;
016    import javax.swing.BoxLayout;
017    import javax.swing.DefaultCellEditor;
018    import javax.swing.JButton;
019    import javax.swing.JCheckBox;
020    import javax.swing.JFrame;
021    import javax.swing.JLabel;
022    import javax.swing.JPanel;
023    import javax.swing.JScrollPane;
024    import javax.swing.JTable;
025    import javax.swing.JTextField;
026    import javax.swing.ListSelectionModel;
027    import javax.swing.SwingUtilities;
028    import javax.swing.WindowConstants;
029    import javax.swing.border.BevelBorder;
030    import javax.swing.event.ListSelectionEvent;
031    import javax.swing.event.ListSelectionListener;
032    import javax.swing.table.DefaultTableCellRenderer;
033    import javax.swing.table.DefaultTableModel;
034    import javax.swing.table.TableCellRenderer;
035    import javax.swing.table.TableColumn;
036    import javax.swing.table.TableColumnModel;
037    
038    import toolbus.StateElement;
039    import toolbus.TBTermFactory;
040    import toolbus.atom.Atom;
041    import toolbus.commandline.CommandLine;
042    import toolbus.environment.Binding;
043    import toolbus.environment.Environment;
044    import toolbus.exceptions.ToolBusException;
045    import toolbus.process.ProcessInstance;
046    import aterm.AFun;
047    import aterm.ATerm;
048    import aterm.ATermAppl;
049    import aterm.ATermList;
050    
051    public class Viewer implements IViewer{
052            protected final DebugToolBus debugToolBus;
053            
054            private final JFrame frame;
055            private final JLabel status;
056            protected final JButton runButton;
057            protected final JButton stopButton;
058            protected final JButton stepButton;
059            protected final JButton killButton;
060            
061            protected final JTextField lastExecutedProcessInstanceField;
062            protected final JTextField lastExecutedStateElementField;
063            
064            protected final JTable processesTable;
065            private final String[] processesTableHeader;
066            protected final JTable stateTable;
067            private final String[] stateTableHeader;
068            
069            private final DefaultTableModel processesTableModel;
070            private final DefaultTableModel subscriptionsTableModel;
071            private final DefaultTableModel variablesTableModel;
072            private final DefaultTableModel noteQueueTableModel;
073            private final DefaultTableModel stateTableModel;
074            
075            private final JScrollPane processesScrollPane;
076            
077            private volatile int stepHighlightedRow = -1;
078            private volatile int breakHighlightedRow = -1;
079            
080            public Viewer(String[] args){
081                    super();
082                    
083                    debugToolBus = new DebugToolBus(args, this, null);
084                    
085                    frame = new JFrame("ToolBus Viewer");
086                    frame.setSize(800, 600);
087                    frame.setLayout(new BorderLayout());
088                    frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
089                    
090                    frame.addWindowListener(new WindowAdapter(){
091                            public void windowClosing(WindowEvent e){
092                                    debugToolBus.doTerminate();
093                            }
094                    });
095                    
096                    JPanel mainPanel = new JPanel();
097                    mainPanel.setLayout(new GridLayout(2, 2));
098                    
099                    TableSelectionListener tableSelectionListener = new TableSelectionListener();
100    
101                    JPanel processesPanel = new JPanel();
102                    processesPanel.setLayout(new BorderLayout());
103                    processesTableHeader = new String[]{"Break", "Process name", "Identifier"};
104                    processesTableModel = new DefaultTableModel(new Object[0][0], processesTableHeader){
105                            private static final long serialVersionUID = 6515489257737761296L;
106                            
107                            public boolean isCellEditable(int row, int column){
108                                    return (column == 0); // Only the checkbox is editable.
109                            }
110                            public void setValueAt(Object aValue, int row, int column){
111                                    super.setValueAt(aValue, row, column);
112                                    
113                                    if(column == 0){
114                                            int processId = ((Integer) processesTable.getValueAt(row, 2)).intValue();
115                                            
116                                            if(((Boolean) aValue).booleanValue()) debugToolBus.addProcessInstanceBreakPoint(processId);
117                                            else debugToolBus.removeProcessInstanceBreakPoint(processId);
118                                    }
119                            }
120                    };
121                    processesTable = new JTable(processesTableModel){
122                            private static final long serialVersionUID = -3338875681802391368L;
123    
124                            public Component prepareRenderer(TableCellRenderer cr, int row, int col){
125                    Component c = super.prepareRenderer(cr, row, col);
126                    
127                    if(row == stepHighlightedRow) c.setBackground(Color.GREEN);
128                    else if(row == breakHighlightedRow) c.setBackground(Color.YELLOW);
129                    else c.setBackground(Color.WHITE);
130                    
131                    return c;
132                }
133            };
134                    TableColumnModel processesTableColumnModel = processesTable.getColumnModel();
135                    TableColumn breakPointColumn = processesTableColumnModel.getColumn(0);
136                    breakPointColumn.setCellRenderer(new DefaultTableCellRenderer(){
137                            private static final long serialVersionUID = 5811556489112969680L;
138    
139                            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
140                                    JCheckBox checkBox = new JCheckBox();
141                            if(Boolean.TRUE.equals(value)) checkBox.setSelected(true);
142                            return checkBox;
143                        }
144                    });
145                    breakPointColumn.setCellEditor(new DefaultCellEditor(new JCheckBox()));
146                    breakPointColumn.setMinWidth(40);
147                    breakPointColumn.setMaxWidth(40);
148                    TableColumn identifierColumn = processesTableColumnModel.getColumn(2);
149                    identifierColumn.setMinWidth(60);
150                    identifierColumn.setMaxWidth(100);
151                    identifierColumn.setPreferredWidth(60);
152                    ListSelectionModel processesSelectionModel = processesTable.getSelectionModel();
153                    processesSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
154                    processesSelectionModel.addListSelectionListener(tableSelectionListener);
155                    processesScrollPane = new JScrollPane(processesTable);
156                    processesPanel.add(processesScrollPane, BorderLayout.CENTER);
157                    frame.add(processesPanel, BorderLayout.WEST);
158                    
159                    JPanel subscriptionsPanel = new JPanel();
160                    subscriptionsPanel.setLayout(new BorderLayout());
161                    subscriptionsTableModel = new DefaultTableModel(new Object[0][0], new String[]{"Subscriptions"}){
162                            private static final long serialVersionUID = 2407227292333227911L;
163    
164                            public boolean isCellEditable(int row, int column){
165                                    return false;
166                            }
167                    };
168                    JTable subscriptionsTable = new JTable(subscriptionsTableModel);
169                    JScrollPane subscriptionsScrollPane = new JScrollPane(subscriptionsTable);
170                    subscriptionsPanel.add(subscriptionsScrollPane, BorderLayout.CENTER);
171                    mainPanel.add(subscriptionsPanel);
172                    
173                    JPanel statePanel = new JPanel();
174                    statePanel.setLayout(new BorderLayout());
175                    stateTableHeader = new String[]{"State"};
176                    stateTableModel = new DefaultTableModel(new Object[0][0], stateTableHeader){
177                            private static final long serialVersionUID = 7405647403653515348L;
178    
179                            public boolean isCellEditable(int row, int column){
180                                    return false;
181                            }
182                    };
183                    stateTable = new JTable(stateTableModel);
184                    ListSelectionModel stateSelectionModel = stateTable.getSelectionModel();
185                    stateSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
186                    stateSelectionModel.addListSelectionListener(tableSelectionListener);
187                    JScrollPane stateScrollPane = new JScrollPane(stateTable);
188                    statePanel.add(stateScrollPane, BorderLayout.CENTER);
189                    mainPanel.add(statePanel);
190                    
191                    JPanel noteQueuePanel = new JPanel();
192                    noteQueuePanel.setLayout(new BorderLayout());
193                    noteQueueTableModel = new DefaultTableModel(new Object[0][0], new String[]{"Note Queue"}){
194                            private static final long serialVersionUID = -5038729871288100318L;
195    
196                            public boolean isCellEditable(int row, int column){
197                                    return false;
198                            }
199                    };
200                    JTable noteQueueTable = new JTable(noteQueueTableModel);
201                    JScrollPane noteQueueScrollPane = new JScrollPane(noteQueueTable);
202                    noteQueuePanel.add(noteQueueScrollPane, BorderLayout.CENTER);
203                    mainPanel.add(noteQueuePanel);
204    
205                    JPanel variablesPanel = new JPanel();
206                    variablesPanel.setLayout(new BorderLayout());
207                    variablesTableModel = new DefaultTableModel(new Object[0][0], new String[]{"Variable", "Value"}){
208                            private static final long serialVersionUID = 4345972041423779621L;
209    
210                            public boolean isCellEditable(int row, int column){
211                                    return false;
212                            }
213                    };
214                    JTable variablesTable = new JTable(variablesTableModel);
215                    JScrollPane variablesScrollPane = new JScrollPane(variablesTable);
216                    variablesPanel.add(variablesScrollPane, BorderLayout.CENTER);
217                    mainPanel.add(variablesPanel);
218                    
219                    JPanel controlPanel = new JPanel();
220                    controlPanel.setLayout(new BorderLayout());
221                    controlPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
222                    
223                    JPanel statusBar = new JPanel();
224                    statusBar.setLayout(new GridLayout(1, 1));
225                    status = new JLabel();
226                    statusBar.add(status);
227                    controlPanel.add(statusBar, BorderLayout.WEST);
228                    
229                    JPanel bottomPanel = new JPanel();
230                    bottomPanel.setLayout(new BorderLayout());
231                    
232                    JPanel lastExecutedAtomPanel = new JPanel();
233                    lastExecutedAtomPanel.setLayout(new GridLayout(2, 1));
234                    Box topBox = new Box(BoxLayout.X_AXIS);
235                    JLabel lastExecutedProcessInstanceLabel = new JLabel("Last executed process instance: ");
236                    topBox.add(lastExecutedProcessInstanceLabel);
237                    lastExecutedProcessInstanceField = new JTextField();
238                    lastExecutedProcessInstanceField.setEditable(false);
239                    lastExecutedProcessInstanceField.setBackground(Color.WHITE);
240                    topBox.add(lastExecutedProcessInstanceField);
241                    lastExecutedAtomPanel.add(topBox);
242                    Box bottomBox = new Box(BoxLayout.X_AXIS);
243                    JLabel lastExecutedStateElementLabel = new JLabel("Last executed state element: ");
244                    bottomBox.add(lastExecutedStateElementLabel);
245                    lastExecutedStateElementField = new JTextField();
246                    lastExecutedStateElementField.setEditable(false);
247                    lastExecutedStateElementField.setBackground(Color.WHITE);
248                    bottomBox.add(lastExecutedStateElementField);
249                    lastExecutedAtomPanel.add(bottomBox);
250                    bottomPanel.add(lastExecutedAtomPanel, BorderLayout.NORTH);
251                    
252                    JPanel controlBar = new JPanel();
253                    controlBar.setLayout(new FlowLayout());
254                    ButtonActionListener buttonActionListener = new ButtonActionListener();
255                    runButton = new JButton("Run");
256                    runButton.addActionListener(buttonActionListener);
257                    controlBar.add(runButton);
258                    stopButton = new JButton("Stop");
259                    stopButton.addActionListener(buttonActionListener);
260                    controlBar.add(stopButton);
261                    stepButton = new JButton("Step");
262                    stepButton.addActionListener(buttonActionListener);
263                    controlBar.add(stepButton);
264                    killButton = new JButton("Terminate");
265                    killButton.addActionListener(buttonActionListener);
266                    controlBar.add(killButton);
267                    controlPanel.add(controlBar, BorderLayout.EAST);
268                    bottomPanel.add(controlPanel, BorderLayout.CENTER);
269                    
270                    frame.add(bottomPanel, BorderLayout.SOUTH);
271                    
272                    frame.add(mainPanel, BorderLayout.CENTER);
273            }
274            
275            public DebugToolBus getDebugToolBus(){
276                    return debugToolBus;
277            }
278            
279            public void toolbusStarting(){
280                    frame.setVisible(true);
281            }
282            
283            public void toolbusTerminating(){
284                    frame.dispose();
285            }
286            
287            // Update the state of the given process after the execution of the step.
288            public void stepExecuted(final ProcessInstance processInstance, final StateElement executedStateElement, final ProcessInstance[] partners){
289                    if(executedStateElement.getPosInfo() == null){
290                            // If the posInfo was 'null', the stateElement isn't related directly related to anything in the ToolBus script (it will be an atom that was inserted during the creation of the statemachine, by the parser).
291                            // In this case do another step.
292                            debugToolBus.doStep();
293                            return;
294                    }
295                    
296                    //if(partners.length > 0) System.out.println(processInstance+" -> "+partners[0]);
297                    
298                    //System.out.println(executedStateElement+" - "+executedStateElement.getPosInfo());
299                    
300                    SwingUtilities.invokeLater(new Runnable(){
301                            public void run(){
302                                    lastExecutedProcessInstanceField.setText(processInstance.getProcessName()+":"+processInstance.getProcessId());
303                                    lastExecutedProcessInstanceField.setCaretPosition(0);
304                                    lastExecutedStateElementField.setText(executedStateElement.toString());
305                                    lastExecutedStateElementField.setCaretPosition(0);
306                                    
307                                    stepHighlightedRow = -1;
308                                    for(int row = processesTableModel.getRowCount() - 1; row >= 0; row--){
309                                            int processId = ((Integer) processesTableModel.getValueAt(row, 2)).intValue();
310                                            if(processId == processInstance.getProcessId()){
311                                                    stepHighlightedRow = row;
312                                                    processesTable.scrollRectToVisible(processesTable.getCellRect(row, 1, true));
313                                                    ListSelectionModel selectionModel = processesTable.getSelectionModel();
314                                                    selectionModel.clearSelection();
315                                                    selectionModel.setSelectionInterval(row, row);
316                                                    break;
317                                            }
318                                    }
319                                    processesTable.repaint();
320                            }
321                    });
322            }
323            
324            public void updateState(int state){
325                    switch(state){
326                            case IViewerConstants.UNKNOWN_STATE:
327                                    status.setText("Unkown");
328                                    break;
329                            case IViewerConstants.STOPPING_STATE:
330                                    status.setText("Stopping");
331                                    break;
332                            case IViewerConstants.WAITING_STATE:
333                                    status.setText("Waiting");
334                                    break;
335                            case IViewerConstants.READY_STATE:
336                                    status.setText("Ready");
337                                    break;
338                            case IViewerConstants.RUNNING_STATE:
339                                    status.setText("Running");
340                                    break;
341                            case IViewerConstants.STEPPING_STATE:
342                                    status.setText("Stepping");
343                                    break;
344                            default:
345                                    System.err.println("Unknown state: "+state);
346                    }
347            }
348            
349            public void processInstanceStarted(final ProcessInstance processInstance){
350                    SwingUtilities.invokeLater(new Runnable(){
351                            public void run(){
352                                    processesTableModel.insertRow(0, new Object[]{Boolean.FALSE, processInstance.getProcessName(), Integer.valueOf(processInstance.getProcessId())});
353                            }
354                    });
355            }
356            
357            public void processInstanceTerminated(final ProcessInstance processInstance){
358                    SwingUtilities.invokeLater(new Runnable(){
359                            public void run(){
360                                    for(int i = processesTableModel.getRowCount() - 1; i >= 0; i--){
361                                            if(new Integer(processInstance.getProcessId()).equals(processesTableModel.getValueAt(i, 2))){
362                                                    debugToolBus.removeProcessInstanceBreakPoint(processInstance.getProcessId()); // Remove breakpoints (if present).
363                                                    processesTableModel.removeRow(i);
364                                            }
365                                    }
366                            }
367                    });
368            }
369            
370            public void processBreakPointHit(ProcessInstance processInstance){
371                    debugToolBus.doStop();
372                    final int processId = processInstance.getProcessId();
373                    SwingUtilities.invokeLater(new Runnable(){
374                            public void run(){
375                                    breakHighlightedRow = -1;
376                                    for(int row = processesTableModel.getRowCount() - 1; row >= 0; row--){
377                                            int pid = ((Integer) processesTableModel.getValueAt(row, 2)).intValue();
378                                            if(pid == processId){
379                                                    breakHighlightedRow = row;
380                                                    processesTable.scrollRectToVisible(processesTable.getCellRect(row, 1, true));
381                                                    ListSelectionModel selectionModel = processesTable.getSelectionModel();
382                                                    selectionModel.clearSelection();
383                                                    selectionModel.setSelectionInterval(row, row);
384                                                    break;
385                                            }
386                                    }
387                                    processesTable.repaint();
388                            }
389                    });
390            }
391            
392            public void stateElementBreakPointHit(StateElement stateElement){
393                    // Ignore, this viewer doesn't support breakpoints on state elements (yet).
394            }
395            
396            public void sourceBreakPointHit(StateElement stateElement){
397                    // Ignore, this viewer doesn't support breakpoints on source code coordinates (yet).
398            }
399            
400            private void clearSubscriptionsTable(){
401                    for(int i = subscriptionsTableModel.getRowCount() - 1; i >= 0; i--){
402                            subscriptionsTableModel.removeRow(i);
403                    }
404            }
405            
406            private void clearNoteQueueTable(){
407                    for(int i = noteQueueTableModel.getRowCount() - 1; i >= 0; i--){
408                            noteQueueTableModel.removeRow(i);
409                    }
410            }
411            
412            private void clearStateTable(){
413                    for(int i = stateTableModel.getRowCount() - 1; i >= 0; i--){
414                            stateTableModel.removeRow(i);
415                    }
416            }
417            
418            private void clearVariablesTable(){
419                    for(int i = variablesTableModel.getRowCount() - 1; i >= 0; i--){
420                            variablesTableModel.removeRow(i);
421                    }
422            }
423            
424            private void fillProcessTables(ProcessInstance processInstance){
425                    clearSubscriptionsTable();
426                    
427                    List<ATerm> subscriptions = processInstance.getSubscriptions();
428                    Iterator<ATerm> subscriptionIterator = subscriptions.iterator();
429                    while(subscriptionIterator.hasNext()){
430                            String subscription = getSubscriptionSignature(subscriptionIterator.next());
431                            subscriptionsTableModel.addRow(new Object[]{subscription});
432                    }
433                    
434                    
435                    clearNoteQueueTable();
436                    
437                    List<ATerm> noteQueue = processInstance.getNoteQueue();
438                    Iterator<ATerm> noteQueueIterator = noteQueue.iterator();
439                    while(noteQueueIterator.hasNext()){
440                            String note = getNoteSignature(noteQueueIterator.next());
441                            noteQueueTableModel.addRow(new Object[]{note});
442                    }
443                    
444                    
445                    clearStateTable();
446                    
447                    List<StateElement> stateElements = processInstance.getCurrentState().getElementsAsList();
448                    Iterator<StateElement> stateElementIterator = stateElements.iterator();
449                    while(stateElementIterator.hasNext()){
450                            StateElement stateElement = stateElementIterator.next();
451                            stateTableModel.addRow(new Object[]{stateElement});
452                    }
453            }
454            
455            private void fillVariables(StateElement stateElement){
456                    // Insert the new data in case the state element is an atom (and thus has an environment).
457                    if(stateElement != null && stateElement instanceof Atom){
458                            Atom atom = (Atom) stateElement;
459                            Environment environment = atom.getEnv();
460                            List<Binding> bindings = environment.getBindingsAsList();
461                            Iterator<Binding> bindingIterator = bindings.iterator();
462                            while(bindingIterator.hasNext()){
463                                    Binding binding = bindingIterator.next();
464                                    String var = binding.getVar().toString();
465                                    String val = getVariableSignature(binding.getVal());
466                                    variablesTableModel.addRow(new Object[]{var, val});
467                            }
468                    }
469            }
470            
471            private class TableSelectionListener implements ListSelectionListener{
472                    
473                    public TableSelectionListener(){
474                            super();
475                    }
476                    
477                    public void valueChanged(ListSelectionEvent e){
478                            if(e.getSource() == processesTable.getSelectionModel() && !e.getValueIsAdjusting()){
479                                    clearSubscriptionsTable();
480                                    clearNoteQueueTable();
481                                    clearStateTable();
482                                    clearVariablesTable();
483                                    
484                                    int row = processesTable.getSelectedRow();
485                                    if(row != -1){
486                                            int processId = ((Integer) processesTableModel.getValueAt(row, 2)).intValue();
487                                            
488                                            List<ProcessInstance> processInstances = debugToolBus.getProcesses();
489                                            Iterator<ProcessInstance> processInstancesIterator = processInstances.iterator();
490                                            while(processInstancesIterator.hasNext()){
491                                                    ProcessInstance pi = processInstancesIterator.next();
492                                                    if(pi.getProcessId() == processId){
493                                                            fillProcessTables(pi);
494                                                            break;
495                                                    }
496                                            }
497                                    }
498                }else if(e.getSource() == stateTable.getSelectionModel() && !e.getValueIsAdjusting()){
499                    clearVariablesTable();
500                    
501                    int row = stateTable.getSelectedRow();
502                    if(row != -1){
503                            StateElement stateElement = (StateElement) stateTableModel.getValueAt(row, 0);
504                            fillVariables(stateElement);
505                    }
506                }else{
507                    // This never happens, unless someone messed up the code.
508                }
509                    }
510            }
511            
512            private void clearProcessTableModifications(){
513                    lastExecutedProcessInstanceField.setText("");
514                    lastExecutedStateElementField.setText("");
515                    stepHighlightedRow = -1;
516                    breakHighlightedRow = -1;
517                    ListSelectionModel selectionModel = processesTable.getSelectionModel();
518                    selectionModel.clearSelection();
519                    processesTable.repaint();
520            }
521            
522            private class ButtonActionListener implements ActionListener{
523                    
524                    public ButtonActionListener(){
525                            super();
526                    }
527    
528                    public void actionPerformed(ActionEvent e){
529                            Object source = e.getSource();
530                            if(source == runButton){
531                                    clearProcessTableModifications();
532                                    debugToolBus.doRun();
533                            }else if(source == stopButton){
534                                    clearProcessTableModifications();
535                                    debugToolBus.doStop();
536                            }else if(source == stepButton){
537                                    clearProcessTableModifications();
538                                    debugToolBus.doStep();
539                            }else if(source == killButton){
540                                    debugToolBus.doTerminate();
541                                    frame.dispose();
542                            }else{
543                                    // This never happens, unless someone messed up the code.
544                            }
545                    }
546            }
547            
548            private final static TBTermFactory tbFactory = TBTermFactory.getInstance();
549            private final static ATerm emptyTerm = tbFactory.makeAppl(tbFactory.makeAFun("...", 0, false));
550            
551            private static ATerm substituteTerm(ATerm term, int maxDept){
552                    int termType = term.getType();
553                    switch(termType){
554                            case ATerm.APPL:
555                                    ATermAppl apt = (ATermAppl) term;
556                                    if(apt.getArity() == 0) return term;
557                                    
558                                    AFun afun = apt.getAFun();
559                                    ATerm args[] = apt.getArgumentArray();
560                                    ATermList annos = tbFactory.EmptyList; // Strip the annotations.
561                                    
562                                    if(maxDept <= 0) return tbFactory.makeAppl(tbFactory.makeAFun(afun.getName(), 1, false), new ATerm[]{emptyTerm}, annos);
563                                    
564                                    int nargs = args.length;
565                                    ATerm vargs[] = new ATerm[nargs];
566                                    for(int i = 0; i < nargs; i++){
567                                            vargs[i] = substituteTerm(args[i], maxDept - 1);
568                                    }
569                                    return tbFactory.makeAppl(afun, vargs, annos);
570                                    
571                            case ATerm.LIST:
572                                    if(maxDept <= 0){
573                                            ATermList emptyListTerm = tbFactory.EmptyList;
574                                            return emptyListTerm.insert(emptyTerm);
575                                    }
576                                    
577                                    ATermList tlst = (ATermList) term;
578                                    
579                                    if(tlst == tbFactory.EmptyList) return term;
580                                    
581                                    int len = tlst.getLength();
582                                    ATerm[] listContent = new ATerm[len];
583                                    for(int i = len - 1; i >= 0; i--){
584                                            listContent[i] = tlst.getFirst();
585                                            tlst = tlst.getNext();
586                                    }
587                                    
588                                    ATermList lst = tbFactory.EmptyList;
589                                    for(int i = 0; i < len; i++){
590                                            lst = lst.insert((substituteTerm(listContent[i], maxDept - 1)));
591                                    }
592                                    
593                                    // We can ignore annotations, since lists with annotations aren't supported anyway
594                                    
595                                    return lst;
596                            default:
597                                    return term;
598                    }
599            }
600            
601            private static String getSubscriptionSignature(ATerm term){
602                    ATerm result = substituteTerm(term, 3);
603                    
604                    return result.toString();
605            }
606            
607            private static String getNoteSignature(ATerm term){
608                    ATerm result = substituteTerm(term, 3);
609                    
610                    return result.toString();
611            }
612            
613            private static String getVariableSignature(ATerm term){
614                    ATerm result = substituteTerm(term, 2);
615                    
616                    return result.toString();
617            }
618            
619            public static void main(String[] args) throws ToolBusException{
620                    Viewer viewer = new Viewer(args);
621                    DebugToolBus debugToolBus = viewer.getDebugToolBus();
622                    debugToolBus.setBreakWhileStepping(false);
623                    
624                    CommandLine.createCommandLine(debugToolBus, System.in, false);
625                    
626                    debugToolBus.doStop(); // The initial state is stopped.
627                    
628                    debugToolBus.parsecup();
629                    debugToolBus.prepare();
630                    debugToolBus.execute();
631            }
632    }