blob: f4ea7a55affd53bcada04d01c79b3b4da533f847 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly marked,
* so as not to confuse it with the version available from LANL.
*
* Additionally, this program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* LA-CC 04-115
*******************************************************************************/
package org.eclipse.ptp.debug.internal.core.model;
import java.text.MessageFormat;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.ptp.debug.core.IPDebugConstants;
import org.eclipse.ptp.debug.core.PTPDebugCorePlugin;
import org.eclipse.ptp.debug.core.model.IPDebugElementStatus;
import org.eclipse.ptp.debug.core.model.IPValue;
import org.eclipse.ptp.debug.core.model.PVariableFormat;
import org.eclipse.ptp.debug.core.pdi.IPDISessionObject;
import org.eclipse.ptp.debug.core.pdi.event.IPDIChangedEvent;
import org.eclipse.ptp.debug.core.pdi.event.IPDIEvent;
import org.eclipse.ptp.debug.core.pdi.event.IPDIEventListener;
import org.eclipse.ptp.debug.core.pdi.event.IPDIResumedEvent;
import org.eclipse.ptp.debug.core.pdi.event.IPDIVariableInfo;
import org.eclipse.ptp.debug.core.pdi.model.IPDIVariable;
import org.eclipse.ptp.debug.core.pdi.model.IPDIVariableDescriptor;
import org.eclipse.ptp.debug.core.pdi.model.aif.IAIF;
import org.eclipse.ptp.debug.core.pdi.model.aif.IAIFTypePointer;
/**
* @author Clement chu
*
*/
public abstract class PVariable extends AbstractPVariable implements IPDIEventListener {
interface IInternalVariable {
IInternalVariable createShadow(int start, int length) throws DebugException;
IInternalVariable createShadow(String type) throws DebugException;
String getQualifiedName() throws DebugException;
IPValue getValue() throws DebugException;
void setValue(String expression) throws DebugException;
boolean isChanged();
void setChanged(boolean changed);
void dispose(boolean destroy);
boolean isSameDescriptor(IPDIVariableDescriptor desc);
boolean isSameVariable(IPDIVariable pdiVar);
void resetValue();
boolean isEditable() throws DebugException;
boolean isArgument();
int sizeof();
void invalidateValue();
void preserve();
}
private boolean fIsEnabled = true;
private IInternalVariable fOriginal;
private IInternalVariable fShadow;
private String fName;
private PVariableFormat fFormat = PVariableFormat.getFormat(PTPDebugCorePlugin.getDefault().getPluginPreferences().getInt(IPDebugConstants.PREF_DEFAULT_VARIABLE_FORMAT));
private boolean fIsDisposed = false;
protected PVariable(PDebugElement parent, IPDIVariableDescriptor pdiVariableObject) {
super(parent);
if (pdiVariableObject != null) {
setName(pdiVariableObject.getName());
createOriginal(pdiVariableObject);
}
fIsEnabled = (parent instanceof AbstractPValue) ? ((AbstractPValue) parent).getParentVariable().isEnabled() : !isBookkeepingEnabled();
getPDISession().getEventManager().addEventListener(this);
}
protected PVariable(PDebugElement parent, IPDIVariableDescriptor pdiVariableObject, String errorMessage) {
super(parent);
if (pdiVariableObject != null) {
setName(pdiVariableObject.getName());
createOriginal(pdiVariableObject);
}
fIsEnabled = !isBookkeepingEnabled();
setStatus(IPDebugElementStatus.ERROR, MessageFormat.format(CoreModelMessages.getString("PVariable.1"), new Object[] { errorMessage }));
getPDISession().getEventManager().addEventListener(this);
}
public boolean isEnabled() {
return fIsEnabled;
}
public void setEnabled(boolean enabled) throws DebugException {
IInternalVariable iv = getOriginal();
if (iv != null)
iv.dispose(true);
iv = getShadow();
if (iv != null)
iv.dispose(true);
fIsEnabled = enabled;
fireChangeEvent(DebugEvent.STATE);
}
public boolean canEnableDisable() {
return !(getParent() instanceof IValue);
}
public boolean isArgument() {
IInternalVariable iv = getOriginal();
return (iv != null) ? iv.isArgument() : false;
}
public IPValue getValue() throws DebugException {
if (!isDisposed() && isEnabled()) {
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null) {
try {
return iv.getValue();
} catch (DebugException e) {
setStatus(IPDebugElementStatus.ERROR, e.getMessage());
}
}
}
return PValueFactory.NULL_VALUE;
}
public String getName() throws DebugException {
return fName;
}
public String getReferenceTypeName() throws DebugException {
IAIF aif = getAIF();
return (aif != null) ? aif.getType().toString() : "";
}
public boolean hasValueChanged() throws DebugException {
if (isDisposed())
return false;
IInternalVariable iv = getCurrentInternalVariable();
return (iv != null) ? iv.isChanged() : false;
}
public boolean supportsFormatting() {
return true;
}
public PVariableFormat getFormat() {
return fFormat;
}
public void changeFormat(PVariableFormat format) throws DebugException {
setFormat(format);
resetValue();
}
public boolean canCastToArray() {
try {
return (getOriginal() != null && isEnabled() && (getAIF().getType() instanceof IAIFTypePointer));
} catch (DebugException e) {
return false;
}
}
public void castToArray(int startIndex, int length) throws DebugException {
IInternalVariable current = getCurrentInternalVariable();
if (current != null) {
IInternalVariable newVar = current.createShadow(startIndex, length);
if (getShadow() != null)
getShadow().dispose(true);
setShadow(newVar);
resetValue();
}
}
public void setValue(String expression) throws DebugException {
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null) {
String newExpression = processExpression(expression);
iv.setValue(newExpression);
}
}
public void setValue(IValue value) throws DebugException {
notSupported(CoreModelMessages.getString("PVariable.3"));
}
public boolean supportsValueModification() {
try {
return getCurrentInternalVariable().isEditable();
} catch (DebugException e) {
return false;
}
}
public boolean verifyValue(String expression) throws DebugException {
return true;
}
public boolean verifyValue(IValue value) throws DebugException {
return value.getDebugTarget().equals(getDebugTarget());
}
public boolean canCast() {
return (getOriginal() != null && isEnabled());
}
public void restoreOriginal() throws DebugException {
IInternalVariable oldVar = getShadow();
setShadow(null);
if (oldVar != null)
oldVar.dispose(true);
IInternalVariable iv = getOriginal();
if (iv != null)
iv.invalidateValue();
resetValue();
}
public boolean isCasted() {
return (getShadow() != null);
}
public void handleDebugEvents(IPDIEvent[] events) {
for (int i = 0; i < events.length; i++) {
IPDIEvent event = events[i];
if (!event.contains(getTasks()))
continue;
if (event instanceof IPDIChangedEvent) {
handleChangedEvent((IPDIChangedEvent) event);
}
else if (event instanceof IPDIResumedEvent) {
handleResumedEvent((IPDIResumedEvent)event);
}
}
}
private void handleResumedEvent(IPDIResumedEvent event) {
boolean changed = false;
if (hasErrors()) {
resetStatus();
changed = true;
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null)
iv.invalidateValue();
}
if (changed)
fireChangeEvent(DebugEvent.STATE);
}
private void handleChangedEvent(IPDIChangedEvent event) {
IPDISessionObject reason = event.getReason();
if (reason instanceof IPDIVariableInfo) {
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null) {
if (iv.isSameVariable(((IPDIVariableInfo)reason).getVariable())) {
iv.setChanged(true);
fireChangeEvent(DebugEvent.STATE);
}
}
}
}
private IInternalVariable getCurrentInternalVariable() {
if (getShadow() != null)
return getShadow();
return getOriginal();
}
private IInternalVariable getOriginal() {
return fOriginal;
}
protected void setOriginal(IInternalVariable original) {
fOriginal = original;
}
private IInternalVariable getShadow() {
return fShadow;
}
private void setShadow(IInternalVariable shadow) {
fShadow = shadow;
}
protected boolean isBookkeepingEnabled() {
boolean result = false;
return result;
}
abstract protected void createOriginal(IPDIVariableDescriptor vo);
protected boolean hasErrors() {
return !isOK();
}
protected void setChanged(boolean changed) {
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null) {
iv.setChanged(changed);
}
}
protected void resetValue() {
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null) {
resetStatus();
iv.resetValue();
fireChangeEvent(DebugEvent.STATE);
}
}
private String processExpression(String oldExpression) throws DebugException {
return oldExpression;
}
public void dispose() {
internalDispose(false);
setDisposed(true);
}
protected int sizeof() {
IInternalVariable iv = getCurrentInternalVariable();
return (iv != null) ? iv.sizeof() : -1;
}
public boolean equals(Object obj) {
if (obj instanceof PVariable) {
if (isDisposed() != ((PVariable)obj).isDisposed())
return false;
IInternalVariable iv = getOriginal();
return (iv != null) ? iv.equals(((PVariable) obj).getOriginal()) : false;
}
return false;
}
protected boolean sameVariable(IPDIVariableDescriptor vo) {
IInternalVariable iv = getOriginal();
return (iv != null && iv.isSameDescriptor(vo));
}
protected void setFormat(PVariableFormat format) {
fFormat = format;
}
public String getExpressionString() throws DebugException {
IInternalVariable iv = getCurrentInternalVariable();
return (iv != null) ? iv.getQualifiedName() : null;
}
protected void preserve() {
resetStatus();
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null)
iv.preserve();
}
protected void internalDispose(boolean destroy) {
getPDISession().getEventManager().removeEventListener(this);
IInternalVariable iv = getOriginal();
if (iv != null)
iv.dispose(destroy);
iv = getShadow();
if (iv != null)
iv.dispose(destroy);
}
protected boolean isDisposed() {
return fIsDisposed;
}
protected void setDisposed(boolean isDisposed) {
fIsDisposed = isDisposed;
}
protected void invalidateValue() {
resetStatus();
IInternalVariable iv = getCurrentInternalVariable();
if (iv != null)
iv.invalidateValue();
}
protected void setName(String name) {
fName = name;
}
}