Package lapsePlus.views

Source Code of lapsePlus.views.LapseView

package lapsePlus.views;

/*
* LapseView.java,version 2.8, 2010
*/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import lapsePlus.CallerFinder;
import lapsePlus.DefinitionLocation;
import lapsePlus.HistoryDefinitionLocation;
import lapsePlus.LapsePlugin;
import lapsePlus.NodeFinder;
import lapsePlus.Utils;
import lapsePlus.views.SinkView;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;

/**JAVA MODEL**/
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
//import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;


import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IProgressConstants;
import org.eclipse.ui.texteditor.IEditorStatusLine;
import org.eclipse.ui.texteditor.ITextEditor;

/**
* Main view class that calls most of the computational logic
* behind the slicer.
*
* It extends from ViewPart: an abstract base implementation of all workbench views.
*
* */
public class LapseView extends ViewPart{
 
  /********************************* Members *********************************/
  LocationViewer     fViewer; //Tree Viewer
  ProvenanceContentProvider fContentProvider;
  IJavaSearchScope   fSearchScope; 
  ITextEditor     fEditor;
  IOpenable       fOpenable;
  CompilationUnit   fRoot;
  IDocument       fCurrentDocument;
  SuperListener     fSuperListener;
  ASTParser       fParser; 
  Clipboard       fClipboard;
  LapseLayoutActionGroup fPullDownActions;
  SlicingJob       fSlicingJob;
  SlicingFromSinkJob  fSlicingFromSinkJob; 
 
  /********************************* Actions *********************************/ 
  private Action updateAction;
  private Action doubleClickAction;
  private Action prefAction;
  private Action historyAction;
  private Action selectAllAction;
  private LapseCopyAction copyAction;
 
  // Expansion/collapsing
  private Action collapseAction;
  private Action expandAction;
 
  private Action expandAllAction;
  private Action collapseAllAction;
  protected int fExpansionLevel;
 
  protected static final boolean TRACE = true;
  protected static final int MIN_EXPANSION_LEVEL = 0;

 
  public LapseView() {
    LapsePlugin.getDefault().setLapseView(this)
  }

  /**
   * Initializes this view
   */
  public void init(IViewSite site) throws PartInitException {
   
    log("In init(...)");
   
    super.setSite(site);
   
    if (fSuperListener == null) {
     
     
      fSuperListener = new SuperListener(this);
     
      //showMessage("Registering the plugin");
     
      //To track if the plugin is selected
      ISelectionService service = site.getWorkbenchWindow().getSelectionService();
     
      //We add a listener to notify if the selection has changed
      service.addPostSelectionListener(fSuperListener);
     
      //A file that can be edited by more than one client
      FileBuffers.getTextFileBufferManager().addFileBufferListener(fSuperListener);
     
    }
   
    //We create the parser for the Abstract Syntax Tree
    fParser = ASTParser.newParser(AST.JLS3);//Java Language Specifitacion 3
   
    fParser.setResolveBindings(true);//The compiler have to provide binding information for the AST nodes
   
    //Backward slicer from sinks
    fSlicingJob = new SlicingJob("Backward data slicer");
    fSlicingFromSinkJob = new SlicingFromSinkJob("Backward slicer from a sink", this);
   
  }
   
 
  public void createPartControl(Composite parent) {
   
    log("In createPartControl(...)");
    //viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
    fViewer = new LocationViewer(parent);
   
    fContentProvider = new ProvenanceContentProvider.HierarchicalViewContentProvider();
    fViewer.setContentProvider(fContentProvider);
    fViewer.setLabelProvider((IBaseLabelProvider) new DLTreeLabelProvider());
    //viewer.setSorter(new NameSorter());
    fViewer.setInput(getViewSite());
    fClipboard = new Clipboard(parent.getDisplay());

    makeActions();
    hookContextMenu();
    hookViewerEvents();
   
    fViewer.getControl().addKeyListener(new KeyListener() {
      public void keyPressed(KeyEvent event) {
        if ((event.stateMask & SWT.CTRL) != 0) {
                switch (event.keyCode) {
                  case '+' :
                    if(expandAction.isEnabled()) {
                      expandAction.run();
                    }
                  return;
                 
                  case '-' :
                    if(collapseAction.isEnabled()) {
                      collapseAction.run();
                    }
                  return;
                 
                  case 'L' :
                    if((event.stateMask & SWT.SHIFT) != 0 && updateAction.isEnabled()) {
                      updateAction.run();
                    }
                    return;
                }           
        }
      }
      public void keyReleased(KeyEvent e) {}
    });
       
    // obtain focus
    setFocus();
  }

  private void hookContextMenu() {
    MenuManager menuMgr = new MenuManager("#PopupMenu");
    menuMgr.setRemoveAllWhenShown(true);
    menuMgr.addMenuListener(new IMenuListener() {
      public void menuAboutToShow(IMenuManager manager) {
        fillContextMenu(manager);
      }
    });
    Menu menu = menuMgr.createContextMenu(fViewer.getControl());
    fViewer.getControl().setMenu(menu);
    getSite().registerContextMenu(menuMgr, fViewer);
  }

  private void contributeToActionBars() {
    IActionBars bars = getViewSite().getActionBars();
    //fillLocalPullDown(bars.getMenuManager());
    fillLocalToolBar(bars.getToolBarManager());
   
    fPullDownActions = new LapseLayoutActionGroup(this);
    fPullDownActions.fillActionBars(bars)
  }

  protected void fillContextMenu(IMenuManager manager) {
    //super.fillContextMenu(manager);
    //manager.add(updateAction);
    manager.add(selectAllAction);
    manager.add(copyAction);
   
    // Other plug-ins can contribute there actions here
    manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
  }

  private void fillLocalToolBar(IToolBarManager manager) {
    manager.add(updateAction);
    //manager.add(expandAction);
    manager.add(expandAllAction);
   
    //manager.add(collapseAction);
    manager.add(collapseAllAction);
   
    manager.add(prefAction);
    manager.add(historyAction);
    manager.add(copyAction);
  }

  class SlicingJob extends Job {
    public SlicingJob(String name) {
      super(name);
     
//      setProperty(IProgressConstants.ACTION_PROPERTY,
//          new Action("Pop up a dialog") {
//            public void run() {
//              MessageDialog.openInformation(getSite().getShell(),
//                  "Goto Action",
//                  "The job can have an action associated with it"
//              );
//            }
//      });
    }

    //Receives the monitor of the progress of the activity
    protected IStatus run(IProgressMonitor monitor) {
     
      IRunnableWithProgress runnable = new IRunnableWithProgress() {
       
        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException{       
         
          try {
            if(fRoot == null || fOpenable == null) {
              logError("Uninitialized inputs");
              throw new RuntimeException();
            }
           
            updateSlice(fRoot, fOpenable.getBuffer().getUnderlyingResource(), monitor);
           
          } catch (InvalidSlicingSelectionException e) {
            throw new RuntimeException(e);
          } catch (JavaModelException e) {
            throw new RuntimeException(e);
          }
        } 
       
      };
     
     
      try {
       
        runnable.run(monitor);       
       
        if(fContentProvider.getTotalElementCount() == 0) {             
          Display.getDefault().syncExec(new Runnable() {
            public void run() {
              setContentDescription("Error creating a slice");
            }
          });
          return Status.CANCEL_STATUS;
         
        } else {
            Display.getDefault().syncExec(new Runnable() {
             
            public void run() {
              // now enable the actions
              collapseAction.setEnabled(true);
              expandAction.setEnabled(true);
             
              collapseAllAction.setEnabled(true);
              expandAllAction.setEnabled(true);
             
              //System.err.println("Setting enabled to true");
              // enable actions in the menu
              fPullDownActions.setEnabled(true);
              refresh();
            }
           
            });
        }
       
        return Status.OK_STATUS;
      } catch (InvocationTargetException e) {
        log(e.getMessage(), e);
      } catch (InterruptedException e) {
                log(e.getMessage(), e);     
      } catch (RuntimeException e) {
                log(e.getMessage(), e);
      }
     
      return Status.CANCEL_STATUS;
    }
  }
 
  class SlicingFromSinkJob extends Job {
   
    ASTNode sink;
    CompilationUnit unit;
    IResource resource;
    private LapseView view;

    public SlicingFromSinkJob(String name, LapseView view) {
      super(name);
      this.view = view;
     
      setProperty(IProgressConstants.ACTION_PROPERTY,
          new Action("Pop up a dialog") {
            public void run() {
              MessageDialog.openInformation(getSite().getShell(), "Goto Action", "The job can have an action associated with it");
            }
      });
    }
     
    public void setSink(ASTNode sink) {
      this.sink = sink;
    }
   
    public ASTNode getSink() {
      return sink;
    }
   
    public IResource getResource() {
      return resource;
    }
   
    public void setResource(IResource resource) {
     
      if(resource == null) {
        throw new RuntimeException("Setting the resource to NULL");
      }
     
      this.resource = resource;
    }
   
    public CompilationUnit getUnit() {
      return unit;
    }
   
    public void setUnit(CompilationUnit unit) {
      if(unit == null) {
        throw new RuntimeException("Setting the unit to NULL");
      }
      this.unit = unit;
    }

    protected IStatus run(IProgressMonitor monitor) {
      IRunnableWithProgress runnable = new IRunnableWithProgress() {
        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {         
         
          try {           
            updateSlice(sink, unit, resource, monitor);
          } catch (InvalidSlicingSelectionException e) {
            throw new RuntimeException(e);
          }
        }       
      };
     
      try {
        try {
          runnable.run(monitor);
        } catch ( RuntimeException e) {         
          return Status.CANCEL_STATUS;
        }
       
        if(fContentProvider.getTotalElementCount() == 0) {             
          Display.getDefault().syncExec(new Runnable() {
            public void run() {
              setContentDescription("Error creating a slice");
            }
          });
          return Status.CANCEL_STATUS;
        } else {
          Display.getDefault().syncExec(new Runnable() {
            public void run() {
              // now enable the actions
              collapseAction.setEnabled(true);
              expandAction.setEnabled(true);
              collapseAllAction.setEnabled(true);
              expandAllAction.setEnabled(true);
              //System.err.println("Setting enabled to true");
              // enable actions in the menu
              fPullDownActions.setEnabled(true);
              view.getViewSite().getWorkbenchWindow().getActivePage().activate(view);
            }});
        }
       
        return Status.OK_STATUS;
      } catch (InvocationTargetException e) {
                log(e.getMessage(), e);
      } catch (InterruptedException e) {
                log(e.getMessage(), e);   
      } catch (RuntimeException e) {
                log(e.getMessage(), e);
        //showMessage("Invalid input state: " + e.getMessage());
      }
     
      return Status.CANCEL_STATUS;
    }
  }
 
  private void makeActions() {
    {
      updateAction = new Action() {
        public void run() {
          log("Pressed the update slice button");
          fSlicingJob.schedule();         
        }
      };
      updateAction.setText("Compute backward slice");
      updateAction.setToolTipText("Compute backward slice");
      ImageDescriptor desc = JavaPluginImages.DESC_OBJS_SEARCH_READACCESS;
      updateAction.setImageDescriptor(desc);
      updateAction.setHoverImageDescriptor(desc);
      updateAction.setAccelerator(SWT.CTRL | SWT.ALT | 'L');
    }
    {
      prefAction = new Action() {
        public void run() {
          LapseConfigurationDialog dialog =
            new LapseConfigurationDialog(fViewer.getControl().getShell());
          //dialog.create();
          dialog.open();
          dialog.getReturnCode();
        }
      };
      prefAction.setText("Set slicing preferences");
      prefAction.setToolTipText("Set slicing preferences");
      ImageDescriptor desc = JavaPluginImages.DESC_ELCL_FILTER;
      prefAction.setImageDescriptor(desc);
      prefAction.setHoverImageDescriptor(desc);
    }
   
    {
      historyAction = new HistoryDropDownAction(this);
      historyAction.setText("Slicing history");
      historyAction.setToolTipText("Slicing history");
      ImageDescriptor desc = JavaPluginImages.DESC_OBJS_SEARCH_REF;
      historyAction.setImageDescriptor(desc);
      historyAction.setHoverImageDescriptor(desc);
    }
   
    {
      collapseAction = new Action() {
        public void run() {
          if(fExpansionLevel == MIN_EXPANSION_LEVEL) {
            beep();
          }else {
            fExpansionLevel--;
            fViewer.collapseAll();
            fViewer.expandToLevel(fExpansionLevel);
            fViewer.getTree().setRedraw(true);
            fViewer.refresh();
            //System.out.println("Expansion level: " + fExpansionLevel);
          }         
        }
      };
      collapseAction.setText("Collapse one level");
      collapseAction.setToolTipText("Collapse one level (Ctrl -)");
      //updateAction.setAccelerator(SWT.CTRL | '-');
      collapseAction.setEnabled(false);
     
      JavaPluginImages.setLocalImageDescriptors(collapseAction, "collapseall.gif");
    }
   
    {
      expandAction = new Action() {
        public void run() {
          if(fExpansionLevel == fContentProvider.getDepth()) {
            beep();
          }else {
            fExpansionLevel++;
            fViewer.expandToLevel(fExpansionLevel);
            fViewer.getTree().setRedraw(true);
            fViewer.refresh();
            //System.out.println("Expansion level: " + fExpansionLevel);
          }
        }
      };
      expandAction.setText("Expand one level");
      expandAction.setToolTipText("Expand one level  (Ctrl +)");
      //updateAction.setAccelerator(SWT.CTRL | '+');
      expandAction.setEnabled(false);
 
      JavaPluginImages.setLocalImageDescriptors(expandAction, "pack_empty_co.gif");
   
   
    {
      collapseAllAction = new Action() {
        public void run() {
          if(fExpansionLevel != MIN_EXPANSION_LEVEL) {
            fExpansionLevel = MIN_EXPANSION_LEVEL; 
            fViewer.collapseAll();
            fViewer.getTree().setRedraw(true);
            fViewer.refresh();
            //System.out.println("Expansion level: " + fExpansionLevel);
          } else {
            beep();
          }         
        }
      };
      collapseAllAction.setText("Collapse all");
      collapseAllAction.setToolTipText("Collapse all");
      collapseAllAction.setEnabled(false);
     
      JavaPluginImages.setLocalImageDescriptors(collapseAllAction, "collapseall.gif");
    }
   
    {
      expandAllAction = new Action() {
        public void run() {
          if(fExpansionLevel != fContentProvider.getDepth()) {
            fExpansionLevel = fContentProvider.getDepth();
            fViewer.expandAll();
            fViewer.getTree().setRedraw(true);
            fViewer.refresh();
            //System.out.println("Expansion level: " + fExpansionLevel);
          } else {
            beep()
          }         
        }
      };
      expandAllAction.setText("Expand all");
      expandAllAction.setToolTipText("Expand all");
      expandAllAction.setEnabled(false);
     
      JavaPluginImages.setLocalImageDescriptors(expandAllAction, "pack_empty_co.gif");
   
    {
      copyAction = new LapseCopyAction(this, fClipboard, fViewer);
      copyAction.setText("Copy to clipboard");
      copyAction.setToolTipText("Copy to clipboard");
      copyAction.setEnabled(true);
      copyAction.setImageDescriptor(JavaPluginImages.DESC_DLCL_COPY_QUALIFIED_NAME);
    }
    {
      selectAllAction = new Action() {
        public void run() {
          fViewer.setSelection(
              new StructuredSelection(
                  fContentProvider.getAllElements()));
        }
      };
      selectAllAction.setText("Select all");
      selectAllAction.setToolTipText("Select all");
      selectAllAction.setEnabled(true);
      ISharedImages workbenchImages = JavaPlugin.getDefault().getWorkbench().getSharedImages();
      selectAllAction.setImageDescriptor(workbenchImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
    }
    log("Done making actions. Adding them to the bars.");
   
    contributeToActionBars();
  }
 
  private void setStatusBarMessage(String message, boolean isError) {
    IEditorStatusLine statusLine= (IEditorStatusLine) fEditor.getAdapter(IEditorStatusLine.class);
    if (statusLine != null) {
      statusLine.setMessage(false, message, JavaPluginImages.get(JavaPluginImages.IMG_MISC_PRIVATE));
    }else {
      logError("No status line!");
    }
    if(isError) {
      beep();
    }
  } 

  private void setStatusBarMessage(String message) {
    setStatusBarMessage(message, false);
  }
 
  private void beep() {
    if(fEditor != null) {
      fEditor.getSite().getShell().getDisplay().beep();
    }
  }

  private void hookViewerEvents()  {
    // double-click
    fViewer.addDoubleClickListener(new IDoubleClickListener() {
      public void doubleClick(DoubleClickEvent event) {
        // handle double-click in the pane
        if(doubleClickAction == null) {
          doubleClickAction = new Action() {
            public void run() {
              //System.err.println("Detected a double-click");
              ISelection selection = fViewer.getSelection();
              HistoryDefinitionLocation dl = (HistoryDefinitionLocation)
                    ((IStructuredSelection) selection).getFirstElement();             
              if(dl.getLineNumber() == DefinitionLocation.INVALID_SOURCE_LINE) {
                setStatusBarMessage("Invalid location", true);
                // invalid location -- get out of here
                return;
              }
             
              ITextEditor editor = null;
              try {
                editor = (ITextEditor) EditorUtility.openInEditor(dl.getResource());
              } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              }
              if(editor == null) {
                JavaPlugin.logErrorMessage("Can't open an editor for " + dl.getASTNode());
                return;
              }
             
              editor.selectAndReveal(
                  dl.getASTNode().getStartPosition(),
                  dl.getASTNode().getLength());             
             
              // activate the new window if necessary
              if(editor != fEditor) {
                try {                 
                  // reset the input
                  setInput(editor);
                 
                  // reactivate the editor
                  editor.getSite().getPage().activate(editor);
                 
                  log("Activated " + editor.getTitle());
                } catch (CoreException e) {
                                    log(e.getMessage(), e);
                  return;
                }
              }
              setStatusBarMessage("Opened " +
                  dl.getResource().getName() + ":" + dl.getLineNumber() +
                  " -- " + dl.toString());
            }
          };
        }

        doubleClickAction.run();
      }
    });
   
    fViewer.addSelectionChangedListener(new ISelectionChangedListener() {
      public void selectionChanged(SelectionChangedEvent event) {
        IStructuredSelection sel = (IStructuredSelection) event.getSelection();
        HistoryDefinitionLocation match = (HistoryDefinitionLocation) sel.getFirstElement();
        if(match != null) {
          IStatusLineManager slManager = getViewSite().getActionBars().getStatusLineManager();
          slManager.setMessage(match.toString());
        }
      }
    });
  }
  private void showMessage(String message) {
    MessageDialog.openInformation(fViewer.getControl().getShell(),
        "Provenance Tracker", message);
  }

  public void setFocus() {
    fViewer.getControl().forceFocus();
  }
 
  public static IOpenable getJavaInput(IEditorPart part) {
      IEditorInput editorInput= part.getEditorInput();
      if (editorInput != null) {
        IJavaElement input= (IJavaElement)editorInput.getAdapter(IJavaElement.class);
        if (input instanceof IOpenable) {
          return (IOpenable) input;
        }
      }
      return null
  }

  static VariableDeclaration name2decl(SimpleName sn, CompilationUnit cu, IResource resource){
    DeclarationInfoManager.DeclarationInfo info = DeclarationInfoManager.retrieveDeclarationInfo(cu);
    //System.out.println(info);
    VariableDeclaration decl = info.getVariableDeclaration(sn);
    if(decl == null) {
      logError("decl == null for " + sn)
    }
    return decl;
  }
 
  static boolean isFinal(SimpleName sn, CompilationUnit cu, IResource resource){
   
    DeclarationInfoManager.DeclarationInfo info = DeclarationInfoManager.retrieveDeclarationInfo(cu);
    return info.isFinal(sn);
  }
 
  /**
   * Tests whether a given expression is a String contant.
   * */
  public static boolean isStringContant(Expression arg, CompilationUnit cu, IResource resource) {
    if(arg instanceof StringLiteral) {   
      return true;
    } else
//    if(arg instanceof SimpleName) {
//      // find out if the name is final...
//    } else
    if(arg instanceof InfixExpression) {
      InfixExpression infixExpr = (InfixExpression) arg;
      if(!isStringContant(infixExpr.getLeftOperand(), cu, resource)) return false;
      if(!isStringContant(infixExpr.getRightOperand(), cu, resource)) return false;
           
      for(Iterator iter2 = infixExpr.extendedOperands().iterator(); iter2.hasNext(); ) {
        if(!isStringContant((Expression) iter2.next(), cu, resource)) {
          return false;
        }
      }
      return true;
    }
    // TODO: add final/const
   
    return false
  }

  void processNodeSelection(SimpleName sn, HistoryDefinitionLocation defl, CompilationUnit cu, IResource resource, IProgressMonitor monitor){
    //_cp.addElement("Visited node " + sn.toString());   
    if(name2decl(sn, cu, resource) == null) {
      // only deal with variables
      logError("No definition for " + sn + " is found");
      return;
    }
   
    //Name otherName = decl.getName();
    //String var = Name.getFullyQualifiedName();
   
    //fContentProvider.clearElements();
    // make the root of the slicing tree
    HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
        sn.toString(),
        (IFile)resource,
        cu.getLineNumber(sn.getStartPosition()),
        sn, defl, HistoryDefinitionLocation.INITIAL);
    if(defl==null){
    setCurrentInput(dl);
    addHistoryEntry(dl);
    fContentProvider.addElement(dl);
    }
    processDecl(sn, cu, resource, dl, new LinkedList<MethodInvocation>(), monitor);
     
    //showMessage("Got " + _cp.getElementsCount() + " in the list");     
    //fViewer.setSelection(new StructuredSelection(covering));
  }
   
  private void processDecl(SimpleName name, CompilationUnit cu, IResource resource,
      HistoryDefinitionLocation parent, LinkedList<MethodInvocation> stack,
      IProgressMonitor monitor)
  {   
    VariableDeclaration decl = name2decl(name, cu, resource);
//    if(TRACE) System.out.print('.');
    if(monitor.isCanceled()) {
      // check if the search has been cancelled
      return;
    }
    //monitor.setTaskName("Processing " + name + " in " + resource.getName/*getFullPath*/());
    monitor.subTask("Processing " + name + " in " + resource.getName/*getFullPath*/());
       
    if(decl == null) {
      logError(
          "decl: " + decl + " on line " + (decl == null ? DefinitionLocation.INVALID_SOURCE_LINE : fRoot.getLineNumber(decl.getStartPosition())) +
          " and name: " + name + "(" + name.hashCode() + ") on line " + fRoot.getLineNumber(name.getStartPosition()));
     
      // the case of no declaration found -- add a question mark
      /*HistoryDefinitionLocation dl = */new HistoryDefinitionLocation(
          name.toString(),
          null,  // this will be ignored
          DefinitionLocation.INVALID_SOURCE_LINE,
          name, parent, HistoryDefinitionLocation.UNDEFINED);
      //System.out.println("Case 1");
    } else
    if(decl.getParent() instanceof MethodDeclaration){
      // the case of a parameter -- add the actuals and recurse
      //showMessage(decl.toString() + " is a parameter of " + parent.getClass());
      MethodDeclaration methodDecl = (MethodDeclaration) decl.getParent();
      IMethod method = new MethodFinder((IFile) resource).convertMethodDecl2IMethod(methodDecl);
      if(method == null) {
        JavaPlugin.logErrorMessage("Internal error: No method found for " + methodDecl);
        return;
      }

      HistoryDefinitionLocation paramDL = new HistoryDefinitionLocation(
          decl.toString(),
          resource,
          cu.getLineNumber(decl.getStartPosition()),
          decl, parent, HistoryDefinitionLocation.FORMAL_PARAMETER);
      if(!registerExpansion(paramDL)) {
        // recursion detected here
        return;
      }

      Expression onlyCall = (Expression) (stack.isEmpty() ? null : stack.getLast());
      log("Looking for calls from " + onlyCall);
      Collection/*<ExpressionUnitPair>*/ c = CallerFinder.getActualsForFormal(method, name, onlyCall, monitor, null);
      if(c.isEmpty()){
        logError(
            "No suitable actual arguments for formal argument " +
            name + " of " + method.getElementName() + " at " +
            resource.getName() + " found");
      } else
      for (Iterator iter = c.iterator(); iter.hasNext();) {
        Utils.ExpressionUnitPair eup = (Utils.ExpressionUnitPair) iter.next();
        Expression     e        = eup.getExpression();
        CompilationUnit nextCU     = eup.getCompilationUnit();
        IResource     nextResource = eup.getResource();
               
        processExpression(paramDL, e, nextCU, nextResource, stack, monitor, HistoryDefinitionLocation.CALL_ARG,false);
      }
      //System.out.println("Case 2");
    } else {
      /**
       * The case of a declaration -- look at the right hand side.
       * */
      Object obj = (decl.getParent() instanceof VariableDeclaration) ?
          decl.getParent() :
          decl;         
      String desc = obj.toString();
      int type = (decl.getParent() instanceof FieldDeclaration) ?
            HistoryDefinitionLocation.FIELD :
            HistoryDefinitionLocation.DECLARATION;
      // the case of a regilar declaration being found
      HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
          desc,
          resource,
          cu.getLineNumber(decl.getStartPosition()),
          decl, parent, type);
      Expression e = decl.getInitializer();
     
      if(e != null) {
        // TODO: add processing of the RHS of the declaration
        processExpression(dl, e, cu, resource, stack, monitor, HistoryDefinitionLocation.COPY,false);
      }
      //System.out.println("Case 3");
    }
  }

  protected void processExpression(HistoryDefinitionLocation parent,
      Expression e, CompilationUnit cu, IResource resource, LinkedList<MethodInvocation> stack,
      IProgressMonitor monitor, int defaultType, boolean first)
  {
    log("In processExpression with expr=" + e);
   
    monitor.subTask("Processing " + e.toString());
    SimpleName nextName = CallerFinder.SlicingUtils.getVariable(e);
    if(nextName != null) {
      /**
       * Follow a simple assignment.
       * */
      HistoryDefinitionLocation actualDL = new HistoryDefinitionLocation(
          nextName/*.getParent()*/.toString(),
          resource,
          cu.getLineNumber(nextName.getStartPosition()),
          nextName,
          parent, defaultType);
      //showMessage("Type " + nextName.getParent().getClass());         
     
      // marks actualDL as recursive if necessary
      if(registerExpansion(actualDL)) {
        processDecl(nextName, cu, resource, actualDL, stack, monitor);
      }
    } else
    if(e instanceof MethodInvocation) {
      /**
       * Go back through a method invocation.
       * */
      MethodInvocation mi = (MethodInvocation) e;
      SimpleName methodName = mi.getName();
      log("Going back through callee " + methodName.toString());
      HistoryDefinitionLocation callDL;
      if(!first){
      callDL= new HistoryDefinitionLocation(
          mi.toString(),
          resource,
          cu.getLineNumber(mi.getStartPosition()),
          mi,
          parent, HistoryDefinitionLocation.CALL);
      }
      else{
        callDL=parent;
      }
     
      if(registerExpansion(callDL)) {
        Collection/*<MethodDeclarationUnitPair>*/ callees = CallerFinder.findCallees(monitor, methodName.toString(), null, false);
        if(callees.isEmpty()) {
          if(SinkView.isDerivationName(methodName.getFullyQualifiedName()))
          {
              HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
                  mi.getExpression().toString(),
                  resource,
                  cu.getLineNumber(mi.getStartPosition()),
                  mi.getExpression(), callDL, HistoryDefinitionLocation.DERIVATION);
              if(registerExpansion(dl)) {
                Expression expr = mi.getExpression();
                if(expr != null) {
                  // Recurse on the returned expression
                  processExpression(dl, expr, cu, resource, stack, monitor, HistoryDefinitionLocation.DERIVATION,false);
                 
                }
              }
          }
          else{
          logError("No suitable callees for " + methodName + " in " + resource + " found");
          System.out.println("No suitable callees for " + methodName + " in " + resource + " found");
          }
        } else
        for (Iterator iter = callees.iterator(); iter.hasNext();) {
          Utils.MethodDeclarationUnitPair element
                            = (Utils.MethodDeclarationUnitPair) iter.next();
          MethodDeclaration methodDeclaration = element.getMethod();
          CompilationUnit nextCU         = element.getCompilationUnit();
          IResource nextResource         = element.getResource();       
       
          if(methodDeclaration  != null){
            if(!LapsePlugin.FOLLOW_INTO_FUNCTIONS) {
              /*HistoryDefinitionLocation dl = */new HistoryDefinitionLocation(
                  "Method " + methodDeclaration.getName().getFullyQualifiedName(),
                  nextResource,
                  nextCU.getLineNumber(e.getStartPosition()),
                  methodDeclaration, callDL, HistoryDefinitionLocation.RETURN);
            } else {
              Collection/*<ReturnStatement>*/ returns = CallerFinder.findReturns(monitor, methodDeclaration, null);
              for (Iterator iter2 = returns.iterator(); iter2.hasNext();) {
                ReturnStatement returnStmt = (ReturnStatement) iter2.next();
             
                HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
                    returnStmt.toString(),
                    nextResource,
                    nextCU.getLineNumber(returnStmt.getStartPosition()),
                    returnStmt, callDL, HistoryDefinitionLocation.RETURN);
                if(registerExpansion(dl)) {
                  Expression expr = returnStmt.getExpression();
                  if(expr != null) {
                    // Recurse on the returned expression
                    stack.addLast(mi);
                    processExpression(dl, expr, nextCU, nextResource, stack, monitor, HistoryDefinitionLocation.COPY,false);
                    stack.removeLast();
                  }
                }
              }
            }
          }
          else{
            //check if it is a derivtion expression
            if(SinkView.isDerivationName(methodName.getFullyQualifiedName()))
            {
       
                    processExpression(callDL, mi.getExpression(), cu, resource, stack, monitor, HistoryDefinitionLocation.DERIVATION,false);
               
                break;
            }
          } 
        }
      }
    } else
    if ( e instanceof InfixExpression && ( ((InfixExpression)e).getOperator() == InfixExpression.Operator.PLUS ) ) {
      /**
       * Follow arguments of a string concatenation.
       * */
      InfixExpression ie   = (InfixExpression) e;
      Expression leftExpr  = ie.getLeftOperand();
      Expression rightExpr = ie.getRightOperand();
      HistoryDefinitionLocation concatDL;
      if(!first){
      concatDL = new HistoryDefinitionLocation(
          e.toString(),
          resource,
          cu.getLineNumber(e.getStartPosition()),
          e,
          parent, HistoryDefinitionLocation.STRING_CONCAT);
      }
      else
      concatDL=parent;
     
      if(registerExpansion(concatDL)) {
        processExpression(concatDL, leftExpr,  cu, resource, stack, monitor, HistoryDefinitionLocation.COPY,false);
        processExpression(concatDL, rightExpr, cu, resource, stack, monitor, HistoryDefinitionLocation.COPY,false);
        if(ie.extendedOperands() != null) {
            for(Iterator iter = ie.extendedOperands().iterator(); iter.hasNext(); ) {
                Expression ext_e = (Expression) iter.next();
               
                processExpression(concatDL, ext_e, cu, resource, stack, monitor, HistoryDefinitionLocation.COPY,false);                     
            }
        }
      }
    }
    else if(e instanceof ParenthesizedExpression){
      ParenthesizedExpression ex=(ParenthesizedExpression)e;
      processExpression(parent, ex.getExpression(), cu, resource, stack, monitor, HistoryDefinitionLocation.UNDEFINED,false);
    }
    else if(e instanceof CastExpression){
      CastExpression cex=(CastExpression)e;
      processExpression(parent, cex.getExpression(), cu, resource, stack, monitor, HistoryDefinitionLocation.UNDEFINED,false);
    }
    else if(e instanceof ArrayAccess) {
      ArrayAccess ae=(ArrayAccess)e;
     
      HistoryDefinitionLocation arrAccess;
      if(!first){
        arrAccess= new HistoryDefinitionLocation(
          e.toString(),
          resource,
          cu.getLineNumber(e.getStartPosition()),
          e,
          parent, HistoryDefinitionLocation.ARRAYACCESS);
      }
      else arrAccess=parent;
      if(registerExpansion(arrAccess))
        processExpression(arrAccess, ae.getArray(),  cu, resource, stack, monitor, HistoryDefinitionLocation.ARRAYACCESS,false);
     
    }
    else if(e instanceof ClassInstanceCreation)
    {
      ClassInstanceCreation c=(ClassInstanceCreation)e;
      HistoryDefinitionLocation cc;
      if(!first){
      cc= new HistoryDefinitionLocation(
          e.toString(),
          resource,
          cu.getLineNumber(e.getStartPosition()),
          e,
          parent, HistoryDefinitionLocation.CLASS_INSTANCE_CREATION);
      }else
        cc=parent;
      String aux=(c.getType()).toString();
      if(SinkView.isDerivationName(aux)){
        for(Object arg:c.arguments()){
          if(registerExpansion(cc))
          processExpression(cc,(Expression)arg,cu,resource,stack,monitor,HistoryDefinitionLocation.DERIVATION,false);
        }
    }
      }
    else {
      /**
       * Some other expression.
       */
      /*HistoryDefinitionLocation dl = */new HistoryDefinitionLocation(
          e.toString(),
          resource,
          cu.getLineNumber(e.getStartPosition()),
          e, parent, getExpressionType(e, cu, resource));           
    }
  }
   
  private int getExpressionType(Expression expr, CompilationUnit cu, IResource resource) {
    if(isStringContant(expr, cu, resource)) {
      return HistoryDefinitionLocation.STRING_CONSTANT;
    }else if(expr instanceof NullLiteral){
      return HistoryDefinitionLocation.NULL;
    }
    else {
      return HistoryDefinitionLocation.UNDEFINED;
    }
  }

  /**
   * @return false means that propagation should be stopped.
   * */
  private boolean registerExpansion(HistoryDefinitionLocation dl) {
    /**
     * Recursion point is here. Before we recurse, we want to make sure we are not entering a
     * potentially infinite loop, so, here goes an occurs check.
     * */
    if(dl.containsAncestor(dl.getASTNode())){
      dl.setRecursive(true);
      logError("Recursion detected for " + dl.getASTNode());
      return false;
    }
    if ( dl.getDepth() >= LapsePlugin.getMaxCallDepth()) {
      dl.setMaxLevel(true);
      logError("Depth of  " +  LapsePlugin.getMaxCallDepth() + " exceeded");
      return false;
    }
    //System.out.println("Recursing on " + dl.getASTNode() + " depth = " + dl.getDepth());
    return true;
  }

  protected void refresh() {
    Display.getDefault().syncExec(new Runnable() {
      public void run() {
        setContentDescription("Created a slice with " +
            fContentProvider.getLeafElementCount() + " leaf element(s) and " +
            fContentProvider.getTotalElementCount() + " element(s) " +
            "located in " + fContentProvider.getFileCount() + " file(s) with " +
            fContentProvider.getTruncatedElementCount() + " element(s) truncated " +
            "with a maximum depth of  " + fContentProvider.getDepth() + ". " +
            "Using a " +
              (fContentProvider instanceof ProvenanceContentProvider.FlatViewContentProvider ?
                  "flat" :
                    "hierarchical")
            " viewer.");
        fViewer.refresh();
        fViewer.expandAll();
        fExpansionLevel = fContentProvider.getDepth();
       
        ISelection selection = fContentProvider.getFirstElement();
        if(selection != null) {
          fViewer.setSelection(selection, true);
        }
      }
    });
  }

  public void setInput(ITextEditor editor) throws CoreException {
    if (fEditor != null) {
      uninstallModificationListener();
    }
 
    fEditor = null;
    fRoot   = null;
    if(editor == null) {
      logError("editor is set to null");
      return;
    }
 
    IOpenable openable = getJavaInput(editor);
    if (openable == null) {
      throw new RuntimeException("Editor not showing a classfile");
    }
    // reset the fields
    fOpenable = openable;
    fRoot     = internalSetInput(openable);
    fEditor    = editor;
   
    installModificationListener();
 
 
  private CompilationUnit internalSetInput(IOpenable input) throws CoreException {
    IBuffer buffer = input.getBuffer();
    if (buffer == null) {
      JavaPlugin.logErrorMessage("Input has no buffer"); //$NON-NLS-1$
    }
    if (input instanceof ICompilationUnit) {
      fParser.setSource((ICompilationUnit) input);
    } else {
      fParser.setSource((IClassFile) input);
    }

    try {
      CompilationUnit root = (CompilationUnit) fParser.createAST(null);
      log("Recomputed the AST for " + buffer.getUnderlyingResource().getName());
             
      if (root == null) {
        JavaPlugin.logErrorMessage("Could not create AST"); //$NON-NLS-1$
      }
 
      return root;
    } catch (RuntimeException e) {
      JavaPlugin.logErrorMessage("Could not create AST:\n" + e.getMessage()); //$NON-NLS-1$
      return null;
    }
  }

  //--------------------------- Utilities ---------------------------
  private void installModificationListener() {
    fCurrentDocument = fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
    fCurrentDocument.addDocumentListener(fSuperListener);
  }

  void uninstallModificationListener() {
    if (fCurrentDocument != null) {
      fCurrentDocument.removeDocumentListener(fSuperListener);
      fCurrentDocument = null;
    }
  }

  void updateSlice(CompilationUnit unit, IResource resource, IProgressMonitor monitor) throws InvalidSlicingSelectionException {
    final NodeFinder finder = new NodeFinder();
    Display.getDefault().syncExec(new Runnable() {
      public void run() {
        try {
          if(fEditor == null) {
            JavaPlugin.logErrorMessage("fEditor == null, can't compute the slice");
            return;
          }
          ISelectionProvider selProv = fEditor.getSelectionProvider();
          if(selProv == null) {
            throw new InvalidSlicingSelectionException("No selection provider. Something is wrong.");
          }
          ISelection selection = selProv.getSelection();
          if(selection == null) {
            throw new InvalidSlicingSelectionException("No selection detected. Please select an identifier.");
          }
          if(! (selection instanceof ITextSelection) ) {
            throw new InvalidSlicingSelectionException("Selection type is not valid. Please select an identifier in a Java text editor.");
          }
          ITextSelection textSelection = (ITextSelection) selection;
          log("Working with " + textSelection.getText() + " in " + fEditor.getTitle());
         
          /*if(textSelection.getLength() == 0) {
            throw new InvalidSlicingSelectionException("The selection is empty. Please select an identifier.");
          }*/
          if(fRoot == null) {
            throw new InvalidSlicingSelectionException("No current document for the plugin. Something is wrong.")
          }
         
          finder.setOffset(textSelection.getOffset());
          finder.setLength(textSelection.getLength());

          fRoot.accept(finder);
        } catch (InvalidSlicingSelectionException e) {
          throw new RuntimeException(e);
        }
      }
    });
   
    // found the relevant ASTNode
    ASTNode covering = finder.getCoveringNode();
    updateSlice(covering, unit, resource, monitor);   
   
    // restore editor position
    // TODO:
    //fEditor.setHighlightRange(textSelection.getOffset(), textSelection.getLength(), true);
  }
 
  void updateSlice(final ASTNode covering, CompilationUnit unit, IResource resource, IProgressMonitor monitor) throws InvalidSlicingSelectionException {
    log("Working with " + covering);
    if(covering instanceof SimpleName) {
      String initialLocation = resource.getFullPath().toOSString() + ":" + unit.getLineNumber(covering.getStartPosition());
      monitor.setTaskName("Computing a backwards slice for " + covering + " at " +
          (initialLocation != null? initialLocation : "") );
      monitor.beginTask("Started the computation", 100);
     
      processNodeSelection((SimpleName)covering,null,unit, resource, monitor);
         
      //String line = "sn: " + sn + ", var: " + var + ", line: " + fRoot.lineNumber(decl.getStartPosition());
      // refresh the screen
     
      refresh();
     
      // finish the job       
      monitor.done();
      }
    else if(covering instanceof InfixExpression){
      InfixExpression infixExpr = (InfixExpression) covering;
      HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
          infixExpr.toString(),
          (IFile)resource,
          unit.getLineNumber(0),
          covering,null, HistoryDefinitionLocation.STRING_CONCAT);
     
      processExpression(dl, infixExpr, unit, resource, new LinkedList<MethodInvocation>(), monitor, HistoryDefinitionLocation.INITIAL,true);
      setCurrentInput(dl);
      addHistoryEntry(dl);
      fContentProvider.addElement(dl);
      refresh();
      }
     else if(covering instanceof ArrayAccess) {
       ArrayAccess ae=(ArrayAccess)covering;
       HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
      ae.toString(),
            (IFile)resource,
            unit.getLineNumber(0),
            covering,null, HistoryDefinitionLocation.ARRAYACCESS);
        processExpression(dl, ae, unit, resource, new LinkedList<MethodInvocation>(), monitor, HistoryDefinitionLocation.INITIAL,true);
        setCurrentInput(dl);
        addHistoryEntry(dl);   
        fContentProvider.addElement(dl);
       
        refresh();
       
      }
       else if(covering instanceof CastExpression) {
         CastExpression ae=(CastExpression)covering;
         HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
              ae.toString(),
              (IFile)resource,
              unit.getLineNumber(0),
              covering,null, HistoryDefinitionLocation.INITIAL);
          processExpression(dl, ae, unit, resource, new LinkedList<MethodInvocation>(), monitor, HistoryDefinitionLocation.CALL,true);
          setCurrentInput(dl);
          addHistoryEntry(dl);
          fContentProvider.addElement(dl);
          refresh();
        }
       else if(covering instanceof ClassInstanceCreation) {
         ClassInstanceCreation ae=(ClassInstanceCreation)covering;
         HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
              ae.toString(),
              (IFile)resource,
              unit.getLineNumber(0),
              covering,null, HistoryDefinitionLocation.CLASS_INSTANCE_CREATION);
          processExpression(dl, ae, unit, resource, new LinkedList<MethodInvocation>(), monitor, HistoryDefinitionLocation.CALL,true);
          setCurrentInput(dl);
          addHistoryEntry(dl);
          fContentProvider.addElement(dl);
          refresh();
        }
       else if(covering instanceof MethodInvocation) {
        MethodInvocation mi=(MethodInvocation)covering;
        HistoryDefinitionLocation dl = new HistoryDefinitionLocation(
              mi.toString(),
              (IFile)resource,
              unit.getLineNumber(0),
              covering,null, HistoryDefinitionLocation.CALL);
          processExpression(dl, mi, unit, resource, new LinkedList<MethodInvocation>(), monitor, HistoryDefinitionLocation.CALL,true);
          setCurrentInput(dl);
          addHistoryEntry(dl);
          fContentProvider.addElement(dl);
          refresh()
        }
    else{
      // do nothing...
      //throw new InvalidSlicingSelectionException
      Display.getDefault().syncExec(new Runnable() {
        public void run() {
          showMessage("No valid identifier corresponds to " + covering);
        }}
      );
     
    }
   
  }

  public boolean isFlatLayout() {
    return fContentProvider instanceof ProvenanceContentProvider.FlatViewContentProvider;
  }
  void toggleViewer() {
    if(fContentProvider == null) {
      JavaPlugin.logErrorMessage("In switchViewer with null");
      return;
    }
    // do the switch
    fContentProvider = fContentProvider.switchType();
    fViewer.setContentProvider(fContentProvider);
   
    //System.out.println("Switched the viewer type to " + fContentProvider);
    refresh();
  }
 
  //-------------------------------------------- History ---------------------------------------------
  private LinkedList<HistoryDefinitionLocation> fInputHistory = new LinkedList<HistoryDefinitionLocation>();
//  private HistoryDefinitionLocation fCurrentInput;
  /**
   * Adds the entry if new. Inserted at the beginning of the history entries list.
   */   
  private void addHistoryEntry(HistoryDefinitionLocation entry) {
    HistoryDefinitionLocation oldEntry = getHistoryEntry(entry);
    if (oldEntry != null) {
      fInputHistory.remove(oldEntry);
    }
   
    fInputHistory.add(0, entry);
   
    historyAction.setEnabled(true);
  }
 
  private HistoryDefinitionLocation getHistoryEntry(HistoryDefinitionLocation entry) {
    for (Iterator iter = fInputHistory.iterator(); iter.hasNext();) {
      HistoryDefinitionLocation element = (HistoryDefinitionLocation) iter.next();
      if(element.getASTNode() == entry.getASTNode()) {
        return element;
      }
    }
    return null;
  }
 
  private void updateHistoryEntries() {
        for (int i = fInputHistory.size() - 1; i >= 0; i--) {
            HistoryDefinitionLocation type = fInputHistory.get(i);
        }
        historyAction.setEnabled(!fInputHistory.isEmpty());
    }
 
  /**
   * Goes to the selected entry, without updating the order of history entries.
   */ 
  public void gotoHistoryEntry(HistoryDefinitionLocation entry) {
    if (fInputHistory.contains(entry)) {
      setCurrentInput(entry);    // TODO
      refresh();
    }
  }
 
  /**
   * Gets all history entries.
   */
  public HistoryDefinitionLocation[] getHistoryEntries() {
    if (fInputHistory.size() > 0) {
      updateHistoryEntries();
    }
    return (HistoryDefinitionLocation[]) fInputHistory.toArray(
        new HistoryDefinitionLocation[fInputHistory.size()]);
  }
 
  /**
   * Sets the history entries
   */
  public void setHistoryEntries(HistoryDefinitionLocation[] elems) {
    fInputHistory.clear();
    for (int i= 0; i < elems.length; i++) {
      fInputHistory.add(elems[i]);
    }
    updateHistoryEntries();
  }

  public HistoryDefinitionLocation getCurrentInput() {
    return fContentProvider.getCurrentInput();
  }
  public void setCurrentInput(HistoryDefinitionLocation currentInput) {
    fContentProvider.setCurrentInput(currentInput);
    //if(lastVariable)
    refresh();
  }

  public SlicingFromSinkJob getSinkSlicingJob() {
    return this.fSlicingFromSinkJob;
  }
   
     private static void log(String message, Throwable e) {
        LapsePlugin.trace(LapsePlugin.ALL_DEBUG, "Lapse view: " + message, e);
    }
   
    private static void logError(String message) {
        log(message, new Throwable());
    }
   
    private static void log(String message) {
        log(message, null);
    }
}



//Tree Viewer for Provenance Tracker
class LocationViewer extends TreeViewer {
   
  LocationViewer(Composite parent) {
      super(new Tree(parent, SWT.MULTI));//For Multiselection behaviour in lists or text fields
//      setAutoExpandLevel(ALL_LEVELS);
    }
   
    /**
     * Attaches a contextmenu listener to the tree
     */
    void initContextMenu(IMenuListener menuListener, String popupId, IWorkbenchPartSite viewSite) {
       
      MenuManager menuMgr= new MenuManager();
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(menuListener);
       
        Menu menu= menuMgr.createContextMenu(getControl());
       
        getControl().setMenu(menu);
        viewSite.registerContextMenu(popupId, menuMgr, this);
    }
}


class InvalidSlicingSelectionException extends Exception {
  /**
   *
   */
  private static final long serialVersionUID = 1L;

  InvalidSlicingSelectionException(String message){
    super(message);
  }
}


class LapseCopyAction extends Action {
    private static final char INDENTATION= '\t';
   
    private LapseView fView;
    private LocationViewer fViewer;
    private final Clipboard fClipboard;

    public LapseCopyAction(LapseView view, Clipboard clipboard, LocationViewer viewer) {
       
      super("LapseCopyAction");//we create the copy action with the name given
     
        Assert.isNotNull(clipboard);
       
        //WorkbenchHelp.setHelp(this, IJavaHelpContextIds.CALL_HIERARCHY_COPY_ACTION);
       
        fView= view;
        fClipboard= clipboard;
        fViewer= viewer;
    }

    public void run() {
        StringBuffer buf= new StringBuffer();
       
        addCalls(fViewer.getTree().getSelection()[0], 0, buf);//we get the node selected in the tree

        TextTransfer plainTextTransfer = TextTransfer.getInstance();//for converting plain text in a String into Platform specific representation
       
        try{
            fClipboard.setContents(
                new String[]{ convertLineTerminators(buf.toString()) },
                new Transfer[]{ plainTextTransfer });
        catch (SWTError e){
            if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD)
                throw e;
            if (MessageDialog.openQuestion(fView.getViewSite().getShell(),
                    ("CopyCallHierarchyAction.problem"), ("CopyCallHierarchyAction.clipboard_busy"))
            )
            {
                run();
            }
        }
    }
   
    private void addCalls(TreeItem item, int indent, StringBuffer buf) {
        for (int i= 0; i < indent; i++) {
            buf.append(INDENTATION);
        }

        buf.append(item.getText());
        buf.append('\n');
       
        if (item.getExpanded()) {
            TreeItem[] items= item.getItems();
            for (int i= 0; i < items.length; i++) {
                addCalls(items[i], indent + 1, buf);
            }
        }       
    }
  
    private String convertLineTerminators(String in) {
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        StringReader stringReader = new StringReader(in);
        BufferedReader bufferedReader = new BufferedReader(stringReader);      
        String line;
        try {
            while ((line= bufferedReader.readLine()) != null) {
                printWriter.println(line);
            }
        } catch (IOException e) {
            return in; // return the call hierarchy unfiltered
        }
        return stringWriter.toString();
    }
}
TOP

Related Classes of lapsePlus.views.LapseView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.