package jetbrains.mps.debugger.java.runtime.state.customViewers;
/*Generated by MPS */
import jetbrains.mps.debugger.java.api.state.customViewers.CustomViewersManager;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import com.intellij.openapi.project.ProjectManager;
import java.util.Map;
import jetbrains.mps.debugger.java.api.state.proxy.ValueWrapperFactory;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.debugger.java.runtime.state.DebugSession;
import jetbrains.mps.debug.api.DebugSessionManagerComponent;
import com.intellij.openapi.project.ProjectManagerListener;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IValueProxy;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.LinkedHashSet;
import com.sun.jdi.VirtualMachine;
import jetbrains.mps.baseLanguage.tuples.runtime.Tuples;
import com.sun.jdi.Type;
import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple;
import jetbrains.mps.debugger.java.api.evaluation.EvaluationUtils;
import com.sun.jdi.InterfaceType;
import com.sun.jdi.ClassType;
import jetbrains.mps.debugger.java.api.evaluation.EvaluationException;
import org.apache.log4j.Level;
import jetbrains.mps.debugger.java.api.state.proxy.ValueWrapper;
import com.sun.jdi.ThreadReference;
import jetbrains.mps.debugger.java.api.evaluation.proxies.INullValueProxy;
import jetbrains.mps.debugger.java.api.evaluation.proxies.IObjectValueProxy;
import com.sun.jdi.ObjectReference;
import com.intellij.openapi.project.Project;
import jetbrains.mps.debug.api.AbstractDebugSession;
import jetbrains.mps.debugger.java.api.state.proxy.JavaValue;
import org.jetbrains.annotations.Nullable;
import com.sun.jdi.Value;
import jetbrains.mps.debugger.java.api.evaluation.proxies.MirrorUtil;
import com.intellij.openapi.project.ProjectManagerAdapter;
public class CustomViewersManagerImpl extends CustomViewersManager {
private static final Logger LOG = LogManager.getLogger(CustomViewersManagerImpl.class);
private final ProjectManager myProjectManager;
private final Map<String, ValueWrapperFactory> myFactories = MapSequence.fromMap(new HashMap<String, ValueWrapperFactory>());
private final Map<DebugSession, Map<Long, String>> myObjectIdToFactory = MapSequence.fromMap(new HashMap<DebugSession, Map<Long, String>>());
private final DebugSessionManagerComponent.DebugSessionAdapter myDebugSessionListener = new CustomViewersManagerImpl.MyDebugSessionAdapter();
private final ProjectManagerListener myProjectManagerListener = new CustomViewersManagerImpl.MyProjectManagerAdapter();
public CustomViewersManagerImpl(ProjectManager projectManager) {
myProjectManager = projectManager;
}
@Override
public void initComponent() {
myProjectManager.addProjectManagerListener(myProjectManagerListener);
}
@Override
public void disposeComponent() {
myProjectManager.removeProjectManagerListener(myProjectManagerListener);
}
@Override
public void addFactory(@NotNull ValueWrapperFactory factory) {
MapSequence.fromMap(myFactories).put(factory.getClass().getName(), factory);
}
@Override
public void removeFactory(@NotNull ValueWrapperFactory factory) {
MapSequence.fromMap(myFactories).removeKey(factory.getClass().getName());
}
public Set<ValueWrapperFactory> getValueWrapperFactories(@NotNull final IValueProxy originalValue) {
Set<ValueWrapperFactory> result = SetSequence.fromSet(new LinkedHashSet<ValueWrapperFactory>());
for (ValueWrapperFactory factory : MapSequence.fromMap(myFactories).values()) {
if (factory.canWrapValue(originalValue)) {
SetSequence.fromSet(result).addElement(factory);
}
}
return result;
}
private ValueWrapperFactory getBestFactory(Set<ValueWrapperFactory> factories, DebugSession session) {
VirtualMachine vm = session.getEventsProcessor().getVirtualMachine();
Tuples._2<ValueWrapperFactory, Type> currentBest = MultiTuple.<ValueWrapperFactory,Type>from(null, null);
for (ValueWrapperFactory factory : SetSequence.fromSet(factories)) {
try {
if (currentBest._0() == null) {
currentBest._0(factory);
currentBest._1(EvaluationUtils.getInstance().findTypeSilently(factory.getWrappedType(), vm));
} else if (!(EvaluationUtils.getInstance().instanceOf(currentBest._1(), factory.getWrappedType(), vm))) {
Type newType = EvaluationUtils.getInstance().findTypeSilently(factory.getWrappedType(), vm);
if (newType instanceof InterfaceType && currentBest._1() instanceof ClassType && !(currentBest._0().getWrappedType().equals(EvaluationUtils.JAVA_LANG_OBJECT))) {
continue;
}
currentBest._0(factory);
currentBest._1(newType);
}
} catch (EvaluationException e) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("Error while trying to select best custom viewer. Current factory is " + factory, e);
}
}
}
return currentBest._0();
}
public synchronized ValueWrapper getValueWrapper(@NotNull IValueProxy proxy, ThreadReference threadReference) {
if (proxy instanceof INullValueProxy) {
return MapSequence.fromMap(myFactories).get(ObjectWrapperFactory.class.getName()).createValueWrapper(proxy, threadReference);
}
ValueWrapperFactory factory = null;
DebugSession session = getSession(proxy);
if (proxy instanceof IObjectValueProxy) {
Map<Long, String> objectIdToFactory = MapSequence.fromMap(myObjectIdToFactory).get(session);
if (objectIdToFactory == null) {
objectIdToFactory = MapSequence.fromMap(new HashMap<Long, String>());
MapSequence.fromMap(myObjectIdToFactory).put(session, objectIdToFactory);
}
long uniqueID = getValueId(proxy);
String factoryId = MapSequence.fromMap(objectIdToFactory).get(uniqueID);
if ((factoryId != null && factoryId.length() > 0)) {
factory = MapSequence.fromMap(myFactories).get(factoryId);
}
}
if (factory == null) {
Set<ValueWrapperFactory> factories = getValueWrapperFactories(proxy);
if (factories.isEmpty()) {
return null;
}
factory = (factories.size() > 1 ? getBestFactory(factories, session) : factories.iterator().next());
}
return factory.createValueWrapper(proxy, threadReference);
}
public synchronized void setValueWrapper(@NotNull IValueProxy value, @NotNull ValueWrapperFactory factory, @NotNull DebugSession session) {
Map<Long, String> objectIdToFactory = MapSequence.fromMap(myObjectIdToFactory).get(session);
if (objectIdToFactory == null) {
objectIdToFactory = MapSequence.fromMap(new HashMap<Long, String>());
MapSequence.fromMap(myObjectIdToFactory).put(session, objectIdToFactory);
}
String oldFactory = MapSequence.fromMap(objectIdToFactory).get(getValueId(value));
String newFactory = factory.getClass().getName();
if (neq_2btpdq_a0e0o(oldFactory, newFactory)) {
MapSequence.fromMap(objectIdToFactory).put(getValueId(value), newFactory);
session.refresh();
}
}
public static CustomViewersManagerImpl getInstanceImpl() {
return (CustomViewersManagerImpl) CustomViewersManager.getInstance();
}
private long getValueId(@NotNull IValueProxy originalValue) {
return ((ObjectReference) originalValue.getJDIValue()).uniqueID();
}
private DebugSession getSession(@NotNull IValueProxy value) {
// this is just wrong
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
for (AbstractDebugSession session : SetSequence.fromSet(DebugSessionManagerComponent.getInstance(project).getDebugSessions())) {
if (session instanceof DebugSession) {
if (((DebugSession) session).getEventsProcessor().getVirtualMachine() == value.getJDIValue().virtualMachine()) {
return (DebugSession) session;
}
}
}
}
return null;
}
public JavaValue fromJdi(@Nullable Value value, @NotNull ThreadReference threadReference) {
return getValueWrapper(MirrorUtil.getInstance().getValueProxy(value), threadReference);
}
private class MyProjectManagerAdapter extends ProjectManagerAdapter {
public MyProjectManagerAdapter() {
}
@Override
public void projectOpened(Project project) {
DebugSessionManagerComponent.getInstance(project).addDebugSessionListener(myDebugSessionListener);
}
@Override
public void projectClosing(Project project) {
DebugSessionManagerComponent.getInstance(project).removeDebugSessionListener(CustomViewersManagerImpl.this.myDebugSessionListener);
}
}
private class MyDebugSessionAdapter extends DebugSessionManagerComponent.DebugSessionAdapter {
public MyDebugSessionAdapter() {
}
@Override
public void detached(AbstractDebugSession session) {
if (session instanceof DebugSession) {
MapSequence.fromMap(myObjectIdToFactory).removeKey((DebugSession) session);
}
}
}
private static boolean neq_2btpdq_a0e0o(Object a, Object b) {
return !(((a != null ? a.equals(b) : a == b)));
}
}