1 /*
2  * Copyright (C) 2016 The Android Open Source Project
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 
17 package com.android.ahat.heapdump;
18 
19 /**
20  * A Java instance or primitive value from a parsed heap dump.
21  * Note: To save memory, a null Value is used to represent a null Java
22  * instance from the heap dump.
23  */
24 public abstract class Value {
25   /**
26    * Constructs a Value for an AhatInstance.
27    * Note: returns null for null <code>value</code>.
28    *
29    * @param value the AhatInstance to make into a value
30    * @return the constructed value.
31    */
pack(AhatInstance value)32   public static Value pack(AhatInstance value) {
33     return value == null ? null : new InstanceValue(value);
34   }
35 
36   /**
37    * Constructs a Value for a boolean.
38    *
39    * @param value the boolean to make into a value
40    * @return the constructed value.
41    */
pack(boolean value)42   public static Value pack(boolean value) {
43     return new BooleanValue(value);
44   }
45 
46   /**
47    * Constructs a Value for a char.
48    *
49    * @param value the char to make into a value
50    * @return the constructed value.
51    */
pack(char value)52   public static Value pack(char value) {
53     return new CharValue(value);
54   }
55 
56   /**
57    * Constructs a Value for a float.
58    *
59    * @param value the float to make into a value
60    * @return the constructed value.
61    */
pack(float value)62   public static Value pack(float value) {
63     return new FloatValue(value);
64   }
65 
66   /**
67    * Constructs a Value for a double.
68    *
69    * @param value the double to make into a value
70    * @return the constructed value.
71    */
pack(double value)72   public static Value pack(double value) {
73     return new DoubleValue(value);
74   }
75 
76   /**
77    * Constructs a Value for a byte.
78    *
79    * @param value the byte to make into a value
80    * @return the constructed value.
81    */
pack(byte value)82   public static Value pack(byte value) {
83     return new ByteValue(value);
84   }
85 
86   /**
87    * Constructs a Value for a short.
88    *
89    * @param value the short to make into a value
90    * @return the constructed value.
91    */
pack(short value)92   public static Value pack(short value) {
93     return new ShortValue(value);
94   }
95 
96   /**
97    * Constructs a Value for a int.
98    *
99    * @param value the int to make into a value
100    * @return the constructed value.
101    */
pack(int value)102   public static Value pack(int value) {
103     return new IntValue(value);
104   }
105 
106   /**
107    * Constructs a Value for a long.
108    *
109    * @param value the long to make into a value
110    * @return the constructed value.
111    */
pack(long value)112   public static Value pack(long value) {
113     return new LongValue(value);
114   }
115 
116   /**
117    * Returns the type of the given value.
118    *
119    * @param value the value to get the type of
120    * @return the value's type
121    */
getType(Value value)122   public static Type getType(Value value) {
123     return value == null ? Type.OBJECT : value.getType();
124   }
125 
126   /**
127    * Return the type of the given value.
128    */
getType()129   abstract Type getType();
130 
131   /**
132    * Returns true if the Value is an AhatInstance rather than a primitive
133    * value.
134    *
135    * @return true if the value is an AhatInstance
136    */
isAhatInstance()137   public boolean isAhatInstance() {
138     return false;
139   }
140 
141   /**
142    * Returns the Value as an AhatInstance if it is one.
143    * Returns null if the Value represents a Java primitive value.
144    *
145    * @return the AhatInstance packed into this value
146    */
asAhatInstance()147   public AhatInstance asAhatInstance() {
148     return null;
149   }
150 
151   /**
152    * Returns true if the Value is an int.
153    *
154    * @return true if the value is an int.
155    */
isInteger()156   public boolean isInteger() {
157     return false;
158   }
159 
160   /**
161    * Returns the Value as an int if it is one.
162    * Returns null if the Value does not represent an int.
163    *
164    * @return the int packed into this value
165    */
asInteger()166   public Integer asInteger() {
167     return null;
168   }
169 
170   /**
171    * Returns true if the Value is an long.
172    *
173    * @return true if the value is an long.
174    */
isLong()175   public boolean isLong() {
176     return false;
177   }
178 
179   /**
180    * Returns the Value as an long if it is one.
181    * Returns null if the Value does not represent an long.
182    *
183    * @return the long packed into this value
184    */
asLong()185   public Long asLong() {
186     return null;
187   }
188 
189   /**
190    * Returns the Value as an byte if it is one.
191    * Returns null if the Value does not represent an byte.
192    *
193    * @return the byte packed into this value
194    */
asByte()195   public Byte asByte() {
196     return null;
197   }
198 
199   /**
200    * Returns the Value as an char if it is one.
201    * Returns null if the Value does not represent an char.
202    *
203    * @return the char packed into this value
204    */
asChar()205   public Character asChar() {
206     return null;
207   }
208 
209   @Override
toString()210   public abstract String toString();
211 
getBaseline()212   private Value getBaseline() {
213     return this;
214   }
215 
216   /**
217    * Returns the baseline of the given value for the purposes of diff.
218    * This method can be used to handle the case when the Value is null.
219    *
220    * @param value the value to get the baseline of
221    * @return the baseline of the value
222    * @see Diffable#getBaseline
223    */
getBaseline(Value value)224   public static Value getBaseline(Value value) {
225     return value == null ? null : value.getBaseline();
226   }
227 
228   @Override
equals(Object other)229   public abstract boolean equals(Object other);
230 
231   private static class BooleanValue extends Value {
232     private boolean mBool;
233 
BooleanValue(boolean bool)234     BooleanValue(boolean bool) {
235       mBool = bool;
236     }
237 
238     @Override
getType()239     Type getType() {
240       return Type.BOOLEAN;
241     }
242 
243     @Override
toString()244     public String toString() {
245       return Boolean.toString(mBool);
246     }
247 
equals(Object other)248     @Override public boolean equals(Object other) {
249       if (other instanceof BooleanValue) {
250         BooleanValue value = (BooleanValue)other;
251         return mBool == value.mBool;
252       }
253       return false;
254     }
255   }
256 
257   private static class ByteValue extends Value {
258     private byte mByte;
259 
ByteValue(byte b)260     ByteValue(byte b) {
261       mByte = b;
262     }
263 
264     @Override
asByte()265     public Byte asByte() {
266       return mByte;
267     }
268 
269     @Override
getType()270     Type getType() {
271       return Type.BYTE;
272     }
273 
274     @Override
toString()275     public String toString() {
276       return Byte.toString(mByte);
277     }
278 
equals(Object other)279     @Override public boolean equals(Object other) {
280       if (other instanceof ByteValue) {
281         ByteValue value = (ByteValue)other;
282         return mByte == value.mByte;
283       }
284       return false;
285     }
286   }
287 
288   private static class CharValue extends Value {
289     private char mChar;
290 
CharValue(char c)291     CharValue(char c) {
292       mChar = c;
293     }
294 
295     @Override
asChar()296     public Character asChar() {
297       return mChar;
298     }
299 
300     @Override
getType()301     Type getType() {
302       return Type.CHAR;
303     }
304 
305     @Override
toString()306     public String toString() {
307       return Character.toString(mChar);
308     }
309 
equals(Object other)310     @Override public boolean equals(Object other) {
311       if (other instanceof CharValue) {
312         CharValue value = (CharValue)other;
313         return mChar == value.mChar;
314       }
315       return false;
316     }
317   }
318 
319   private static class DoubleValue extends Value {
320     private double mDouble;
321 
DoubleValue(double d)322     DoubleValue(double d) {
323       mDouble = d;
324     }
325 
326     @Override
getType()327     Type getType() {
328       return Type.DOUBLE;
329     }
330 
331     @Override
toString()332     public String toString() {
333       return Double.toString(mDouble);
334     }
335 
equals(Object other)336     @Override public boolean equals(Object other) {
337       if (other instanceof DoubleValue) {
338         DoubleValue value = (DoubleValue)other;
339         return mDouble == value.mDouble;
340       }
341       return false;
342     }
343   }
344 
345   private static class FloatValue extends Value {
346     private float mFloat;
347 
FloatValue(float f)348     FloatValue(float f) {
349       mFloat = f;
350     }
351 
352     @Override
getType()353     Type getType() {
354       return Type.FLOAT;
355     }
356 
357     @Override
toString()358     public String toString() {
359       return Float.toString(mFloat);
360     }
361 
equals(Object other)362     @Override public boolean equals(Object other) {
363       if (other instanceof FloatValue) {
364         FloatValue value = (FloatValue)other;
365         return mFloat == value.mFloat;
366       }
367       return false;
368     }
369   }
370 
371   private static class InstanceValue extends Value {
372     private AhatInstance mInstance;
373 
InstanceValue(AhatInstance inst)374     InstanceValue(AhatInstance inst) {
375       assert(inst != null);
376       mInstance = inst;
377     }
378 
379     @Override
isAhatInstance()380     public boolean isAhatInstance() {
381       return true;
382     }
383 
384     @Override
asAhatInstance()385     public AhatInstance asAhatInstance() {
386       return mInstance;
387     }
388 
389     @Override
getType()390     Type getType() {
391       return Type.OBJECT;
392     }
393 
394     @Override
toString()395     public String toString() {
396       return mInstance.toString();
397     }
398 
getBaseline()399     public Value getBaseline() {
400       return InstanceValue.pack(mInstance.getBaseline());
401     }
402 
equals(Object other)403     @Override public boolean equals(Object other) {
404       if (other instanceof InstanceValue) {
405         InstanceValue value = (InstanceValue)other;
406         return mInstance.equals(value.mInstance);
407       }
408       return false;
409     }
410   }
411 
412   private static class IntValue extends Value {
413     private int mInt;
414 
IntValue(int i)415     IntValue(int i) {
416       mInt = i;
417     }
418 
419     @Override
isInteger()420     public boolean isInteger() {
421       return true;
422     }
423 
424     @Override
asInteger()425     public Integer asInteger() {
426       return mInt;
427     }
428 
429     @Override
getType()430     Type getType() {
431       return Type.INT;
432     }
433 
434     @Override
toString()435     public String toString() {
436       return Integer.toString(mInt);
437     }
438 
equals(Object other)439     @Override public boolean equals(Object other) {
440       if (other instanceof IntValue) {
441         IntValue value = (IntValue)other;
442         return mInt == value.mInt;
443       }
444       return false;
445     }
446   }
447 
448   private static class LongValue extends Value {
449     private long mLong;
450 
LongValue(long l)451     LongValue(long l) {
452       mLong = l;
453     }
454 
455     @Override
isLong()456     public boolean isLong() {
457       return true;
458     }
459 
460     @Override
asLong()461     public Long asLong() {
462       return mLong;
463     }
464 
465     @Override
getType()466     Type getType() {
467       return Type.LONG;
468     }
469 
470     @Override
toString()471     public String toString() {
472       return Long.toString(mLong);
473     }
474 
equals(Object other)475     @Override public boolean equals(Object other) {
476       if (other instanceof LongValue) {
477         LongValue value = (LongValue)other;
478         return mLong == value.mLong;
479       }
480       return false;
481     }
482   }
483 
484   private static class ShortValue extends Value {
485     private short mShort;
486 
ShortValue(short s)487     ShortValue(short s) {
488       mShort = s;
489     }
490 
491     @Override
getType()492     Type getType() {
493       return Type.SHORT;
494     }
495 
496     @Override
toString()497     public String toString() {
498       return Short.toString(mShort);
499     }
500 
equals(Object other)501     @Override public boolean equals(Object other) {
502       if (other instanceof ShortValue) {
503         ShortValue value = (ShortValue)other;
504         return mShort == value.mShort;
505       }
506       return false;
507     }
508   }
509 }
510