/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package dbgplot;
import static dbgplot.DebugPlotPrint.printThrowable;
import dbgplot.evaluator.spi.Evaluator;
import dbgplot.evaluator.spi.Returner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ProgressMonitor;
import org.netbeans.api.debugger.DebuggerEngine;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.netbeans.api.debugger.jpda.ObjectVariable;
import org.netbeans.api.debugger.jpda.Variable;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author Will Shackleford<wshackle@gmail.com>
*/
@ServiceProvider(service = Evaluator.class)
public class JDPAEvaluator implements Evaluator {
private JPDADebugger getDebugger() {
try {
final DebuggerManager dm = DebuggerManager.getDebuggerManager();
if (null == dm) {
System.err.println("DebuggerManager.getDebuggerManager() == null");
return null;
}
DebuggerEngine currentEngine = dm.getCurrentEngine();
if (currentEngine == null) {
System.err.println("currentEngine == null");
return null;
}
final JPDADebugger d = currentEngine.lookupFirst(null, JPDADebugger.class);
if (d == null) {
System.err.println("JPDADebugger == null");
return null;
}
return d;
} catch (Exception e) {
printThrowable(e);
}
return null;
}
private static String cleanName(String input) {
input = input.trim();
while (input.startsWith("\"")) {
input = input.substring(1).trim();
}
while (input.endsWith("\"")) {
input = input.substring(0, input.length() - 1).trim();
}
return input;
}
@Override
public void evaluate(
final String expr,
final String mapper,
ProgressMonitor pm,
Returner r,
boolean showGetters) {
try {
final JPDADebugger d = this.getDebugger();
if (null == d) {
r.returnResult(null);
return;
}
Variable ov = d.evaluate(expr);
if (ov.getValue().equals("null")) {
r.returnResult(null);
return;
}
//System.out.println("v = " + v);
//System.out.println(v.getType());
//System.out.println(v.getValue());
final Object mirror = ov.createMirrorObject();
//System.out.println("mirror = " + mirror);
if (mirror != null && (mapper == null || mapper.length() < 1)) {
r.returnResult(mirror);
return;
}
final List<Object> fakeMirror = new ArrayList<Object>();
// org.netbeans.api.debugger.jpda.Field ovfa[] = ov.getFields(0, ov.getFieldsCount());
// System.out.println("ovfa = " + ovfa);
final boolean is_array = ov.getType().endsWith("[]");
final int n = is_array
? Integer.valueOf(d.evaluate(expr + ".length").getValue())
: Integer.valueOf(d.evaluate(expr + ".size()").getValue());
List<String> mapperparts = null;
if (mapper != null && mapper.length() > 1) {
mapperparts = new ArrayList<String>();
String part = "";
for (int ci = 0; ci < mapper.length(); ci++) {
char c = mapper.charAt(ci);
if (c == '_'
&& (ci == 0 || !Character.isJavaIdentifierPart(mapper.charAt(ci - 1)))
&& (ci == mapper.length() - 1 || !Character.isJavaIdentifierPart(mapper.charAt(ci + 1)))) {
mapperparts.add(part);
part = "";
} else {
part += mapper.substring(ci, ci + 1);
}
}
if (part.length() > 0) {
mapperparts.add(part);
}
}
//System.out.println("n = " + n);
// org.netbeans.api.debugger.jpda.Field elementData = ov.getField("elementData");
// Object o = elementData.createMirrorObject();
pm.setMaximum(n);
for (int i = 0; i < n; i++) {
pm.setProgress(i);
if (pm.isCanceled()) {
r.returnResult(null);
return;
}
final String pre_mapped_elem_name
= is_array
? expr + "[" + i + "]"
: expr + ".get(" + i + ")";
String mapped_elem_name = pre_mapped_elem_name;
if (mapperparts != null) {
mapped_elem_name
= mapperparts.size() < 2
? pre_mapped_elem_name + mapperparts.get(0)
: mapperparts.get(0);
for (int mpi = 1; mpi < mapperparts.size(); mpi++) {
mapped_elem_name
+= pre_mapped_elem_name
+ mapperparts.get(mpi);
}
}
final Variable elem_v = d.evaluate(mapped_elem_name);
if (elem_v.getValue().equals("null")) {
fakeMirror.add(null);
continue;
}
Object elem_mirror = elem_v.createMirrorObject();
if (elem_mirror != null) {
fakeMirror.add(elem_mirror);
continue;
}
// final String fn_expr = expr + ".get(" + i + ").getClass().getFields().length";
// final int fn = Integer.valueOf(d.evaluate(fn_expr).getValue());
ObjectVariable elem_ov = null;
if (elem_v instanceof ObjectVariable) {
elem_ov = (ObjectVariable) elem_v;
}
final int fn = elem_ov.getFieldsCount();
final Map<String, Object> map = new HashMap<String, Object>();
org.netbeans.api.debugger.jpda.Field fa[] = elem_ov.getFields(0, fn);
for (int j = 0; j < fa.length; j++) {
try {
final String name = fa[j].getName();
// final String name_expr = expr + ".get(" + i + ").getClass().getFields()[" + j + "].getName()";
// final String name = cleanName(d.evaluate(name_expr).getValue());
//System.out.println("name = " + name);
final Double D = Double.valueOf(fa[j].getValue());
// final Variable fv = d.evaluate(expr + ".get(" + i + ")." + name);
// //System.out.println("fv = " + fv);
// final Object eov = fv.createMirrorObject();
//System.out.println("ov = " + ov);
map.put(name, D);
} catch (Exception exception) {
// ignore
}
}
org.netbeans.api.debugger.jpda.Field ifa[] = elem_ov.getInheritedFields(0, 100);
for (int j = 0; j < ifa.length; j++) {
try {
final String name = ifa[j].getName();
// final String name_expr = expr + ".get(" + i + ").getClass().getFields()[" + j + "].getName()";
// final String name = cleanName(d.evaluate(name_expr).getValue());
//System.out.println("name = " + name);
final Double D = Double.valueOf(ifa[j].getValue());
// final Variable fv = d.evaluate(expr + ".get(" + i + ")." + name);
// //System.out.println("fv = " + fv);
// final Object eov = fv.createMirrorObject();
//System.out.println("ov = " + ov);
map.put(name, D);
} catch (Exception exception) {
// ignore
}
}
if (showGetters) {
final String mn_expr = mapped_elem_name + ".getClass().getMethods().length";
final int mn = Integer.valueOf(d.evaluate(mn_expr).getValue());
for (int k = 0; k < mn; k++) {
final String name_expr = mapped_elem_name + ".getClass().getMethods()[" + k + "].getName()";
final String name = cleanName(d.evaluate(name_expr).getValue());
//System.out.println("name = " + name);
String propName = null;
if (name.startsWith("get") && name.length() > 3) {
propName = name.substring(3, 4).toLowerCase()
+ (name.length() > 4
? name.substring(4)
: "");
} else if (name.startsWith("is") && name.length() > 2) {
propName = name.substring(2, 3).toLowerCase()
+ (name.length() > 3
? name.substring(3)
: "");
}
if (null == propName) {
continue;
}
if (map.containsKey(propName)) {
continue;
}
final String param_count_expr
= expr + ".get(" + i + ").getClass().getMethods()[" + k + "].getParameterTypes().length";
final int param_count = Integer.valueOf(d.evaluate(param_count_expr).getValue());
if (param_count != 0) {
continue;
}
//System.out.println("name = " + name);
final Variable return_fv = d.evaluate(mapped_elem_name + "." + name + "()");
//System.out.println("fv = " + fv);
final Object return_ov = return_fv.createMirrorObject();
//System.out.println("ov = " + ov);
map.put(propName, return_ov);
}
}
fakeMirror.add(map);
}
//System.out.println("fakeMirror = " + fakeMirror);
r.returnResult(fakeMirror);
return;
} catch (Exception exception) {
printThrowable(exception);
}
r.returnResult(null);
return;
}
@Override
public boolean isValid() {
return this.getDebugger() != null;
}
}