/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* 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.drools.eclipse.debug;
import org.drools.eclipse.DroolsEclipsePlugin;
import org.drools.eclipse.debug.actions.ShowLogicalStructureAction;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.internal.ui.VariablesViewModelPresentation;
import org.eclipse.debug.internal.ui.contexts.DebugContextManager;
import org.eclipse.debug.internal.ui.views.variables.VariablesView;
import org.eclipse.debug.ui.AbstractDebugView;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.debug.ui.contexts.IDebugContextListener;
import org.eclipse.debug.ui.contexts.IDebugContextService;
import org.eclipse.jdt.debug.core.IJavaFieldVariable;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
/**
* A generic Drools debug view.
*/
public abstract class DroolsDebugEventHandlerView extends AbstractDebugView implements IDebugContextListener, ISelectionListener {
private VariablesViewModelPresentation modelPresentation;
private boolean showLogical = true;
private Object[] oldExpandedElements = new Object[0];
public void dispose() {
DebugContextManager.getDefault().removeDebugContextListener(this);
getSite().getPage().removeSelectionListener(IDebugUIConstants.ID_VARIABLE_VIEW, this);
super.dispose();
}
public boolean isShowLogicalStructure() {
return showLogical;
}
public void setShowLogicalStructure(boolean showLogical) {
this.showLogical = showLogical;
}
protected void setViewerInput(Object context) {
Object input = null;
// if a working memory has been explicitly selected as variable, use this
if (context instanceof IVariable) {
IVariable variable = (IVariable) context;
try {
IValue value = ((IVariable) context).getValue();
if (value != null && value instanceof IJavaObject) {
if ("org.drools.core.common.AbstartWorkingMemory".equals(variable.getValue().getReferenceTypeName()) ||
"org.drools.core.reteoo.ReteooStatefulSession".equals(variable.getValue().getReferenceTypeName()) ||
// for backwards compatibility
"org.drools.reteoo.ReteooStatefulSession".equals(variable.getValue().getReferenceTypeName())) {
input = value;
} else if ("org.drools.core.impl.StatefulKnowledgeSessionImpl".equals(variable.getValue().getReferenceTypeName())
|| "org.drools.impl.StatefulKnowledgeSessionImpl".equals(variable.getValue().getReferenceTypeName())) {
IJavaFieldVariable sessionVar = ((IJavaObject) value).getField("session", false);
if (sessionVar != null) {
input = sessionVar.getValue();
} else {
input = variable.getValue();
}
}
}
} catch (Throwable t) {
DroolsEclipsePlugin.log(t);
}
}
// else get selected thread and determine if any of the stack frames
// is executing in a working memory, if so, use that one
if (input == null) {
IDebugContextService debugContextService = DebugContextManager.getDefault().getContextService(getSite().getWorkbenchWindow());
if (debugContextService != null) {
ISelection stackSelection = debugContextService.getActiveContext();
if (stackSelection instanceof IStructuredSelection) {
Object selection = ((IStructuredSelection) stackSelection).getFirstElement();
if (selection instanceof IJavaStackFrame) {
try {
IJavaThread thread = (IJavaThread) ((IJavaStackFrame) selection).getThread();
IStackFrame[] frames = thread.getStackFrames();
for (int i = 0; i < frames.length; i++) {
IJavaObject stackObj = ((IJavaStackFrame) frames[i]).getThis();
if ((stackObj != null)
&& (stackObj.getJavaType() != null)
&& ("org.drools.core.common.AbstractWorkingMemory".equals(stackObj.getJavaType().getName())
|| "org.drools.core.reteoo.ReteooStatefulSession".equals(stackObj.getJavaType().getName())
|| "org.drools.reteoo.ReteooStatefulSession".equals(stackObj.getJavaType().getName())
|| "org.drools.core.impl.StatefulKnowledgeSessionImpl".equals(stackObj.getJavaType().getName()))) {
input = stackObj;
break;
}
}
} catch (Throwable t) {
DroolsEclipsePlugin.log(t);
}
}
}
}
}
Object current = getViewer().getInput();
if (current == null && input == null) {
return;
}
Object[] newExpandedElements = ((TreeViewer) getViewer()).getExpandedElements();
if (newExpandedElements.length != 0) {
oldExpandedElements = newExpandedElements;
}
getViewer().setInput(input);
if (input != null) {
((TreeViewer) getViewer()).setExpandedElements(oldExpandedElements);
((TreeViewer) getViewer()).expandToLevel(getAutoExpandLevel());
}
}
protected Viewer createViewer(Composite parent) {
TreeViewer variablesViewer = new TreeViewer(parent);
variablesViewer.setContentProvider(createContentProvider());
variablesViewer.setLabelProvider(new VariablesViewLabelProvider(
getModelPresentation()));
variablesViewer.setUseHashlookup(true);
DebugContextManager.getDefault().addDebugContextListener(this);
getSite().getPage().addSelectionListener(IDebugUIConstants.ID_VARIABLE_VIEW, this);
return variablesViewer;
}
protected int getAutoExpandLevel() {
return 0;
}
protected abstract IContentProvider createContentProvider();
protected String getHelpContextId() {
return null;
}
protected void becomesHidden() {
setViewerInput(null);
super.becomesHidden();
}
protected void becomesVisible() {
super.becomesVisible();
ISelection selection = getSite().getPage().getSelection(
IDebugUIConstants.ID_VARIABLE_VIEW);
if (selection instanceof IStructuredSelection) {
setViewerInput(((IStructuredSelection) selection).getFirstElement());
} else {
setViewerInput(null);
}
}
protected void createActions() {
IAction action = new ShowLogicalStructureAction(this);
setAction("ShowLogicalStructure", action);
}
protected void configureToolBar(IToolBarManager tbm) {
tbm.add(getAction("ShowLogicalStructure"));
}
protected void fillContextMenu(IMenuManager menu) {
menu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
}
public void contextActivated(ISelection selection, IWorkbenchPart part) {
if (!isAvailable() || !isVisible()) {
return;
}
if (selection instanceof IStructuredSelection) {
setViewerInput(((IStructuredSelection)selection).getFirstElement());
}
showViewer();
}
public void debugContextChanged(DebugContextEvent event) {
//selectionChanged(null, event.getContext());
}
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (!isAvailable()) {
return;
}
// In Eclipse 3.5.x, an additional selection changed event with selection null is
// generated when clicking on a process instance in the process instance view
// replacing this null by the actual selected element in those cases
if (part instanceof VariablesView) {
selection = ((VariablesView) part).getCurrentSelection();
}
if (selection == null) {
setViewerInput(null);
} else if (selection instanceof IStructuredSelection) {
setViewerInput(((IStructuredSelection) selection).getFirstElement());
}
}
protected void initActionState(IAction action) {
// The show logical structure action is always enabled by default
// when (re)starting the view
String id = action.getId();
if (id.endsWith("ShowLogicalStructureAction")) {
action.setChecked(true);
} else {
super.initActionState(action);
}
}
protected IDebugModelPresentation getModelPresentation() {
if (modelPresentation == null) {
modelPresentation = new VariablesViewModelPresentation();
}
return modelPresentation;
}
private class VariablesViewLabelProvider implements ILabelProvider, IColorProvider {
private IDebugModelPresentation presentation;
public VariablesViewLabelProvider(IDebugModelPresentation presentation) {
this.presentation = presentation;
}
public IDebugModelPresentation getPresentation() {
return presentation;
}
public Image getImage(Object element) {
return presentation.getImage(element);
}
public String getText(Object element) {
return presentation.getText(element);
}
public void addListener(ILabelProviderListener listener) {
presentation.addListener(listener);
}
public void dispose() {
presentation.dispose();
}
public boolean isLabelProperty(Object element, String property) {
return presentation.isLabelProperty(element, property);
}
public void removeListener(ILabelProviderListener listener) {
presentation.removeListener(listener);
}
public Color getForeground(Object element) {
if (element instanceof IVariable) {
IVariable variable = (IVariable) element;
try {
if (variable.hasValueChanged()) {
return JFaceResources.getColorRegistry()
.get(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR);
}
} catch (DebugException e) {
DroolsEclipsePlugin.log(e);
}
}
return null;
}
public Color getBackground(Object element) {
return null;
}
}
}