sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/ui/TreeHelper.java
changeset 1 1050670c6980
child 6 f65f740e69f9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/analyzetoolext/com.nokia.s60tools.analyzetool/src/com/nokia/s60tools/analyzetool/ui/TreeHelper.java	Thu Feb 11 15:22:14 2010 +0200
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:  Definitions for the class TreeHelper
+ *
+ */
+
+package com.nokia.s60tools.analyzetool.ui;
+
+import java.util.AbstractList;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import com.nokia.s60tools.analyzetool.engine.AnalysisItem;
+import com.nokia.s60tools.analyzetool.engine.CallstackItem;
+import com.nokia.s60tools.analyzetool.engine.MMPInfo;
+import com.nokia.s60tools.analyzetool.engine.RunResults;
+import com.nokia.s60tools.analyzetool.engine.Subtest;
+import com.nokia.s60tools.analyzetool.global.Constants;
+import com.nokia.s60tools.analyzetool.global.Util;
+
+/**
+ * Class to create Tree model for the AnalyzeTool view.
+ *
+ * @author kihe
+ *
+ */
+public class TreeHelper {
+
+
+	/** Last active memory leak tree item. */
+	private TreeObject activeTreeItem;
+
+	/** Last selected tree item. */
+	private final Object lastSelectedObject;
+
+	/** Contains module leak info. */
+	private final java.util.Hashtable<String, Integer> moduleLeaks;
+
+	/** Used AnalyzeTool preference store */
+	private final IPreferenceStore store;
+
+	/** Contains already checked modules states */
+	private final Hashtable<String, Boolean> checkedModules;
+
+	/** Contains information which modules are part of the project */
+	private final Hashtable<String, Boolean> projectModules;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param selectedObject
+	 *            Last selected tree item
+	 *
+	 * @param storeRef AnalyzeTool preference store reference
+	 */
+	public TreeHelper(final Object selectedObject,
+			final IPreferenceStore storeRef) {
+		lastSelectedObject = selectedObject;
+		moduleLeaks = new java.util.Hashtable<String, Integer>();
+		store = storeRef;
+		checkedModules = new Hashtable<String, Boolean>();
+		projectModules = new Hashtable<String, Boolean>();
+	}
+
+	/**
+	 * Compares two different TreeObject.
+	 *
+	 * @param obj1
+	 *            Actual
+	 * @param obj2
+	 *            New object
+	 * @return True if objects equals otherwise false
+	 */
+	public final boolean compareItems(final Object obj1, final Object obj2) {
+		boolean found = false;
+
+		if (obj1 == null || obj2 == null) {
+			return false;
+		}
+
+		TreeObject tree1 = (TreeObject) obj1;
+		TreeObject tree2 = (TreeObject) obj2;
+
+		if (tree1.getMemLeakID() == tree2.getMemLeakID()
+				&& tree1.getRunID() == tree2.getRunID()
+				&& tree1.getName().equals(tree2.getName())
+				&& tree1.getSubtestID() == tree2.getSubtestID()) {
+			activeTreeItem = (TreeObject) obj1;
+			found = true;
+		}
+		return found;
+	}
+
+	/**
+	 * Creates tree node for analysis items.
+	 *
+	 * @param oneRunTree
+	 *            Current item parent tree node
+	 * @param items
+	 *            Analysis items
+	 * @param runID
+	 *            Current run id
+	 * @param isSubtest
+	 *            Is this element subtest
+	 * @param subTestID
+	 *            Subtest ID
+	 * @param modules Selected project target modules
+	 * @return How many items created
+	 */
+	public final int createItemResults(final TreeParent oneRunTree,
+			final AbstractList<AnalysisItem> items, final int runID,
+			final boolean isSubtest, final int subTestID, AbstractList<MMPInfo> modules) {
+		boolean thereAreItemsDisplayed = false;
+		moduleLeaks.clear();
+
+		int displayed = 0;
+		// thru actual memory leaks
+		Iterator<AnalysisItem> iterItem = items.iterator();
+		while (iterItem.hasNext()) {
+			// get one analysis file
+			AnalysisItem oneItem = iterItem.next();
+
+			if (getActiveDetailLevel().equals(Constants.REPORT_EVERY)
+					|| oneItem.containValidCallstack()) {
+				displayed++;
+				char space = ' ';
+				StringBuffer leakString = new StringBuffer(64);
+				leakString.append(Constants.ITEM_TREE_MEM_LEAKS);
+				leakString.append(oneItem.getID());
+				leakString.append(" (");
+				leakString.append(oneItem.getLeakSize());
+				leakString.append(" bytes) (");
+				leakString.append(oneItem.getMemoryAddress());
+				leakString.append(") ");
+				leakString.append(oneItem.getMemoryLeakTime());
+				leakString.append(space);
+				leakString.append(oneItem.getModuleName());
+
+				TreeObject oneLeak = new TreeObject();
+				if (!modules.isEmpty()) {
+					oneLeak.setBuild(checkItemBuildState(modules, oneItem.getModuleName()));
+					oneLeak.setBelongs(checkProjectModules(modules, oneItem.getModuleName()));
+				}
+
+				if (isSubtest) {
+					oneLeak.setSubtest(true);
+					oneLeak.setSubtestID(subTestID);
+				}
+				oneLeak.setRunID(runID);
+				oneLeak.setMemLeakID(oneItem.getID());
+				oneLeak.setName(leakString.toString());
+				oneLeak.setModuleName(oneItem.getModuleName());
+				oneLeak.setMemAddress(oneItem.getMemoryAddress());
+
+				oneRunTree.addChild(oneLeak);
+				thereAreItemsDisplayed = true;
+				updateModuleLeaksInfo(oneItem.getModuleName());
+				compareItems(oneLeak, lastSelectedObject);
+			}
+
+		}
+
+		// if no leaks added to list
+		if (!thereAreItemsDisplayed && !items.isEmpty()) {
+			TreeObject infoObject = new TreeObject();
+			infoObject.setName(Constants.NO_MEM_LEAKS_CURRENT_LEVEL);
+			oneRunTree.addChild(infoObject);
+		}
+		return displayed;
+	}
+
+	/**
+	 * Check is module built with AnalyzeTool
+	 * @param modules Project modules
+	 * @param moduleName Module name
+	 * @return True if module is built with AnalyzeTool otherwise false
+	 */
+	private final boolean checkItemBuildState( AbstractList<MMPInfo> modules, String moduleName)
+	{
+		if( checkedModules.containsKey(moduleName)) {
+			return checkedModules.get(moduleName);
+		}
+		else if (!modules.isEmpty()) {
+			boolean build = Util.chechModuleBuildState(modules, moduleName);
+			if( !build ) {
+				checkedModules.put(moduleName, build);
+			}
+			return build;
+		}
+		return false;
+	}
+
+	/**
+	 * Checks is module part of the project
+	 * @param modules Project modules
+	 * @param moduleName Module name
+	 * @return True if module is part of the project otherwise false
+	 */
+	private final boolean checkProjectModules(AbstractList<MMPInfo> modules, String moduleName)
+	{
+		if( projectModules.containsKey(moduleName) ) {
+			return projectModules.get(moduleName);
+		}
+		else if( !modules.isEmpty() ) {
+			boolean partOfTheProject = Util.isModulePartOfProject(modules,moduleName);
+			projectModules.put(moduleName, partOfTheProject);
+			return partOfTheProject;
+		}
+		return false;
+	}
+
+	/**
+	 * Creates tree item for run results.
+	 *
+	 * @param oneRunResults
+	 *            One run results
+	 * @param modules Selected project target modules
+	 * @return Tree item which contains run results
+	 */
+	public final TreeParent createRunResults(final RunResults oneRunResults, AbstractList<MMPInfo> modules) {
+
+		// create new run tree
+		TreeParent oneRunTree = new TreeParent("");
+		oneRunTree.setRunID(oneRunResults.getItemID());
+
+		// create new handle leak tree
+		TreeParent handleSummary = getHandleLeakInfo(oneRunResults
+				.getHandleLeaks(), oneRunResults.getItemID(), modules);
+		if (handleSummary.hasChildren()) {
+			oneRunTree.addChild(handleSummary);
+		}
+
+		// if no memory leaks set "No memory leaks" info
+		AbstractList<AnalysisItem> items = oneRunResults.getAnalysisItems();
+		if (items.isEmpty()) {
+			TreeObject noLeaks = new TreeObject();
+			noLeaks.setName(Constants.RUN_NO_LEAKS);
+			oneRunTree.addChild(noLeaks);
+		}
+
+		// create item tree and calculate how many of memory leaks are displayed
+		int howManyDisplayed = createItemResults(oneRunTree, items,
+				oneRunResults.getItemID(), false, 0, modules);
+		oneRunTree.setName(getRunTreeTitle(oneRunResults, howManyDisplayed));
+
+		// module leaks
+		TreeParent moduleSummary = getModuleLeakInfo(getCalcModuleLeaksInfo(),
+				oneRunResults.getItemID(), modules);
+		if (moduleSummary.hasChildren()) {
+			oneRunTree.addChild(0, moduleSummary);
+		}
+
+		// get subtests
+		AbstractList<Subtest> subtest = oneRunResults.getSubtest();
+		createSubtestResults(oneRunTree, subtest, oneRunResults.getItemID(), modules);
+
+		return oneRunTree;
+	}
+
+	/**
+	 * Creates tree node for subtests.
+	 *
+	 * @param oneRunTree
+	 *            Parent tree node
+	 * @param subtest
+	 *            Subtest information
+	 * @param runID
+	 *            Current run id
+	 * @param modules Selected project target modules
+	 */
+	public final void createSubtestResults(final TreeParent oneRunTree,
+			final AbstractList<Subtest> subtest, final int runID, AbstractList<MMPInfo> modules) {
+		// thru subtest
+		Iterator<Subtest> iterSubtest = subtest.iterator();
+
+		// thru subtest
+		while (iterSubtest.hasNext()) {
+			// get subtest
+			Subtest oneSubtest = iterSubtest.next();
+
+			// create tree item for the subtest
+			TreeParent oneSubtestParent = new TreeParent("");
+
+			// get and calculate how many memory leaks subtest contains
+			int howManyDisplayed = createItemResults(oneSubtestParent,
+					oneSubtest.getAnalysisItems(), runID, true, oneSubtest
+							.getItemID(), modules);
+
+			// udpate subtest tree title
+			oneSubtestParent.setName(getSubtestTreeTitle(oneSubtest,
+					howManyDisplayed));
+
+			if (oneSubtest.getAnalysisItems().isEmpty()) {
+				TreeObject noLeaks = new TreeObject();
+				noLeaks.setName(Constants.RUN_NO_LEAKS);
+				oneSubtestParent.addChild(noLeaks);
+			}
+
+			// if subtest contains handle leaks
+			TreeParent handleLeaksInfo = getHandleLeakInfo(oneSubtest
+					.getHandleLeaks(), oneSubtest.getItemID(), modules);
+			if (handleLeaksInfo.hasChildren()) {
+				oneSubtestParent.addChild(handleLeaksInfo);
+			}
+
+			// set subtest module leak info
+			TreeParent moduleLeaksInfo = getModuleLeakInfo(
+					getCalcModuleLeaksInfo(), oneSubtest.getItemID(), modules);
+			if (moduleLeaksInfo.hasChildren()) {
+				oneSubtestParent.addChild(0, moduleLeaksInfo);
+			}
+
+			oneRunTree.addChild(oneSubtestParent);
+		}
+	}
+
+	/**
+	 * Gets active detail level.
+	 *
+	 * @return Active detail level
+	 */
+	public final String getActiveDetailLevel() {
+		// get active report level
+		return store.getString(Constants.REPORT_LEVEL);
+	}
+
+	/**
+	 * Returns active item of tree.
+	 *
+	 * @return Active itemf
+	 */
+	public final TreeObject getActiveItem() {
+		return activeTreeItem;
+	}
+
+	/**
+	 * Returns tree item which contains callstack information.
+	 *
+	 * @param item
+	 *            AnalysisItem
+	 * @param modules Selected project target modules
+	 * @return Tree item
+	 */
+	public final TreeParent getCallstack(final AnalysisItem item, AbstractList<MMPInfo> modules) {
+
+		// get active logging mode
+		String reportLevel = store.getString(Constants.REPORT_LEVEL);
+
+		// create tree parent for test runs
+		TreeParent testRuns = new TreeParent(Constants.ITEM_TREE_MEM_LEAKS
+				+ item.getID() + " " + item.getMemoryLeakTime());
+
+		// get callstack items
+		Iterator<CallstackItem> stackItems = item.getCallstackItems()
+				.iterator();
+
+		// is one know line printed
+		boolean printed = false;
+
+		// thru call stack items
+		while (stackItems.hasNext()) {
+			// get one callstack item
+			CallstackItem oneStackItem = stackItems.next();
+
+			TreeObject to = new TreeObject();
+
+			// get function name, memory leak line number and file name
+			String functionName = oneStackItem.getFunctionName();
+			int leakLineNumber = oneStackItem.getLeakLineNumber();
+			String fileName = oneStackItem.getFileName();
+			String memAddress = oneStackItem.getMemoryAddress();
+			String moduleName = oneStackItem.getModuleName();
+
+			if (!modules.isEmpty()) {
+				to.setBuild(checkItemBuildState(modules, moduleName));
+				to.setBelongs(checkProjectModules(modules, moduleName));
+			}
+
+			// report all
+			if (Constants.REPORT_EVERY.equals(reportLevel)) {
+
+				if (leakLineNumber > 0) {
+					// if build is urel
+					// => change info order
+					if (oneStackItem.isUrelBuild()) {
+						to.setName(memAddress + " " + moduleName + " "
+								+ functionName + " " + leakLineNumber + " "
+								+ fileName);
+					} else {
+						to.setName(memAddress + " " + moduleName + " "
+								+ functionName + " " + fileName + " "
+								+ leakLineNumber);
+					}
+
+				} else {
+					to.setName(memAddress + " " + moduleName + " "
+							+ functionName + " " + fileName);
+				}
+
+				to.setCallstackItem(oneStackItem);
+				testRuns.addChild(to);
+			}
+			// display only known lines
+			else if (Constants.REPORT_KNOWN.equals(reportLevel)
+					&& (functionName != null && leakLineNumber > 0 && fileName != null)) {
+				// if build is urel
+				// => change info order
+				if (oneStackItem.isUrelBuild()) {
+					to.setName(memAddress + " " + moduleName + " "
+							+ functionName + " " + leakLineNumber + " "
+							+ fileName);
+				} else {
+					to.setName(memAddress + " " + moduleName + " "
+							+ functionName + " " + fileName + " "
+							+ leakLineNumber);
+				}
+				to.setCallstackItem(oneStackItem);
+				testRuns.addChild(to);
+			}
+			// display only topmost
+			else if (Constants.REPORT_TOPMOST.equals(reportLevel)
+					&& !printed
+					&& (functionName != null && leakLineNumber > 0 && fileName != null)) {
+				// if build is urel
+				// => change info order
+				if (oneStackItem.isUrelBuild()) {
+					to.setName(memAddress + " " + moduleName + " "
+							+ functionName + " " + leakLineNumber + " "
+							+ fileName);
+				} else {
+					to.setName(memAddress + " " + moduleName + " "
+							+ functionName + " " + fileName + " "
+							+ leakLineNumber);
+				}
+				to.setCallstackItem(oneStackItem);
+				testRuns.addChild(to);
+				printed = true;
+			}
+
+		}
+
+		TreeParent incRoot;
+		incRoot = new TreeParent(Constants.ANALYZE_TOOL_TITLE);
+		incRoot.addChild(testRuns);
+		return incRoot;
+	}
+
+	/**
+	 * Gets handle leaks tree item.
+	 *
+	 * @param handleLeaks
+	 *            Handle leaks information
+	 * @param runID
+	 *            Run id
+	 * @param modules Selected project target modules
+	 * @return Handle leak tree item
+	 */
+	public final TreeParent getHandleLeakInfo(
+			final Hashtable<String, Integer> handleLeaks, final int runID, AbstractList<MMPInfo> modules) {
+		// get handle leak information
+		TreeParent handleSummary = new TreeParent(
+				Constants.HANDLE_LEAK_MODULES_TITLE);
+		handleSummary.setRunID(runID);
+		for (java.util.Enumeration<String> e1 = handleLeaks.keys(); e1
+				.hasMoreElements();) {
+			String moduleName = e1.nextElement();
+			int handleLeakCount = handleLeaks.get(moduleName);
+			TreeObject object = new TreeObject();
+			object.setRunID(runID);
+			object.setName(moduleName + " (" + handleLeakCount
+					+ Constants.MODULE_TREE_HANDLE_LEAKS + ")");
+			if (!modules.isEmpty()) {
+				object.setBuild(checkItemBuildState(modules, moduleName));
+				object.setBelongs(checkProjectModules(modules, moduleName));
+			}
+
+			handleSummary.addChild(object);
+		}
+		return handleSummary;
+	}
+
+	/**
+	 * Gets module leaks tree item.
+	 *
+	 * @param moduleLeaksInfo
+	 *            Module leaks information
+	 * @param runID
+	 *            Run id
+	 * @param modules Selected project target modules
+	 * @return Module leak tree item
+	 */
+	public final TreeParent getModuleLeakInfo(
+			final Hashtable<String, Integer> moduleLeaksInfo, final int runID, AbstractList<MMPInfo> modules) {
+		TreeParent moduleSummary = new TreeParent(
+				Constants.MEMORY_LEAK_MODULES_TITLE);
+
+		moduleSummary.setRunID(runID);
+		for (java.util.Enumeration<String> e = moduleLeaksInfo.keys(); e
+				.hasMoreElements();) {
+			String moduleName = e.nextElement();
+			int moduleLeakCount = moduleLeaksInfo.get(moduleName);
+			TreeObject object = new TreeObject();
+			object.setRunID(runID);
+			object.setName(moduleName + " (" + moduleLeakCount
+					+ Constants.MODULE_TREE_MEM_LEAKS + ")");
+			if (!modules.isEmpty()) {
+				object.setBuild(checkItemBuildState(modules, moduleName));
+				object.setBelongs(checkProjectModules(modules, moduleName));
+			}
+
+			moduleSummary.addChild(object);
+		}
+		return moduleSummary;
+	}
+
+	/**
+	 * Return moduleaks info.
+	 *
+	 * @return Module leaks info
+	 */
+	public final Hashtable<String, Integer> getCalcModuleLeaksInfo() {
+		return moduleLeaks;
+	}
+
+	/**
+	 * Gets run tree title.
+	 *
+	 * @param oneRunResults
+	 *            Run results
+	 * @param howManyDisplayed
+	 *            How many of memory leak items are displayed
+	 * @return Run tree title
+	 */
+	public final String getRunTreeTitle(final RunResults oneRunResults,
+			final int howManyDisplayed) {
+		StringBuffer runTreeTitle = new StringBuffer(64);
+		runTreeTitle.append(Constants.RUN_TREE_RUN);
+		runTreeTitle.append(Integer.toString(oneRunResults.getItemID()));
+		runTreeTitle.append(Constants.RUN_TREE_RUN_MEM_LEAKS);
+		runTreeTitle.append(oneRunResults.getAnalysisItems().size());
+		if (howManyDisplayed > 0
+				&& oneRunResults.getAnalysisItems().size() != howManyDisplayed) {
+			int diff = oneRunResults.getAnalysisItems().size()
+					- howManyDisplayed;
+			runTreeTitle.append(" (");
+			runTreeTitle.append(Integer.toString(diff));
+			runTreeTitle.append(Constants.RUN_TREE_FILTERED);
+
+		}
+		runTreeTitle.append(Constants.RUN_TREE_RUN_HANDLE_LEAKS);
+		runTreeTitle.append(oneRunResults.getHandleLeakCount());
+		runTreeTitle.append(Constants.RUN_TREE_START_TIME);
+		runTreeTitle.append(oneRunResults.getStartTime());
+		runTreeTitle.append(Constants.RUN_TREE_PROCESS_NAME);
+		runTreeTitle.append(oneRunResults.getProcessName());
+		runTreeTitle.append(Constants.RUN_TREE_BUILD_TARGET);
+		runTreeTitle.append(oneRunResults.getBuildTarget());
+
+		if (oneRunResults.getEndTime() == null
+				|| ("").equals(oneRunResults.getEndTime())) {
+			runTreeTitle.append(Constants.RUN_FAILED);
+		} else if ((Constants.RUN_ABNORMAL).equals(oneRunResults.getEndTime())) {
+			runTreeTitle.append(' ');
+			runTreeTitle.append(Constants.RUN_ABNORMAL);
+			runTreeTitle.append(' ');
+		}
+
+		return runTreeTitle.toString();
+	}
+
+	/**
+	 * Gets subtest title.
+	 *
+	 * @param oneSubtest
+	 *            Subtest info
+	 * @param howManyDisplayed
+	 *            How many of subtest items are displayed
+	 * @return Subtest title
+	 */
+	public final String getSubtestTreeTitle(final Subtest oneSubtest,
+			final int howManyDisplayed) {
+		StringBuffer subtestTitle = new StringBuffer(64);
+		String startTime = oneSubtest.getStartTime();
+		subtestTitle.append(Constants.SUBTEST_TREE_TITLE);
+		subtestTitle.append(oneSubtest.getName());
+		subtestTitle.append(Constants.RUN_TREE_RUN_MEM_LEAKS);
+		subtestTitle.append(oneSubtest.getAnalysisItems().size());
+
+		if (howManyDisplayed > 0
+				&& oneSubtest.getAnalysisItems().size() != howManyDisplayed) {
+			int diff = oneSubtest.getAnalysisItems().size() - howManyDisplayed;
+
+			subtestTitle.append(" (");
+			subtestTitle.append(diff);
+			subtestTitle.append(Constants.RUN_TREE_FILTERED);
+		}
+		subtestTitle.append(Constants.RUN_TREE_RUN_HANDLE_LEAKS);
+		subtestTitle.append(oneSubtest.getHandleLeakCount());
+		if (startTime.length() != 0) {
+			subtestTitle.append(Constants.RUN_TREE_START_TIME);
+			subtestTitle.append(oneSubtest.getStartTime());
+		}
+		return subtestTitle.toString();
+	}
+
+	/**
+	 * Updates module leak count for current module.
+	 *
+	 * @param moduleName
+	 *            Module name
+	 */
+	public final void updateModuleLeaksInfo(final String moduleName) {
+
+		//check module name
+		if( moduleName == null || ("").equals(moduleName) ) {
+			return;
+		}
+		//if same module name is already added => update count value
+		else if (moduleLeaks.containsKey(moduleName)) {
+			int currentCount = moduleLeaks.get(moduleName);
+			currentCount++;
+			moduleLeaks.put(moduleName, currentCount);
+		} else {
+			moduleLeaks.put(moduleName, 1);
+		}
+	}
+}