Package codeStatistics.actions

Source Code of codeStatistics.actions.CodeStats$PatternSearchRunnable

package codeStatistics.actions;

import input.Configuration;
import input.ConfigurationReader;
import input.Pattern;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.transform.dom.DOMSource;

import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.ItemTypeFactory;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.WhitespaceStrippingPolicy;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmNode;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

import statistics.StatisticsCollector;
import statistics.StatisticsDetailsFactory;
import ast.XmlVisitor;
import codeStatistics.AnalysisPluginsManager;
import codeStatistics.AnalysisPluginsManager.Summary;
import codeStatistics.CodeStatisticsPlugin;
import codeStatistics.InfoMessageDialog;
import codeStatistics.Utils;
import codeStatistics.preferences.PreferenceConstants;
import codeStatistics.xpathfunctions.AstTextExtensionFunction;
import codeStatistics.xpathfunctions.ExtensionFunctions;
import codeStatistics.xpathfunctions.FunctionUtils;
import codeStatistics.xpathfunctions.GetAstNodeFunction;

/**
* Our sample action implements workbench action delegate. The action proxy will
* be created by the workbench and shown in the UI. When the user tries to use
* the action, this delegate will be created and execution will be delegated to
* it.
*
* @see IWorkbenchWindowActionDelegate
*/
public class CodeStats implements IWorkbenchWindowActionDelegate {
  private static final QName CONTEXT_VARIABLE = FunctionUtils.getName("context");
  private class PatternSearchRunnable implements IRunnableWithProgress{
    private final DocumentBuilder builder;
    private final XPathCompiler xpath;
    private final GetAstNodeFunction func;
    public Exception error;
    private Logger logger;
    private final ExtensionFunctions extFuncs;

    public PatternSearchRunnable(DocumentBuilder builder, XPathCompiler xpath, GetAstNodeFunction func,
        ExtensionFunctions extFuncs, Logger logger) {
      this.logger = logger;
      this.builder = builder;
      this.xpath = xpath;
      this.func = func;
      this.extFuncs = extFuncs;
    }

    private void processIcu(ICompilationUnit icu, DocumentBuilder builder,
        XPathCompiler xpath) throws Exception {
      IJavaProject project = icu.getJavaProject();
      CompilationUnit cu = Utils.parse(icu);
      //analysis
      ArrayList<Map<ASTNode, Object>> analysisResult = AnalysisPluginsManager.analyse(cu);
      for(int i=0; i < analysisResult.size(); i++)
        extFuncs.setAnalysisResult(i, analysisResult.get(i));

      XmlVisitor visitor = new XmlVisitor();
      cu.accept(visitor);
      func.setNodeMapping(visitor);
     
      String xmlDoc = Utils.print(visitor.getDocument());

      XdmNode sourceDoc = builder.build(new DOMSource(visitor.getDocument())); // builder.build(new
      // StreamSource(new
      // StringReader(xmlDoc)));
      logger.fine("Compilation unit is " + xmlDoc);
      Set<ASTNode> allMatchingNodes = findMatches(xmlDoc, configuration.allCasesDescriptor, visitor, sourceDoc, xpath).keySet();
      Set<ASTNode> notCategorized = new HashSet<ASTNode>(allMatchingNodes);
      for (Pattern description : configuration.categorizedCases) {
        Map<ASTNode, String> matchingNodes = null;
        try {
          matchingNodes = findMatches(xmlDoc, description, visitor, sourceDoc, xpath);
        } catch (Exception e) {
          System.out.println("ERROR in XPath: " + description.name + ", file:" + cu.getJavaElement().getPath().toString());
          func.setNodeMapping(null);
          throw e;
        }
        for (Map.Entry<ASTNode, String> entry: matchingNodes.entrySet()) {
          ASTNode node = entry.getKey();
          notCategorized.remove(node);
          if (!allMatchingNodes.contains(node)) {
            String message = "ERROR: In file "
                + icu.getElementName()
                + " line: "
                + cu.getLineNumber(node.getStartPosition())
                + "\nCategorized case not found in all matched cases:"
                + node.toString();
            logger.info(message);
            throw new RuntimeException(message);
          }
          statsCollector.add(project, cu, description.name, node, entry.getValue());
        }
      }
      for (ASTNode node : notCategorized) {
        statsCollector.add(project, cu, "notCategorized", node, null);
      }
      for (ASTNode node : allMatchingNodes) {
        statsCollector.add(project, cu, "ALL: " + configuration.allCasesDescriptor.name, node, null);
      }
      func.setNodeMapping(null);
      for(int i=0; i < analysisResult.size(); i++)
        extFuncs.setAnalysisResult(i, null);
    }
    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException,
        InterruptedException {
      try {
        List<ICompilationUnit> allTasks = Utils.getSelectedIcu(selection);
        monitor.beginTask("Executing pattern search", allTasks.size());
        for (ICompilationUnit icu : allTasks) {
          monitor.subTask("Processing: "+ icu.getParent().getElementName() + "." + icu.getElementName());
          processIcu(icu, builder, xpath);
          monitor.worked(1);
        }
      } catch (JavaModelException e) {
        error = e;
      } catch (Exception e) {
        error = e;
      } finally {
        monitor.done();
      }
    }
  }
 
  private IWorkbenchWindow window;
  private ITreeSelection selection;
  private StatisticsCollector statsCollector;
  private Configuration configuration;
  private Logger logger = Logger.getLogger("codeStats");
  private FileHandler logFileHandler;
  private XPathCompiler outputXPathCompiler;

  /**
   * The constructor.
   */
  public CodeStats() {
    statsCollector = new StatisticsCollector(
        StatisticsDetailsFactory.TOTAL_COUNT);
  }
 
  private XPathSelector compileExpr(XPathCompiler xpath, String expression) throws SaxonApiException {
    try {
      return xpath.compile(expression).load();
    } catch (SaxonApiException e) {
      System.err.println("Error compiling: '" + expression +"'");
      throw e;
    }
  }

  private Map<ASTNode, String> findMatches(String xmlDoc, Pattern description,
      XmlVisitor visitor, XdmNode sourceDoc, XPathCompiler xpath)
      throws SaxonApiException {
    Map<ASTNode, String> result = new HashMap<ASTNode, String>();
    String expression = description.xpath;
    XPathSelector selector = compileExpr(xpath, expression);
    selector.setContextItem(sourceDoc);
    XPathSelector outputBeforeSelector = null;
    if (description.outputBefore != null) {
      outputBeforeSelector = outputXPathCompiler.compile(description.outputBefore).load();
    }

    for (XdmItem item : selector) {
      String valueToInsertBefore = null;
      ASTNode node = Utils.getMappedAstNode(visitor, item);
      if (node == null)
        throw new RuntimeException("Found node is not in AST: " + item);
      if (outputBeforeSelector != null) {
        outputBeforeSelector.setContextItem(item);
        outputBeforeSelector.setVariable(CONTEXT_VARIABLE, item);
        valueToInsertBefore = outputBeforeSelector.evaluate().toString();
      }
      result.put(node, valueToInsertBefore);
    }

    return result;
  }

  private void doRun(IAction action) throws Exception {
    if (selection == null){
      MessageDialog.openInformation(window.getShell(), "Information",
          "No input files selected");
      return;
    }
    // Remove old handler
    if (logFileHandler != null) {
      logFileHandler.flush();
      logFileHandler.close();
      logger.removeHandler(logFileHandler);
    }

    // Set new logging parameters
    logger.setLevel(getLoggerLevel());
    statsCollector = new StatisticsCollector(getStatsLevel());

    logFileHandler = new FileHandler(CodeStatisticsPlugin.getDefault()
        .getPluginPreferences().getString(
            PreferenceConstants.P_LOG_FILE), true);
    logFileHandler.setFormatter(new java.util.logging.SimpleFormatter());
    logger.addHandler(logFileHandler);

    String xpathFile = CodeStatisticsPlugin.getDefault()
        .getPluginPreferences().getString(
            PreferenceConstants.P_XPATH_FILE);

    configuration = ConfigurationReader.loadConfiguration(xpathFile);

    Set<Object> roots = new HashSet<Object>();
    for (TreePath path : selection.getPaths()) {
      roots.add(path.getFirstSegment());
    }
    Processor proc = new Processor(false);
    ItemTypeFactory fact = new ItemTypeFactory(proc);
    GetAstNodeFunction func = new GetAstNodeFunction(fact);
    proc.registerExtensionFunction(func);
    proc.registerExtensionFunction(new AstTextExtensionFunction(fact));
    AnalysisPluginsManager.initialiseExtensions();
    ExtensionFunctions extFuncs = new ExtensionFunctions(fact, proc);
   
//    XPathCompiler xpath = proc.newXPathCompiler();
//    xpath.declareNamespace("cs", FunctionUtils.NAMESPACE);
    DocumentBuilder builder = proc.newDocumentBuilder();
    builder.setLineNumbering(true);
    builder.setWhitespaceStrippingPolicy(WhitespaceStrippingPolicy.ALL);

    //show progress dialog
    ProgressMonitorDialog dialog = new ProgressMonitorDialog(window.getShell());

    this.outputXPathCompiler = FunctionUtils.createCompiler(proc);
    this.outputXPathCompiler.declareVariable(CONTEXT_VARIABLE);

   
    PatternSearchRunnable runnable = new PatternSearchRunnable(builder, FunctionUtils.createCompiler(proc), func,
        extFuncs, logger);
    dialog.run(true, false, runnable);
    if (runnable.error != null){
      throw runnable.error;
    }
   
    //prepare summary dialog
    for(Summary summary: AnalysisPluginsManager.getSummaries())
      InfoMessageDialog.openInformation(window.getShell(), "Analysis summary", "Plugin:" + summary.title, summary.message);
    logger.info("current content of statsCollector: "
        + statsCollector.toString() + "\n");
  }

  /**
   * The action has been activated. The argument of the method represents the
   * 'real' action sitting in the workbench UI.
   *
   * @see IWorkbenchWindowActionDelegate#run
   */
  public void run(IAction action) {
    try {
      doRun(action);
    } catch (Throwable e) {
      Utils.displayError(window, e);
    }
  }

  private Level getLoggerLevel() {
    String levelName = CodeStatisticsPlugin.getDefault()
        .getPluginPreferences().getString(
            PreferenceConstants.P_LOG_LEVEL);
    if ("ALL".equals(levelName))
      return Level.INFO;
    return Level.INFO;
  }

  private int getStatsLevel() {
    String levelName = CodeStatisticsPlugin.getDefault()
        .getPluginPreferences().getString(
            PreferenceConstants.P_LOG_LEVEL);
    if ("FULL".equals(levelName))
      return StatisticsDetailsFactory.FULL_STATS;
    if ("COUNT_FOR_FILE".equals(levelName))
      return StatisticsDetailsFactory.COUNT_FOR_FILE;
    return StatisticsDetailsFactory.TOTAL_COUNT;
  }

  /**
   * Selection in the workbench has been changed. We can change the state of
   * the 'real' action here if we want, but this can only happen after the
   * delegate has been created.
   *
   * @see IWorkbenchWindowActionDelegate#selectionChanged
   */
  public void selectionChanged(IAction action, ISelection selection) {
    if (selection instanceof ITreeSelection) {
      this.selection = (ITreeSelection) selection;
    }
  }

  /**
   * We can use this method to dispose of any system resources we previously
   * allocated.
   *
   * @see IWorkbenchWindowActionDelegate#dispose
   */
  public void dispose() {
  }

  /**
   * We will cache window object in order to be able to provide parent shell
   * for the message dialog.
   *
   * @see IWorkbenchWindowActionDelegate#init
   */
  public void init(IWorkbenchWindow window) {
    this.window = window;
  }

}
TOP

Related Classes of codeStatistics.actions.CodeStats$PatternSearchRunnable

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.