/*
* NCSSParserWrapper.java
*
* Copyright (c) 2007
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dcarew.javancss.metrics;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.dcarew.javancss.JavaNCSSPlugin;
import org.dcarew.javancss.util.JavaElementVisitor;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.dialogs.PropertyPage;
/**
*
*
* @author Devon Carew
*/
public class NCSSProjectPropertyPage
extends PropertyPage
{
private static final String NCSS_URL = "http://www.kclee.com/clemens/java/javancss/";
private Label ncssCountText;
private Label avgCycCountText;
private Label fileCountText;
private Label packageCountText;
private Label kbCountText;
private boolean stopStatsCalculation;
/**
* Create a new NCSSProjectPropertyPage.
*/
public NCSSProjectPropertyPage()
{
noDefaultAndApplyButton();
setMessage("Java Metrics");
}
public void dispose()
{
stopStatistics();
super.dispose();
}
protected Control createContents(Composite parent)
{
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.marginWidth = 0;
layout.marginHeight = 0;
composite.setLayout(layout);
Control simpleStats = createSimpleStats(composite);
simpleStats.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//createSeparator(composite);
Control ncssStats = createNCSSStats(composite);
ncssStats.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//createSeparator(composite);
Link link = new Link(composite, SWT.WRAP);
link.setLayoutData(new GridData(SWT.BEGINNING, SWT.END, true, true));
link.setText(
"Non-Commenting Source Statements (NCSS) are an estimate of the actual lines\n" +
"of Java code. Cyclomatic Complexity Numbers (CCN), or McCabe metrics, are a\n" +
"measure of code complexity.\n" +
//"<a href=\"http://en.wikipedia.org/wiki/Cyclomatic_complexity\">Cyclomatic Complexity Numbers</a> (CCN), or McCabe metrics, are a measure of code complexity.\n" +
"\n" +
"Metrics are calculated using the JavaNCSS library. JavaNCSS is copyright Chr.\n" +
"Clemens Lee and licensed under the GNU General Public License.\n" +
"<a>" + NCSS_URL + "</a>");
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
openURL(event.text);
}
});
// Start the statistics calculation.
startStatistics();
return composite;
}
protected Control createSimpleStats(Composite parent)
{
Group group = new Group(parent, SWT.NONE);
group.setText("Java Source Statistics");
group.setLayout(new GridLayout(2, false));
Label label = new Label(group, SWT.NONE);
label.setText("Packages:");
packageCountText = new Label(group, SWT.NONE);
packageCountText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
label = new Label(group, SWT.NONE);
label.setText("Files:");
fileCountText = new Label(group, SWT.NONE);
fileCountText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
label = new Label(group, SWT.NONE);
label.setText("Total size:");
kbCountText = new Label(group, SWT.NONE);
kbCountText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
return group;
}
protected Control createNCSSStats(Composite parent)
{
Group group = new Group(parent, SWT.NONE);
group.setText("NCSS and CCN Statistics");
group.setLayout(new GridLayout(2, false));
Label label = new Label(group, SWT.NONE);
label.setText("NCSS count:");
ncssCountText = new Label(group, SWT.NONE);
ncssCountText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
label = new Label(group, SWT.NONE);
label.setText("Average CCN:");
avgCycCountText = new Label(group, SWT.NONE);
avgCycCountText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
return group;
}
protected Control createSeparator(Composite parent)
{
Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.grabExcessHorizontalSpace = true;
separator.setLayoutData(gridData);
return separator;
}
private void startStatistics()
{
stopStatsCalculation = false;
final List resources = getJavaResources();
Runnable statsRunnable = new Runnable() {
public void run()
{
final NCSSMetrics metrics = new NCSSMetrics();
NCSSParserWrapper parser = new NCSSParserWrapper();
for (Iterator itor = resources.iterator(); itor.hasNext() && !stopStatsCalculation;)
{
IResource resource = (IResource) itor.next();
parser.parse(resource, metrics);
getControl().getDisplay().syncExec(new Runnable() {
public void run()
{
if (!ncssCountText.isDisposed())
{
ncssCountText.setText(metrics.getNcssCountText());
avgCycCountText.setText(metrics.getAverageCycCountText());
fileCountText.setText(metrics.getFileCountText());
packageCountText.setText(metrics.getPackageCountText());
kbCountText.setText(metrics.getByteCountText());
ncssCountText.getParent().layout();
ncssCountText.getParent().getParent().layout();
kbCountText.getParent().layout();
kbCountText.getParent().getParent().layout();
}
}
});
}
}
};
new Thread(statsRunnable).start();
}
private List getJavaResources()
{
try
{
if (!(getElement() instanceof IJavaElement))
return Collections.EMPTY_LIST;
final List resources = new ArrayList();
JavaElementVisitor.accept(new JavaElementVisitor() {
protected boolean visit(IJavaProject javaProject)
{
return javaProject.getProject().getLocation() != null;
}
protected boolean visit(IPackageFragmentRoot packageFragmentRoot)
throws JavaModelException
{
return packageFragmentRoot.exists() && !packageFragmentRoot.isArchive()
&& packageFragmentRoot.getKind() == IPackageFragmentRoot.K_SOURCE;
}
protected boolean visit(ICompilationUnit compilationUnit)
{
resources.add(compilationUnit.getResource());
return true;
}
}, (IJavaElement)getElement());
return resources;
}
catch (JavaModelException exception)
{
JavaNCSSPlugin.log(exception);
return Collections.EMPTY_LIST;
}
}
private void stopStatistics()
{
stopStatsCalculation = true;
}
/**
* Open the given URL in the platform specific default browser.
*
* @param url
*/
private static void openURL(String url)
{
try
{
IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
IWebBrowser browser = browserSupport.getExternalBrowser();
browser.openURL(new URL(url));
}
catch (PartInitException exception)
{
JavaNCSSPlugin.log(exception);
}
catch (MalformedURLException exception)
{
JavaNCSSPlugin.log(exception);
}
}
}