org.splevo.ui.refinementbrowser.ArgoUMLVariantScanHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.splevo.ui.refinementbrowser.ArgoUMLVariantScanHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2014
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Benjamin Klatt
 *******************************************************************************/
package org.splevo.ui.refinementbrowser;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.HandlerUtil;
import org.splevo.vpm.refinement.Refinement;
import org.splevo.vpm.software.SoftwareElement;
import org.splevo.vpm.software.SourceLocation;
import org.splevo.vpm.variability.Variant;
import org.splevo.vpm.variability.VariationPoint;

import com.google.common.base.Joiner;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Lists;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;

/**
 * Action to scan the selected variation points for indicators which feature the variant
 * implementing software elements belong to.
 */
public class ArgoUMLVariantScanHandler extends AbstractHandler {

    private static final String MARKER = "//@#$LPS-";
    private static final int MARKER_LENGTH = MARKER.length();

    @Override
    public Object execute(ExecutionEvent event) throws ExecutionException {

        ISelection curSelection = HandlerUtil.getCurrentSelection(event);
        curSelection = convertTreeSelection(curSelection);

        if (curSelection instanceof IStructuredSelection) {
            IStructuredSelection selection = (IStructuredSelection) curSelection;

            List<VariationPoint> vps = Lists.newArrayList();
            for (Object selectedItem : selection.toList()) {
                if (selectedItem instanceof VariationPoint) {
                    vps.add((VariationPoint) selectedItem);
                } else if (selectedItem instanceof Refinement) {
                    vps.addAll(((Refinement) selectedItem).getVariationPoints());
                }
            }

            scanForIncludedFeatures(vps);

        }
        return null;
    }

    private ISelection convertTreeSelection(ISelection curSelection) {
        if (curSelection instanceof TreeSelection && ((TreeSelection) curSelection).isEmpty()) {
            IWorkbench wb = PlatformUI.getWorkbench();
            IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
            ISelectionService selectionService = win.getSelectionService();
            curSelection = selectionService.getSelection();
        }
        return curSelection;
    }

    private void scanForIncludedFeatures(List<VariationPoint> vps) {

        Multiset<String> identifiedFeatues = HashMultiset.create();
        List<String> errors = Lists.newArrayList();

        for (VariationPoint vp : vps) {

            Set<SoftwareElement> elements = getNotLeadingImplementingElements((VariationPoint) vp);
            if (elements.size() == 0) {
                identifiedFeatues.add("{NONE}");
            }
            for (SoftwareElement element : elements) {

                SourceLocation sourceLocation = element.getSourceLocation();
                String path = sourceLocation.getFilePath();
                List<String> lines = null;
                try {
                    lines = FileUtils.readLines(new File(path));

                } catch (IOException e) {
                    e.printStackTrace();
                    continue;
                }
                int markerLineIndex = getMarkerLineIndex(vp, sourceLocation, lines);
                if (markerLineIndex == -1) {
                    errors.add("No marker found for " + path.substring(path.length() - 20));
                    continue;
                }

                String featureId = getFeatureId(lines, markerLineIndex);

                if (isMarkerLine(lines, markerLineIndex - 1)) {
                    featureId = getFeatureId(lines, markerLineIndex - 1) + " + " + featureId;
                } else if (isMarkerLine(lines, markerLineIndex + 1)) {
                    featureId += " + " + getFeatureId(lines, markerLineIndex + 1);
                }

                identifiedFeatues.add(featureId);
            }
        }

        if (errors.size() > 0) {
            MessageDialog.openError(Display.getCurrent().getActiveShell(), "Marker Detection Errors",
                    Joiner.on("\n").join(errors));
        }

        StringBuilder message = new StringBuilder();
        message.append("VP Count Total: ");
        message.append(vps.size());
        for (String featureId : identifiedFeatues.elementSet()) {
            message.append("\n");
            message.append(identifiedFeatues.count(featureId));
            message.append(" x ");
            message.append(featureId);
        }
        MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Info", message.toString());
    }

    private String getFeatureId(List<String> lines, int lineIndex) {
        String line = lines.get(lineIndex).trim();
        return line.substring(MARKER_LENGTH, line.indexOf(":", MARKER_LENGTH));
    }

    private int getMarkerLineIndex(VariationPoint vp, SourceLocation sourceLocation, List<String> lines) {
        int elementIdentation = getIdentation(lines, sourceLocation.getStartLine() - 1);

        int markerLineIndex = -1;
        if (vp.getVariants().size() == 1) {
            for (int lineIndex = sourceLocation.getStartLine(); lineIndex >= 0; lineIndex--) {
                if (isMarkerLine(lines, lineIndex) && getIdentation(lines, lineIndex) == elementIdentation) {
                    markerLineIndex = lineIndex;
                    break;
                }
            }
        } else {
            for (int lineIndex = sourceLocation.getStartLine(); lineIndex < lines.size(); lineIndex++) {
                if (isMarkerLine(lines, lineIndex)) {
                    markerLineIndex = lineIndex;
                    break;
                }
            }
        }
        return markerLineIndex;
    }

    private int getIdentation(List<String> lines, int index) {
        String line = lines.get(index);
        int identation = line.length() - line.replaceFirst("^\\s*", "").length();
        return identation;
    }

    /**
     * Check a line if it matches the feature annotation used by couto et al.
     *
     * They used different comments for different information.<br>
     * The one of interest here includes the granularity type of the feature specific code:<br>
     * <code>//@#$LPS-COGNITIVE:GranularityType:MethodCall</code>
     *
     * @param lines
     *            The list of lines.
     * @param lineIndex
     *            The index of the line to check.
     * @return True if the line contains a marker of interest.
     */
    private boolean isMarkerLine(List<String> lines, int lineIndex) {
        return lines.get(lineIndex).trim().matches("//@#\\$LPS-.*:GranularityType:.*");
    }

    private Set<SoftwareElement> getNotLeadingImplementingElements(VariationPoint vp) {
        Set<SoftwareElement> elements = Sets.newLinkedHashSet();
        for (Variant v : vp.getVariants()) {
            if (v.getLeading()) {
                continue;
            }
            EList<SoftwareElement> implementingElements = v.getImplementingElements();
            elements.addAll(implementingElements);
        }
        return elements;
    }
}