Commit 2a2d17a9 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ added skeleton for usage analysis #4

parent 24f05fa2
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ public class T3Q {
	private boolean generateLocalDependencies = false;
	private final Stopwatch stopwatch = Stopwatch.createUnstarted();
	private boolean singleCore = false;
	private boolean analyzeUsage = false;
	
	// private boolean formattingEnabled = false;

@@ -114,8 +115,10 @@ public class T3Q {
		}
		resourceProvider.loadResources();
		//TODO: check if it has to be exclusive
		if (!this.isGenerateLocalDependencies()) {
		if (!this.isGenerateLocalDependencies() && !this.isAnalyzeUsage() ) {
			resourceProvider.analyzeResources();
		} else if (this.isAnalyzeUsage()) {
			resourceProvider.analyzeUsage();
		} else {
			resourceProvider.analyzeDependencies();
		}
@@ -205,6 +208,9 @@ public class T3Q {
		if (commandLine.hasOption("single-core")) {
			this.setSingleCore(true);
		}
		if (commandLine.hasOption("analyze-usage")) {
			this.setAnalyzeUsage(true);
		}
		if (commandLine.hasOption("verbosity")) {
			this.selectLogLevel(commandLine.getOptionValue("verbosity"));
		}
@@ -439,4 +445,12 @@ public class T3Q {
	public void setSingleCore(boolean singleCore) {
		this.singleCore = singleCore;
	}

	public boolean isAnalyzeUsage() {
		return analyzeUsage;
	}

	public void setAnalyzeUsage(boolean analyzeUsage) {
		this.analyzeUsage = analyzeUsage;
	}
}
+40 −1
Original line number Diff line number Diff line
@@ -241,11 +241,50 @@ public class TTCN3ResourceProvider {

	}

	public void analyzeUsage() {
		Stopwatch watchAnalyzing = Stopwatch.createStarted();
		ExecutorService pool = Executors.newFixedThreadPool(getCores());
		
		// Check if resource is a ignored one and if so, do not analyze it.
		Pattern pattern = Pattern.compile(activeProfile.getIgnoredResourceRegExp());
		Matcher matcher = null;		
		
		ArrayList<UsageAnalyzer> analyzer = new ArrayList<UsageAnalyzer>();
		for (int i = 0; i < TTCN3GlobalScopeProvider.RESOURCES.size(); i++) {
			Resource resource = TTCN3GlobalScopeProvider.RESOURCES.get(i);
			matcher = pattern.matcher(resource.getURI().toFileString());
			if(!matcher.matches()) {
				analyzer.add(new UsageAnalyzer(TTCN3GlobalScopeProvider.RESOURCES.get(i), logger));
			}
		}
		try {
			List<Future<TTCN3Usage>> output = pool.invokeAll(analyzer);
			pool.shutdown();
			System.out.print('\n');
			
			for (Future<TTCN3Usage> f : output) {
				TTCN3Usage o = f.get();
				System.out.println("Usage analysis output of " + o.getResource().getURI().lastSegment());
				printOutput(o.getResource(), o.getOutput());
			}
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		watchAnalyzing.stop();
		System.out.println("Test suite analyzed in "
				+ MiscTools.msToString(watchAnalyzing.elapsed(TimeUnit.MILLISECONDS)) + " minutes." + '\n');

	}

	
	private void printOutput(Resource resource, String message) {
		System.out.println(message);
	}
	
	
	private void printOutput(Resource resource, Map<String,Integer> usage) {
		usage.forEach((k,v) -> System.out.println(k+","+v));
	}
	
	private void printOutput(Resource resource, FeatureBasedDiagnostic featureDiagnostic) {
			switch (featureDiagnostic.getSeverity()) {
+26 −0
Original line number Diff line number Diff line
package de.ugoe.cs.swe.T3Q;

import java.util.Map;

import org.eclipse.emf.ecore.resource.Resource;

import com.google.common.collect.Maps;

public class TTCN3Usage {
	private final Resource resource;
	private final Map<String,Integer> output;
	
	public TTCN3Usage(final Resource resource) {
		this.resource = resource;
		this.output  = Maps.newLinkedHashMap();
	}

	public Resource getResource() {
		return resource;
	}

	public Map<String,Integer> getOutput() {
		return output;
	}

}
+89 −0
Original line number Diff line number Diff line
package de.ugoe.cs.swe.T3Q;

import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.EcoreUtil2;

import com.google.common.base.Stopwatch;

import de.ugoe.cs.swe.common.MiscTools;
import de.ugoe.cs.swe.common.logging.LoggingInterface;
import de.ugoe.cs.swe.tTCN3.AltConstruct;
import de.ugoe.cs.swe.tTCN3.FunctionDef;
import de.ugoe.cs.swe.tTCN3.ModuleDefinition;
import de.ugoe.cs.swe.tTCN3.TTCN3File;
import de.ugoe.cs.swe.tTCN3.TTCN3Module;

public class UsageAnalyzer implements Callable<TTCN3Usage> {
	private final Resource resource;
	private final LoggingInterface logger;
	public static boolean printUnresolvedObjects = false;

	public UsageAnalyzer(Resource resource, LoggingInterface logger) {
		this.resource = resource;
		this.logger = logger;
	}

	private TTCN3Usage analyze() {
		final TTCN3Usage output = new TTCN3Usage(this.resource);
		final Stopwatch stopwatch = Stopwatch.createUnstarted();

		stopwatch.start();

		// validate the resource
		EcoreUtil.resolveAll(this.resource);
		//get root element
		EObject model = this.resource.getContents().get(0);
		//collect basic stats (keep in mind multi-threaded processing, need to collect output in a file or in output), 
		//for initial basic testing single-threaded mode should provide first results
		System.out.println("Module,FunctionDef,AltConstruct,...");
		for (TTCN3Module module : ((TTCN3File)model).getModules()) {
			//immediate output (will look weird if single-core is not activated)
			//TODO: count different constructs (naive approach), e.g.
			System.out.println(module.getName() 
					+ "," +EcoreUtil2.getAllContentsOfType(module, FunctionDef.class).size()
					+ "," +EcoreUtil2.getAllContentsOfType(module, AltConstruct.class).size()
					+ ",..." 
					);
			//TODO: very inefficient, better to traverse tree once, e.g.
			List<ModuleDefinition> definitions = EcoreUtil2.getAllContentsOfType(module, ModuleDefinition.class);

			//process with a stream
			Map<String, List<ModuleDefinition>> groupedDefinitions = definitions.stream()
					.collect(Collectors.groupingBy(e->e.getDef().eClass().getName()));
			//immediate output (will look weird if single-core is not activated)
			//groupedDefinitions.forEach((k,v) -> System.out.println(k+","+v.size()));
			//collect for synchronised output
			output.getOutput().putAll(groupedDefinitions.entrySet().stream()
					.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().size())));
			//or
			//groupedDefinitions.forEach((k,v) -> output.getOutput().put(k, v.size()));
			
			//...or with a loop
			for (ModuleDefinition d : definitions) {
				String eClassName = d.getDef().eClass().getName();
				//...
			}
		}

		stopwatch.stop();

		System.out.println("Analyzing usage in file: " + this.resource.getURI().devicePath().replaceFirst("///", "") + '\n'
				+ "       ...done in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms ("
				+ MiscTools.secondsToString(stopwatch.elapsed(TimeUnit.SECONDS)) + " minutes).");

		return output;
	}

	@Override
	public TTCN3Usage call() throws Exception {
		return analyze();
	}
}