faa963756f8d6ff0a66eea000a4f336cdcac8b14
[idea/community.git] / java / debugger / impl / src / com / intellij / debugger / engine / evaluation / expression / UnBoxingEvaluator.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.debugger.engine.evaluation.expression;
17
18 import com.intellij.debugger.engine.DebugProcessImpl;
19 import com.intellij.debugger.engine.evaluation.EvaluateException;
20 import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
21 import com.intellij.openapi.util.Pair;
22 import com.intellij.util.containers.HashMap;
23 import com.sun.jdi.ClassType;
24 import com.sun.jdi.Method;
25 import com.sun.jdi.ObjectReference;
26 import com.sun.jdi.Value;
27 import org.jetbrains.annotations.Nullable;
28
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Map;
32
33 /**
34  * @author Eugene Zhuravlev
35  *         Date: Feb 8, 2010
36  */
37 public class UnBoxingEvaluator implements Evaluator{
38   private final Evaluator myOperand;
39   private static final Map<String, Pair<String, String>> TYPES_TO_CONVERSION_METHOD_MAP = new HashMap<String, Pair<String, String>>();
40   static {
41     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Boolean", new Pair<String, String>("booleanValue", "()Z"));
42     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Byte", new Pair<String, String>("byteValue", "()B"));
43     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Character", new Pair<String, String>("charValue", "()C"));
44     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Short", new Pair<String, String>("shortValue", "()S"));
45     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Integer", new Pair<String, String>("intValue", "()I"));
46     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Long", new Pair<String, String>("longValue", "()J"));
47     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Float", new Pair<String, String>("floatValue", "()F"));
48     TYPES_TO_CONVERSION_METHOD_MAP.put("java.lang.Double", new Pair<String, String>("doubleValue", "()D"));
49   }
50
51   public static boolean isTypeUnboxable(String typeName) {
52     return TYPES_TO_CONVERSION_METHOD_MAP.containsKey(typeName);
53   }
54
55   public UnBoxingEvaluator(Evaluator operand) {
56     myOperand = operand;
57   }
58
59   public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
60     final Value result = (Value)myOperand.evaluate(context);
61     if (result instanceof ObjectReference) {
62       final String valueTypeName = result.type().name();
63       final Pair<String, String> pair = TYPES_TO_CONVERSION_METHOD_MAP.get(valueTypeName);
64       if (pair != null) {
65         return convertToPrimitive(context, (ObjectReference)result, pair.getFirst(), pair.getSecond());
66       }
67     }
68     return result;
69   }
70                                           
71   @Nullable
72   public Modifier getModifier() {
73     return null;
74   }
75
76   private static Value convertToPrimitive(EvaluationContextImpl context, ObjectReference value, final String conversionMethodName,
77                                           String conversionMethodSignature) throws EvaluateException {
78     final DebugProcessImpl process = context.getDebugProcess();
79     final ClassType wrapperClass = (ClassType)value.referenceType();
80     final List<Method> methods = wrapperClass.methodsByName(conversionMethodName, conversionMethodSignature);
81     if (methods.size() == 0) { 
82       throw new EvaluateException("Cannot convert to primitive value of type " + value.type() + ": Unable to find method " +
83                                   conversionMethodName + conversionMethodSignature);
84     }
85
86     final Method method = methods.get(0);
87
88     return process.invokeMethod(context, value, method, new ArrayList());
89   }
90 }