/*
* Copyright 2017 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.debug.utils;
import java.io.File;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.robotframework.ide.eclipse.main.plugin.debug.model.RobotDebugElement;
import org.robotframework.ide.eclipse.main.plugin.debug.model.RobotDebugTarget;
import org.robotframework.ide.eclipse.main.plugin.debug.model.RobotLineBreakpoint;
public class KeywordExecutionManager {
private final List<IResource> resourcesUnderDebug;
private IFile currentInitFile;
private IFile currentSuiteFile;
private IPath currentSuiteLocation;
private String currentSuiteName = "";
private IContainer currentSuiteParent;
private IContainer currentResourceParent;
private String currentResourceFile;
private String breakpointCondition = "";
private final Map<IBreakpoint, Integer> breakpointHitCounts;
public KeywordExecutionManager(final List<IResource> resourcesUnderDebug) {
this.resourcesUnderDebug = resourcesUnderDebug;
breakpointHitCounts = new LinkedHashMap<>();
}
public IFile extractCurrentSuite(final IPath suiteFilePath) {
currentSuiteName = suiteFilePath.lastSegment();
currentSuiteFile = extractSuiteFile(currentSuiteName, suiteFilePath.removeLastSegments(1), resourcesUnderDebug);
if (currentSuiteFile != null) {
currentSuiteParent = currentSuiteFile.getParent();
}
currentSuiteLocation = suiteFilePath;
return currentSuiteFile;
}
public String extractCurrentResourceFile(final String resourceFilePath) {
currentResourceFile = resourceFilePath;
if (currentResourceFile != null) {
extractResourceParent();
}
return currentResourceFile;
}
public String extractExecutedFileNameWithParentFolderInfo(final String executedSuiteName) {
String fileName = executedSuiteName;
if (currentResourceFile != null && currentResourceParent != null && currentResourceParent instanceof IFolder) {
fileName = currentResourceParent.getName() + File.separator + fileName;
} else if (currentSuiteParent != null && currentSuiteParent instanceof IFolder) {
fileName = currentSuiteParent.getName() + File.separator + fileName;
}
return fileName;
}
public boolean hasBreakpointAtCurrentKeywordPosition(final String executedSuite, final int keywordLineNumber,
final RobotDebugTarget target) {
if (keywordLineNumber < 0) {
return false;
}
final IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
if (!breakpointManager.isEnabled()) {
return false;
}
boolean hasBreakpoint = false;
final IBreakpoint[] currentBreakpoints = breakpointManager.getBreakpoints(RobotDebugElement.DEBUG_MODEL_ID);
for (final IBreakpoint currentBreakpoint : currentBreakpoints) {
final RobotLineBreakpoint robotLineBreakpoint = (RobotLineBreakpoint) currentBreakpoint;
try {
if (robotLineBreakpoint.isEnabled() && isBreakpointSourceFileInCurrentExecutionContext(
robotLineBreakpoint.getMarker().getResource(), executedSuite)) {
final int breakpointLineNum = robotLineBreakpoint.getLineNumber();
if (keywordLineNumber == breakpointLineNum) {
if (isHitCountFulfilled(robotLineBreakpoint)) {
if (robotLineBreakpoint.isConditionEnabled()) {
breakpointCondition = robotLineBreakpoint.getCondition();
}
hasBreakpoint = true;
target.breakpointHit(currentBreakpoint);
}
}
}
} catch (final CoreException e) {
e.printStackTrace();
}
}
return hasBreakpoint;
}
private boolean isBreakpointSourceFileInCurrentExecutionContext(final IResource breakpointSourceFile,
final String executedSuite) {
String currentFileParentName = "";
if (currentResourceFile != null && currentResourceParent != null) {
currentFileParentName = currentResourceParent.getName();
} else {
currentFileParentName = currentSuiteParent.getName();
}
return breakpointSourceFile.getName().equals(executedSuite)
&& breakpointSourceFile.getParent().getName().equalsIgnoreCase(currentFileParentName);
}
private boolean isHitCountFulfilled(final RobotLineBreakpoint currentBreakpoint) {
if (currentBreakpoint.isHitCountEnabled()) {
final int breakpointHitCount = currentBreakpoint.getHitCount();
breakpointHitCounts.putIfAbsent(currentBreakpoint, 0);
breakpointHitCounts.put(currentBreakpoint, breakpointHitCounts.get(currentBreakpoint) + 1);
return breakpointHitCount == breakpointHitCounts.get(currentBreakpoint).intValue();
} else {
// user could disabled hit count in the meantime so we remove the counter
breakpointHitCounts.remove(currentBreakpoint);
return true;
}
}
private IFile extractSuiteFile(final String suiteName, final IPath suiteParentPath,
final List<IResource> resources) {
for (final IResource resource : resources) {
if (resource instanceof IFile && resource.getName().equalsIgnoreCase(suiteName)
&& isParentsEqual(suiteParentPath, resource)) {
return (IFile) resource;
} else if (resource instanceof IContainer) {
try {
final IFile file = extractSuiteFile(suiteName, suiteParentPath,
Arrays.asList(((IContainer) resource).members()));
if (file != null) {
return file;
}
} catch (final CoreException e) {
e.printStackTrace();
}
}
}
return null;
}
private boolean isParentsEqual(final IPath suiteParentPath, final IResource resource) {
final IContainer suiteParent = ResourcesPlugin.getWorkspace()
.getRoot()
.getContainerForLocation(suiteParentPath);
if (suiteParent != null) {
return resource.getParent().getName().equalsIgnoreCase(suiteParent.getName());
}
return true; // e.g. remote files can have different parents
}
private void extractResourceParent() {
final IContainer resourceContainer = ResourcesPlugin.getWorkspace()
.getRoot()
.getContainerForLocation(new Path(currentResourceFile));
if (resourceContainer != null) {
currentResourceParent = resourceContainer.getParent();
} else {
currentResourceParent = null;
}
}
public IFile getCurrentInitFile() {
return currentInitFile;
}
public void setCurrentInitFile(final IFile currentInitFile) {
this.currentInitFile = currentInitFile;
}
public IFile getCurrentSuiteFile() {
return currentSuiteFile;
}
public void setCurrentSuiteFile(final IFile currentSuiteFile) {
this.currentSuiteFile = currentSuiteFile;
}
public String getCurrentSuiteName() {
return currentSuiteName;
}
public void setCurrentSuiteName(final String currentSuiteName) {
this.currentSuiteName = currentSuiteName;
}
public IContainer getCurrentResourceParent() {
return currentResourceParent;
}
public void setCurrentResourceParent(final IContainer currentResourceParent) {
this.currentResourceParent = currentResourceParent;
}
public String getCurrentResourceFile() {
return currentResourceFile;
}
public void setCurrentResourceFile(final String currentResourceFile) {
this.currentResourceFile = currentResourceFile;
}
public IPath getCurrentSuiteLocation() {
return currentSuiteLocation;
}
public void setCurrentSuiteParent(final IContainer currentSuiteParent) {
this.currentSuiteParent = currentSuiteParent;
}
public boolean hasBreakpointCondition() {
return !breakpointCondition.isEmpty();
}
public List<String> getBreakpointConditionCall() {
return Arrays.asList(breakpointCondition.split("(\\s{2,}|\t)"));
}
public void resetBreakpointCondition() {
this.breakpointCondition = "";
}
}